mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
2481
IDEHelper/Linker/BlCodeView.cpp
Normal file
2481
IDEHelper/Linker/BlCodeView.cpp
Normal file
File diff suppressed because it is too large
Load diff
463
IDEHelper/Linker/BlCodeView.h
Normal file
463
IDEHelper/Linker/BlCodeView.h
Normal file
|
@ -0,0 +1,463 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "BeefySysLib/FileStream.h"
|
||||
#include "BeefySysLib/MemStream.h"
|
||||
#include "BeefySysLib/util/BumpAllocator.h"
|
||||
#include "BeefySysLib/util/ChunkedDataBuffer.h"
|
||||
#include "BeefySysLib/util/Array.h"
|
||||
#include "BeefySysLib/util/String.h"
|
||||
#include "BeefySysLib/util/Hash.h"
|
||||
#include "BeefySysLib/util/CritSect.h"
|
||||
#include "BeefySysLib/util/WorkThread.h"
|
||||
#include "BeefySysLib/util/PerfTimer.h"
|
||||
#include "../Compiler/BfUtil.h"
|
||||
#include "BlMsf.h"
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "BlPdbParser.h"
|
||||
//#include "Hash.h"
|
||||
#include "BlCvTypeSource.h"
|
||||
#include "BlContext.h"
|
||||
#include <queue>
|
||||
|
||||
//#define BL_USE_DENSEMAP_CV
|
||||
|
||||
#ifdef BL_USE_DENSEMAP_CV
|
||||
#include <sparsehash/dense_hash_map>
|
||||
#include <sparsehash/dense_hash_set>
|
||||
#endif
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
struct PE_SymInfo;
|
||||
struct COFFRelocation;
|
||||
class BlContext;
|
||||
class BlObjectData;
|
||||
class BlCvTypeSource;
|
||||
|
||||
class BlCVStream
|
||||
{
|
||||
public:
|
||||
String mName;
|
||||
Array<int> mBlocks;
|
||||
int mSize;
|
||||
|
||||
public:
|
||||
BlCVStream()
|
||||
{
|
||||
mSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class BlCvFileInfo
|
||||
{
|
||||
public:
|
||||
int mStrTableIdx;
|
||||
int mChksumOfs;
|
||||
int8 mHashType;
|
||||
uint8 mHash[16];
|
||||
};
|
||||
|
||||
class BlCvLine
|
||||
{
|
||||
public:
|
||||
int mOffset;
|
||||
int mLineNumStart;
|
||||
};
|
||||
|
||||
class BlCvLineInfoBlock
|
||||
{
|
||||
public:
|
||||
int mFileInfoIdx;
|
||||
std::vector<BlCvLine> mLines;
|
||||
std::vector<int16> mColumns;
|
||||
};
|
||||
|
||||
class BlCvLineInfo
|
||||
{
|
||||
public:
|
||||
int mStartSegmentIdx;
|
||||
int mStartSegmentOffset;
|
||||
int mContribBytes;
|
||||
std::vector<BlCvLineInfoBlock> mLineInfoBlocks;
|
||||
|
||||
BlCvLineInfo()
|
||||
{
|
||||
mStartSegmentIdx = -1;
|
||||
mStartSegmentOffset = 0;
|
||||
mContribBytes = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct BlCvSymDataBlock
|
||||
{
|
||||
void* mData;
|
||||
int mSize;
|
||||
int mOutSize;
|
||||
int mSourceSectOffset;
|
||||
COFFRelocation* mRelocStart;
|
||||
COFFRelocation* mRelocEnd;
|
||||
|
||||
FILE* mFP;
|
||||
int mFPOfs;
|
||||
};
|
||||
|
||||
enum BlSectInfoState : intptr
|
||||
{
|
||||
BlSectInfoState_QueuedData = -1,
|
||||
BlSectInfoState_QueuedDebugT = -2,
|
||||
BlSectInfoState_QueuedDebugS = -3
|
||||
};
|
||||
|
||||
struct BlObjectDataSectInfo
|
||||
{
|
||||
int mSegmentIdx;
|
||||
int mSegmentOffset;
|
||||
void* mRelocData;
|
||||
union
|
||||
{
|
||||
void* mChunkData;
|
||||
BlSectInfoState mState;
|
||||
};
|
||||
uint16 mSelectNum;
|
||||
int8 mSelection;
|
||||
|
||||
bool IsUsed()
|
||||
{
|
||||
return (intptr)mChunkData >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct BlObjectDataSectInfo;
|
||||
|
||||
class BlCvModuleContrib
|
||||
{
|
||||
public:
|
||||
int mBlSectionIdx;
|
||||
int mBlSectionOfs;
|
||||
int mSize;
|
||||
int mCharacteristics;
|
||||
|
||||
public:
|
||||
BlCvModuleContrib()
|
||||
{
|
||||
mBlSectionIdx = 0;
|
||||
mBlSectionOfs = 0;
|
||||
mSize = 0;
|
||||
mCharacteristics = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class BlCvModuleInfo
|
||||
{
|
||||
public:
|
||||
int mIdx;
|
||||
String mName;
|
||||
const char* mStrTab;
|
||||
BlObjectData* mObjectData;
|
||||
int mSymStreamIdx;
|
||||
BlCvTypeSource* mTypeSource;
|
||||
PE_SymInfo* mObjSyms;
|
||||
BfSizedVector<BlObjectDataSymInfo, 0> mSymInfo;
|
||||
BfSizedVector<BlCvSymDataBlock, 1> mSymData;
|
||||
int mLineInfoSize;
|
||||
//BfSizedVector<BlCvContrib, 1> mContribs;
|
||||
BlCvModuleContrib mContrib;
|
||||
std::vector<BlCvFileInfo> mFileInfos;
|
||||
OwnedVector<BlCvLineInfo> mLineInfo;
|
||||
BfSizedVector<BlCvSymDataBlock, 1> mInlineData;
|
||||
BfSizedVector<BlObjectDataSectInfo, 1> mSectInfos;
|
||||
int mDeferredSegOfsStart;
|
||||
int mDeferredSegOfsLen;
|
||||
|
||||
public:
|
||||
BlCvModuleInfo()
|
||||
{
|
||||
mIdx = -1;
|
||||
mStrTab = NULL;
|
||||
//mObjSyms = NULL;
|
||||
mObjectData = NULL;
|
||||
mSymStreamIdx = -1;
|
||||
mLineInfoSize = 0;
|
||||
mTypeSource = NULL;
|
||||
mDeferredSegOfsStart = 0;
|
||||
mDeferredSegOfsLen = 0;
|
||||
mObjSyms = NULL;
|
||||
}
|
||||
|
||||
~BlCvModuleInfo()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class BlTypeInfo
|
||||
{
|
||||
public:
|
||||
#ifdef BL_USE_DENSEMAP_CV
|
||||
google::dense_hash_map<Val128, int, Val128::Hash, Val128::Equals> mTypeMap;
|
||||
#else
|
||||
std::unordered_map<Val128, int, Val128::Hash, Val128::Equals> mTypeMap;
|
||||
#endif
|
||||
ChunkedDataBuffer mData;
|
||||
int mCurTagId;
|
||||
|
||||
public:
|
||||
BlTypeInfo()
|
||||
{
|
||||
mCurTagId = 0x1000;
|
||||
|
||||
#ifdef BL_USE_DENSEMAP_CV
|
||||
mTypeMap.set_empty_key(Val128(-1));
|
||||
mTypeMap.min_load_factor(0);
|
||||
mTypeMap.resize(100000);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
class BlCvRecordEntry
|
||||
{
|
||||
public:
|
||||
Val128 mKey;
|
||||
int mRecordIndex;
|
||||
BlCvRecordEntry* mNext;
|
||||
};
|
||||
|
||||
class BlCvRecordMap
|
||||
{
|
||||
public:
|
||||
#ifdef BL_USE_DENSEMAP_CV
|
||||
google::dense_hash_set<Val128, Val128::Hash, Val128::Equals> mKeySet;
|
||||
#else
|
||||
std::unordered_set<Val128, Val128::Hash, Val128::Equals> mKeySet;
|
||||
#endif
|
||||
BlCodeView* mCodeView;
|
||||
BlCvRecordEntry* mBuckets[4096];
|
||||
BumpAllocator mAlloc;
|
||||
int mNumEntries;
|
||||
|
||||
public:
|
||||
BlCvRecordMap()
|
||||
{
|
||||
mCodeView = NULL;
|
||||
memset(&mBuckets, 0, sizeof(mBuckets));
|
||||
mNumEntries = 0;
|
||||
|
||||
#ifdef BL_USE_DENSEMAP_CV
|
||||
mKeySet.set_empty_key(Val128(-1));
|
||||
mKeySet.min_load_factor(0);
|
||||
mKeySet.resize(100000);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Insert(const char* name, int symIdx);
|
||||
int TryInsert(const char* name, const Val128& key);
|
||||
};
|
||||
|
||||
class BlCvContrib
|
||||
{
|
||||
public:
|
||||
int mModuleIdx;
|
||||
int mBlSectionOfs;
|
||||
int mSize;
|
||||
int mCharacteristics;
|
||||
};
|
||||
|
||||
class BlCvContributionSeg
|
||||
{
|
||||
public:
|
||||
std::vector<BlCvContrib> mContribs;
|
||||
};
|
||||
|
||||
class BlCvContributionMap
|
||||
{
|
||||
public:
|
||||
OwnedVector<BlCvContributionSeg> mSegments;
|
||||
};
|
||||
|
||||
class BlCvTypeWorkThread : public WorkThread
|
||||
{
|
||||
public:
|
||||
std::deque<BlCvTypeSource*> mTypeSourceWorkQueue;
|
||||
BlCodeView* mCodeView;
|
||||
CritSect mCritSect;
|
||||
SyncEvent mWorkEvent;
|
||||
volatile bool mTypesDone;
|
||||
volatile bool mThreadDone;
|
||||
|
||||
public:
|
||||
BlCvTypeWorkThread();
|
||||
~BlCvTypeWorkThread();
|
||||
|
||||
virtual void Stop() override;
|
||||
virtual void Run() override;
|
||||
|
||||
void Add(BlCvTypeSource* typeSource);
|
||||
};
|
||||
|
||||
class BlCvModuleWorkThread : public WorkThread
|
||||
{
|
||||
public:
|
||||
std::deque<BlCvModuleInfo*> mModuleWorkQueue;
|
||||
BlCodeView* mCodeView;
|
||||
CritSect mCritSect;
|
||||
SyncEvent mWorkEvent;
|
||||
volatile bool mModulesDone;
|
||||
|
||||
public:
|
||||
BlCvModuleWorkThread();
|
||||
~BlCvModuleWorkThread();
|
||||
|
||||
virtual void Stop() override;
|
||||
virtual void Run() override;
|
||||
|
||||
void Add(BlCvModuleInfo* module);
|
||||
};
|
||||
|
||||
class BlCvStreamWriter
|
||||
{
|
||||
public:
|
||||
BlMsf* mMsf;
|
||||
BlCVStream* mCurStream;
|
||||
uint8* mCurBlockPos;
|
||||
uint8* mCurBlockEnd;
|
||||
|
||||
public:
|
||||
BlCvStreamWriter();
|
||||
|
||||
void Start(BlCVStream* stream);
|
||||
void Continue(BlCVStream* stream);
|
||||
void End(bool flush = true);
|
||||
|
||||
void Write(const void* data, int size);
|
||||
template <typename T>
|
||||
void WriteT(const T& val)
|
||||
{
|
||||
Write(&val, sizeof(T));
|
||||
}
|
||||
void Write(ChunkedDataBuffer& buffer);
|
||||
|
||||
int GetStreamPos();
|
||||
void StreamAlign(int align);
|
||||
void* GetStreamPtr(int pos);
|
||||
};
|
||||
|
||||
class BlCvStreamReader
|
||||
{
|
||||
public:
|
||||
BlMsf* mMsf;
|
||||
int mBlockIdx;
|
||||
BlCVStream* mCurStream;
|
||||
uint8* mCurBlockPos;
|
||||
uint8* mCurBlockEnd;
|
||||
|
||||
public:
|
||||
BlCvStreamReader();
|
||||
|
||||
void Open(BlCVStream* stream);
|
||||
|
||||
void* ReadFast(void* data, int size);
|
||||
void Seek(int size);
|
||||
int GetStreamPos();
|
||||
};
|
||||
|
||||
class BlCodeView
|
||||
{
|
||||
public:
|
||||
BlContext* mContext;
|
||||
BumpAllocator mAlloc;
|
||||
BlMsf mMsf;
|
||||
|
||||
int mStat_TypeMapInserts;
|
||||
int mStat_ParseTagFuncs;
|
||||
|
||||
OwnedVector<BlCVStream> mStreams;
|
||||
|
||||
OwnedVector<BlCvModuleInfo> mModuleInfo;
|
||||
int mSectStartFilePos;
|
||||
|
||||
BlTypeInfo mTPI;
|
||||
BlTypeInfo mIPI;
|
||||
|
||||
int8 mSignature[16];
|
||||
int mAge;
|
||||
|
||||
DynMemStream mSectionHeaders;
|
||||
ChunkedVector<int> mSymRecordDeferredPositions;
|
||||
int mSymRecordsStream;
|
||||
//ChunkedDataBuffer mSymRecords;
|
||||
BlCvRecordMap mGlobals;
|
||||
|
||||
std::unordered_map<String, BlCvTypeSource*> mTypeServerFiles;
|
||||
std::unordered_map<String, int> mStrTabMap;
|
||||
String mStrTab;
|
||||
|
||||
BlCvContributionMap mContribMap;
|
||||
|
||||
BlCvTypeWorkThread mTypeWorkThread;
|
||||
BlCvModuleWorkThread mModuleWorkThread;
|
||||
|
||||
ChunkedVector<int> mDeferedSegOffsets;
|
||||
|
||||
BlCvStreamWriter mWriter;
|
||||
BlCvStreamWriter mSymRecordsWriter;
|
||||
|
||||
public:
|
||||
void NotImpl();
|
||||
void Fail(const StringImpl& err);
|
||||
char* StrDup(const char* str);
|
||||
|
||||
void FixSymAddress(void* oldDataStart, void* oldDataPos, void* outDataPos, BlCvModuleInfo* module, BlCvSymDataBlock* dataBlock, COFFRelocation*& nextReloc);
|
||||
|
||||
int StartStream(int streamIdx = -1);
|
||||
void StartUnnamedStream(BlCVStream& stream);
|
||||
void EndStream(bool flush = true);
|
||||
void FlushStream(BlCVStream* stream);
|
||||
void CvEncodeString(const StringImpl& str);
|
||||
int AddToStringTable(const StringImpl& str);
|
||||
void WriteStringTable(const StringImpl& strTable, std::unordered_map<String, int>& strTabMap);
|
||||
void GetOutSectionAddr(int segIdx, int segOfs, uint16& cvSectIdx, long& cvSectOfs);
|
||||
bool FixTPITag(BlCvModuleInfo* module, unsigned long& typeId);
|
||||
bool FixIPITag(BlCvModuleInfo* module, unsigned long& typeId);
|
||||
bool FixIPITag_Member(BlCvModuleInfo* module, unsigned long& typeId);
|
||||
|
||||
bool OnlyHasSimpleRelocs(BlCvModuleInfo * module);
|
||||
|
||||
void StartSection(int sectionNum);
|
||||
int EndSection();
|
||||
void FlushMemStream();
|
||||
|
||||
void CreatePDBInfoStream();
|
||||
void WriteTypeData(int streamId, BlTypeInfo& typeInfo);
|
||||
void CreateTypeStream();
|
||||
void CreateIPIStream();
|
||||
void WriteRecordMap(BlCvRecordMap * recordMap);
|
||||
int CreateGlobalStream();
|
||||
int CreatePublicStream();
|
||||
void FinishSymRecords();
|
||||
int CreateSymRecordStream();
|
||||
int CreateSectionHeaderStream();
|
||||
void CreateDBIStream();
|
||||
void CreateLinkInfoStream();
|
||||
void CreateHeaderBlockStream();
|
||||
void CreateNamesStream();
|
||||
void CreateModuleStreamSyms(BlCvModuleInfo* module, BlCvSymDataBlock* dataBlock, int dataOfs);
|
||||
void CreateLinkerSymStream();
|
||||
void CreateModuleStream(BlCvModuleInfo* module);
|
||||
void FinishModuleStream(BlCvModuleInfo* module);
|
||||
void CreateLinkerModule();
|
||||
void DoFinish();
|
||||
|
||||
public:
|
||||
BlCodeView();
|
||||
~BlCodeView();
|
||||
|
||||
bool Create(const StringImpl& fileName);
|
||||
void StartWorkThreads();
|
||||
void StopWorkThreads();
|
||||
void Finish();
|
||||
};
|
||||
|
||||
NS_BF_END
|
3929
IDEHelper/Linker/BlContext.cpp
Normal file
3929
IDEHelper/Linker/BlContext.cpp
Normal file
File diff suppressed because it is too large
Load diff
572
IDEHelper/Linker/BlContext.h
Normal file
572
IDEHelper/Linker/BlContext.h
Normal file
|
@ -0,0 +1,572 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "../Compiler/BfUtil.h"
|
||||
#include "BeefySysLib/util/Hash.h"
|
||||
#include "BeefySysLib/util/BumpAllocator.h"
|
||||
#include "BeefySysLib/util/ChunkedDataBuffer.h"
|
||||
#include "BlSymTable.h"
|
||||
#include "BeefySysLib/MemStream.h"
|
||||
#include "BeefySysLib/util/ChunkedVector.h"
|
||||
#include "BeefySysLib/util/CritSect.h"
|
||||
#include "BeefySysLib/util/MappedFile.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
//#define BL_PERFTIME
|
||||
|
||||
|
||||
#ifdef BL_PERFTIME
|
||||
#define BL_AUTOPERF(name) AutoPerf autoPerf##__LINE__(name);
|
||||
#else
|
||||
#define BL_AUTOPERF(name)
|
||||
#endif
|
||||
|
||||
struct BlSymHash
|
||||
{
|
||||
public:
|
||||
const char* mName;
|
||||
};
|
||||
|
||||
enum BlSymKind
|
||||
{
|
||||
BlSymKind_Undefined = -1,
|
||||
BlSymKind_LibSymbolRef = -2,
|
||||
BlSymKind_LibSymbolGroupRef = -3,
|
||||
BlSymKind_WeakSymbol = -4,
|
||||
BlSymKind_ImageBaseRel = -5,
|
||||
BlSymKind_Import = -6,
|
||||
BlSymKind_ImportImp = -7,
|
||||
BlSymKind_Absolute = -8,
|
||||
};
|
||||
|
||||
class BlCodeView;
|
||||
|
||||
class BlSymbol
|
||||
{
|
||||
public:
|
||||
const char* mName;
|
||||
union
|
||||
{
|
||||
// If mSectionIdx is negative, then we're not a resolved symbol and the mKind member is used instead
|
||||
int mSegmentIdx;
|
||||
BlSymKind mKind;
|
||||
};
|
||||
union
|
||||
{
|
||||
int mSegmentOffset;
|
||||
int mParam;
|
||||
};
|
||||
|
||||
int mObjectDataIdx;
|
||||
};
|
||||
|
||||
class BlLib
|
||||
{
|
||||
public:
|
||||
String mFileName;
|
||||
char* mStrTable;
|
||||
|
||||
public:
|
||||
BlLib()
|
||||
{
|
||||
mStrTable = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// From lowest priority to highest
|
||||
enum BlObjectDataKind
|
||||
{
|
||||
BlObjectDataKind_DirectiveLib,
|
||||
BlObjectDataKind_DefaultLib,
|
||||
BlObjectDataKind_SpecifiedLib,
|
||||
BlObjectDataKind_SpecifiedObj,
|
||||
};
|
||||
|
||||
struct BlObjectDataSymInfo
|
||||
{
|
||||
BlSymbol* mSym;
|
||||
|
||||
enum Kind
|
||||
{
|
||||
Kind_None = -1,
|
||||
Kind_Section = -2
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
int mSegmentIdx;
|
||||
Kind mKind;
|
||||
};
|
||||
union
|
||||
{
|
||||
int mSegmentOffset;
|
||||
int mSectionNum;
|
||||
};
|
||||
|
||||
BlObjectDataSymInfo()
|
||||
{
|
||||
mSym = NULL;
|
||||
mSegmentIdx = Kind_None;
|
||||
mSegmentOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
enum BlObjectDataLoadState
|
||||
{
|
||||
BlObjectDataLoadState_UnloadedLib = -1,
|
||||
BlObjectDataLoadState_UnloadedThinLib = -2,
|
||||
BlObjectDataLoadState_ImportObject = -3,
|
||||
};
|
||||
|
||||
class BlObjectData
|
||||
{
|
||||
public:
|
||||
BlObjectDataKind mKind;
|
||||
int mIdx;
|
||||
BlLib* mLib;
|
||||
char* mName;
|
||||
union
|
||||
{
|
||||
void* mData;
|
||||
BlSymbol* mImportSym;
|
||||
};
|
||||
union
|
||||
{
|
||||
int mSize;
|
||||
BlObjectDataLoadState mLoadState;
|
||||
};
|
||||
|
||||
FILE* mFP;
|
||||
int mFPOfs;
|
||||
|
||||
public:
|
||||
BlObjectData()
|
||||
{
|
||||
mKind = BlObjectDataKind_DefaultLib;
|
||||
mIdx = -1;
|
||||
mLib = NULL;
|
||||
mName = NULL;
|
||||
mData = NULL;
|
||||
mSize = 0;
|
||||
|
||||
mFP = NULL;
|
||||
mFPOfs = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct BlLibMemberHeader
|
||||
{
|
||||
char mName[16];
|
||||
char mDate[12];
|
||||
char mUserId[6];
|
||||
char mGroupId[6];
|
||||
char mMode[8];
|
||||
char mSize[10];
|
||||
char mEnd[2];
|
||||
|
||||
void Init()
|
||||
{
|
||||
char* spaces = " ";
|
||||
memcpy(mName, spaces, 16);
|
||||
memcpy(mDate, spaces, 12);
|
||||
memcpy(mUserId, spaces, 6);
|
||||
memcpy(mGroupId, spaces, 6);
|
||||
memcpy(mMode, spaces, 8);
|
||||
memcpy(mSize, spaces, 10);
|
||||
mEnd[0] = '`';
|
||||
mEnd[1] = '\n';
|
||||
}
|
||||
};
|
||||
|
||||
class BlChunk
|
||||
{
|
||||
public:
|
||||
int mOffset;
|
||||
int mAlignPad; // Before data
|
||||
void* mData;
|
||||
int mSize;
|
||||
int mObjectDataIdx;
|
||||
};
|
||||
|
||||
enum BlRelocKind : uint8
|
||||
{
|
||||
BlRelocKind_ADDR32NB,
|
||||
BlRelocKind_ADDR64,
|
||||
BlRelocKind_REL32,
|
||||
BlRelocKind_REL32_1,
|
||||
BlRelocKind_REL32_4,
|
||||
BlRelocKind_SECREL,
|
||||
BlRelocKind_SECTION,
|
||||
};
|
||||
|
||||
enum BeRelocFlags : uint8
|
||||
{
|
||||
//BeRelocFlags_SymName = 1,
|
||||
BeRelocFlags_Sym = 2,
|
||||
BeRelocFlags_SymIsNew = 4,
|
||||
BeRelocFlags_Loc = 8,
|
||||
BeRelocFlags_Func = 0x10
|
||||
};
|
||||
|
||||
class BlReloc
|
||||
{
|
||||
public:
|
||||
BlRelocKind mKind;
|
||||
BeRelocFlags mFlags;
|
||||
int32 mOutOffset;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int32 mSegmentIdx;
|
||||
int32 mSegmentOffset;
|
||||
};
|
||||
const char* mSymName;
|
||||
BlSymbol* mSym;
|
||||
};
|
||||
};
|
||||
|
||||
class BlContext;
|
||||
|
||||
class BlSegmentInfo
|
||||
{
|
||||
public:
|
||||
String mName;
|
||||
};
|
||||
|
||||
// Segments are almost like sections, but segments like ".text" and ".text$mn" get
|
||||
// combined together into BlOutSection objects so there's not a one-to-one correspondence.
|
||||
class BlSegment : public BlSegmentInfo
|
||||
{
|
||||
public:
|
||||
int mOutSectionIdx;
|
||||
int mCharacteristics;
|
||||
BumpAllocator mAlloc;
|
||||
|
||||
BlContext* mContext;
|
||||
std::vector<BlChunk> mChunks;
|
||||
std::vector<BlReloc> mRelocs;
|
||||
int mResolvedRelocIdx;
|
||||
int mCurSize;
|
||||
int mSegmentIdx;
|
||||
int mAlign;
|
||||
|
||||
int mRVA;
|
||||
|
||||
public:
|
||||
BlSegment()
|
||||
{
|
||||
mOutSectionIdx = -1;
|
||||
mCharacteristics = 0;
|
||||
mContext = NULL;
|
||||
mCurSize = 0;
|
||||
mSegmentIdx = -1;
|
||||
mAlign = 1;
|
||||
mRVA = 0;
|
||||
mResolvedRelocIdx = 0;
|
||||
}
|
||||
|
||||
BlChunk* AddChunk(void* data, int size, int characteristics, int& offset);
|
||||
};
|
||||
|
||||
class BlOutSection
|
||||
{
|
||||
public:
|
||||
int mIdx;
|
||||
String mName;
|
||||
std::vector<BlSegment*> mSegments;
|
||||
int mCharacteristics;
|
||||
int mAlign;
|
||||
int mRVA;
|
||||
int mRawDataPos;
|
||||
int mRawSize;
|
||||
int mVirtualSize;
|
||||
|
||||
public:
|
||||
BlOutSection()
|
||||
{
|
||||
mIdx = 0;
|
||||
mCharacteristics = 0;
|
||||
mAlign = 1;
|
||||
mRawDataPos = 0;
|
||||
mRVA = 0;
|
||||
mRawSize = 0;
|
||||
mVirtualSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class BlPendingComdat
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
class BlImportLookup
|
||||
{
|
||||
public:
|
||||
String mName;
|
||||
int mHint;
|
||||
int mThunkIdx;
|
||||
int mIDataIdx;
|
||||
|
||||
public:
|
||||
BlImportLookup()
|
||||
{
|
||||
mHint = 0;
|
||||
mThunkIdx = -1;
|
||||
mIDataIdx = -1;
|
||||
}
|
||||
};
|
||||
|
||||
class BlImportFile
|
||||
{
|
||||
public:
|
||||
OwnedVector<BlImportLookup> mLookups;
|
||||
};
|
||||
|
||||
struct BlResIdLess
|
||||
{
|
||||
bool operator()(const char16_t* lhs, const char16_t* rhs) const
|
||||
{
|
||||
bool lhsIsID = ((uintptr)lhs < 0x10000);
|
||||
bool rhsIsID = ((uintptr)rhs < 0x10000);
|
||||
|
||||
// Strings before IDs
|
||||
if (lhsIsID && !rhsIsID)
|
||||
return false;
|
||||
if (!lhsIsID && rhsIsID)
|
||||
return true;
|
||||
if (lhsIsID && rhsIsID)
|
||||
return (uintptr)lhs < (uintptr)rhs;
|
||||
return wcscmp((wchar_t*)lhs, (wchar_t*)rhs) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
class BlResEntry
|
||||
{
|
||||
public:
|
||||
bool mIsDir;
|
||||
|
||||
virtual ~BlResEntry()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class BlResData : public BlResEntry
|
||||
{
|
||||
public:
|
||||
BlResData()
|
||||
{
|
||||
mIsDir = false;
|
||||
}
|
||||
void* mData;
|
||||
int mSize;
|
||||
};
|
||||
|
||||
class BlResDirectory : public BlResEntry
|
||||
{
|
||||
public:
|
||||
BlResDirectory()
|
||||
{
|
||||
mIsDir = true;
|
||||
}
|
||||
std::map<const char16_t*, BlResEntry*, BlResIdLess> mEntries;
|
||||
};
|
||||
|
||||
class BlPeRelocs
|
||||
{
|
||||
public:
|
||||
ChunkedDataBuffer mData;
|
||||
uint32 mBlockAddr;
|
||||
int32* mLenPtr;
|
||||
|
||||
public:
|
||||
BlPeRelocs()
|
||||
{
|
||||
mBlockAddr = 0;
|
||||
mLenPtr = NULL;
|
||||
}
|
||||
|
||||
void Add(uint32 addr, int fixupType);
|
||||
};
|
||||
|
||||
class BlExport
|
||||
{
|
||||
public:
|
||||
String mSrcName;
|
||||
int mOrdinal;
|
||||
bool mNoName;
|
||||
bool mIsPrivate;
|
||||
bool mIsData;
|
||||
bool mOrdinalSpecified;
|
||||
|
||||
public:
|
||||
BlExport()
|
||||
{
|
||||
mOrdinal = -1;
|
||||
mNoName = false;
|
||||
mIsPrivate = false;
|
||||
mIsData = false;
|
||||
mOrdinalSpecified = false;
|
||||
}
|
||||
};
|
||||
|
||||
class BlImportGroup
|
||||
{
|
||||
public:
|
||||
std::vector<int> mObjectDatas;
|
||||
};
|
||||
|
||||
class BlSymNotFound
|
||||
{
|
||||
public:
|
||||
BlSymbol* mSym;
|
||||
int mSegmentIdx;
|
||||
int mOutOffset;
|
||||
};
|
||||
|
||||
class BlContext
|
||||
{
|
||||
public:
|
||||
CritSect mCritSect;
|
||||
String mOutName;
|
||||
String mPDBPath;
|
||||
String mImpLibName;
|
||||
int mDebugKind;
|
||||
bool mVerbose;
|
||||
bool mNoDefaultLib;
|
||||
std::set<String> mNoDefaultLibs;
|
||||
std::vector<String> mDefaultLibs;
|
||||
bool mHasFixedBase;
|
||||
bool mHasDynamicBase;
|
||||
bool mHighEntropyVA;
|
||||
bool mIsNXCompat;
|
||||
bool mIsTerminalServerAware;
|
||||
int mPeSubsystem;
|
||||
int mHeapReserve;
|
||||
int mHeapCommit;
|
||||
int mStackReserve;
|
||||
int mStackCommit;
|
||||
int mPeVersionMajor;
|
||||
int mPeVersionMinor;
|
||||
int mProcessingSegIdx;
|
||||
int mDbgSymSectsFound;
|
||||
int mDbgSymSectsUsed;
|
||||
bool mIsDLL;
|
||||
String mEntryPoint;
|
||||
uint32 mTimestamp;
|
||||
int mNumObjFiles;
|
||||
int mNumLibs;
|
||||
int mNumImportedObjs;
|
||||
int mNumWeakSymbols;
|
||||
|
||||
BumpAllocator mAlloc;
|
||||
bool mFailed;
|
||||
int mErrorCount;
|
||||
|
||||
std::vector<String> mSearchPaths;
|
||||
OwnedVector<MappedFile> mMappedFiles;
|
||||
OwnedVector<BlObjectData> mObjectDatas;
|
||||
std::vector<BlObjectData*> mObjectDataWorkQueue;
|
||||
//std::vector<BlChunk*> mChunks;
|
||||
std::vector<BlSegment*> mSegments;
|
||||
std::vector<BlSegment*> mOrderedSegments;
|
||||
std::map<String, String> mSectionMerges;
|
||||
OwnedVector<BlSegment> mDynSegments;
|
||||
OwnedVector<BlLib> mLibs;
|
||||
BlSymTable mSymTable;
|
||||
std::vector<String> mRemapStrs;
|
||||
OwnedVector<BlOutSection> mOutSections;
|
||||
std::map<String, BlImportFile> mImportFiles;
|
||||
std::vector<BlImportLookup*> mImportLookups;
|
||||
std::map<String, BlExport> mExports;
|
||||
std::vector<String> mForcedSyms;
|
||||
OwnedVector<BlImportGroup> mImportGroups;
|
||||
std::vector<BlSymNotFound> mSymNotFounds;
|
||||
|
||||
BlResDirectory mRootResDirectory;
|
||||
OwnedVector<BlResEntry> mResEntries;
|
||||
DynMemStream mImportStream;
|
||||
DynMemStream mThunkStream;
|
||||
DynMemStream mDebugDirStream;
|
||||
DynMemStream mCvInfoStream;
|
||||
DynMemStream mResDataStream;
|
||||
DynMemStream mLoadConfigStream;
|
||||
DynMemStream mExportStream;
|
||||
BlCodeView* mCodeView;
|
||||
BlSegment* mIDataSeg;
|
||||
BlSegment* mTextSeg;
|
||||
BlSegment* mRDataSeg;
|
||||
BlSegment* mDataSeg;
|
||||
BlSegment* mBSSSeg;
|
||||
int mNumFixedSegs;
|
||||
String mManifestUAC;
|
||||
String mManifestData;
|
||||
BlPeRelocs mPeRelocs;
|
||||
|
||||
int64 mImageBase;
|
||||
/*BlSection mTextSect;
|
||||
BlSection mRDataSect;
|
||||
BlSection mBSSSect; */
|
||||
|
||||
std::set<String> mSeenLibs;
|
||||
|
||||
public:
|
||||
BlSymHash Hash(const char* symName);
|
||||
String ObjectDataIdxToString(int objectDataIdx);
|
||||
String GetSymDisp(const StringImpl& name);
|
||||
String FixFilePath(const StringImpl& path, const StringImpl& actualFileName);
|
||||
void Fail(const StringImpl& error);
|
||||
void Warn(const StringImpl& error);
|
||||
void Fail(BlObjectData* objectData, const StringImpl& error);
|
||||
void AssertFailed();
|
||||
void NotImpl();
|
||||
void PrintStats();
|
||||
void AddSegment(BlSegment* section);
|
||||
void LoadFiles();
|
||||
bool HandleLibSymbolRef(BlSymbol* sym, int objectDataIds);
|
||||
BlSymbol* ProcessSymbol(BlSymbol* sym);
|
||||
BlSymbol* ResolveSym(const char* name, bool throwError = true);
|
||||
uint64 GetSymAddr(BlSymbol* sym);
|
||||
void AddAbsoluteSym(const char* name, int val);
|
||||
BlSegment* CreateSegment(const StringImpl& name, int characteristics, int align);
|
||||
void PlaceSections();
|
||||
void ResolveRelocs();
|
||||
void LoadResourceData(BlObjectData* objectData);
|
||||
void LoadDefData(BlObjectData* objectData);
|
||||
void WriteDLLLib(const StringImpl& libName);
|
||||
|
||||
void PopulateIData_LookupTable(BlSegment* iDataSect, int& hintNameTableSize);
|
||||
void PopulateIData(BlSegment* iDataSeg);
|
||||
BlSegment* CreateIData();
|
||||
void PopulateThunkData(BlSegment* thunkSeg, BlSegment* iDataSeg);
|
||||
BlSegment* CreateThunkData();
|
||||
void PopulateExportData(BlSegment * exportSeg);
|
||||
BlSegment * CreateExportData();
|
||||
void PopulateCvInfoData(BlSegment* cvInfoSeg);
|
||||
BlSegment* CreateCvInfoData();
|
||||
void PopulateDebugDirData(BlSegment* debugDirSeg, BlSegment* cvInfoSeg);
|
||||
BlSegment* CreateDebugDirData();
|
||||
void PopulateResData(BlSegment* resSeg);
|
||||
void GetResDataStats(BlResDirectory* resDir, int& dirCount, int& dataCount, int& symsStrsSize, int& dataSize);
|
||||
void CreateResData(BlSegment* resSeg, BlResDirectory* resDir, int resDirSize, int symsStrSize, DynMemStream& symStrsStream, DynMemStream& dataEntryStream);
|
||||
BlSegment* CreateResData();
|
||||
void WriteOutSection(BlOutSection * outSection, DataStream * st);
|
||||
|
||||
public:
|
||||
BlContext();
|
||||
~BlContext();
|
||||
|
||||
void Init(bool is64Bit, bool isDebug);
|
||||
void AddSearchPath(const StringImpl& directory);
|
||||
bool DoAddFile(const StringImpl& path, BlObjectDataKind objectDataKind);
|
||||
bool AddFile(const StringImpl& fileName, BlObjectDataKind objectDataKind);
|
||||
|
||||
void Link();
|
||||
};
|
||||
|
||||
NS_BF_END
|
534
IDEHelper/Linker/BlCvParser.cpp
Normal file
534
IDEHelper/Linker/BlCvParser.cpp
Normal file
|
@ -0,0 +1,534 @@
|
|||
#include "BlCvParser.h"
|
||||
#include "BlContext.h"
|
||||
#include "BlCodeView.h"
|
||||
#include "codeview/cvinfo.h"
|
||||
#include "../COFFData.h"
|
||||
#include "BeefySysLib/util/PerfTimer.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
#define CV_BLOCK_SIZE 0x1000
|
||||
#define MSF_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"
|
||||
#define GET(T) *((T*)(data += sizeof(T)) - 1)
|
||||
#define PTR_ALIGN(ptr, origPtr, alignSize) ptr = ( (origPtr)+( ((ptr - origPtr) + (alignSize - 1)) & ~(alignSize - 1) ) )
|
||||
|
||||
BlCvParser::BlCvParser(BlContext* context)
|
||||
{
|
||||
mContext = context;
|
||||
mCodeView = context->mCodeView;
|
||||
mCurModule = NULL;
|
||||
mSyms = NULL;
|
||||
}
|
||||
|
||||
void BlCvParser::NotImpl()
|
||||
{
|
||||
}
|
||||
|
||||
void BlCvParser::Fail(const StringImpl& err)
|
||||
{
|
||||
mContext->Fail(StrFormat("%s in %s", err.c_str(), mContext->ObjectDataIdxToString(mCurModule->mObjectData->mIdx).c_str()));
|
||||
}
|
||||
|
||||
int64 BlCvParser::CvParseConstant(uint16 constVal, uint8*& data)
|
||||
{
|
||||
if (constVal < LF_NUMERIC) // 0x8000
|
||||
return constVal;
|
||||
switch (constVal)
|
||||
{
|
||||
case LF_CHAR:
|
||||
return GET(int8);
|
||||
case LF_SHORT:
|
||||
return GET(int16);
|
||||
case LF_USHORT:
|
||||
return GET(uint16);
|
||||
case LF_LONG:
|
||||
return GET(int32);
|
||||
case LF_ULONG:
|
||||
return GET(uint32);
|
||||
case LF_QUADWORD:
|
||||
return GET(int64);
|
||||
case LF_UQUADWORD:
|
||||
return (int64)GET(uint64);
|
||||
default:
|
||||
BF_FATAL("Not handled");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64 BlCvParser::CvParseConstant(uint8*& data)
|
||||
{
|
||||
uint16 val = GET(uint16);
|
||||
return CvParseConstant(val, data);
|
||||
}
|
||||
|
||||
const char* BlCvParser::CvParseString(uint8*& data)
|
||||
{
|
||||
const char* strStart = (const char*)data;
|
||||
int strLen = (int)strlen((const char*)data);
|
||||
data += strLen + 1;
|
||||
if (strLen == 0)
|
||||
return NULL;
|
||||
return strStart;
|
||||
}
|
||||
|
||||
bool BlCvParser::MapAddress(void* symbolData, void* cvLoc, BlReloc& outReloc, COFFRelocation*& nextReloc)
|
||||
{
|
||||
int posOfs = (int)((uint8*)cvLoc - (uint8*)symbolData);
|
||||
int posSect = (int)((uint8*)cvLoc + 4 - (uint8*)symbolData);
|
||||
|
||||
if (nextReloc->mVirtualAddress != posOfs)
|
||||
{
|
||||
outReloc.mFlags = (BeRelocFlags)0;
|
||||
outReloc.mSymName = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto sym = &(*mSyms)[nextReloc->mSymbolTableIndex];
|
||||
if (sym->mSym != NULL)
|
||||
{
|
||||
outReloc.mFlags = BeRelocFlags_Sym;
|
||||
outReloc.mSym = sym->mSym;
|
||||
}
|
||||
else
|
||||
{
|
||||
outReloc.mFlags = BeRelocFlags_Loc;
|
||||
outReloc.mSegmentIdx = sym->mSegmentIdx;
|
||||
outReloc.mSegmentOffset = sym->mSegmentOffset;
|
||||
}
|
||||
|
||||
nextReloc++;
|
||||
if (nextReloc->mVirtualAddress != posSect)
|
||||
return false;
|
||||
// It MUST be the same sym
|
||||
nextReloc++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlCvParser::TryReloc(void* symbolData, void* cvLoc, int32* outVal, COFFRelocation*& nextReloc)
|
||||
{
|
||||
int posOfs = (int)((uint8*)cvLoc - (uint8*)symbolData);
|
||||
if (nextReloc->mVirtualAddress != posOfs)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BlCvParser::AddModule(BlObjectData* objectData, const char* strTab)
|
||||
{
|
||||
//const char* invalidStrs[] = { "delete_scalar", "new_scalar", "throw_bad_alloc", "std_type_info_static", "delete_scalar_size", "main2" };
|
||||
//const char* invalidStrs[] = { "delete_scalar", "new_scalar" };
|
||||
/*const char* invalidStrs[] = { "delete_scalar" };
|
||||
for (const char* invalidStr : invalidStrs)
|
||||
{
|
||||
//TODO:
|
||||
if (strstr(objectData->mName, invalidStr) != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strstr(objectData->mName, "new_scalar") != NULL)
|
||||
{
|
||||
mTEMP_Testing = true;
|
||||
}*/
|
||||
|
||||
mCurModule = mCodeView->mModuleInfo.Alloc();
|
||||
mCurModule->mObjectData = objectData;
|
||||
mCurModule->mIdx = (int)mCodeView->mModuleInfo.size() - 1;
|
||||
mCurModule->mStrTab = strTab;
|
||||
}
|
||||
|
||||
void BlCvParser::AddTypeData(PESectionHeader* sect)
|
||||
{
|
||||
mTypeSects.push_back(sect);
|
||||
}
|
||||
|
||||
void BlCvParser::AddSymbolData(PESectionHeader* sect)
|
||||
{
|
||||
mSymSects.push_back(sect);
|
||||
}
|
||||
|
||||
void BlCvParser::ParseTypeData(void* typeData, int size)
|
||||
{
|
||||
uint8* data = (uint8*)typeData;
|
||||
uint8* dataEnd = data + size;
|
||||
|
||||
int sig = GET(int32);
|
||||
if (sig != CV_SIGNATURE_C13)
|
||||
{
|
||||
Fail("Invalid debug signature");
|
||||
return;
|
||||
}
|
||||
|
||||
bool useWorkList = true;
|
||||
|
||||
if (*(int16*)(data + 2) == LF_TYPESERVER2)
|
||||
{
|
||||
lfTypeServer2& typeServer = *(lfTypeServer2*)(data + 2);
|
||||
|
||||
String filePath = (char*)typeServer.name;
|
||||
String fixedFilePath = FixPathAndCase(filePath);
|
||||
auto itr = mCodeView->mTypeServerFiles.find(fixedFilePath);
|
||||
if (itr == mCodeView->mTypeServerFiles.end())
|
||||
{
|
||||
auto itrPair = mCodeView->mTypeServerFiles.insert(std::make_pair(fixedFilePath, (BlCvTypeSource*)NULL));
|
||||
BlPdbParser* pdbParser = new BlPdbParser();
|
||||
pdbParser->mTypeSource = new BlCvTypeSource;
|
||||
itrPair.first->second = pdbParser->mTypeSource;
|
||||
pdbParser->mTypeSource->mTypeServerLib = pdbParser;
|
||||
pdbParser->mTypeSource->Init(mCodeView);
|
||||
|
||||
if (FileExists(filePath))
|
||||
{
|
||||
pdbParser->mFileName = filePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
String fileName = GetFileName(filePath);
|
||||
String checkFilePath;
|
||||
if (mCurModule->mObjectData->mLib != NULL)
|
||||
checkFilePath = GetFileDir(mCurModule->mObjectData->mLib->mFileName);
|
||||
else
|
||||
checkFilePath = GetFileDir(mCurModule->mObjectData->mName);
|
||||
checkFilePath += fileName;
|
||||
pdbParser->mFileName = checkFilePath;
|
||||
}
|
||||
|
||||
if (useWorkList)
|
||||
{
|
||||
mCodeView->mTypeWorkThread.Add(pdbParser->mTypeSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
pdbParser->Load(pdbParser->mFileName);
|
||||
}
|
||||
|
||||
mCurModule->mTypeSource = pdbParser->mTypeSource;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurModule->mTypeSource = itr->second;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto typeSource = new BlCvTypeSource();
|
||||
typeSource->Init(mCodeView);
|
||||
mCurModule->mTypeSource = typeSource;
|
||||
typeSource->mTPI.mSectionData = data;
|
||||
typeSource->mTPI.mSectionSize = size - 4;
|
||||
typeSource->mObjectData = mCurModule->mObjectData;
|
||||
|
||||
if (useWorkList)
|
||||
{
|
||||
mCodeView->mTypeWorkThread.Add(typeSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
typeSource->mTPI.ScanTypeData();
|
||||
typeSource->mTPI.ParseTypeData();
|
||||
}
|
||||
}
|
||||
|
||||
void BlCvParser::ParseSymbolData(void* symbolData, int size, void* relocData, int numRelocs)
|
||||
{
|
||||
// static int itrCount = 0;
|
||||
// itrCount++;
|
||||
//
|
||||
// if (itrCount == 0x32)
|
||||
// {
|
||||
// NOP;
|
||||
// }
|
||||
|
||||
uint8* data = (uint8*)symbolData;
|
||||
uint8* symDataEnd = data + size;
|
||||
|
||||
int sig = GET(int32);
|
||||
if (sig != CV_SIGNATURE_C13)
|
||||
{
|
||||
Fail("Invalid debug signature");
|
||||
return;
|
||||
}
|
||||
|
||||
bool relocFailed = false;
|
||||
uint8* fileChecksumStart = NULL;
|
||||
uint8* fileChecksumEnd = NULL;
|
||||
|
||||
COFFRelocation* nextReloc = (COFFRelocation*)relocData;
|
||||
COFFRelocation* relocEnd = nextReloc + numRelocs;
|
||||
const char* strTable = NULL;
|
||||
|
||||
while (data < symDataEnd)
|
||||
{
|
||||
int sectionNum = GET(int32);
|
||||
int sectionLen = GET(int32);
|
||||
uint8* sectionStart = data;
|
||||
uint8* sectionEnd = data + sectionLen;
|
||||
if (sectionNum == DEBUG_S_STRINGTABLE)
|
||||
{
|
||||
//BF_ASSERT(mCurModule->mStrTab.size() == 0);
|
||||
//mCurModule->mStrTab.insert(mCurModule->mStrTab.begin(), (char*)sectionStart, (char*)sectionEnd);
|
||||
strTable = (char*)sectionStart;
|
||||
}
|
||||
else if (sectionNum == DEBUG_S_FILECHKSMS)
|
||||
{
|
||||
fileChecksumStart = sectionStart;
|
||||
fileChecksumEnd = sectionEnd;
|
||||
}
|
||||
data = sectionEnd;
|
||||
PTR_ALIGN(data, (uint8*)symbolData, 4);
|
||||
}
|
||||
|
||||
//int bytesPerFile = 24;
|
||||
|
||||
// Handle DEBUG_S_FILECHKSMS
|
||||
if (fileChecksumStart != NULL)
|
||||
{
|
||||
data = fileChecksumStart;
|
||||
uint8* sectionStart = data;
|
||||
uint8* sectionEnd = fileChecksumEnd;
|
||||
|
||||
// Always at least 8 bytes per file info
|
||||
mChksumOfsToFileIdx.resize((sectionEnd - data) / 8);
|
||||
mCurModule->mFileInfos.reserve((sectionEnd - data) / 24);
|
||||
|
||||
while (data < sectionEnd)
|
||||
{
|
||||
int dataOfs = (int)(data - sectionStart);
|
||||
|
||||
uint32 fileTableOfs = GET(uint32);
|
||||
|
||||
const char* fileName = strTable + fileTableOfs;
|
||||
|
||||
uint8 hashLen = GET(uint8);
|
||||
uint8 hashType = GET(uint8);
|
||||
|
||||
BlCvFileInfo fileInfo;
|
||||
fileInfo.mChksumOfs = dataOfs;
|
||||
fileInfo.mStrTableIdx = mCodeView->AddToStringTable(fileName);
|
||||
|
||||
if (hashLen > 0)
|
||||
{
|
||||
BF_ASSERT(hashType == 1);
|
||||
fileInfo.mHashType = 1;
|
||||
memcpy(fileInfo.mHash, data, 16);
|
||||
data += hashLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileInfo.mHashType = 0;
|
||||
}
|
||||
|
||||
mChksumOfsToFileIdx[dataOfs / 8] = (int)mCurModule->mFileInfos.size();
|
||||
mCurModule->mFileInfos.push_back(fileInfo);
|
||||
PTR_ALIGN(data, sectionStart, 4);
|
||||
}
|
||||
}
|
||||
|
||||
data = (uint8*)symbolData + 4;
|
||||
while (data < symDataEnd)
|
||||
{
|
||||
int sectionNum = GET(int32);
|
||||
int sectionLen = GET(int32);
|
||||
uint8* sectionStart = data;
|
||||
uint8* sectionEnd = data + sectionLen;
|
||||
|
||||
if ((sectionNum == DEBUG_S_SYMBOLS) || (sectionNum == DEBUG_S_INLINEELINES))
|
||||
{
|
||||
//BL_AUTOPERF("DEBUG_S_SYMBOLS");
|
||||
|
||||
BlCvSymDataBlock dataBlock;
|
||||
dataBlock.mSize = (int)(sectionEnd - sectionStart);
|
||||
dataBlock.mData = sectionStart;
|
||||
dataBlock.mSourceSectOffset = (int)((uint8*)sectionStart - (uint8*)symbolData);
|
||||
dataBlock.mRelocStart = nextReloc;
|
||||
dataBlock.mOutSize = -1;
|
||||
|
||||
WIN32_MEMORY_RANGE_ENTRY vAddrs = { dataBlock.mData, (SIZE_T)dataBlock.mSize };
|
||||
PrefetchVirtualMemory(GetCurrentProcess(), 1, &vAddrs, 0);
|
||||
|
||||
data = sectionEnd;
|
||||
while ((nextReloc < relocEnd) && ((int)nextReloc->mVirtualAddress < (int)(sectionEnd - (uint8*)symbolData)))
|
||||
nextReloc++;
|
||||
|
||||
dataBlock.mRelocEnd = nextReloc;
|
||||
if (sectionNum == DEBUG_S_SYMBOLS)
|
||||
mCurModule->mSymData.push_back(dataBlock);
|
||||
else
|
||||
mCurModule->mInlineData.push_back(dataBlock);
|
||||
PTR_ALIGN(data, (uint8*)symbolData, 4);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((sectionNum & DEBUG_S_IGNORE) != 0)
|
||||
{
|
||||
data = sectionEnd;
|
||||
while ((nextReloc < relocEnd) && ((int)nextReloc->mVirtualAddress < (int)(sectionEnd - (uint8*)symbolData)))
|
||||
nextReloc++;
|
||||
PTR_ALIGN(data, (uint8*)symbolData, 4);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (sectionNum)
|
||||
{
|
||||
case DEBUG_S_LINES:
|
||||
{
|
||||
//BL_AUTOPERF("DEBUG_S_LINES");
|
||||
|
||||
CV_DebugSLinesHeader_t& lineSec = GET(CV_DebugSLinesHeader_t);
|
||||
|
||||
BlReloc reloc;
|
||||
MapAddress(symbolData, &lineSec.offCon, reloc, nextReloc);
|
||||
|
||||
auto lineInfo = mCurModule->mLineInfo.Alloc();
|
||||
|
||||
/*if ((reloc.mFlags & BeRelocFlags_Sym) != 0)
|
||||
{
|
||||
auto sym = mContext->ProcessSymbol(reloc.mSym);
|
||||
if (sym->mSegmentIdx >= 0)
|
||||
{
|
||||
lineInfo->mStartSegmentIdx = sym->mSegmentIdx;
|
||||
lineInfo->mStartSegmentOffset = sym->mSegmentOffset;
|
||||
}
|
||||
else
|
||||
relocFailed = true;
|
||||
}
|
||||
else*/ if ((reloc.mFlags & BeRelocFlags_Loc) != 0)
|
||||
{
|
||||
lineInfo->mStartSegmentIdx = reloc.mSegmentIdx;
|
||||
lineInfo->mStartSegmentOffset = reloc.mSegmentOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
relocFailed = true;
|
||||
}
|
||||
|
||||
lineInfo->mContribBytes = lineSec.cbCon;
|
||||
|
||||
|
||||
while (data < sectionEnd)
|
||||
{
|
||||
CV_DebugSLinesFileBlockHeader_t& linesFileHeader = GET(CV_DebugSLinesFileBlockHeader_t);
|
||||
|
||||
lineInfo->mLineInfoBlocks.emplace_back(BlCvLineInfoBlock());
|
||||
auto& lineInfoBlock = lineInfo->mLineInfoBlocks.back();
|
||||
lineInfoBlock.mLines.reserve(linesFileHeader.nLines);
|
||||
if ((lineSec.flags & CV_LINES_HAVE_COLUMNS) != 0)
|
||||
lineInfoBlock.mColumns.reserve(linesFileHeader.nLines);
|
||||
//BF_ASSERT(linesFileHeader.offFile % bytesPerFile == 0);
|
||||
//lineInfoBlock.mFileInfoIdx = linesFileHeader.offFile / bytesPerFile;
|
||||
lineInfoBlock.mFileInfoIdx = mChksumOfsToFileIdx[linesFileHeader.offFile / 8];
|
||||
|
||||
for (int lineIdx = 0; lineIdx < linesFileHeader.nLines; lineIdx++)
|
||||
{
|
||||
CV_Line_t& srcLineData = GET(CV_Line_t);
|
||||
|
||||
BlCvLine cvLine;
|
||||
cvLine.mLineNumStart = srcLineData.linenumStart;
|
||||
cvLine.mOffset = srcLineData.offset;
|
||||
lineInfoBlock.mLines.push_back(cvLine);
|
||||
}
|
||||
|
||||
if ((lineSec.flags & CV_LINES_HAVE_COLUMNS) != 0)
|
||||
{
|
||||
for (int lineIdx = 0; lineIdx < linesFileHeader.nLines; lineIdx++)
|
||||
{
|
||||
CV_Column_t& srcColumnData = GET(CV_Column_t);
|
||||
lineInfoBlock.mColumns.push_back(srcColumnData.offColumnStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEBUG_S_INLINEELINES:
|
||||
{
|
||||
// Already handled
|
||||
}
|
||||
break;
|
||||
case DEBUG_S_STRINGTABLE:
|
||||
{
|
||||
// Already handled
|
||||
}
|
||||
break;
|
||||
case DEBUG_S_FILECHKSMS:
|
||||
{
|
||||
// Already handled
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NotImpl();
|
||||
}
|
||||
|
||||
data = sectionEnd;
|
||||
PTR_ALIGN(data, (uint8*)symbolData, 4);
|
||||
}
|
||||
|
||||
if (nextReloc != (COFFRelocation*)relocData + numRelocs)
|
||||
relocFailed = true;
|
||||
if (relocFailed)
|
||||
Fail("Failed to apply relocations to debug symbol data");
|
||||
}
|
||||
|
||||
void BlCvParser::AddContribution(int blSectionIdx, int blSectionOfs, int size, int characteristics)
|
||||
{
|
||||
if (mCurModule == NULL)
|
||||
return;
|
||||
|
||||
if ((characteristics & IMAGE_SCN_MEM_EXECUTE) != 0)
|
||||
{
|
||||
if (mCurModule->mContrib.mCharacteristics == 0)
|
||||
{
|
||||
mCurModule->mContrib.mBlSectionIdx = blSectionIdx;
|
||||
mCurModule->mContrib.mBlSectionOfs = blSectionOfs;
|
||||
mCurModule->mContrib.mSize = size;
|
||||
mCurModule->mContrib.mCharacteristics = characteristics;
|
||||
}
|
||||
}
|
||||
|
||||
BlCvContrib contrib;
|
||||
contrib.mModuleIdx = mCurModule->mIdx;
|
||||
contrib.mBlSectionOfs = blSectionOfs;
|
||||
contrib.mSize = size;
|
||||
contrib.mCharacteristics = characteristics;
|
||||
|
||||
while (blSectionIdx >= (int)mCodeView->mContribMap.mSegments.size())
|
||||
mCodeView->mContribMap.mSegments.Alloc();
|
||||
auto contribMapSeg = mCodeView->mContribMap.mSegments[blSectionIdx];
|
||||
contribMapSeg->mContribs.push_back(contrib);
|
||||
}
|
||||
|
||||
void BlCvParser::FinishModule(PESectionHeader* sectHeaderArr, const BfSizedVectorRef<BlObjectDataSectInfo>& sectInfos, PE_SymInfo* objSyms, const BfSizedVectorRef<BlObjectDataSymInfo>& syms)
|
||||
{
|
||||
if (mCurModule == NULL)
|
||||
return;
|
||||
|
||||
mCurModule->mObjSyms = objSyms;
|
||||
if (!syms.empty())
|
||||
mCurModule->mSymInfo.insert(mCurModule->mSymInfo.begin(), syms.begin(), syms.end());
|
||||
for (auto sectInfo : sectInfos)
|
||||
mCurModule->mSectInfos.push_back(sectInfo);
|
||||
mSyms = &syms;
|
||||
|
||||
//
|
||||
{
|
||||
BL_AUTOPERF("BlCvParser::FinishModule ParseTypeData");
|
||||
for (auto sect : mTypeSects)
|
||||
{
|
||||
ParseTypeData((uint8*)mCurModule->mObjectData->mData + sect->mPointerToRawData, sect->mSizeOfRawData);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
{
|
||||
BL_AUTOPERF("BlCvParser::FinishModule ParseSymbolData");
|
||||
for (auto sect : mSymSects)
|
||||
{
|
||||
ParseSymbolData(
|
||||
(uint8*)mCurModule->mObjectData->mData + sect->mPointerToRawData, sect->mSizeOfRawData,
|
||||
(uint8*)mCurModule->mObjectData->mData + sect->mPointerToRelocations, sect->mNumberOfRelocations);
|
||||
}
|
||||
}
|
||||
|
||||
mCodeView->mModuleWorkThread.Add(mCurModule);
|
||||
}
|
57
IDEHelper/Linker/BlCvParser.h
Normal file
57
IDEHelper/Linker/BlCvParser.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "BeefySysLib/FileStream.h"
|
||||
#include "BeefySysLib/util/BumpAllocator.h"
|
||||
#include "../Compiler/BfUtil.h"
|
||||
#include <unordered_map>
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
struct PESectionHeader;
|
||||
struct PE_SymInfo;
|
||||
class BlContext;
|
||||
class BlObjectData;
|
||||
class BlCodeView;
|
||||
class BlCvModuleInfo;
|
||||
class BlReloc;
|
||||
struct BlObjectDataSectInfo;
|
||||
struct BlObjectDataSymInfo;
|
||||
struct COFFRelocation;
|
||||
|
||||
class BlCvParser
|
||||
{
|
||||
public:
|
||||
BlContext* mContext;
|
||||
BlCodeView* mCodeView;
|
||||
|
||||
BlCvModuleInfo* mCurModule;
|
||||
const BfSizedVectorRef<BlObjectDataSymInfo>* mSyms;
|
||||
BfSizedVector<PESectionHeader*, 1> mTypeSects;
|
||||
BfSizedVector<PESectionHeader*, 1> mSymSects;
|
||||
|
||||
std::vector<int16> mChksumOfsToFileIdx;
|
||||
|
||||
public:
|
||||
void NotImpl();
|
||||
void Fail(const StringImpl& err);
|
||||
static int64 CvParseConstant(uint16 constVal, uint8*& data);
|
||||
static int64 CvParseConstant(uint8*& data);
|
||||
static const char* CvParseString(uint8*& data);
|
||||
bool MapAddress(void* symbolData, void* cvLoc, BlReloc& outReloc, COFFRelocation*& nextReloc);
|
||||
bool TryReloc(void* symbolData, void* cvLoc, int32* outVal, COFFRelocation*& nextReloc);
|
||||
void ParseSymbolData(void* symbolData, int size, void* relocData, int numRelocs);
|
||||
|
||||
public:
|
||||
BlCvParser(BlContext* context);
|
||||
|
||||
void AddModule(BlObjectData* objectData, const char* strTab);
|
||||
void AddTypeData(PESectionHeader* sect);
|
||||
void AddSymbolData(PESectionHeader* sects);
|
||||
void ParseTypeData(void * typeData, int size);
|
||||
void AddContribution(int blSectionIdx, int blSectionOfs, int size, int characteristics);
|
||||
|
||||
void FinishModule(PESectionHeader* sectHeaderArr, const BfSizedVectorRef<BlObjectDataSectInfo>& sectInfos, PE_SymInfo* symInfo, const BfSizedVectorRef<BlObjectDataSymInfo>& syms);
|
||||
};
|
||||
|
||||
NS_BF_END
|
913
IDEHelper/Linker/BlCvTypeSource.cpp
Normal file
913
IDEHelper/Linker/BlCvTypeSource.cpp
Normal file
|
@ -0,0 +1,913 @@
|
|||
#include "BlCvTypeSource.h"
|
||||
#include "BlContext.h"
|
||||
#include "codeview/cvinfo.h"
|
||||
#include "BlCvParser.h"
|
||||
#include "BlPdbParser.h"
|
||||
#include "BlCodeView.h"
|
||||
|
||||
#define GET(T) *((T*)(data += sizeof(T)) - 1)
|
||||
#define GET_INTO(T, name) T name = GET(T)
|
||||
#define PTR_ALIGN(ptr, origPtr, alignSize) ptr = ( (origPtr)+( ((ptr - origPtr) + (alignSize - 1)) & ~(alignSize - 1) ) )
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
static int sIdx = 0;
|
||||
|
||||
BlCvTypeContainer::BlCvTypeContainer()
|
||||
{
|
||||
mSectionData = NULL;
|
||||
mSectionSize = 0;
|
||||
mCvMinTag = -1;
|
||||
mCvMaxTag = -1;
|
||||
mCodeView = NULL;
|
||||
mOutTypeInfo = NULL;
|
||||
mIdx = sIdx++;
|
||||
}
|
||||
|
||||
BlCvTypeContainer::~BlCvTypeContainer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::Fail(const StringImpl& err)
|
||||
{
|
||||
BF_FATAL("Err");
|
||||
}
|
||||
|
||||
const char* BlCvTypeContainer::CvParseAndDupString(uint8*& data, bool hasUniqueName)
|
||||
{
|
||||
const char* strStart = (const char*)data;
|
||||
int strLen = (int)strlen((const char*)data);
|
||||
if (strLen == 0)
|
||||
return NULL;
|
||||
data += strLen + 1;
|
||||
if (hasUniqueName)
|
||||
{
|
||||
strLen = (int)strlen((const char*)data);
|
||||
data += strLen + 1;
|
||||
}
|
||||
char* retVal = (char*)mCodeView->mAlloc.AllocBytes((int)(data - (uint8*)strStart));
|
||||
memcpy(retVal, strStart, data - (uint8*)strStart);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int BlCvTypeContainer::CreateMasterTag(int tagId, BlTypeInfo* outTypeInfo)
|
||||
{
|
||||
#define DECL_LEAF(leafType, leafName) \
|
||||
leafType& leafName = *(leafType*)&outBuffer[2];
|
||||
#define FIXTPI(varName) \
|
||||
varName = GetMasterTPITag(varName);
|
||||
#define FIXIPI(varName) \
|
||||
varName = GetMasterIPITag(varName);
|
||||
|
||||
uint8* sectionData = mSectionData; //mCvTypeSectionData;
|
||||
|
||||
uint8* srcDataStart = sectionData + mCvTagStartMap[tagId - mCvMinTag];
|
||||
int16 tagLen = *(int16*)(srcDataStart - 2);
|
||||
uint8* srcDataEnd = srcDataStart + tagLen;
|
||||
|
||||
int outSize = (int)(srcDataEnd - srcDataStart) + 2;
|
||||
uint8 outBuffer[0x10000];
|
||||
memcpy(outBuffer, srcDataStart - 2, outSize);
|
||||
uint8* data = (uint8*)outBuffer + 2;
|
||||
uint8* dataEnd = data + tagLen;
|
||||
|
||||
int16 trLeafType = GET(uint16);
|
||||
|
||||
BF_ASSERT(((intptr)data) % 4 == 0);
|
||||
|
||||
switch (trLeafType)
|
||||
{
|
||||
case LF_VTSHAPE:
|
||||
break;
|
||||
case LF_LABEL:
|
||||
break;
|
||||
case LF_STRUCTURE:
|
||||
case LF_CLASS:
|
||||
{
|
||||
DECL_LEAF(lfClass, classInfo);
|
||||
FIXTPI(classInfo.derived);
|
||||
FIXTPI(classInfo.field);
|
||||
FIXTPI(classInfo.vshape);
|
||||
}
|
||||
break;
|
||||
case LF_ENUM:
|
||||
{
|
||||
DECL_LEAF(lfEnum, enumInfo);
|
||||
FIXTPI(enumInfo.field);
|
||||
}
|
||||
break;
|
||||
case LF_UNION:
|
||||
{
|
||||
DECL_LEAF(lfUnion, unionInfo);
|
||||
FIXTPI(unionInfo.field);
|
||||
}
|
||||
break;
|
||||
case LF_ARRAY:
|
||||
{
|
||||
DECL_LEAF(lfArray, arrayInfo);
|
||||
FIXTPI(arrayInfo.elemtype);
|
||||
FIXTPI(arrayInfo.idxtype);
|
||||
}
|
||||
break;
|
||||
case LF_POINTER:
|
||||
{
|
||||
DECL_LEAF(lfPointer, pointerInfo);
|
||||
FIXTPI(pointerInfo.utype);
|
||||
if ((pointerInfo.attr.ptrmode == CV_PTR_MODE_PMEM) || (pointerInfo.attr.ptrmode == CV_PTR_MODE_PMFUNC))
|
||||
{
|
||||
FIXTPI(pointerInfo.pbase.pm.pmclass);
|
||||
}
|
||||
else if (pointerInfo.attr.ptrmode == CV_PTR_BASE_TYPE)
|
||||
{
|
||||
FIXTPI(pointerInfo.pbase.btype.index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_MODIFIER:
|
||||
{
|
||||
DECL_LEAF(lfModifier, modifierInfo);
|
||||
FIXTPI(modifierInfo.type);
|
||||
}
|
||||
break;
|
||||
case LF_MFUNCTION:
|
||||
{
|
||||
DECL_LEAF(lfMFunc, func);
|
||||
FIXTPI(func.rvtype);
|
||||
FIXTPI(func.classtype);
|
||||
FIXTPI(func.thistype);
|
||||
FIXTPI(func.arglist);
|
||||
}
|
||||
break;
|
||||
case LF_PROCEDURE:
|
||||
{
|
||||
DECL_LEAF(lfProc, proc);
|
||||
FIXTPI(proc.rvtype);
|
||||
FIXTPI(proc.arglist);
|
||||
}
|
||||
break;
|
||||
case LF_FIELDLIST:
|
||||
{
|
||||
while (data < dataEnd)
|
||||
{
|
||||
static int itrIdx = 0;
|
||||
itrIdx++;
|
||||
|
||||
uint8* leafDataStart = data;
|
||||
int leafType = (int)GET(uint16);
|
||||
switch (leafType)
|
||||
{
|
||||
case LF_VFUNCTAB:
|
||||
{
|
||||
lfVFuncTab& vfuncTab = *(lfVFuncTab*)leafDataStart;
|
||||
FIXTPI(vfuncTab.type);
|
||||
data = (uint8*)(&vfuncTab + 1);
|
||||
}
|
||||
break;
|
||||
case LF_BCLASS:
|
||||
{
|
||||
lfBClass& baseClassInfo = *(lfBClass*)leafDataStart;
|
||||
data = (uint8*)&baseClassInfo.offset;
|
||||
int thisOffset = (int)BlCvParser::CvParseConstant(data);
|
||||
FIXTPI(baseClassInfo.index);
|
||||
}
|
||||
break;
|
||||
case LF_VBCLASS:
|
||||
case LF_IVBCLASS:
|
||||
{
|
||||
lfVBClass& baseClassInfo = *(lfVBClass*)leafDataStart;
|
||||
data = (uint8*)&baseClassInfo.vbpoff;
|
||||
int thisOffset = (int)BlCvParser::CvParseConstant(data);
|
||||
int vTableOffset = (int)BlCvParser::CvParseConstant(data);
|
||||
FIXTPI(baseClassInfo.index);
|
||||
FIXTPI(baseClassInfo.vbptr);
|
||||
}
|
||||
break;
|
||||
case LF_ENUMERATE:
|
||||
{
|
||||
CV_fldattr_t fieldAttr = GET(CV_fldattr_t);
|
||||
int64 fieldVal = BlCvParser::CvParseConstant(data);
|
||||
const char* fieldName = BlCvParser::CvParseString(data);
|
||||
}
|
||||
break;
|
||||
case LF_NESTTYPE:
|
||||
{
|
||||
lfNestType& nestType = *(lfNestType*)leafDataStart;
|
||||
FIXTPI(nestType.index);
|
||||
data = (uint8*)&nestType.Name;
|
||||
const char* typeName = BlCvParser::CvParseString(data);
|
||||
}
|
||||
break;
|
||||
case LF_ONEMETHOD:
|
||||
{
|
||||
lfOneMethod& oneMethod = *(lfOneMethod*)leafDataStart;
|
||||
FIXTPI(oneMethod.index);
|
||||
data = (uint8*)&oneMethod.vbaseoff;
|
||||
int virtOffset = -1;
|
||||
if ((oneMethod.attr.mprop == CV_MTintro) || (oneMethod.attr.mprop == CV_MTpureintro))
|
||||
{
|
||||
virtOffset = GET(int32);
|
||||
}
|
||||
const char* methodName = BlCvParser::CvParseString(data);
|
||||
}
|
||||
break;
|
||||
case LF_METHOD:
|
||||
{
|
||||
lfMethod& method = *(lfMethod*)leafDataStart;
|
||||
FIXTPI(method.mList);
|
||||
data = (uint8*)&method.Name;
|
||||
const char* methodName = BlCvParser::CvParseString(data);
|
||||
}
|
||||
break;
|
||||
case LF_MEMBER:
|
||||
case LF_STMEMBER:
|
||||
{
|
||||
lfMember& member = *(lfMember*)leafDataStart;
|
||||
FIXTPI(member.index);
|
||||
bool isStatic = leafType == LF_STMEMBER;
|
||||
data = (uint8*)&member.offset;
|
||||
int memberOffset = -1;
|
||||
if (!isStatic)
|
||||
{
|
||||
memberOffset = (int)BlCvParser::CvParseConstant(data);
|
||||
//
|
||||
}
|
||||
char* fieldName = (char*)BlCvParser::CvParseString(data);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BF_FATAL("Unhandled");
|
||||
}
|
||||
|
||||
PTR_ALIGN(data, outBuffer, 4);
|
||||
//BF_ASSERT(((intptr)data) % 4 == 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_ARGLIST:
|
||||
{
|
||||
int argCount = GET(int32);
|
||||
for (int argIdx = 0; argIdx < argCount; argIdx++)
|
||||
{
|
||||
CV_typ_t& argTypeId = GET(CV_typ_t);
|
||||
FIXTPI(argTypeId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_METHODLIST:
|
||||
{
|
||||
while (data < dataEnd)
|
||||
{
|
||||
mlMethod& method = *(mlMethod*)data;
|
||||
FIXTPI(method.index);
|
||||
data = (uint8*)method.vbaseoff;
|
||||
if ((method.attr.mprop == CV_MTintro) || (method.attr.mprop == CV_MTpureintro))
|
||||
{
|
||||
int virtOffset = GET(int32);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_STRING_ID:
|
||||
break;
|
||||
case LF_SUBSTR_LIST:
|
||||
{
|
||||
DECL_LEAF(lfArgList, argList);
|
||||
data = (uint8*)&argList.arg;
|
||||
for (int idx = 0; idx < (int)argList.count; idx++)
|
||||
{
|
||||
CV_ItemId& itemId = GET(CV_ItemId);
|
||||
FIXIPI(itemId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_UDT_SRC_LINE:
|
||||
{
|
||||
DECL_LEAF(lfUdtSrcLine, udtSrcLine);
|
||||
udtSrcLine.leaf = LF_UDT_MOD_SRC_LINE;
|
||||
FIXTPI(udtSrcLine.type);
|
||||
FIXIPI(udtSrcLine.src);
|
||||
|
||||
lfUdtModSrcLine& udtModSrcLine = *(lfUdtModSrcLine*)&udtSrcLine;
|
||||
udtModSrcLine.imod = 1;
|
||||
outSize += 4;
|
||||
*(int16*)(outBuffer) += 4;
|
||||
}
|
||||
break;
|
||||
case LF_FUNC_ID:
|
||||
{
|
||||
DECL_LEAF(lfFuncId, funcId);
|
||||
FIXIPI(funcId.scopeId);
|
||||
FIXTPI(funcId.type);
|
||||
}
|
||||
break;
|
||||
case LF_MFUNC_ID:
|
||||
{
|
||||
DECL_LEAF(lfMFuncId, mfuncId);
|
||||
FIXTPI(mfuncId.parentType);
|
||||
FIXTPI(mfuncId.type);
|
||||
}
|
||||
break;
|
||||
case LF_BUILDINFO:
|
||||
{
|
||||
DECL_LEAF(lfBuildInfo, buildInfo);
|
||||
data = (uint8*)&buildInfo.arg;
|
||||
for (int idx = 0; idx < buildInfo.count; idx++)
|
||||
{
|
||||
CV_ItemId& itemId = GET(CV_ItemId);
|
||||
FIXIPI(itemId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_BITFIELD:
|
||||
{
|
||||
DECL_LEAF(lfBitfield, bitfield);
|
||||
FIXTPI(bitfield.type);
|
||||
}
|
||||
break;
|
||||
case LF_VFTABLE:
|
||||
{
|
||||
DECL_LEAF(lfVftable, vtTable);
|
||||
FIXTPI(vtTable.type);
|
||||
FIXTPI(vtTable.baseVftable);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NotImpl();
|
||||
break;
|
||||
}
|
||||
|
||||
BF_ASSERT(*(int16*)(outBuffer) == outSize - 2);
|
||||
outTypeInfo->mData.Write(outBuffer, outSize);
|
||||
return outTypeInfo->mCurTagId++;
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::HashName(const char* namePtr, bool hasMangledName, HashContext& hashContext)
|
||||
{
|
||||
int hashSize = (int)strlen(namePtr);
|
||||
if (hasMangledName)
|
||||
hashSize += 1 + (int)strlen(namePtr + hashSize + 1);
|
||||
hashContext.Mixin(namePtr, hashSize);
|
||||
}
|
||||
|
||||
int BlCvTypeContainer::GetMasterTPITag(int tagId)
|
||||
{
|
||||
if (tagId == 0)
|
||||
return 0;
|
||||
if (tagId < mCvMinTag)
|
||||
return tagId;
|
||||
int masterTag = (*mTPIMap)[tagId - mCvMinTag];
|
||||
if (masterTag == -1)
|
||||
{
|
||||
// Ensure we're TPI
|
||||
BF_ASSERT(&mTagMap == mTPIMap);
|
||||
ParseTag(tagId);
|
||||
masterTag = (*mTPIMap)[tagId - mCvMinTag];
|
||||
BF_ASSERT(masterTag != -1);
|
||||
return masterTag;
|
||||
}
|
||||
|
||||
BF_ASSERT(masterTag != -1);
|
||||
return masterTag;
|
||||
}
|
||||
|
||||
int BlCvTypeContainer::GetMasterIPITag(int tagId)
|
||||
{
|
||||
if (tagId == 0)
|
||||
return 0;
|
||||
// Ensure we're IPI
|
||||
BF_ASSERT(&mTagMap == mIPIMap);
|
||||
if (tagId < mCvMinTag)
|
||||
return tagId;
|
||||
int typeIdx = mTagMap[tagId - mCvMinTag];
|
||||
BF_ASSERT(typeIdx != -1);
|
||||
return typeIdx;
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::NotImpl()
|
||||
{
|
||||
BF_FATAL("NotImpl");
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::ScanTypeData()
|
||||
{
|
||||
uint8* sectionData = mSectionData;
|
||||
int sectionSize = mSectionSize;
|
||||
|
||||
uint8* data = (uint8*)sectionData;
|
||||
uint8* dataEnd = data + sectionSize;
|
||||
|
||||
if (mCvMinTag == -1)
|
||||
{
|
||||
mCvMinTag = 0x1000;
|
||||
|
||||
int tagCountGuess = sectionSize / 128;
|
||||
mCvTagStartMap.reserve(tagCountGuess);
|
||||
|
||||
int tagIdx = mCvMinTag;
|
||||
while (data < dataEnd)
|
||||
{
|
||||
int tagLen = GET(uint16);
|
||||
uint8* dataStart = data;
|
||||
uint8* dataTagEnd = data + tagLen;
|
||||
|
||||
mCvTagStartMap.push_back((int)(data - sectionData));
|
||||
|
||||
data = dataTagEnd;
|
||||
tagIdx++;
|
||||
}
|
||||
mCvMaxTag = tagIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
int tagIdx = mCvMinTag;
|
||||
while (data < dataEnd)
|
||||
{
|
||||
int tagLen = GET(uint16);
|
||||
uint8* dataStart = data;
|
||||
uint8* dataTagEnd = data + tagLen;
|
||||
|
||||
mCvTagStartMap[tagIdx - mCvMinTag] = (int)(data - sectionData);
|
||||
|
||||
data = dataTagEnd;
|
||||
tagIdx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::HashTPITag(int tagId, HashContext& hashContext)
|
||||
{
|
||||
int masterTagId = GetMasterTPITag(tagId);
|
||||
hashContext.Mixin(masterTagId);
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::HashIPITag(int tagId, HashContext& hashContext)
|
||||
{
|
||||
int masterTagId = GetMasterIPITag(tagId);
|
||||
hashContext.Mixin(masterTagId);
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::HashTagContent(int tagId, HashContext& hashContext, bool& isIPI)
|
||||
{
|
||||
uint8* sectionData = mSectionData; //mCvTypeSectionData;
|
||||
|
||||
uint8* data = sectionData + mCvTagStartMap[tagId - mCvMinTag];
|
||||
uint8* dataStart = data;
|
||||
int16 tagLen = *(int16*)(data - 2);
|
||||
uint8* dataEnd = data + tagLen;
|
||||
int16 trLeafType = GET(uint16);
|
||||
|
||||
hashContext.Mixin(trLeafType);
|
||||
|
||||
switch (trLeafType)
|
||||
{
|
||||
case LF_VTSHAPE:
|
||||
{
|
||||
lfVTShape& vtShape = *(lfVTShape*)dataStart;
|
||||
data = (uint8*)&vtShape.desc;
|
||||
int shapeBytes = (vtShape.count + 1) / 2;
|
||||
hashContext.Mixin(data, shapeBytes);
|
||||
}
|
||||
break;
|
||||
case LF_LABEL:
|
||||
{
|
||||
lfLabel& label = *(lfLabel*)dataStart;
|
||||
hashContext.Mixin(label.mode);
|
||||
}
|
||||
break;
|
||||
case LF_ARGLIST:
|
||||
{
|
||||
int argCount = (int)GET(int32);
|
||||
hashContext.Mixin(argCount);
|
||||
for (int argIdx = 0; argIdx < (int)argCount; argIdx++)
|
||||
{
|
||||
HashTPITag(GET(CV_typ_t), hashContext);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_FIELDLIST:
|
||||
{
|
||||
while (data < dataEnd)
|
||||
{
|
||||
uint8* leafDataStart = data;
|
||||
int leafType = (int)GET(uint16);
|
||||
hashContext.Mixin(leafType);
|
||||
switch (leafType)
|
||||
{
|
||||
case LF_VFUNCTAB:
|
||||
{
|
||||
lfVFuncTab& vfuncTab = *(lfVFuncTab*)leafDataStart;
|
||||
HashTPITag(vfuncTab.type, hashContext);
|
||||
data = (uint8*)(&vfuncTab + 1);
|
||||
}
|
||||
break;
|
||||
case LF_BCLASS:
|
||||
{
|
||||
lfBClass& baseClassInfo = *(lfBClass*)leafDataStart;
|
||||
data = (uint8*)&baseClassInfo.offset;
|
||||
int thisOffset = (int)BlCvParser::CvParseConstant(data);
|
||||
hashContext.Mixin(thisOffset);
|
||||
HashTPITag(baseClassInfo.index, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_VBCLASS:
|
||||
case LF_IVBCLASS:
|
||||
{
|
||||
lfVBClass& baseClassInfo = *(lfVBClass*)leafDataStart;
|
||||
data = (uint8*)&baseClassInfo.vbpoff;
|
||||
int thisOffset = (int)BlCvParser::CvParseConstant(data);
|
||||
int vTableOffset = (int)BlCvParser::CvParseConstant(data);
|
||||
hashContext.Mixin(baseClassInfo.attr);
|
||||
HashTPITag(baseClassInfo.index, hashContext);
|
||||
HashTPITag(baseClassInfo.vbptr, hashContext);
|
||||
HashTPITag(thisOffset, hashContext);
|
||||
HashTPITag(vTableOffset, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_ENUMERATE:
|
||||
{
|
||||
CV_fldattr_t fieldAttr = GET(CV_fldattr_t);
|
||||
int64 fieldVal = BlCvParser::CvParseConstant(data);
|
||||
const char* fieldName = BlCvParser::CvParseString(data);
|
||||
hashContext.Mixin(fieldAttr);
|
||||
hashContext.Mixin(fieldVal);
|
||||
hashContext.MixinStr(fieldName);
|
||||
}
|
||||
break;
|
||||
case LF_NESTTYPE:
|
||||
{
|
||||
int16 pad = GET(int16);
|
||||
int32 nestedTypeId = GET(int32);
|
||||
//int64 nestedSize = BlCvParser::CvParseConstant(data);
|
||||
const char* typeName = BlCvParser::CvParseString(data);
|
||||
HashTPITag(nestedTypeId, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_ONEMETHOD:
|
||||
{
|
||||
CV_fldattr_t attr = GET(CV_fldattr_t);
|
||||
CV_typ_t methodTypeId = GET(CV_typ_t);
|
||||
hashContext.Mixin(attr);
|
||||
HashTPITag(methodTypeId, hashContext);
|
||||
|
||||
int virtOffset = -1;
|
||||
if ((attr.mprop == CV_MTintro) || (attr.mprop == CV_MTpureintro))
|
||||
{
|
||||
virtOffset = GET(int32);
|
||||
hashContext.Mixin(virtOffset);
|
||||
}
|
||||
const char* name = BlCvParser::CvParseString(data);
|
||||
hashContext.MixinStr(name);
|
||||
}
|
||||
break;
|
||||
case LF_METHOD:
|
||||
{
|
||||
int count = (int)GET(uint16);
|
||||
int32 methodList = GET(int32);
|
||||
const char* name = BlCvParser::CvParseString(data);
|
||||
hashContext.MixinStr(name);
|
||||
}
|
||||
break;
|
||||
case LF_MEMBER:
|
||||
case LF_STMEMBER:
|
||||
{
|
||||
bool isStatic = leafType == LF_STMEMBER;
|
||||
bool isConst = false;
|
||||
CV_fldattr_t attr = GET(CV_fldattr_t);
|
||||
CV_typ_t fieldTypeId = GET(CV_typ_t);
|
||||
hashContext.Mixin(attr);
|
||||
|
||||
int memberOffset = -1;
|
||||
if (!isStatic)
|
||||
{
|
||||
memberOffset = (int)BlCvParser::CvParseConstant(data);
|
||||
hashContext.Mixin(memberOffset);
|
||||
}
|
||||
const char* name = BlCvParser::CvParseString(data);
|
||||
hashContext.MixinStr(name);
|
||||
HashTPITag(fieldTypeId, hashContext);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BF_FATAL("Unhandled");
|
||||
}
|
||||
|
||||
PTR_ALIGN(data, sectionData, 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_METHODLIST:
|
||||
{
|
||||
while (data < dataEnd)
|
||||
{
|
||||
mlMethod& method = *(mlMethod*)data;
|
||||
bool tempBool = false;
|
||||
HashTagContent(method.index, hashContext, tempBool);
|
||||
data = (uint8*)method.vbaseoff;
|
||||
if ((method.attr.mprop == CV_MTintro) || (method.attr.mprop == CV_MTpureintro))
|
||||
{
|
||||
int virtOffset = GET(int32);
|
||||
hashContext.Mixin(virtOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_STRUCTURE:
|
||||
case LF_CLASS:
|
||||
{
|
||||
lfClass& classInfo = *(lfClass*)dataStart;
|
||||
data = (uint8*)&classInfo.data;
|
||||
int dataSize = (int)BlCvParser::CvParseConstant(data);
|
||||
HashName((char*)data, classInfo.property.hasuniquename, hashContext);
|
||||
hashContext.Mixin(dataSize);
|
||||
hashContext.Mixin(classInfo.property);
|
||||
HashTPITag(classInfo.field, hashContext);
|
||||
HashTPITag(classInfo.derived, hashContext);
|
||||
HashTPITag(classInfo.vshape, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_ENUM:
|
||||
{
|
||||
lfEnum& enumInfo = *(lfEnum*)dataStart;
|
||||
data = (uint8*)enumInfo.Name;
|
||||
HashName((char*)data, enumInfo.property.hasuniquename, hashContext);
|
||||
hashContext.Mixin(enumInfo.property);
|
||||
HashTPITag(enumInfo.utype, hashContext);
|
||||
HashTPITag(enumInfo.field, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_UNION:
|
||||
{
|
||||
lfUnion& unionInfo = *(lfUnion*)dataStart;
|
||||
data = (uint8*)unionInfo.data;
|
||||
int dataSize = (int)BlCvParser::CvParseConstant(data);
|
||||
HashName((char*)data, unionInfo.property.hasuniquename, hashContext);
|
||||
hashContext.Mixin(dataSize);
|
||||
hashContext.Mixin(unionInfo.property);
|
||||
HashTPITag(unionInfo.field, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_ARRAY:
|
||||
{
|
||||
lfArray& arrayInfo = *(lfArray*)dataStart;
|
||||
data = (uint8*)arrayInfo.data;
|
||||
int dataSize = (int)BlCvParser::CvParseConstant(data);
|
||||
HashName((char*)data, false, hashContext);
|
||||
HashTPITag(arrayInfo.elemtype, hashContext);
|
||||
HashTPITag(arrayInfo.idxtype, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_MFUNCTION:
|
||||
{
|
||||
lfMFunc& func = *(lfMFunc*)dataStart;
|
||||
HashTPITag(func.thistype, hashContext);
|
||||
HashTPITag(func.classtype, hashContext);
|
||||
HashTPITag(func.rvtype, hashContext);
|
||||
HashTPITag(func.arglist, hashContext);
|
||||
hashContext.Mixin(func.funcattr);
|
||||
hashContext.Mixin(func.calltype);
|
||||
hashContext.Mixin(func.parmcount);
|
||||
hashContext.Mixin(func.thisadjust);
|
||||
}
|
||||
break;
|
||||
case LF_PROCEDURE:
|
||||
{
|
||||
lfProc& proc = *(lfProc*)dataStart;
|
||||
HashTPITag(proc.rvtype, hashContext);
|
||||
HashTPITag(proc.arglist, hashContext);
|
||||
hashContext.Mixin(proc.funcattr);
|
||||
hashContext.Mixin(proc.calltype);
|
||||
hashContext.Mixin(proc.parmcount);
|
||||
}
|
||||
break;
|
||||
case LF_POINTER:
|
||||
{
|
||||
lfPointer& pointerInfo = *(lfPointer*)dataStart;
|
||||
HashTPITag(pointerInfo.utype, hashContext);
|
||||
hashContext.Mixin(pointerInfo.attr);
|
||||
}
|
||||
break;
|
||||
case LF_MODIFIER:
|
||||
{
|
||||
lfModifier& modifierInfo = *(lfModifier*)dataStart;
|
||||
HashTPITag(modifierInfo.type, hashContext);
|
||||
hashContext.Mixin(modifierInfo.attr);
|
||||
}
|
||||
break;
|
||||
case LF_STRING_ID:
|
||||
{
|
||||
isIPI = true;
|
||||
lfStringId& stringId = *(lfStringId*)dataStart;
|
||||
HashIPITag(stringId.id, hashContext);
|
||||
HashName((char*)stringId.name, false, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_SUBSTR_LIST:
|
||||
{
|
||||
lfArgList& argList = *(lfArgList*)dataStart;
|
||||
data = (uint8*)&argList.arg;
|
||||
for (int idx = 0; idx < (int)argList.count; idx++)
|
||||
{
|
||||
CV_ItemId& itemId = GET(CV_ItemId);
|
||||
HashIPITag(itemId, hashContext);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_UDT_SRC_LINE:
|
||||
{
|
||||
lfUdtSrcLine& srcLine = *(lfUdtSrcLine*)dataStart;
|
||||
HashTPITag(srcLine.type, hashContext);
|
||||
HashIPITag(srcLine.src, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_FUNC_ID:
|
||||
{
|
||||
isIPI = true;
|
||||
lfFuncId& funcId = *(lfFuncId*)dataStart;
|
||||
HashIPITag(funcId.scopeId, hashContext);
|
||||
HashTPITag(funcId.type, hashContext);
|
||||
HashName((char*)funcId.name, false, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_MFUNC_ID:
|
||||
{
|
||||
isIPI = true;
|
||||
lfMFuncId& mfuncId = *(lfMFuncId*)dataStart;
|
||||
HashTPITag(mfuncId.parentType, hashContext);
|
||||
HashTPITag(mfuncId.type, hashContext);
|
||||
HashName((char*)mfuncId.name, false, hashContext);
|
||||
}
|
||||
break;
|
||||
case LF_BUILDINFO:
|
||||
{
|
||||
lfBuildInfo& buildInfo = *(lfBuildInfo*)dataStart;
|
||||
data = (uint8*)&buildInfo.arg;
|
||||
for (int idx = 0; idx < (int)buildInfo.count; idx++)
|
||||
{
|
||||
CV_ItemId& itemId = GET(CV_ItemId);
|
||||
HashIPITag(itemId, hashContext);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LF_BITFIELD:
|
||||
{
|
||||
lfBitfield& bitfield = *(lfBitfield*)dataStart;
|
||||
HashTPITag(bitfield.type, hashContext);
|
||||
hashContext.Mixin(bitfield.length);
|
||||
hashContext.Mixin(bitfield.position);
|
||||
}
|
||||
break;
|
||||
case LF_VFTABLE:
|
||||
{
|
||||
lfVftable& vtTable = *(lfVftable*)dataStart;
|
||||
HashTPITag(vtTable.type, hashContext);
|
||||
HashTPITag(vtTable.baseVftable, hashContext);
|
||||
hashContext.Mixin(vtTable.offsetInObjectLayout);
|
||||
data = (uint8*)&vtTable.Names;
|
||||
hashContext.Mixin(data, vtTable.len);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NotImpl();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::ParseTag(int tagId, bool forceFull)
|
||||
{
|
||||
uint8* data = mSectionData + mCvTagStartMap[tagId - mCvMinTag];
|
||||
uint8* dataStart = data;
|
||||
int16 tagLen = *(int16*)(data - 2);
|
||||
uint8* dataEnd = data + tagLen;
|
||||
int16 trLeafType = GET(uint16);
|
||||
|
||||
//TODO: Bad? Good?
|
||||
//forceFull = true;
|
||||
|
||||
bool wantsExt = false;
|
||||
int memberMasterTag = 0;
|
||||
switch (trLeafType)
|
||||
{
|
||||
case LF_FUNC_ID:
|
||||
{
|
||||
mCodeView->mStat_ParseTagFuncs++;
|
||||
|
||||
wantsExt = true;
|
||||
lfFuncId& funcId = *(lfFuncId*)dataStart;
|
||||
int memberTagId = GetMasterTPITag(funcId.type);
|
||||
mElementMap[tagId - mCvMinTag] = memberTagId;
|
||||
|
||||
/*if (!forceFull)
|
||||
{
|
||||
mTagMap[tagId - mCvMinTag] = memberMasterTag | BlTypeMapFlag_InfoExt_ProcId_TypeOnly;
|
||||
return;
|
||||
}*/
|
||||
|
||||
//return;
|
||||
}
|
||||
break;
|
||||
case LF_MFUNC_ID:
|
||||
{
|
||||
mCodeView->mStat_ParseTagFuncs++;
|
||||
|
||||
wantsExt = true;
|
||||
lfMFuncId& funcId = *(lfMFuncId*)dataStart;
|
||||
|
||||
int memberTagId = GetMasterTPITag(funcId.type);
|
||||
mElementMap[tagId - mCvMinTag] = memberTagId;
|
||||
/*if (!forceFull)
|
||||
{
|
||||
mTagMap[tagId - mCvMinTag] = memberMasterTag | BlTypeMapFlag_InfoExt_ProcId_TypeOnly;
|
||||
return;
|
||||
}*/
|
||||
|
||||
//return;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
HashContext hashContext;
|
||||
bool isIPI = false;
|
||||
HashTagContent(tagId, hashContext, isIPI);
|
||||
auto outTypeInfo = mOutTypeInfo;
|
||||
if (isIPI)
|
||||
outTypeInfo = &mCodeView->mIPI;
|
||||
|
||||
mCodeView->mStat_TypeMapInserts++;
|
||||
|
||||
Val128 hashVal = hashContext.Finish128();
|
||||
|
||||
int masterTagId;
|
||||
auto insertPair = outTypeInfo->mTypeMap.insert(std::make_pair(hashVal, -1));
|
||||
if (insertPair.second)
|
||||
{
|
||||
masterTagId = CreateMasterTag(tagId, outTypeInfo);
|
||||
insertPair.first->second = masterTagId;
|
||||
}
|
||||
else
|
||||
{
|
||||
masterTagId = insertPair.first->second;
|
||||
}
|
||||
|
||||
/*if (wantsExt)
|
||||
{
|
||||
mTagMap[tagId - mCvMinTag] = (int)mInfoExts.size() | BlTypeMapFlag_InfoExt_ProcId_Resolved;
|
||||
|
||||
BlCvTypeInfoExt infoExt;
|
||||
infoExt.mMasterTag = masterTagId;
|
||||
infoExt.mMemberMasterTag = memberMasterTag;
|
||||
mInfoExts.push_back(infoExt);
|
||||
}
|
||||
else*/
|
||||
mTagMap[tagId - mCvMinTag] = masterTagId;
|
||||
}
|
||||
|
||||
void BlCvTypeContainer::ParseTypeData()
|
||||
{
|
||||
mTagMap.insert(mTagMap.begin(), mCvTagStartMap.size(), -1);
|
||||
mElementMap.insert(mElementMap.begin(), mCvTagStartMap.size(), -1);
|
||||
for (int tagId = mCvMinTag; tagId < mCvMaxTag; tagId++)
|
||||
{
|
||||
if (mTagMap[tagId - mCvMinTag] == -1)
|
||||
ParseTag(tagId);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BlCvTypeSource::BlCvTypeSource()
|
||||
{
|
||||
mTypeServerLib = NULL;
|
||||
mIPI = NULL;
|
||||
mIsDone = false;
|
||||
mObjectData = NULL;
|
||||
}
|
||||
|
||||
BlCvTypeSource::~BlCvTypeSource()
|
||||
{
|
||||
delete mTypeServerLib;
|
||||
if (mIPI != &mTPI)
|
||||
delete mIPI;
|
||||
}
|
||||
|
||||
void BlCvTypeSource::CreateIPI()
|
||||
{
|
||||
auto codeView = mTPI.mCodeView;
|
||||
|
||||
BF_ASSERT(mIPI == &mTPI);
|
||||
mIPI = new BlCvTypeContainer();
|
||||
mIPI->mCodeView = codeView;
|
||||
mIPI->mOutTypeInfo = &codeView->mIPI;
|
||||
mIPI->mTPIMap = &mTPI.mTagMap;
|
||||
mIPI->mIPIMap = &mIPI->mTagMap;
|
||||
}
|
||||
|
||||
void BlCvTypeSource::Init(BlCodeView* codeView)
|
||||
{
|
||||
mTPI.mCodeView = codeView;
|
||||
mTPI.mOutTypeInfo = &codeView->mTPI;
|
||||
mTPI.mTPIMap = &mTPI.mTagMap;
|
||||
mTPI.mIPIMap = &mTPI.mTagMap;
|
||||
mIPI = &mTPI;
|
||||
}
|
94
IDEHelper/Linker/BlCvTypeSource.h
Normal file
94
IDEHelper/Linker/BlCvTypeSource.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "BeefySysLib/FileStream.h"
|
||||
#include "BeefySysLib/util/BumpAllocator.h"
|
||||
#include "BeefySysLib/util/Hash.h"
|
||||
#include "BeefySysLib/util/CritSect.h"
|
||||
#include "../Compiler/BfUtil.h"
|
||||
#include <unordered_map>
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
class BlPdbParser;
|
||||
class BlTypeInfo;
|
||||
class BlCompositeType;
|
||||
class BlCodeView;
|
||||
class BlType;
|
||||
class BlStructType;
|
||||
class BlProcType;
|
||||
|
||||
class BlCvTypeInfoExt
|
||||
{
|
||||
public:
|
||||
int mMasterTag;
|
||||
int mMemberMasterTag;
|
||||
};
|
||||
|
||||
enum BlTypeMapFlag
|
||||
{
|
||||
BlTypeMapFlag_InfoExt_ProcId_TypeOnly = 0x80000000,
|
||||
BlTypeMapFlag_InfoExt_ProcId_Resolved = 0x40000000,
|
||||
BlTypeMapFlag_InfoExt_MASK = 0x0FFFFFFF
|
||||
};
|
||||
|
||||
class BlCvTypeContainer
|
||||
{
|
||||
public:
|
||||
int mCvMinTag;
|
||||
int mCvMaxTag;
|
||||
// Negative values in mTagMap are contextual:
|
||||
// For LF_FUNC_ID, refers to embedded FunctionType
|
||||
std::vector<int> mTagMap;
|
||||
std::vector<int> mElementMap; // From FUNC_ID to FuncType, for example
|
||||
std::vector<int> mCvTagStartMap;
|
||||
uint8* mSectionData;
|
||||
int mSectionSize;
|
||||
BlCodeView* mCodeView;
|
||||
BlTypeInfo* mOutTypeInfo;
|
||||
std::vector<int>* mTPIMap;
|
||||
std::vector<int>* mIPIMap;
|
||||
int mIdx;
|
||||
//std::vector<BlCvTypeInfoExt> mInfoExts;
|
||||
|
||||
public:
|
||||
void NotImpl();
|
||||
void Fail(const StringImpl& err);
|
||||
const char* CvParseAndDupString(uint8 *& data, bool hasUniqueName = false);
|
||||
int CreateMasterTag(int tagId, BlTypeInfo* outTypeInfo);
|
||||
void HashName(const char* namePtr, bool hasMangledName, HashContext& hashContext);
|
||||
void HashTPITag(int tagId, HashContext& hashContext);
|
||||
void HashIPITag(int tagId, HashContext& hashContext);
|
||||
void HashTagContent(int tagId, HashContext& hashContext, bool& isIPI);
|
||||
void ParseTag(int tagId, bool forceFull = false);
|
||||
|
||||
public:
|
||||
BlCvTypeContainer();
|
||||
~BlCvTypeContainer();
|
||||
|
||||
int GetMasterTPITag(int tagId);
|
||||
int GetMasterIPITag(int tagId);
|
||||
void ScanTypeData();
|
||||
void ParseTypeData();
|
||||
};
|
||||
|
||||
class BlObjectData;
|
||||
|
||||
class BlCvTypeSource
|
||||
{
|
||||
public:
|
||||
BlPdbParser* mTypeServerLib;
|
||||
BlObjectData* mObjectData;
|
||||
BlCvTypeContainer mTPI;
|
||||
BlCvTypeContainer* mIPI;
|
||||
volatile bool mIsDone;
|
||||
|
||||
public:
|
||||
BlCvTypeSource();
|
||||
~BlCvTypeSource();
|
||||
|
||||
void CreateIPI();
|
||||
void Init(BlCodeView* codeView);
|
||||
};
|
||||
|
||||
NS_BF_END
|
209
IDEHelper/Linker/BlHash.cpp
Normal file
209
IDEHelper/Linker/BlHash.cpp
Normal file
|
@ -0,0 +1,209 @@
|
|||
#include "BlHash.h"
|
||||
#include "codeview/cvinfo.h"
|
||||
#include "BlCvParser.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
#define GET(T) *((T*)(data += sizeof(T)) - 1)
|
||||
|
||||
// These are derived from
|
||||
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/include/misc.h
|
||||
// and
|
||||
// https://github.com/Microsoft/microsoft-pdb/blob/master/langapi/shared/crc32.h
|
||||
|
||||
uint32 BlHash::HashStr_PdbV1(const char* str, int len)
|
||||
{
|
||||
uint8* ptr = (uint8*)str;
|
||||
uint8* end;
|
||||
if (len != -1)
|
||||
end = (uint8*)ptr + len;
|
||||
else
|
||||
end = (uint8*)ptr + strlen(str);
|
||||
|
||||
uint32 hash = 0;
|
||||
while (ptr <= end - 4)
|
||||
{
|
||||
hash ^= *(uint32*)ptr;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
while (ptr <= end - 2)
|
||||
{
|
||||
hash ^= *(uint16*)ptr;
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
while (ptr < end)
|
||||
hash ^= *(ptr++);
|
||||
|
||||
hash |= 0x20202020;
|
||||
hash ^= hash >> 11;
|
||||
return hash ^ (hash >> 16);
|
||||
}
|
||||
|
||||
uint32 BlHash::HashStr_PdbV2(const char* str)
|
||||
{
|
||||
uint8* ptr = (uint8*)str;
|
||||
uint8* end = (uint8*)ptr + strlen(str);
|
||||
|
||||
uint32 hash = 0xb170a1bf;
|
||||
while (ptr <= end - 4)
|
||||
{
|
||||
hash += *(uint32*)ptr;
|
||||
ptr += 4;
|
||||
hash += hash << 10;
|
||||
hash ^= hash >> 6;
|
||||
}
|
||||
|
||||
while (ptr < end)
|
||||
{
|
||||
hash += *(uint8*)(ptr++);
|
||||
hash += hash << 10;
|
||||
hash ^= hash >> 6;
|
||||
}
|
||||
|
||||
return hash * 1664525 + 1013904223;
|
||||
}
|
||||
|
||||
uint32 BlHash::GetSig_Pdb(void* data, int len)
|
||||
{
|
||||
static const uint32 crcTab[] = {
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
|
||||
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
||||
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
|
||||
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
|
||||
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
||||
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
|
||||
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
|
||||
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
||||
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
|
||||
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
|
||||
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
|
||||
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
|
||||
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
||||
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
|
||||
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
|
||||
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
|
||||
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
|
||||
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
|
||||
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
|
||||
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
|
||||
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
|
||||
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
||||
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
|
||||
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
|
||||
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
|
||||
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
|
||||
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
|
||||
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
|
||||
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
|
||||
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
|
||||
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||
};
|
||||
|
||||
uint8* ptr = (uint8*)data;
|
||||
uint8* end = ptr + len;
|
||||
uint32 crc = 0;
|
||||
while (ptr < end)
|
||||
crc = (crc >> 8) ^ crcTab[(crc & 0xff) ^ *ptr++];
|
||||
return crc;
|
||||
}
|
||||
|
||||
static bool IsUnnamed(const char* name)
|
||||
{
|
||||
if (strcmp(name, "<unnamed-tag>") == 0)
|
||||
return true;
|
||||
if (strcmp(name, "__unnamed") == 0)
|
||||
return true;
|
||||
|
||||
int nameLen = (int)strlen(name);
|
||||
if ((nameLen > 15) && (strcmp(name + nameLen - 15, "::<unnamed-tag>") == 0))
|
||||
return true;
|
||||
if ((nameLen > 11) && (strcmp(name + nameLen - 15, "::__unnamed") == 0))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 BlHash::GetTypeHash(uint8*& data)
|
||||
{
|
||||
uint16 trLength = GET(uint16);
|
||||
uint8* dataStart = data;
|
||||
uint16 trLeafType = GET(uint16);
|
||||
uint8* dataEnd = dataStart + trLength;
|
||||
|
||||
bool didHash = false;
|
||||
|
||||
const char* name = NULL;
|
||||
|
||||
switch (trLeafType)
|
||||
{
|
||||
case LF_STRUCTURE:
|
||||
case LF_CLASS:
|
||||
{
|
||||
lfClass& classInfo = *(lfClass*)dataStart;
|
||||
data = (uint8*)&classInfo.data;
|
||||
int dataSize = (int)BlCvParser::CvParseConstant(data);
|
||||
name = (const char*)data;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LF_ENUM:
|
||||
{
|
||||
lfEnum& enumInfo = *(lfEnum*)dataStart;
|
||||
name = (const char*)enumInfo.Name;
|
||||
}
|
||||
break;
|
||||
case LF_UNION:
|
||||
{
|
||||
lfUnion& unionInfo = *(lfUnion*)dataStart;
|
||||
data = (uint8*)&unionInfo.data;
|
||||
int dataSize = (int)BlCvParser::CvParseConstant(data);
|
||||
name = (const char*)data;
|
||||
|
||||
}
|
||||
break;
|
||||
case LF_UDT_MOD_SRC_LINE:
|
||||
{
|
||||
lfUdtModSrcLine& modSrcLine = *(lfUdtModSrcLine*)dataStart;
|
||||
// Weird, but this is what's required
|
||||
data = dataEnd;
|
||||
return BlHash::HashStr_PdbV1((const char*)&modSrcLine.type, 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
data = dataEnd;
|
||||
|
||||
if (name != NULL)
|
||||
{
|
||||
lfClass& classInfo = *(lfClass*)dataStart;
|
||||
if (!classInfo.property.fwdref)
|
||||
{
|
||||
if (classInfo.property.scoped)
|
||||
{
|
||||
if (!classInfo.property.hasuniquename)
|
||||
name = NULL;
|
||||
else
|
||||
name = name + strlen(name) + 1;
|
||||
}
|
||||
if ((name != NULL) && (!IsUnnamed(name)))
|
||||
{
|
||||
return BlHash::HashStr_PdbV1(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BlHash::GetSig_Pdb(dataStart - 2, trLength + 2);
|
||||
}
|
16
IDEHelper/Linker/BlHash.h
Normal file
16
IDEHelper/Linker/BlHash.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
class BlHash
|
||||
{
|
||||
public:
|
||||
static uint32 HashStr_PdbV1(const char* str, int len = -1);
|
||||
static uint32 HashStr_PdbV2(const char* str);
|
||||
static uint32 GetSig_Pdb(void* data, int len);
|
||||
static uint32 GetTypeHash(uint8*& data);
|
||||
};
|
||||
|
||||
NS_BF_END
|
228
IDEHelper/Linker/BlMsf.cpp
Normal file
228
IDEHelper/Linker/BlMsf.cpp
Normal file
|
@ -0,0 +1,228 @@
|
|||
#include "BlMsf.h"
|
||||
#include "BeefySysLib/MemStream.h"
|
||||
#include "../Compiler/BfAstAllocator.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
#define MSF_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"
|
||||
#define CV_BLOCK_SIZE 0x1000
|
||||
#define PTR_ALIGN(ptr, origPtr, alignSize) ptr = ( (origPtr)+( ((ptr - origPtr) + (alignSize - 1)) & ~(alignSize - 1) ) )
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
BlMsfWorkThread::BlMsfWorkThread()
|
||||
{
|
||||
mMsf = NULL;
|
||||
mDone = false;
|
||||
mSortDirty = false;
|
||||
}
|
||||
|
||||
BlMsfWorkThread::~BlMsfWorkThread()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
void BlMsfWorkThread::Stop()
|
||||
{
|
||||
mDone = true;
|
||||
mWorkEvent.Set();
|
||||
WorkThread::Stop();
|
||||
}
|
||||
|
||||
void BlMsfWorkThread::Run()
|
||||
{
|
||||
while (!mDone)
|
||||
{
|
||||
if (mSortedWriteBlockWorkQueue.empty())
|
||||
{
|
||||
// Only fill in new entries when our queue is empty. This is not a strong ordering guarantee.
|
||||
bool sortDirty = false;
|
||||
mCritSect.Lock();
|
||||
if (!mWriteBlockWorkQueue.empty())
|
||||
{
|
||||
sortDirty = true;
|
||||
mSortedWriteBlockWorkQueue.insert(mSortedWriteBlockWorkQueue.begin(), mWriteBlockWorkQueue.begin(), mWriteBlockWorkQueue.end());
|
||||
mWriteBlockWorkQueue.clear();
|
||||
}
|
||||
mCritSect.Unlock();
|
||||
|
||||
BlMsfBlock* block = NULL;
|
||||
if (sortDirty)
|
||||
{
|
||||
std::sort(mSortedWriteBlockWorkQueue.begin(), mSortedWriteBlockWorkQueue.end(), [](BlMsfBlock* lhs, BlMsfBlock* rhs)
|
||||
{
|
||||
return lhs->mIdx < rhs->mIdx;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
BlMsfBlock* block = NULL;
|
||||
if (!mSortedWriteBlockWorkQueue.empty())
|
||||
{
|
||||
block = mSortedWriteBlockWorkQueue.front();
|
||||
mSortedWriteBlockWorkQueue.pop_front();
|
||||
}
|
||||
|
||||
if (block == NULL)
|
||||
{
|
||||
mWorkEvent.WaitFor();
|
||||
continue;
|
||||
}
|
||||
|
||||
mMsf->WriteBlock(block);
|
||||
}
|
||||
}
|
||||
|
||||
void BlMsfWorkThread::Add(BlMsfBlock* block)
|
||||
{
|
||||
AutoCrit autoCrit(mCritSect);
|
||||
mWriteBlockWorkQueue.push_back(block);
|
||||
mWorkEvent.Set();
|
||||
mSortDirty = true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
BlMsf::BlMsf()
|
||||
{
|
||||
mCodeView = NULL;
|
||||
mBlockSize = 0x1000;
|
||||
mFreePageBitmapIdx = 1;
|
||||
mFileSize = 0;
|
||||
mAllocatedFileSize = 0;
|
||||
|
||||
mWorkThread.mMsf = this;
|
||||
}
|
||||
|
||||
BlMsf::~BlMsf()
|
||||
{
|
||||
for (auto block : mBlocks)
|
||||
delete block->mData;
|
||||
}
|
||||
|
||||
void BlMsf::WriteBlock(BlMsfBlock* block)
|
||||
{
|
||||
if (mAllocatedFileSize > mFileSize)
|
||||
{
|
||||
mFS.SetSizeFast(mAllocatedFileSize);
|
||||
mFileSize = mAllocatedFileSize;
|
||||
}
|
||||
|
||||
int wantPos = block->mIdx * CV_BLOCK_SIZE;
|
||||
if (wantPos > mFileSize)
|
||||
{
|
||||
mFS.SetSizeFast(wantPos);
|
||||
mFileSize = wantPos;
|
||||
}
|
||||
|
||||
if (mFileSize == wantPos)
|
||||
mFileSize = wantPos + CV_BLOCK_SIZE;
|
||||
|
||||
mFS.SetPos(block->mIdx * CV_BLOCK_SIZE);
|
||||
mFS.Write(block->mData, CV_BLOCK_SIZE);
|
||||
delete block->mData;
|
||||
block->mData = NULL;
|
||||
}
|
||||
|
||||
bool BlMsf::Create(const StringImpl& fileName)
|
||||
{
|
||||
mFileName = fileName;
|
||||
//if (!mFS.Open(fileName, GENERIC_WRITE | GENERIC_READ))
|
||||
//return false;
|
||||
|
||||
if (!mFS.Open(fileName, BfpFileCreateKind_CreateAlways, (BfpFileCreateFlags)(BfpFileCreateFlag_Write | BfpFileCreateFlag_Read)))
|
||||
return false;
|
||||
|
||||
// Header
|
||||
Alloc(true, false);
|
||||
|
||||
// First FPM block
|
||||
Alloc(true, false);
|
||||
|
||||
// 'Old' FPM block
|
||||
Alloc(true, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int BlMsf::Alloc(bool clear, bool skipFPMBlock)
|
||||
{
|
||||
int blockIdx = (int)mBlocks.size();
|
||||
|
||||
BlMsfBlock* msfBlock = mBlocks.Alloc();
|
||||
msfBlock->mData = new uint8[CV_BLOCK_SIZE];
|
||||
if (clear)
|
||||
memset(msfBlock->mData, 0, CV_BLOCK_SIZE);
|
||||
msfBlock->mIdx = blockIdx;
|
||||
|
||||
if ((skipFPMBlock) && ((blockIdx % CV_BLOCK_SIZE) == mFreePageBitmapIdx))
|
||||
{
|
||||
// We need this page as a Free Page Bitmap. This will be triggered once for
|
||||
// every 16MB of PDB. It should be once every 128MB but isn't because of a
|
||||
// Microsoft bug in their initial implementation.
|
||||
return Alloc();
|
||||
}
|
||||
|
||||
mAllocatedFileSize = (int)(mBlocks.size() * CV_BLOCK_SIZE);
|
||||
return blockIdx;
|
||||
}
|
||||
|
||||
void BlMsf::FlushBlock(int blockIdx)
|
||||
{
|
||||
if (mWorkThread.mThread == NULL)
|
||||
mWorkThread.Start();
|
||||
mWorkThread.Add(mBlocks[blockIdx]);
|
||||
}
|
||||
|
||||
void BlMsf::Finish(int rootBlockNum, int streamDirLen)
|
||||
{
|
||||
mWorkThread.Stop();
|
||||
|
||||
int numBlocks = (int)mBlocks.size();
|
||||
|
||||
MemStream headerStream(mBlocks[0]->mData, CV_BLOCK_SIZE, false);
|
||||
headerStream.Write(MSF_SIGNATURE_700, 32);
|
||||
headerStream.Write((int32)CV_BLOCK_SIZE); // Page size
|
||||
headerStream.Write((int32)mFreePageBitmapIdx); // FreeBlockMapBlock - always use page 1. It's allowed to flip between 1 and 2.
|
||||
headerStream.Write((int32)numBlocks); // Total page count
|
||||
headerStream.Write((int32)streamDirLen);
|
||||
headerStream.Write((int32)0); // Unknown
|
||||
headerStream.Write((int32)rootBlockNum);
|
||||
|
||||
// Create Free Page Bitmap
|
||||
BfBitSet bitset;
|
||||
bitset.Init(numBlocks);
|
||||
int numBytes = (numBlocks + 7) / 8;
|
||||
memset(bitset.mBits, 0xFF, numBytes);
|
||||
for (int i = 0; i < numBlocks; i++)
|
||||
bitset.Clear(i);
|
||||
|
||||
// Bits are written in blocks at block nums (mFreePageBitmapIdx + k*CV_BLOCK_SIZE)
|
||||
// This is a little strange, but the actual mFreePageBitmapIdx block can only hold enough bits for
|
||||
// 128MB of pages, so PSBs over that size get spread at 'CV_BLOCK_SIZE' intervals. This is technically
|
||||
// wrong, as it should be 'CV_BLOCK_SIZE*8', but that's an Microsoft bug that can't be fixed now.
|
||||
uint8* data = (uint8*)bitset.mBits;
|
||||
int bytesLeft = numBytes;
|
||||
int curBlockNum = mFreePageBitmapIdx;
|
||||
while (bytesLeft > 0)
|
||||
{
|
||||
int writeBytes = std::min(bytesLeft, CV_BLOCK_SIZE);
|
||||
|
||||
uint8* dataDest = (uint8*)mBlocks[curBlockNum]->mData;
|
||||
memcpy(dataDest, data, writeBytes);
|
||||
bytesLeft -= writeBytes;
|
||||
data += writeBytes;
|
||||
|
||||
curBlockNum += CV_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
// Do actual write
|
||||
for (auto block : mBlocks)
|
||||
{
|
||||
if (block->mData != NULL)
|
||||
WriteBlock(block);
|
||||
}
|
||||
|
||||
mFS.Close();
|
||||
}
|
85
IDEHelper/Linker/BlMsf.h
Normal file
85
IDEHelper/Linker/BlMsf.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "BeefySysLib/FileStream.h"
|
||||
#include "BeefySysLib/util/CritSect.h"
|
||||
#include "BeefySysLib/util/WorkThread.h"
|
||||
#include "../Compiler/BfUtil.h"
|
||||
#include <queue>
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
struct BlMsfBlock
|
||||
{
|
||||
public:
|
||||
int mIdx;
|
||||
bool mIsUsed;
|
||||
void* mData;
|
||||
|
||||
public:
|
||||
BlMsfBlock()
|
||||
{
|
||||
mIdx = -1;
|
||||
mIsUsed = true;
|
||||
mData = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class BlCodeView;
|
||||
class BlMsf;
|
||||
|
||||
class BlMsfWorkThread : public WorkThread
|
||||
{
|
||||
public:
|
||||
BlMsf* mMsf;
|
||||
bool mDone;
|
||||
CritSect mCritSect;
|
||||
SyncEvent mWorkEvent;
|
||||
std::deque<BlMsfBlock*> mSortedWriteBlockWorkQueue;
|
||||
std::deque<BlMsfBlock*> mWriteBlockWorkQueue;
|
||||
bool mSortDirty;
|
||||
|
||||
|
||||
public:
|
||||
BlMsfWorkThread();
|
||||
~BlMsfWorkThread();
|
||||
|
||||
virtual void Stop() override;
|
||||
virtual void Run() override;
|
||||
|
||||
void Add(BlMsfBlock* block);
|
||||
};
|
||||
|
||||
class BlMsf
|
||||
{
|
||||
public:
|
||||
SysFileStream mFS;
|
||||
String mFileName;
|
||||
int mFileSize;
|
||||
int mAllocatedFileSize;
|
||||
|
||||
BlCodeView* mCodeView;
|
||||
int mBlockSize;
|
||||
|
||||
int mFreePageBitmapIdx; // Either 1 or 2
|
||||
|
||||
OwnedVector<BlMsfBlock> mBlocks;
|
||||
|
||||
BlMsfWorkThread mWorkThread;
|
||||
|
||||
public:
|
||||
void WriteBlock(BlMsfBlock* block);
|
||||
|
||||
public:
|
||||
BlMsf();
|
||||
~BlMsf();
|
||||
|
||||
bool Create(const StringImpl& fileName);
|
||||
|
||||
int Alloc(bool clear = true, bool skipFPMBlocks = true);
|
||||
void FlushBlock(int blockIdx);
|
||||
|
||||
void Finish(int rootBlockNum, int streamDirLen);
|
||||
};
|
||||
|
||||
NS_BF_END
|
322
IDEHelper/Linker/BlPdbParser.cpp
Normal file
322
IDEHelper/Linker/BlPdbParser.cpp
Normal file
|
@ -0,0 +1,322 @@
|
|||
#include "BlPdbParser.h"
|
||||
#include "BlContext.h"
|
||||
#include "codeview/cvinfo.h"
|
||||
#include "BlCvParser.h"
|
||||
#include "BlCvTypeSource.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
#define MSF_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"
|
||||
#define GET(T) *((T*)(data += sizeof(T)) - 1)
|
||||
#define GET_INTO(T, name) T name = GET(T)
|
||||
#define PTR_ALIGN(ptr, origPtr, alignSize) ptr = ( (origPtr)+( ((ptr - origPtr) + (alignSize - 1)) & ~(alignSize - 1) ) )
|
||||
|
||||
void BlPdbParser::Fail(const StringImpl& err)
|
||||
{
|
||||
BF_FATAL("Err");
|
||||
}
|
||||
|
||||
void BlPdbParser::NotImpl()
|
||||
{
|
||||
BF_FATAL("NotImpl");
|
||||
}
|
||||
|
||||
BlPdbParser::BlPdbParser()
|
||||
{
|
||||
mCvHeaderData = NULL;
|
||||
mCvTypeSectionData = NULL;
|
||||
mCvIPIData = NULL;
|
||||
mMappedFile = NULL;
|
||||
}
|
||||
|
||||
BlPdbParser::~BlPdbParser()
|
||||
{
|
||||
delete mCvHeaderData;
|
||||
delete mCvTypeSectionData;
|
||||
delete mCvIPIData;
|
||||
delete mMappedFile;
|
||||
}
|
||||
|
||||
bool BlPdbParser::Load(const StringImpl& fileName)
|
||||
{
|
||||
mMappedFile = new MappedFile();
|
||||
if (!mMappedFile->Open(fileName))
|
||||
return false;
|
||||
mData = (uint8*)mMappedFile->mData;
|
||||
|
||||
uint8* data = (uint8*)mMappedFile->mData;
|
||||
if (memcmp(data, MSF_SIGNATURE_700, 32) != 0)
|
||||
{
|
||||
Fail("PDB signature error");
|
||||
return false;
|
||||
}
|
||||
data += 32;
|
||||
|
||||
int pageSize = GET(int32);
|
||||
int fpmPageNum = GET(int32);
|
||||
int totalPageCount = GET(int32);
|
||||
int rootDirSize = GET(int32);
|
||||
int unknown = GET(int32);
|
||||
int rootDirPtr = GET(int32);
|
||||
|
||||
bool failed = false;
|
||||
|
||||
mCvPageSize = pageSize;
|
||||
|
||||
int rootPageCount = (rootDirSize + pageSize - 1) / pageSize;
|
||||
int rootPointersPages = (rootPageCount * sizeof(int32) + pageSize - 1) / pageSize;
|
||||
int rootPageIdx = 0;
|
||||
|
||||
std::vector<uint8> rootDirData;
|
||||
rootDirData.resize(rootPageCount * pageSize);
|
||||
data = mData + (rootDirPtr * pageSize);
|
||||
|
||||
int32* rootPages = (int32*)data;
|
||||
for (int subRootPageIdx = 0; subRootPageIdx < pageSize / 4; subRootPageIdx++, rootPageIdx++)
|
||||
{
|
||||
if (rootPageIdx >= rootPageCount)
|
||||
break;
|
||||
|
||||
int rootPagePtr = rootPages[subRootPageIdx];
|
||||
if (rootPagePtr == 0)
|
||||
break;
|
||||
data = mData + (rootPagePtr * pageSize);
|
||||
memcpy(&rootDirData[rootPageIdx * pageSize], data, pageSize);
|
||||
data += pageSize;
|
||||
}
|
||||
|
||||
if (!ParseCv(&rootDirData[0]))
|
||||
{
|
||||
Fail("Failed to parse PDB");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlPdbParser::CvParseHeader()
|
||||
{
|
||||
uint8* data = CvReadStream(1);
|
||||
mCvHeaderData = data;
|
||||
|
||||
int32 pdbVersion = GET(int32);
|
||||
int32 timestamp = GET(int32);
|
||||
int32 pdbAge = GET(int32);
|
||||
int8 pdbGuid[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
pdbGuid[i] = GET(int8);
|
||||
|
||||
/*if ((wantAge != -1) &&
|
||||
((pdbAge != wantAge) || (memcmp(pdbGuid, wantGuid, 16) != 0)))
|
||||
{
|
||||
String msg = "PDB version did not match requested version\n";
|
||||
|
||||
msg += StrFormat(" Age: %d Module GUID: ", wantAge);
|
||||
for (int i = 0; i < 16; i++)
|
||||
msg += StrFormat("%02X", (uint8)wantGuid[i]);
|
||||
msg += "\n";
|
||||
|
||||
msg += StrFormat(" Age: %d PDB GUID : ", pdbAge);
|
||||
for (int i = 0; i < 16; i++)
|
||||
msg += StrFormat("%02X", (uint8)pdbGuid[i]);
|
||||
msg += "\n";
|
||||
|
||||
mDebugger->OutputMessage(msg);
|
||||
return false;
|
||||
}*/
|
||||
|
||||
int nameTableIdx = -1;
|
||||
|
||||
GET_INTO(int32, strTabLen);
|
||||
const char* strTab = (const char*)data;
|
||||
data += strTabLen;
|
||||
|
||||
GET_INTO(int32, numStrItems);
|
||||
GET_INTO(int32, strItemMax);
|
||||
|
||||
GET_INTO(int32, usedLen);
|
||||
data += usedLen * sizeof(int32);
|
||||
GET_INTO(int32, deletedLen);
|
||||
data += deletedLen * sizeof(int32);
|
||||
|
||||
for (int tableIdx = 0; tableIdx < numStrItems; tableIdx++)
|
||||
{
|
||||
GET_INTO(int32, strOfs);
|
||||
GET_INTO(int32, streamNum);
|
||||
|
||||
const char* tableName = strTab + strOfs;
|
||||
if (strcmp(tableName, "/names") == 0)
|
||||
mStringTable.mStream = streamNum;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8* BlPdbParser::CvReadStream(int streamIdx, int* outSize)
|
||||
{
|
||||
int streamSize = mCvStreamSizes[streamIdx];
|
||||
if (outSize != NULL)
|
||||
*outSize = streamSize;
|
||||
if (streamSize <= 0)
|
||||
return NULL;
|
||||
int streamPageCount = (streamSize + mCvPageSize - 1) / mCvPageSize;
|
||||
|
||||
uint8* sectionData = new uint8[streamSize];
|
||||
bool deferDeleteSectionData = false;
|
||||
|
||||
int streamPtrIdx = mCvStreamPtrStartIdxs[streamIdx];
|
||||
for (int streamPageIdx = 0; streamPageIdx < streamPageCount; streamPageIdx++)
|
||||
{
|
||||
uint8* data = mData + (mCvStreamPtrs[streamPtrIdx] * mCvPageSize);
|
||||
memcpy(sectionData + streamPageIdx * mCvPageSize, data, std::min(streamSize - (streamPageIdx * mCvPageSize), mCvPageSize));
|
||||
streamPtrIdx++;
|
||||
}
|
||||
|
||||
return sectionData;
|
||||
}
|
||||
|
||||
bool BlPdbParser::ParseCv(uint8* rootDirData)
|
||||
{
|
||||
uint8* data = rootDirData;
|
||||
|
||||
bool failed = false;
|
||||
int numStreams = GET(int32);
|
||||
if (numStreams == 0)
|
||||
return true;
|
||||
|
||||
mCvStreamSizes.resize(numStreams);
|
||||
mCvStreamPtrStartIdxs.resize(numStreams);
|
||||
|
||||
int streamPages = 0;
|
||||
for (int i = 0; i < (int)mCvStreamSizes.size(); i++)
|
||||
mCvStreamSizes[i] = GET(int32);
|
||||
for (int streamIdx = 0; streamIdx < numStreams; streamIdx++)
|
||||
{
|
||||
mCvStreamPtrStartIdxs[streamIdx] = streamPages;
|
||||
if (mCvStreamSizes[streamIdx] > 0)
|
||||
streamPages += (mCvStreamSizes[streamIdx] + mCvPageSize - 1) / mCvPageSize;
|
||||
}
|
||||
mCvStreamPtrs.resize(streamPages);
|
||||
for (int i = 0; i < (int)mCvStreamPtrs.size(); i++)
|
||||
mCvStreamPtrs[i] = GET(int32);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (!CvParseHeader())
|
||||
return false;
|
||||
|
||||
ParseTypeData();
|
||||
ParseIPIData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BlPdbParser::ParseTypeData()
|
||||
{
|
||||
int sectionSize = 0;
|
||||
mCvTypeSectionData = CvReadStream(2, §ionSize);
|
||||
uint8* data = mCvTypeSectionData;
|
||||
uint8* sectionData = mCvTypeSectionData;
|
||||
|
||||
int32 ver = GET(int32);
|
||||
int32 headerSize = GET(int32);
|
||||
int32 minVal = GET(int32);
|
||||
int32 maxVal = GET(int32);
|
||||
int32 followSize = GET(int32);
|
||||
|
||||
int16 hashStream = GET(int16);
|
||||
int16 hashStreamPadding = GET(int16);
|
||||
int32 hashKey = GET(int32);
|
||||
int32 hashBucketsSize = GET(int32);
|
||||
int32 hashValsOffset = GET(int32);
|
||||
int32 hashValsSize = GET(int32);
|
||||
int32 hashTypeInfoOffset = GET(int32);
|
||||
int32 hashTypeInfoSize = GET(int32);
|
||||
int32 hashAdjOffset = GET(int32);
|
||||
int32 hashAdjSize = GET(int32);
|
||||
|
||||
mTypeSource->mTPI.mCvMinTag = minVal;
|
||||
mTypeSource->mTPI.mCvMaxTag = maxVal;
|
||||
//mCvTypeMap.clear();
|
||||
//mTypeSource->mTPI.mCvTagStartMap.clear();
|
||||
//mCvTypeMap.resize(maxVal - minVal);
|
||||
mTypeSource->mTPI.mCvTagStartMap.resize(maxVal - minVal);
|
||||
|
||||
//DbgDataMap dataMap(minVal, maxVal);
|
||||
|
||||
mTypeSource->mTPI.mSectionData = data;
|
||||
mTypeSource->mTPI.mSectionSize = sectionSize - (int)(data - sectionData);
|
||||
mTypeSource->mTPI.ScanTypeData();
|
||||
mTypeSource->mTPI.ParseTypeData();
|
||||
|
||||
if (hashAdjSize > 0)
|
||||
{
|
||||
int sectionSize = 0;
|
||||
uint8* data = CvReadStream(hashStream, §ionSize);
|
||||
uint8* sectionData = data;
|
||||
|
||||
data = sectionData + hashAdjOffset;
|
||||
|
||||
GET_INTO(int32, adjustCount);
|
||||
GET_INTO(int32, unk0);
|
||||
GET_INTO(int32, unkCount);
|
||||
for (int i = 0; i < unkCount; i++)
|
||||
{
|
||||
GET_INTO(int32, unk2);
|
||||
}
|
||||
GET_INTO(int32, unkCount2);
|
||||
for (int i = 0; i < unkCount2; i++)
|
||||
{
|
||||
GET_INTO(int32, unk3);
|
||||
}
|
||||
|
||||
// Types listed in the adjustment table are always primary types,
|
||||
// they should override any "old types" with the same name
|
||||
for (int adjIdx = 0; adjIdx < adjustCount; adjIdx++)
|
||||
{
|
||||
GET_INTO(int32, adjVal);
|
||||
GET_INTO(CV_typ_t, typeId);
|
||||
}
|
||||
|
||||
delete[] sectionData;
|
||||
}
|
||||
}
|
||||
|
||||
void BlPdbParser::ParseIPIData()
|
||||
{
|
||||
int sectionSize = 0;
|
||||
mCvIPIData = CvReadStream(4, §ionSize);
|
||||
uint8* data = mCvIPIData;
|
||||
uint8* sectionData = data;
|
||||
|
||||
int32 ver = GET(int32);
|
||||
int32 headerSize = GET(int32);
|
||||
int32 minVal = GET(int32);
|
||||
int32 maxVal = GET(int32);
|
||||
int32 followSize = GET(int32);
|
||||
|
||||
int16 hashStream = GET(int16);
|
||||
int16 hashStreamPadding = GET(int16);
|
||||
int32 hashKey = GET(int32);
|
||||
int32 hashBucketsSize = GET(int32);
|
||||
int32 hashValsOffset = GET(int32);
|
||||
int32 hashValsSize = GET(int32);
|
||||
int32 hashTypeInfoOffset = GET(int32);
|
||||
int32 hashTypeInfoSize = GET(int32);
|
||||
int32 hashAdjOffset = GET(int32);
|
||||
int32 hashAdjSize = GET(int32);
|
||||
|
||||
mTypeSource->CreateIPI();
|
||||
mTypeSource->mIPI->mCvMinTag = minVal;
|
||||
mTypeSource->mIPI->mCvMaxTag = maxVal;
|
||||
int recordCount = maxVal - minVal;
|
||||
mTypeSource->mIPI->mCvTagStartMap.resize(recordCount);
|
||||
|
||||
int typeDataSize = sectionSize - (int)(data - sectionData);
|
||||
mTypeSource->mIPI->mSectionData = data;
|
||||
mTypeSource->mIPI->mSectionSize = typeDataSize;
|
||||
mTypeSource->mIPI->ScanTypeData();
|
||||
mTypeSource->mIPI->ParseTypeData();
|
||||
}
|
||||
|
65
IDEHelper/Linker/BlPdbParser.h
Normal file
65
IDEHelper/Linker/BlPdbParser.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include "BeefySysLib/FileStream.h"
|
||||
#include "BeefySysLib/util/BumpAllocator.h"
|
||||
#include "BeefySysLib/util/Hash.h"
|
||||
#include "../Compiler/BfUtil.h"
|
||||
#include <unordered_map>
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
struct BlCvStringTable
|
||||
{
|
||||
int mStream;
|
||||
int mStreamOffset;
|
||||
const char* mStrTable;
|
||||
|
||||
BlCvStringTable()
|
||||
{
|
||||
mStream = -1;
|
||||
mStreamOffset = 0;
|
||||
mStrTable = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class MappedFile;
|
||||
class BlCvTypeSource;
|
||||
|
||||
class BlPdbParser
|
||||
{
|
||||
public:
|
||||
String mFileName;
|
||||
MappedFile* mMappedFile;
|
||||
uint8* mData;
|
||||
int mCvPageSize;
|
||||
BlCvStringTable mStringTable;
|
||||
|
||||
std::vector<int32> mCvStreamSizes;
|
||||
std::vector<int32> mCvStreamPtrStartIdxs;
|
||||
std::vector<int32> mCvStreamPtrs;
|
||||
std::vector<int> mCvIPITagStartMap;
|
||||
|
||||
uint8* mCvHeaderData;
|
||||
uint8* mCvTypeSectionData;
|
||||
uint8* mCvIPIData;
|
||||
BlCvTypeSource* mTypeSource;
|
||||
|
||||
public:
|
||||
void Fail(const StringImpl& err);
|
||||
void NotImpl();
|
||||
|
||||
uint8* CvReadStream(int streamIdx, int* outSize = NULL);
|
||||
bool CvParseHeader();
|
||||
void ParseTypeData();
|
||||
void ParseIPIData();
|
||||
|
||||
public:
|
||||
BlPdbParser();
|
||||
~BlPdbParser();
|
||||
|
||||
bool Load(const StringImpl& fileName);
|
||||
bool ParseCv(uint8 * rootDirData);
|
||||
};
|
||||
|
||||
NS_BF_END
|
36
IDEHelper/Linker/BlSymTable.cpp
Normal file
36
IDEHelper/Linker/BlSymTable.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "BlSymTable.h"
|
||||
#include "BlContext.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
BlSymTable::BlSymTable()
|
||||
{
|
||||
#ifdef BL_USE_DENSEMAP_SYMTAB
|
||||
mMap.set_empty_key(Val128(-1));
|
||||
//mMap.set_empty_key("");
|
||||
mMap.min_load_factor(0);
|
||||
mMap.resize(100000);
|
||||
#endif
|
||||
}
|
||||
|
||||
BlSymbol* BlSymTable::Add(const char* name, bool* isNew)
|
||||
{
|
||||
Val128 val128 = Hash128(name, (int)strlen(name));
|
||||
auto itr = mMap.insert(std::make_pair(val128, (BlSymbol*)NULL));
|
||||
if (!itr.second)
|
||||
{
|
||||
if (isNew != NULL)
|
||||
*isNew = false;
|
||||
return itr.first->second;
|
||||
}
|
||||
|
||||
if (isNew != NULL)
|
||||
*isNew = true;
|
||||
auto blSymbol = new BlSymbol();
|
||||
itr.first->second = blSymbol;
|
||||
blSymbol->mName = name;
|
||||
blSymbol->mKind = BlSymKind_Undefined;
|
||||
blSymbol->mObjectDataIdx = -1;
|
||||
return blSymbol;
|
||||
}
|
||||
|
36
IDEHelper/Linker/BlSymTable.h
Normal file
36
IDEHelper/Linker/BlSymTable.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Beef/BfCommon.h"
|
||||
#include <unordered_map>
|
||||
#include "BeefySysLib/util/Hash.h"
|
||||
|
||||
//#define BL_USE_DENSEMAP_SYMTAB
|
||||
|
||||
#ifdef BL_USE_DENSEMAP_SYMTAB
|
||||
#include <sparsehash/dense_hash_map>
|
||||
#include <sparsehash/dense_hash_set>
|
||||
#endif
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
class BlContext;
|
||||
class BlSymbol;
|
||||
|
||||
class BlSymTable
|
||||
{
|
||||
public:
|
||||
BlContext* mContext;
|
||||
#ifdef BL_USE_DENSEMAP_SYMTAB
|
||||
google::dense_hash_map<Val128, BlSymbol*, Val128::Hash, Val128::Equals> mMap;
|
||||
#else
|
||||
std::unordered_map<Val128, BlSymbol*, Val128::Hash, Val128::Equals> mMap;
|
||||
#endif
|
||||
|
||||
public:
|
||||
BlSymTable();
|
||||
|
||||
BlSymbol* Add(const char* name, bool* isNew = NULL);
|
||||
};
|
||||
|
||||
NS_BF_END
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue