1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Working on installer, fixing more Win32 issues

Throwing error on member references with ".." cascade token outside invocations (ie: "ts..mA = 123")
Fixed 'Thread.ModuleTLSIndex' error - which caused us TLS lookup failures in Beef DLLs
Fixed some hotswap errors
Made BeefPerf shut down properly
Fixed an 'int literal' FixIntUnknown issue where rhs was System.Object which caused an illegal boxing
Fixed COFF::LocateSymbol issues with Win32 and also with linking to static libraries - showed up with hot-linking in fmod when hot-adding a floating point mod
Fixed a couple memory leaks
Fixed alignment issue in COFF::ParseCompileUnit
This commit is contained in:
Brian Fiete 2019-09-02 17:39:47 -07:00
parent aad0a640c5
commit b63a243fd7
73 changed files with 2474 additions and 293 deletions

View file

@ -70,6 +70,11 @@ public:
mNextWithSameName = NULL;
}
~BeLibEntry()
{
delete mNextWithSameName;
}
void AddSymbol(const StringImpl& sym);
};

View file

@ -236,9 +236,7 @@ COFF::COFF(DebugTarget* debugTarget) : DbgModule(debugTarget)
mCvPageBits = 31;
mCvDataStream = NULL;
mCvHeaderData = NULL;
mCvStrTableData = NULL;
mCvTypeSectionData = NULL;
mCvTypeSectionDataSize = -1;
mCvStrTableData = NULL;
mCvPublicSymbolData = NULL;
mCvGlobalSymbolData = NULL;
mNewFPOData = NULL;
@ -251,10 +249,7 @@ COFF::COFF(DebugTarget* debugTarget) : DbgModule(debugTarget)
mCvMappedViewOfFile = NULL;
mCvMappedFileSize = 0;
//mParsedProcRecs = false;
mCvCompileUnitData = NULL;
mCvCompileUnitDataSize = 0;
mGlobalsTargetType = NULL;
mPrevScanName = NULL;
mProcSymCount = 0;
@ -273,7 +268,7 @@ COFF::~COFF()
{
BF_ASSERT(mTempBufIdx == 0);
ClosePDB();
mDebugger->mDbgSymSrv.ReleaseRequest(mDbgSymRequest);
mDebugger->mDbgSymSrv.ReleaseRequest(mDbgSymRequest);
}
const char* COFF::CvCheckTargetMatch(const char* name, bool& wasBeef)
@ -3209,7 +3204,7 @@ void COFF::ParseCompileUnit_Symbols(DbgCompileUnit* compileUnit, uint8* sectionD
_FlushDeferredVariableLocations();
}
CvCompileUnit* COFF::ParseCompileUnit(CvModuleInfo* moduleInfo, uint8* sectionData, int sectionSize)
CvCompileUnit* COFF::ParseCompileUnit(CvModuleInfo* moduleInfo, CvCompileUnit* compileUnit, uint8* sectionData, int sectionSize)
{
BP_ZONE("COFF::ParseCompileUnit");
@ -3227,7 +3222,11 @@ CvCompileUnit* COFF::ParseCompileUnit(CvModuleInfo* moduleInfo, uint8* sectionDa
int allocSizeStart = mAlloc.GetAllocSize();
CvCompileUnit* compileUnit = new CvCompileUnit(this);
if (compileUnit == NULL)
{
compileUnit = new CvCompileUnit(this);
mCompileUnits.push_back(compileUnit);
}
compileUnit->mDbgModule = this;
if (moduleInfo != NULL)
{
@ -3239,8 +3238,7 @@ CvCompileUnit* COFF::ParseCompileUnit(CvModuleInfo* moduleInfo, uint8* sectionDa
{
compileUnit->mModuleIdx = NULL;
compileUnit->mName = mFilePath.c_str();
}
mCompileUnits.push_back(compileUnit);
}
uint8* data = sectionData;
uint8* dataEnd = NULL;
@ -3373,9 +3371,11 @@ CvCompileUnit* COFF::ParseCompileUnit(CvModuleInfo* moduleInfo, uint8* sectionDa
data = debugSubSectionsStart;
dataEnd = data + taggedSize;
while (data < dataEnd)
while (true)
{
PTR_ALIGN(data, sectionData, 4);
if (data >= dataEnd)
break;
GET_INTO(int32, lineInfoType);
GET_INTO(int32, lineInfoLength);
uint8* dataStart = data;
@ -3895,7 +3895,7 @@ CvCompileUnit* COFF::ParseCompileUnit(int compileUnitId)
int sectionSize = 0;
uint8* sectionData = CvReadStream(moduleInfo->mStream, &sectionSize);
ParseCompileUnit(moduleInfo, sectionData, sectionSize);
ParseCompileUnit(moduleInfo, NULL, sectionData, sectionSize);
delete sectionData;
return moduleInfo->mCompileUnit;
}
@ -5641,10 +5641,10 @@ void COFF::ReportMemory(MemReporter* memReporter)
if (mCvHeaderData != NULL)
memReporter->Add("mCvHeaderData", mCvStreamSizes[1]);
if (mCvTypeSectionData != NULL)
for (auto& entry : mCvTypeSectionData)
{
if (mCvTypeSectionDataSize != -1)
memReporter->Add("mCvTypeSectionData", mCvTypeSectionDataSize);
if (entry.mSize != -1)
memReporter->Add("mCvTypeSectionData", entry.mSize);
else
memReporter->Add("mCvTypeSectionData", mCvStreamSizes[2]);
}
@ -5784,10 +5784,12 @@ void COFF::ClosePDB()
mCvHeaderData = NULL;
delete mCvStrTableData;
mCvStrTableData = NULL;
delete mCvTypeSectionData;
mCvTypeSectionData = NULL;
delete mCvCompileUnitData;
mCvCompileUnitData = NULL;
for (auto& entry : mCvTypeSectionData)
delete entry.mData;
mCvTypeSectionData.Clear();
for (auto& entry : mCvCompileUnitData)
delete entry.mData;
mCvCompileUnitData.Clear();
delete mCvPublicSymbolData;
mCvPublicSymbolData = NULL;
delete mCvGlobalSymbolData;
@ -5806,7 +5808,8 @@ void COFF::ClosePDB()
for (auto kv : mHotLibMap)
delete kv.mValue;
mHotLibMap.Clear();
mHotLibMap.Clear();
mHotLibSymMap.Clear();
}
bool COFF::LoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge)
@ -5883,15 +5886,19 @@ bool COFF::CheckSection(const char* name, uint8* sectionData, int sectionSize)
if (strcmp(name, ".debug$T") == 0)
{
mDbgFlavor = DbgFlavor_MS;
mCvTypeSectionData = sectionData;
mCvTypeSectionDataSize = sectionSize;
DbgSectionData entry;
entry.mData = sectionData;
entry.mSize = sectionSize;
mCvTypeSectionData.Add(entry);
return true;
}
if (strcmp(name, ".debug$S") == 0)
{
mCvCompileUnitData = sectionData;
mCvCompileUnitDataSize = sectionSize;
{
DbgSectionData entry;
entry.mData = sectionData;
entry.mSize = sectionSize;
mCvCompileUnitData.Add(entry);
return true;
}
@ -5902,20 +5909,23 @@ void COFF::ProcessDebugInfo()
{
BP_ZONE("COFF::ProcessDebugInfo");
if ((mCvTypeSectionDataSize > 0) && (mCvCompileUnitDataSize > 0))
if ((!mCvTypeSectionData.IsEmpty()) && (!mCvCompileUnitData.IsEmpty()))
{
auto linkedModule = (COFF*)GetLinkedModule();
int startingTypeIdx = (int)linkedModule->mTypes.size();
InitCvTypes();
uint8* data = mCvTypeSectionData;
GET_INTO(uint32, infoType);
BF_ASSERT(infoType == CV_SIGNATURE_C13);
for (auto entry : mCvTypeSectionData)
{
uint8* data = entry.mData;
GET_INTO(uint32, infoType);
BF_ASSERT(infoType == CV_SIGNATURE_C13);
CvInitStreamRaw(mCvTypeSectionReader, mCvTypeSectionData + 4, mCvTypeSectionDataSize - 4);
//ParseTypeData(data, mCvTypeSectionDataSize - sizeof(uint32));
ParseTypeData(mCvTypeSectionReader, 0);
CvInitStreamRaw(mCvTypeSectionReader, entry.mData + 4, entry.mSize - 4);
//ParseTypeData(data, mCvTypeSectionDataSize - sizeof(uint32));
ParseTypeData(mCvTypeSectionReader, 0);
}
FixTypes(startingTypeIdx);
linkedModule->MapTypes(startingTypeIdx);
@ -5930,7 +5940,11 @@ void COFF::ProcessDebugInfo()
}
}*/
auto compileUnit = ParseCompileUnit(NULL, mCvCompileUnitData, mCvCompileUnitDataSize);
CvCompileUnit* compileUnit = NULL;
for (auto entry : mCvCompileUnitData)
{
compileUnit = ParseCompileUnit(NULL, compileUnit, entry.mData, entry.mSize);
}
compileUnit->mLanguage = DbgLanguage_Beef;
mMasterCompileUnit->mLanguage = DbgLanguage_Beef;
MapCompileUnitMethods(compileUnit);
@ -6538,6 +6552,12 @@ addr_target COFF::LocateSymbol(const StringImpl& name)
{
for (auto sym : libEntry->mSymbols)
{
#ifdef BF_DBG_32
if (sym.StartsWith('_'))
mHotLibSymMap[sym.Substring(1)] = libEntry;
else
// Fallthrough
#endif
mHotLibSymMap[sym] = libEntry;
}
libEntry = libEntry->mNextWithSameName;
@ -6626,15 +6646,27 @@ addr_target COFF::LocateSymbol(const StringImpl& name)
return 0;
}
BfLogDbg("Loading obj '%s' in '%s'\n", libEntry->mName.c_str(), libEntry->mLibFile->mFilePath.c_str());
// #ifdef _DEBUG
// FILE* fpTest = fopen("c:\\temp\\locateSym.obj", "wb");
//
// uint8* data = new uint8[libEntry->mLength];
//
// fseek(libEntry->mLibFile->mOldFileStream.mFP, libEntry->mOldDataPos + sizeof(BeLibMemberHeader), SEEK_SET);
// fread(data, 1, libEntry->mLength, libEntry->mLibFile->mOldFileStream.mFP);
// fwrite(data, 1, libEntry->mLength, fpTest);
// fclose(fpTest);
// delete data;
// #endif
FileSubStream fileStream;
fileStream.mFP = libEntry->mLibFile->mOldFileStream.mFP;
fileStream.mOffset = libEntry->mOldDataPos + sizeof(BeLibMemberHeader);
fileStream.mSize = libEntry->mLength;
fileStream.SetPos(0);
DbgModule* dbgModule = new COFF(mDebugger->mDebugTarget);
dbgModule->mHotIdx = mDebugger->mActiveHotIdx;
dbgModule->mFilePath = libEntry->mName + "@" + libEntry->mLibFile->mFilePath;
@ -6789,21 +6821,21 @@ void COFF::ParseFrameDescriptors()
}
NS_BF_DBG_BEGIN
void TestCoff(void* tdata, int tdataSize, void* cuData, int cuDataSize)
{
DebugTarget* debugTarget = new DebugTarget(NULL);
{
COFF coff(debugTarget);
coff.mCvTypeSectionData = (uint8*)tdata;
coff.mCvTypeSectionDataSize = tdataSize;
coff.mCvCompileUnitData = (uint8*)cuData;
coff.mCvCompileUnitDataSize = cuDataSize;
coff.ProcessDebugInfo();
}
delete debugTarget;
}
// void TestCoff(void* tdata, int tdataSize, void* cuData, int cuDataSize)
// {
// DebugTarget* debugTarget = new DebugTarget(NULL);
// {
// COFF coff(debugTarget);
// coff.mCvTypeSectionData = (uint8*)tdata;
// coff.mCvTypeSectionDataSize = tdataSize;
//
// coff.mCvCompileUnitData = (uint8*)cuData;
// coff.mCvCompileUnitDataSize = cuDataSize;
//
// coff.ProcessDebugInfo();
// }
// delete debugTarget;
// }
void TestPDB(const String& fileName)
{

View file

@ -202,6 +202,7 @@ public:
Dictionary<String, BeLibEntry*> mSymDict;
};
class COFF : public DbgModule
{
public:
@ -247,8 +248,8 @@ public:
SafeMemStream* mCvDataStream;
CvStringTable mStringTable;
uint8* mCvHeaderData;
uint8* mCvTypeSectionData;
uint8* mCvHeaderData;
//uint8* mCvTypeSectionData
uint8* mCvStrTableData;
uint8* mCvPublicSymbolData;
uint8* mCvGlobalSymbolData;
@ -270,9 +271,11 @@ public:
const char* mPrevScanName;
// For hot data
int mCvTypeSectionDataSize;
uint8* mCvCompileUnitData;
int mCvCompileUnitDataSize;
Array<DbgSectionData> mCvTypeSectionData;
Array<DbgSectionData> mCvCompileUnitData;
//int mCvTypeSectionDataSize;
//uint8* mCvCompileUnitData;
//int mCvCompileUnitDataSize;
HANDLE mCvMappedFile;
void* mCvMappedViewOfFile;
@ -292,7 +295,7 @@ public:
void ParseTypeData(int sectionNum, CvStreamReader& reader, int& sectionSize, int& dataOfs, int& hashStream, int& hashAdjOffset, int& hashAdjSize, int& minVal, int& maxVal);
virtual void ParseTypeData() override;
void ParseCompileUnit_Symbols(DbgCompileUnit* compileUnit, uint8* sectionData, uint8* data, uint8* dataEnd, CvInlineInfoVec& inlineDataVec, bool deferInternals, DbgSubprogram* useSubprogram);
CvCompileUnit* ParseCompileUnit(CvModuleInfo* moduleInfo, uint8* sectionData, int sectionSize);
CvCompileUnit* ParseCompileUnit(CvModuleInfo* moduleInfo, CvCompileUnit* compileUnit, uint8* sectionData, int sectionSize);
virtual CvCompileUnit* ParseCompileUnit(int compileUnitId) override;
virtual void MapCompileUnitMethods(DbgCompileUnit* compileUnit) override;
virtual void MapCompileUnitMethods(int compileUnitId) override;

View file

@ -5049,12 +5049,7 @@ void BfCompiler::HotResolve_ReportType(BfHotTypeVersion* hotTypeVersion, HotType
bool applyFlags = true;
if ((flags & (BfCompiler::HotTypeFlag_ActiveFunction | BfCompiler::HotTypeFlag_Delegate | BfCompiler::HotTypeFlag_FuncPtr)) != 0)
{
// These flags only get applied if we detect we're using an old version
// auto hotTypeData = mContext->GetHotTypeData(hotTypeVersion->mTypeId);
// auto latestTypeVersion = hotTypeData->GetLatestVersion();
// applyFlags = hotTypeVersion->mDataHash != latestTypeVersion->mDataHash;
{
applyFlags = (hotTypeVersion->mCommittedHotCompileIdx != -1) && (mHotState->mPendingDataChanges.Contains(hotTypeVersion->mTypeId));
if ((!applyFlags) && (hotTypeVersion->mCommittedHotCompileIdx != -1))
@ -5074,12 +5069,9 @@ void BfCompiler::HotResolve_ReportType(BfHotTypeVersion* hotTypeVersion, HotType
BfLogSysM("HotResolve_ReportType %p %s Flags:%X DeclHotIdx:%d\n", hotTypeVersion, mContext->TypeIdToString(hotTypeVersion->mTypeId).c_str(), flags, hotTypeVersion->mDeclHotCompileIdx);
//if ((flags & (BfCompiler::HotTypeFlag_Heap | BfCompiler::HotTypeFlag_Delegate | BfCompiler::HotTypeFlag_CanAllocate)) != 0)
for (auto member : hotTypeVersion->mMembers)
{
for (auto member : hotTypeVersion->mMembers)
{
HotResolve_ReportType(member, flags, reason);
}
HotResolve_ReportType(member, flags, reason);
}
}
@ -5465,6 +5457,8 @@ void BfCompiler::ClearOldHotData()
if (typeInst->mHotTypeData == NULL)
continue;
bool foundCommittedVersion = false;
auto latestVersionHead = typeInst->mHotTypeData->GetLatestVersionHead();
for (int typeIdx = (int)typeInst->mHotTypeData->mTypeVersions.size() - 1; typeIdx >= 0; typeIdx--)
{
@ -5475,8 +5469,13 @@ void BfCompiler::ClearOldHotData()
continue;
}
if (hotVersion->mRefCount == 1)
{
if ((!foundCommittedVersion) && (mHotState != NULL) && (hotVersion->mDeclHotCompileIdx <= mHotState->mCommittedHotCompileIdx))
{
// Don't remove the latest committed version
foundCommittedVersion = true;
}
else if (hotVersion->mRefCount == 1)
{
typeInst->mHotTypeData->mTypeVersions.RemoveAt(typeIdx);
hotVersion->Deref();
BF_ASSERT(typeInst->mHotTypeData->mTypeVersions.size() > 0);

View file

@ -14503,9 +14503,7 @@ void BfModule::CallChainedMethods(BfMethodInstance* methodInstance, bool reverse
}
void BfModule::AddHotDataReferences(BfHotDataReferenceBuilder* builder)
{
//auto methodName = MethodToString(mCurMethodInstance, BfMethodNameFlag_OmitTypeName);
{
BF_ASSERT(mCurMethodInstance->mIsReified);
if (mCurTypeInstance->mHotTypeData == NULL)
@ -14519,8 +14517,6 @@ void BfModule::AddHotDataReferences(BfHotDataReferenceBuilder* builder)
}
BF_ASSERT(hotMethod->mSrcTypeVersion != NULL);
//hotMethod->mSrcTypeVersion = mCurTypeInstance->mHotTypeData->GetLatestVersion();
//hotMethod->mSrcTypeVersion->mRefCount++;
int prevSize = (int)hotMethod->mReferences.size();
int refCount = (int)(prevSize + builder->mUsedData.size() + builder->mCalledMethods.size() + builder->mDevirtualizedCalledMethods.size());
@ -17167,14 +17163,6 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
else if (wantsRemoveBody)
mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
//TODO: Can we actually do this?
/*if ((!HasCompiledOutput()) && (!mCompiler->mOptions.mExtraResolveChecks))
{
mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
mBfIRBuilder->Func_EraseFromParent(mCurMethodInstance->mIRFunction);
mCurMethodInstance->mIRFunction = BfIRFunction();
}*/
// We don't want to hold on to pointers to LLVMFunctions of unspecialized types.
// This allows us to delete the mScratchModule LLVM module without rebuilding all
// unspecialized types

View file

@ -4536,7 +4536,7 @@ void BfModule::FixIntUnknown(BfTypedValue& typedVal)
void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs)
{
if ((lhs.mType != NULL) && (lhs.mType->IsIntUnknown()))
if ((lhs.mType != NULL) && (lhs.mType->IsIntUnknown()) && (rhs.mType != NULL) && (rhs.mType->IsInteger()))
{
if (CanImplicitlyCast(lhs, rhs.mType))
{
@ -4547,7 +4547,7 @@ void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs)
}
}
if ((rhs.mType != NULL) && (rhs.mType->IsIntUnknown()))
if ((rhs.mType != NULL) && (rhs.mType->IsIntUnknown()) && (lhs.mType != NULL) && (lhs.mType->IsInteger()))
{
if (CanImplicitlyCast(rhs, lhs.mType))
{

View file

@ -1121,6 +1121,9 @@ bool DbgExprEvaluator::TypeIsSubTypeOf(DbgType* srcType, DbgType* wantType, int*
DbgTypedValue DbgExprEvaluator::GetBeefTypeById(int typeId)
{
if (mDebugTarget->mTargetBinary == NULL)
return DbgTypedValue();
auto typeTypeEntry = mDebugTarget->mTargetBinary->FindType("System.Type", DbgLanguage_Beef);
if ((typeTypeEntry == NULL) || (typeTypeEntry->mValue == NULL))
return DbgTypedValue();
@ -3433,9 +3436,11 @@ DbgTypedValue DbgExprEvaluator::LookupIdentifier(BfAstNode* identifierNode, bool
else if (findName == "$ThreadName")
return GetString(mDebugger->mActiveThread->mName);
else if (findName == "$TargetName")
return GetString(GetFileName(mDebugTarget->mTargetBinary->mFilePath));
return GetString(GetFileName(mDebugTarget->mTargetPath));
else if (findName == "LaunchName")
return GetString(GetFileName(mDebugTarget->mLaunchBinary->mFilePath));
else if (findName == "$TargetPath")
return GetString(mDebugTarget->mTargetBinary->mFilePath);
return GetString(mDebugTarget->mTargetPath);
else if (findName == "$ModuleName")
return GetString(GetFileName(mDbgModule->mFilePath));
else if (findName == "$ModulePath")

View file

@ -1922,9 +1922,7 @@ DbgModule::DbgModule(DebugTarget* debugTarget) : mDefaultCompileUnit(this)
mDebugLocationData = NULL;
mDebugRangesData = NULL;
mDebugAbbrevData = NULL;
mDebugStrData = NULL;
mExceptionDirectoryData = NULL;
mExceptionDirectoryDataLen = 0;
mDebugStrData = NULL;
mDebugAbbrevPtrData = NULL;
mEHFrameData = NULL;
mEHFrameAddress = 0;
@ -1986,7 +1984,8 @@ DbgModule::~DbgModule()
delete mDebugAbbrevData;
delete mDebugAbbrevPtrData;
delete mDebugStrData;
delete mExceptionDirectoryData;
for (auto entry : mExceptionDirectory)
delete entry.mData;
delete mEHFrameData;
delete mOrigImageData;
@ -2123,47 +2122,50 @@ void DbgModule::ParseAbbrevData(const uint8* data)
void DbgModule::ParseExceptionData()
{
if (mExceptionDirectoryData == NULL)
if (mExceptionDirectory.IsEmpty())
return;
BP_ZONE("DbgModule::ParseExceptionData");
const uint8* data = mExceptionDirectoryData;
const uint8* dataEnd = data + mExceptionDirectoryDataLen;
static int entryCount = 0;
addr_target imageBase = GetTargetImageBase();
while (data < dataEnd)
for (auto entry : mExceptionDirectory)
{
addr_target beginAddress = GET(uint32);
addr_target endAddress = GET(uint32);
uint32 unwindData = GET(uint32);
//TODO: Apparently unwindData can refer to another runtime entry in the .pdata if the LSB is set to 1?
const uint8* data = entry.mData;
const uint8* dataEnd = data + entry.mSize;
beginAddress += (addr_target)imageBase;
endAddress += (addr_target)imageBase;
int exSize = (int)(endAddress - beginAddress);
for (int exOffset = 0; true; exOffset += DBG_MAX_LOOKBACK)
static int entryCount = 0;
addr_target imageBase = GetTargetImageBase();
while (data < dataEnd)
{
int curSize = exSize - exOffset;
if (curSize <= 0)
break;
BP_ALLOC_T(DbgExceptionDirectoryEntry);
DbgExceptionDirectoryEntry* exceptionDirectoryEntry = mAlloc.Alloc<DbgExceptionDirectoryEntry>();
addr_target beginAddress = GET(uint32);
addr_target endAddress = GET(uint32);
uint32 unwindData = GET(uint32);
exceptionDirectoryEntry->mAddress = beginAddress + exOffset;
exceptionDirectoryEntry->mOrigAddressOffset = exOffset;
exceptionDirectoryEntry->mAddressLength = curSize;
exceptionDirectoryEntry->mExceptionPos = (int)unwindData;
exceptionDirectoryEntry->mDbgModule = this;
mDebugTarget->mExceptionDirectoryMap.Insert(exceptionDirectoryEntry);
//TODO: Apparently unwindData can refer to another runtime entry in the .pdata if the LSB is set to 1?
entryCount++;
beginAddress += (addr_target)imageBase;
endAddress += (addr_target)imageBase;
int exSize = (int)(endAddress - beginAddress);
for (int exOffset = 0; true; exOffset += DBG_MAX_LOOKBACK)
{
int curSize = exSize - exOffset;
if (curSize <= 0)
break;
BP_ALLOC_T(DbgExceptionDirectoryEntry);
DbgExceptionDirectoryEntry* exceptionDirectoryEntry = mAlloc.Alloc<DbgExceptionDirectoryEntry>();
exceptionDirectoryEntry->mAddress = beginAddress + exOffset;
exceptionDirectoryEntry->mOrigAddressOffset = exOffset;
exceptionDirectoryEntry->mAddressLength = curSize;
exceptionDirectoryEntry->mExceptionPos = (int)unwindData;
exceptionDirectoryEntry->mDbgModule = this;
mDebugTarget->mExceptionDirectoryMap.Insert(exceptionDirectoryEntry);
entryCount++;
}
}
}
}
@ -5310,7 +5312,9 @@ bool DbgModule::ReadCOFF(DataStream* stream, bool isHotObjectFile)
targetSection->mNoTargetAlloc = true;
}
if ((!mIsHotObjectFile) /*&& (!isUnwindSection)*/)
bool isExportDataDir = ((exportDataDir->mVirtualAddress != 0) && (exportDataDir->mVirtualAddress >= sectHdr.mVirtualAddress) && (exportDataDir->mVirtualAddress < sectHdr.mVirtualAddress + sectHdr.mSizeOfRawData));
if ((!mIsHotObjectFile) && (!isExportDataDir))
{
if (((strcmp(name, ".text")) == 0) ||
((strcmp(name, ".textbss")) == 0) ||
@ -5341,7 +5345,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, bool isHotObjectFile)
targetSection->mData = data;
addr_target addrOffset = sectHdr.mVirtualAddress;
if ((exportDataDir->mVirtualAddress != 0) && (exportDataDir->mVirtualAddress >= sectHdr.mVirtualAddress) && (exportDataDir->mVirtualAddress < sectHdr.mVirtualAddress + sectHdr.mSizeOfRawData))
if (isExportDataDir)
{
BP_ZONE("DbgModule::ReadCOFF_SymbolMap");
@ -5565,9 +5569,11 @@ bool DbgModule::ReadCOFF(DataStream* stream, bool isHotObjectFile)
}*/
if (strcmp(name, ".pdata") == 0)
{
mExceptionDirectoryData = data;
mExceptionDirectoryDataLen = sectHdr.mSizeOfRawData;
{
DbgSectionData entry;
entry.mData = data;
entry.mSize = sectHdr.mSizeOfRawData;
mExceptionDirectory.Add(entry);
}
/*else if (strcmp(name, ".rdata") == 0)
{

View file

@ -122,6 +122,12 @@ enum DbgFileExistKind : uint8
class DbgCompileUnit;
struct DbgSectionData
{
uint8* mData;
int mSize;
};
class DbgDebugData
{
public:
@ -1095,9 +1101,8 @@ public:
addr_target mCodeAddress;
const uint8* mDebugAbbrevData;
const uint8* mDebugStrData;
const uint8** mDebugAbbrevPtrData;
const uint8* mExceptionDirectoryData;
int mExceptionDirectoryDataLen;
const uint8** mDebugAbbrevPtrData;
Array<DbgSectionData> mExceptionDirectory;
const uint8* mEHFrameData;
const char* mStringTable;
const uint8* mSymbolData;

View file

@ -795,18 +795,18 @@ BF_EXPORT int BF_CALLTYPE Debugger_GetAddrSize()
return gDebugger->GetAddrSize();
}
BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* fileName, const char* args, const char* workingDir, void* envBlockPtr, int envBlockSize)
BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* launchPath, const char* targetPath, const char* args, const char* workingDir, void* envBlockPtr, int envBlockSize)
{
BF_ASSERT(gDebugger == NULL);
if (!FileExists(fileName))
if (!FileExists(launchPath))
{
gDebugManager->mOutMessages.push_back(StrFormat("error Unable to locate specified debug target '%s'", fileName));
gDebugManager->mOutMessages.push_back(StrFormat("error Unable to locate specified launch target '%s'", launchPath));
return false;
}
DebuggerResult debuggerResult = DebuggerResult_Ok;
if ((gDebugManager->mDebugger64 != NULL) && (gDebugManager->mDebugger64->CanOpen(fileName, &debuggerResult)))
if ((gDebugManager->mDebugger64 != NULL) && (gDebugManager->mDebugger64->CanOpen(launchPath, &debuggerResult)))
gDebugger = gDebugManager->mDebugger64;
else
gDebugger = gDebugManager->mDebugger32;
@ -814,7 +814,7 @@ BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* fileName, const char* a
if (gDebugger == NULL)
{
if (debuggerResult == DebuggerResult_WrongBitSize)
gDebugManager->mOutMessages.push_back(StrFormat("error The file 32-bit file '%s' cannot be debugged because 32-bit debugger has been disabled", fileName));
gDebugManager->mOutMessages.push_back(StrFormat("error The file 32-bit file '%s' cannot be debugged because 32-bit debugger has been disabled", launchPath));
return false;
}
@ -825,7 +825,7 @@ BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* fileName, const char* a
envBlock.Insert(0, (uint8*)envBlockPtr, envBlockSize);
}
gDebugger->OpenFile(fileName, args, workingDir, envBlock);
gDebugger->OpenFile(launchPath, targetPath, args, workingDir, envBlock);
return true;
}

View file

@ -23,6 +23,7 @@ DebugTarget::DebugTarget(WinDebugger* debugger)
mBfObjectVDataIntefaceSlotCount = -1;
mBfObjectSize = -1;
mDebugger = debugger;
mLaunchBinary = NULL;
mTargetBinary = NULL;
mCapturedNamesPtr = NULL;
mCapturedTypesPtr = NULL;
@ -50,31 +51,113 @@ DebugTarget::~DebugTarget()
mHotHeap = NULL;
}
DbgModule* DebugTarget::Init(const StringImpl& fileName, intptr imageBase)
static bool PathEquals(const String& pathA, String& pathB)
{
const char* ptrA = pathA.c_str();
const char* ptrB = pathB.c_str();
while (true)
{
char cA = *(ptrA++);
char cB = *(ptrB++);
if ((cA == 0) || (cB == 0))
{
return (cA == 0) && (cB == 0);
}
cA = toupper((uint8)cA);
cB = toupper((uint8)cB);
if (cA == '\\')
cA = '/';
if (cB == '\\')
cB = '/';
if (cA != cB)
return false;
}
return true;
}
void DebugTarget::SetupTargetBinary()
{
bool wantsHotHeap = mDebugger->mDbgProcessId == 0;
#ifdef BF_DBG_32
if (wantsHotHeap)
mHotHeap = new HotHeap();
#else
if (wantsHotHeap)
{
// 64-bit hot loaded code needs to be placed close to the original EXE so 32-bit relative
// offsets within the hot code can still reach the old code
addr_target checkHotReserveAddr = (addr_target)mTargetBinary->mImageBase + mTargetBinary->mImageSize;
int mb = 1024 * 1024;
int reserveSize = 512 * mb;
// Round up to MB boundary + 64MB, to help keep other DLLs at their preferred base addresses
checkHotReserveAddr = ((checkHotReserveAddr + 64 * mb) & ~(mb - 1));
checkHotReserveAddr = (addr_target)mTargetBinary->mImageBase;
addr_target reservedPtr = NULL;
while ((addr_target)checkHotReserveAddr < (addr_target)mTargetBinary->mImageBase + 0x30000000)
{
reservedPtr = (addr_target)VirtualAllocEx(mDebugger->mProcessInfo.hProcess, (void*)(intptr)checkHotReserveAddr, reserveSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (reservedPtr != NULL)
break;
checkHotReserveAddr += 4 * mb;
}
if (reservedPtr != 0)
{
BF_ASSERT(mHotHeap == NULL);
mHotHeap = new HotHeap(reservedPtr, reserveSize);
}
//TODO: Throw actual error if we can't reserve HOT area
BF_ASSERT(reservedPtr != NULL);
}
#endif
}
void DebugTarget::CheckTargetBinary(DbgModule* module)
{
if (mTargetBinary != NULL)
return;
if (!PathEquals(module->mFilePath, mTargetPath))
return;
mTargetBinary = module;
if (mTargetBinary != mLaunchBinary)
SetupTargetBinary();
}
DbgModule* DebugTarget::Init(const StringImpl& launchPath, const StringImpl& targetPath, intptr imageBase)
{
BP_ZONE("DebugTarget::Init");
AutoDbgTime dbgTime("DebugTarget::Init " + fileName);
AutoDbgTime dbgTime("DebugTarget::Init Launch:" + launchPath + " Target:" + targetPath);
mTargetPath = targetPath;
FileStream fileStream;
fileStream.mFP = _wfopen(UTF8Decode(fileName).c_str(), L"rb");
fileStream.mFP = _wfopen(UTF8Decode(launchPath).c_str(), L"rb");
if (fileStream.mFP == NULL)
{
mDebugger->OutputMessage(StrFormat("Debugger failed to open binary: %s\n", fileName.c_str()));
mDebugger->OutputMessage(StrFormat("Debugger failed to open binary: %s\n", launchPath.c_str()));
return NULL;
}
DbgModule* dwarf = new COFF(this);
mTargetBinary = dwarf;
dwarf->mDisplayName = GetFileName(fileName);
dwarf->mFilePath = fileName;
mLaunchBinary = dwarf;
dwarf->mDisplayName = GetFileName(launchPath);
dwarf->mFilePath = launchPath;
dwarf->mImageBase = (intptr)imageBase;
if (!dwarf->ReadCOFF(&fileStream, false))
{
mDebugger->OutputMessage(StrFormat("Debugger failed to read binary: %s\n", fileName.c_str()));
mDebugger->OutputMessage(StrFormat("Debugger failed to read binary: %s\n", launchPath.c_str()));
delete dwarf;
return NULL;
}
CheckTargetBinary(dwarf);
mDbgModules.push_back(dwarf);
return dwarf;
@ -85,6 +168,7 @@ void DebugTarget::CreateEmptyTarget()
auto emptyTarget = new DbgModule(this);
mDbgModules.push_back(emptyTarget);
mTargetBinary = emptyTarget;
mLaunchBinary = emptyTarget;
}
DbgModule* DebugTarget::HotLoad(const StringImpl& fileName, int hotIdx)
@ -134,7 +218,7 @@ DbgModule* DebugTarget::SetupDyn(const StringImpl& filePath, DataStream* stream,
dwarf->mDisplayName = GetFileName(filePath);
dwarf->mOrigImageData = new DbgModuleMemoryCache(dwarf->mImageBase, dwarf->mImageSize);
CheckTargetBinary(dwarf);
/*dbgModule->mOrigImageData = new uint8[dbgModule->mImageSize];
memset(dbgModule->mOrigImageData, 0xCC, dbgModule->mImageSize);
@ -163,11 +247,14 @@ String DebugTarget::UnloadDyn(addr_target imageBase)
RemoveTargetData();
filePath = dwarf->mFilePath;
if (mTargetBinary == dwarf)
mTargetBinary = NULL;
delete dwarf;
mDbgModules.erase(mDbgModules.begin() + i);
return filePath;
}
}
}
return "";
}
@ -801,7 +888,10 @@ void DebugTarget::GetCompilerSettings()
{
if (!mCheckedCompilerSettings)
{
DbgType* bfObjectType = GetMainDbgModule()->FindType("System.CompilerSettings", NULL, DbgLanguage_Beef);
auto dbgModule = GetMainDbgModule();
if (dbgModule == NULL)
return;
DbgType* bfObjectType = dbgModule->FindType("System.CompilerSettings", NULL, DbgLanguage_Beef);
if (bfObjectType != NULL)
{
bfObjectType->PopulateType();

View file

@ -35,7 +35,10 @@ public:
HotHeap* mHotHeap;
int mLastHotHeapCleanIdx;
DbgModule* mTargetBinary;
String mTargetPath;
DbgModule* mLaunchBinary;
DbgModule* mTargetBinary;
//DbgModule* m
Array<DbgModule*> mDbgModules;
//DbgModule* mLastDWARF;
HashSet<DbgSrcFile*> mPendingSrcFileRehup; // Waiting to remove old/invalid line info
@ -69,8 +72,10 @@ protected:
public:
DebugTarget(WinDebugger* debugger);
~DebugTarget();
DbgModule* Init(const StringImpl& fileName, intptr imageBase = 0);
DbgModule* Init(const StringImpl& launchPath, const StringImpl& targetPath, intptr imageBase = 0);
void SetupTargetBinary();
void CheckTargetBinary(DbgModule* module);
void CreateEmptyTarget();
DbgModule* HotLoad(const StringImpl& fileName, int hotIdx);
DbgModule* SetupDyn(const StringImpl& filePath, DataStream* stream, intptr imageBase);

View file

@ -230,7 +230,7 @@ public:
virtual void OutputRawMessage(const StringImpl& msg) = 0;
virtual int GetAddrSize() = 0;
virtual bool CanOpen(const StringImpl& fileName, DebuggerResult* outResult) = 0;
virtual void OpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock) = 0;
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock) = 0;
virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) = 0;
virtual void Run() = 0;
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) = 0;

View file

@ -44,7 +44,10 @@ MiniDumpDebugger::MiniDumpDebugger(DebugManager* debugManager, DbgMiniDump* mini
auto& module = moduleList.Modules[moduleIdx];
COFF* dbgModule = new COFF(mDebugTarget);
if (mDebugTarget->mTargetBinary == NULL)
{
mDebugTarget->mLaunchBinary = dbgModule;
mDebugTarget->mTargetBinary = dbgModule;
}
dbgModule->mImageBase = module.BaseOfImage;
dbgModule->mImageSize = module.SizeOfImage;

View file

@ -879,12 +879,12 @@ void WinDebugger::DebugThreadProc()
if (!IsMiniDumpDebugger())
{
if (!DoOpenFile(mFileName, mArgs, mWorkingDir, mEnvBlock))
if (!DoOpenFile(mLaunchPath, mArgs, mWorkingDir, mEnvBlock))
{
if (mDbgProcessId != 0)
OutputRawMessage("error Unable to attach to process");
else
OutputRawMessage(StrFormat("error Failed to launch: %s", mFileName.c_str()));
OutputRawMessage(StrFormat("error Failed to launch: %s", mLaunchPath.c_str()));
mShuttingDown = true;
mRunState = RunState_Terminated;
}
@ -960,10 +960,11 @@ bool WinDebugger::CanOpen(const StringImpl& fileName, DebuggerResult* outResult)
return canRead;
}
void WinDebugger::OpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock)
void WinDebugger::OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock)
{
BF_ASSERT(!mIsRunning);
mFileName = fileName;
mLaunchPath = launchPath;
mTargetPath = targetPath;
mArgs = args;
mWorkingDir = workingDir;
mEnvBlock = envBlock;
@ -1000,7 +1001,8 @@ bool WinDebugger::Attach(int processId, BfDbgAttachFlags attachFlags)
WCHAR fileName[MAX_PATH] = {0};
GetModuleFileNameExW(mDbgProcessHandle, mainModule, fileName, MAX_PATH);
mFileName = UTF8Encode(fileName);
mLaunchPath = UTF8Encode(fileName);
mTargetPath = mLaunchPath;
mDbgProcessId = processId;
mDbgProcessHandle = 0;
@ -1209,7 +1211,7 @@ bool WinDebugger::DoOpenFile(const StringImpl& fileName, const StringImpl& args,
ContinueDebugEvent();
if ((mDebugTarget->mTargetBinary != NULL) && (mDebugTarget->mTargetBinary->mOrigImageData != NULL))
if ((mDebugTarget->mLaunchBinary != NULL) && (mDebugTarget->mLaunchBinary->mOrigImageData != NULL))
break;
}
@ -1534,56 +1536,20 @@ bool WinDebugger::DoUpdate()
BF_GetThreadContext(threadInfo->mHThread, &lcContext);
threadInfo->mStartSP = BF_CONTEXT_SP(lcContext);
DbgModule* targetBinary = mDebugTarget->Init(mFileName, (addr_target)(intptr)mDebugEvent.u.CreateProcessInfo.lpBaseOfImage);
DbgModule* launchBinary = mDebugTarget->Init(mLaunchPath, mTargetPath, (addr_target)(intptr)mDebugEvent.u.CreateProcessInfo.lpBaseOfImage);
addr_target gotImageBase = (addr_target)(intptr)mDebugEvent.u.CreateProcessInfo.lpBaseOfImage;
if (targetBinary->mImageBase != gotImageBase)
if (launchBinary->mImageBase != gotImageBase)
{
BF_FATAL("Image base didn't match");
}
targetBinary->mImageBase = gotImageBase;
targetBinary->mImageSize = (int)targetBinary->GetImageSize();
targetBinary->mOrigImageData = new DbgModuleMemoryCache(targetBinary->mImageBase, targetBinary->mImageSize);
launchBinary->mImageBase = gotImageBase;
launchBinary->mImageSize = (int)launchBinary->GetImageSize();
launchBinary->mOrigImageData = new DbgModuleMemoryCache(launchBinary->mImageBase, launchBinary->mImageSize);
if (launchBinary == mDebugTarget->mTargetBinary)
mDebugTarget->SetupTargetBinary();
bool wantsHotHeap = mDbgProcessId == 0;
#ifdef BF_DBG_32
if (wantsHotHeap)
mDebugTarget->mHotHeap = new HotHeap();
#else
if (wantsHotHeap)
{
// 64-bit hot loaded code needs to be placed close to the original EXE so 32-bit relative
// offsets within the hot code can still reach the old code
addr_target checkHotReserveAddr = (addr_target)targetBinary->mImageBase + targetBinary->mImageSize;
int mb = 1024 * 1024;
int reserveSize = 512 * mb;
// Round up to MB boundary + 64MB, to help keep other DLLs at their preferred base addresses
checkHotReserveAddr = ((checkHotReserveAddr + 64 * mb) & ~(mb - 1));
checkHotReserveAddr = (addr_target)targetBinary->mImageBase;
addr_target reservedPtr = NULL;
while ((addr_target)checkHotReserveAddr < (addr_target)targetBinary->mImageBase + 0x30000000)
{
reservedPtr = (addr_target)VirtualAllocEx(mProcessInfo.hProcess, (void*)(intptr)checkHotReserveAddr, reserveSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (reservedPtr != NULL)
break;
checkHotReserveAddr += 4 * mb;
}
if (reservedPtr != 0)
{
BF_ASSERT(mDebugTarget->mHotHeap == NULL);
mDebugTarget->mHotHeap = new HotHeap(reservedPtr, reserveSize);
}
//TODO: Throw actual error if we can't reserve HOT area
BF_ASSERT(reservedPtr != NULL);
}
#endif
if (mDebugEvent.u.CreateProcessInfo.hFile != NULL)
CloseHandle(mDebugEvent.u.CreateProcessInfo.hFile);
@ -1700,7 +1666,7 @@ bool WinDebugger::DoUpdate()
if (mDebugTarget->SetupDyn(moduleName, &stream, (intptr)mDebugEvent.u.LoadDll.lpBaseOfDll) == NULL)
loadMsg += " - Failed to load";
stream.mFileHandle = 0;
}
}
OutputMessage(loadMsg + "\n");
@ -3225,7 +3191,7 @@ void WinDebugger::CheckBreakpoint(WdBreakpoint* wdBreakpoint)
{
if (symbolName == ".")
{
targetAddr = mDebugTarget->mTargetBinary->mImageBase + mDebugTarget->mTargetBinary->mEntryPoint;
targetAddr = mDebugTarget->mLaunchBinary->mImageBase + mDebugTarget->mLaunchBinary->mEntryPoint;
onlyBindFirst = true;
}
}
@ -4547,7 +4513,7 @@ bool WinDebugger::SetupStep(StepType stepType)
}
void WinDebugger::CheckNonDebuggerBreak()
{
{
enum MessageType
{
MessageType_None = 0,
@ -4559,8 +4525,12 @@ void WinDebugger::CheckNonDebuggerBreak()
PopulateRegisters(&registers);
addr_target pcAddress = registers.GetPC();
mDebugTarget->mTargetBinary->ParseSymbolData();
addr_target debugMessageDataAddr = mDebugTarget->FindSymbolAddr("gBfDebugMessageData");
addr_target debugMessageDataAddr = (addr_target)-1;
if (mDebugTarget->mTargetBinary != NULL)
{
mDebugTarget->mTargetBinary->ParseSymbolData();
debugMessageDataAddr = mDebugTarget->FindSymbolAddr("gBfDebugMessageData");
}
if (debugMessageDataAddr != (addr_target)-1)
{
struct BfDebugMessageData
@ -4684,7 +4654,7 @@ void WinDebugger::CheckNonDebuggerBreak()
DbgModule* dbgModule;
if (mDebugTarget->FindSymbolAt(pcAddress, &symbol, &offset, &dbgModule))
{
if (symbol == "DbgBreakPoint")
if ((symbol == "DbgBreakPoint") || (symbol == "RtlUserThreadStart@8"))
{
showMainThread = true;
}
@ -8859,15 +8829,18 @@ String WinDebugger::EvaluateContinue(DbgPendingExpr* pendingExpr, BfPassInstance
if ((pendingExpr->mFormatInfo.mLanguage == DbgLanguage_Beef) && (mDebugTarget != NULL) && (mDebugTarget->mTargetBinary != NULL))
dbgModule = mDebugTarget->mTargetBinary;
else
dbgModule = mEmptyDebugTarget->GetMainDbgModule();
dbgModule = mEmptyDebugTarget->GetMainDbgModule();
}
else
{
dbgModule = GetCallStackDbgModule(pendingExpr->mCallStackIdx);
if (!dbgModule->mDebugTarget->mIsEmpty)
if ((dbgModule != NULL) &&(!dbgModule->mDebugTarget->mIsEmpty))
dbgCompileUnit = GetCallStackCompileUnit(pendingExpr->mCallStackIdx);
}
if (dbgModule == NULL)
dbgModule = mEmptyDebugTarget->GetMainDbgModule();
if (!pendingExpr->mException.empty())
{
RestoreAllRegisters();
@ -9315,7 +9288,7 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in
if (dbgSubprogram != NULL)
curLanguage = dbgSubprogram->GetLanguage();
if (language != curLanguage)
{
{
dbgModule = mDebugTarget->mTargetBinary;
dbgSubprogram = NULL;
formatInfo.mLanguage = language;
@ -10146,8 +10119,9 @@ String WinDebugger::GetThreadInfo()
threadName = module->mDisplayName + " thread";
if ((mActiveThread == mExplicitStopThread) && (mActiveBreakpoint != NULL))
{
if ((mActiveBreakpoint->mAddr < subProgram->mBlock.mLowPC) ||
{
if ((subProgram == NULL) ||
(mActiveBreakpoint->mAddr < subProgram->mBlock.mLowPC) ||
(mActiveBreakpoint->mAddr >= subProgram->mBlock.mHighPC))
break;
}

View file

@ -369,7 +369,8 @@ public:
volatile bool mShuttingDown;
volatile bool mIsRunning;
bool mDestroying;
String mFileName;
String mLaunchPath;
String mTargetPath;
String mArgs;
String mWorkingDir;
Array<uint8> mEnvBlock;
@ -450,7 +451,7 @@ public:
uint8 mMemCacheData[WD_MEMCACHE_SIZE];
public:
void Fail(const StringImpl& error);
void Fail(const StringImpl& error);
void TryGetThreadName(WdThreadInfo* threadInfo);
void ThreadRestorePause(WdThreadInfo* onlyPauseThread, WdThreadInfo* dontPauseThread);
void ThreadRestoreUnpause();
@ -479,7 +480,7 @@ public:
virtual bool PopulateRegisters(CPURegisters* registers);
bool RollBackStackFrame(CPURegisters* registers, bool isStackStart);
bool SetHotJump(DbgSubprogram* oldSubprogram, DbgSubprogram* newSubprogram);
DbgSubprogram* TryFollowHotJump(DbgSubprogram* subprogram, addr_target addr);
DbgSubprogram* TryFollowHotJump(DbgSubprogram* subprogram, addr_target addr);
bool ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExpr = NULL, String* errorString = NULL, DbgTypedValue contextTypedValue = DbgTypedValue());
String MaybeQuoteFormatInfoParam(const StringImpl& str);
@ -558,7 +559,7 @@ public:
virtual void OutputRawMessage(const StringImpl& msg) override;
virtual int GetAddrSize() override;
virtual bool CanOpen(const StringImpl& fileName, DebuggerResult* outResult) override;
virtual void OpenFile(const StringImpl& fileName, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock) override;
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock) override;
virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) override;
virtual void Run() override;
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) override;