mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
572 lines
10 KiB
C++
572 lines
10 KiB
C++
#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
|