2019-08-23 11:56:54 -07:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "DebugCommon.h"
|
|
|
|
#include "CPU.h"
|
|
|
|
#include "BeefySysLib/Common.h"
|
|
|
|
#include "BeefySysLib/util/SLIList.h"
|
|
|
|
#include "BeefySysLib/util/BumpAllocator.h"
|
|
|
|
#include "BeefySysLib/util/HashSet.h"
|
|
|
|
#include "BeefySysLib/util/MappedFile.h"
|
|
|
|
#include "BeefySysLib/DataStream.h"
|
|
|
|
#include "Compiler/BfAst.h"
|
|
|
|
#include "Compiler/BfUtil.h"
|
|
|
|
#include "BumpList.h"
|
|
|
|
#include "RadixMap.h"
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <unordered_set>
|
|
|
|
#include <functional>
|
|
|
|
#include "Debugger.h"
|
|
|
|
#include "StrHashMap.h"
|
|
|
|
#include "DbgTypeMap.h"
|
|
|
|
#include "COFFData.h"
|
|
|
|
#include "X86Target.h"
|
|
|
|
|
|
|
|
NS_BF_DBG_BEGIN
|
|
|
|
|
|
|
|
using namespace Beefy;
|
|
|
|
|
|
|
|
class DbgModule;
|
|
|
|
|
|
|
|
enum DbgTypeCode : uint8
|
|
|
|
{
|
|
|
|
DbgType_Void,
|
|
|
|
DbgType_Root,
|
|
|
|
DbgType_Null,
|
|
|
|
DbgType_i8,
|
|
|
|
DbgType_u8,
|
|
|
|
DbgType_i16,
|
|
|
|
DbgType_u16,
|
|
|
|
DbgType_i32,
|
|
|
|
DbgType_u32,
|
|
|
|
DbgType_i64,
|
|
|
|
DbgType_u64,
|
|
|
|
DbgType_i128,
|
|
|
|
DbgType_u128,
|
|
|
|
DbgType_Single,
|
|
|
|
DbgType_Double,
|
|
|
|
DbgType_Float96,
|
|
|
|
DbgType_Float128,
|
|
|
|
DbgType_ComplexFloat,
|
|
|
|
DbgType_ComplexDouble,
|
|
|
|
DbgType_ComplexDouble96,
|
|
|
|
DbgType_ComplexDouble128,
|
|
|
|
DbgType_SChar,
|
|
|
|
DbgType_SChar16,
|
|
|
|
DbgType_SChar32,
|
|
|
|
DbgType_UChar,
|
|
|
|
DbgType_UChar16,
|
|
|
|
DbgType_UChar32,
|
|
|
|
DbgType_Utf8,
|
|
|
|
DbgType_Utf16,
|
|
|
|
DbgType_Utf32,
|
|
|
|
DbgType_Bool,
|
|
|
|
DbgType_Namespace,
|
|
|
|
DbgType_Enum,
|
|
|
|
DbgType_VTable,
|
|
|
|
DbgType_Bitfield,
|
|
|
|
DbgType_Class,
|
|
|
|
DbgType_Struct,
|
|
|
|
DbgType_Union,
|
|
|
|
DbgType_TypeDef,
|
|
|
|
|
|
|
|
#ifdef BF_DBG_32
|
|
|
|
DbgType_IntPtr_Alias = DbgType_i32,
|
|
|
|
DbgType_UIntPtr_Alias = DbgType_u32,
|
|
|
|
#else
|
|
|
|
DbgType_IntPtr_Alias = DbgType_i64,
|
|
|
|
DbgType_UIntPtr_Alias = DbgType_u64,
|
|
|
|
#endif
|
|
|
|
DbgType_DefinitionEnd = DbgType_TypeDef,
|
|
|
|
|
|
|
|
DbgType_Ptr,
|
|
|
|
DbgType_PtrToMember,
|
|
|
|
DbgType_SizedArray,
|
|
|
|
DbgType_Ref,
|
|
|
|
DbgType_RValueReference,
|
|
|
|
DbgType_Const,
|
|
|
|
DbgType_Volatile,
|
|
|
|
DbgType_Unaligned,
|
|
|
|
DbgType_Restrict,
|
|
|
|
DbgType_Subroutine,
|
|
|
|
DbgType_Unspecified,
|
|
|
|
DbgType_RawText,
|
|
|
|
|
|
|
|
DbgType_RegGroup,
|
|
|
|
|
|
|
|
DbgType_COUNT,
|
|
|
|
};
|
|
|
|
|
|
|
|
class DebugTarget;
|
|
|
|
class WinDebugger;
|
|
|
|
class DbgType;
|
|
|
|
class DbgBlock;
|
|
|
|
|
|
|
|
enum DbgClassType : uint8
|
|
|
|
{
|
|
|
|
DbgClassType_None,
|
|
|
|
DbgClassType_CompileUnit,
|
|
|
|
DbgClassType_Subprogram,
|
|
|
|
DbgClassType_Type,
|
|
|
|
DbgClassType_Member,
|
|
|
|
DbgClassType_Block,
|
|
|
|
DbgClassType_Variable,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum DbgFileExistKind : uint8
|
|
|
|
{
|
|
|
|
DbgFileExistKind_NotChecked,
|
|
|
|
DbgFileExistKind_NotFound,
|
|
|
|
DbgFileExistKind_HasOldSourceCommand,
|
|
|
|
DbgFileExistKind_Found
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgCompileUnit;
|
|
|
|
|
2019-09-02 17:39:47 -07:00
|
|
|
struct DbgSectionData
|
|
|
|
{
|
|
|
|
uint8* mData;
|
|
|
|
int mSize;
|
|
|
|
};
|
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
class DbgDebugData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgCompileUnit* mCompileUnit;
|
|
|
|
int mTagIdx;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgDebugData()
|
|
|
|
{
|
|
|
|
mCompileUnit = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
virtual ~DbgDebugData()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
enum DbgLocationLenKind
|
|
|
|
{
|
|
|
|
DbgLocationLenKind_SegPlusOffset = -0x80
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgVariable : public DbgDebugData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const DbgClassType ClassType = DbgClassType_Variable;
|
|
|
|
|
|
|
|
const char* mName;
|
|
|
|
const char* mLinkName;
|
|
|
|
addr_target mRangeStart;
|
|
|
|
int64 mConstValue;
|
|
|
|
DbgType* mType;
|
|
|
|
const uint8* mLocationData;
|
|
|
|
int mRangeLen;
|
|
|
|
int mMemberOffset;
|
|
|
|
int8 mLocationLen;
|
|
|
|
uint8 mBitSize;
|
|
|
|
uint8 mBitOffset;
|
|
|
|
bool mIsExtern;
|
|
|
|
bool mIsParam;
|
|
|
|
bool mIsMember;
|
|
|
|
bool mIsStatic;
|
|
|
|
bool mIsConst;
|
|
|
|
bool mInAutoStaticMap;
|
|
|
|
bool mSigNoPointer; // Signature was without pointer, mType has pointer
|
|
|
|
|
|
|
|
addr_target mStaticCachedAddr;
|
|
|
|
DbgVariable* mNext;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgVariable()
|
|
|
|
{
|
|
|
|
mBitSize = 0;
|
|
|
|
mBitOffset = 0;
|
|
|
|
mIsParam = false;
|
|
|
|
mLocationData = NULL;
|
|
|
|
mLocationLen = 0;
|
|
|
|
mIsStatic = false;
|
|
|
|
mIsConst = false;
|
|
|
|
mConstValue = 0;
|
|
|
|
mMemberOffset = 0;
|
|
|
|
mInAutoStaticMap = false;
|
|
|
|
mStaticCachedAddr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* GetMappedName()
|
|
|
|
{
|
|
|
|
if (mLinkName != NULL)
|
|
|
|
return mLinkName;
|
|
|
|
return mName;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgType;
|
|
|
|
class DbgDataMap;
|
|
|
|
|
|
|
|
typedef std::map<int, Array<int> > DwAsmDebugLineMap;
|
|
|
|
|
|
|
|
class DbgBlock : public DbgDebugData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const DbgClassType ClassType = DbgClassType_Block;
|
|
|
|
|
|
|
|
addr_target mLowPC; // If LowPC is -1 then mHighPC is index into debugRanges
|
|
|
|
addr_target mHighPC;
|
|
|
|
|
|
|
|
SLIList<DbgVariable*> mVariables;
|
|
|
|
SLIList<DbgBlock*> mSubBlocks;
|
|
|
|
|
|
|
|
DwAsmDebugLineMap* mAsmDebugLineMap; // empty unless inline asm is used
|
|
|
|
|
|
|
|
DbgBlock* mNext;
|
|
|
|
|
|
|
|
bool mAutoStaticVariablesProcessed;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgBlock()
|
|
|
|
{
|
|
|
|
mLowPC = 0;
|
|
|
|
mHighPC = 0;
|
|
|
|
mAutoStaticVariablesProcessed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsEmpty()
|
|
|
|
{
|
|
|
|
return mLowPC == mHighPC;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
enum DbgMethodType
|
|
|
|
{
|
|
|
|
DbgMethodType_Ctor,
|
|
|
|
DbgMethodType_Normal,
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgModule;
|
|
|
|
class DbgSrcFile;
|
|
|
|
class DbgSrcFileReference;
|
|
|
|
class DbgSubprogram;
|
|
|
|
|
|
|
|
class DbgLineData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
uint32 mRelAddress;
|
|
|
|
int32 mLine;
|
|
|
|
int16 mColumn;
|
|
|
|
uint16 mContribSize;
|
|
|
|
uint16 mCtxIdx;
|
|
|
|
|
|
|
|
bool IsStackFrameSetup()
|
|
|
|
{
|
|
|
|
return mColumn != -2;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DbgLineDataEx
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgLineData* mLineData;
|
|
|
|
DbgSubprogram* mSubprogram;
|
|
|
|
|
|
|
|
DbgLineDataEx()
|
|
|
|
{
|
|
|
|
mLineData = NULL;
|
|
|
|
mSubprogram = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DbgLineDataEx(DbgLineData* lineData, DbgSubprogram* subprogram)
|
|
|
|
{
|
|
|
|
mLineData = lineData;
|
|
|
|
mSubprogram = subprogram;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr_target GetAddress();
|
|
|
|
DbgSrcFile* GetSrcFile();
|
|
|
|
|
|
|
|
bool operator==(DbgLineData* lineData)
|
|
|
|
{
|
|
|
|
return lineData == mLineData;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsNull()
|
|
|
|
{
|
|
|
|
return mLineData == NULL;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgLineInfoCtx
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgSubprogram* mInlinee;
|
|
|
|
DbgSrcFile* mSrcFile;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgLineInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgLineInfoCtx* mContexts;
|
|
|
|
BfSizedArray<DbgLineData> mLines;
|
|
|
|
bool mHasInlinees;
|
|
|
|
};
|
|
|
|
|
|
|
|
class HotReplacedLineInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Entry
|
|
|
|
{
|
|
|
|
DbgLineInfo* mLineInfo;
|
|
|
|
DbgSubprogram* mSubprogram;
|
|
|
|
};
|
|
|
|
|
|
|
|
Array<Entry> mEntries;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgInlineeInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgSubprogram* mInlineParent;
|
|
|
|
DbgSubprogram* mRootInliner;
|
|
|
|
DbgLineData mFirstLineData;
|
|
|
|
DbgLineData mLastLineData;
|
|
|
|
uint32 mInlineeId;
|
|
|
|
int mInlineDepth;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgSubprogram : public DbgDebugData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const DbgClassType ClassType = DbgClassType_Subprogram;
|
|
|
|
|
|
|
|
#ifdef BF_DBG_32
|
|
|
|
enum LocalBaseRegKind : uint8
|
|
|
|
{
|
|
|
|
LocalBaseRegKind_None,
|
|
|
|
LocalBaseRegKind_ESP,
|
|
|
|
LocalBaseRegKind_EBP,
|
|
|
|
LocalBaseRegKind_EBX
|
|
|
|
};
|
|
|
|
#else
|
|
|
|
enum LocalBaseRegKind : uint8
|
|
|
|
{
|
|
|
|
LocalBaseRegKind_None,
|
|
|
|
LocalBaseRegKind_RSP,
|
|
|
|
LocalBaseRegKind_RBP,
|
|
|
|
LocalBaseRegKind_R13
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const char* mName;
|
|
|
|
const char* mLinkName;
|
|
|
|
int mTemplateNameIdx;
|
|
|
|
int mDeclLine;
|
|
|
|
int mFrameBaseLen;
|
|
|
|
int mPrologueSize;
|
|
|
|
const uint8* mFrameBaseData;
|
|
|
|
DbgBlock mBlock;
|
|
|
|
int mDeferredInternalsSize;
|
|
|
|
int mVTableLoc;
|
|
|
|
int mStepFilterVersion;
|
|
|
|
LocalBaseRegKind mLocalBaseReg;
|
|
|
|
bool mHasQualifiedName;
|
|
|
|
bool mIsStepFiltered;
|
|
|
|
bool mIsStepFilteredDefault;
|
|
|
|
bool mVirtual;
|
|
|
|
bool mHasThis;
|
|
|
|
bool mNeedLineDataFixup;
|
|
|
|
bool mWasHotReplaced;
|
|
|
|
bool mWasModuleHotReplaced; // Module was hot replaced but a new version of the subprogram wasn't found
|
|
|
|
bool mIsOptimized;
|
|
|
|
bool mHasLineAddrGaps; // There are gaps of addresses which are not covered by lineinfo
|
|
|
|
DbgLineInfo* mLineInfo;
|
|
|
|
DbgInlineeInfo* mInlineeInfo;
|
|
|
|
DbgType* mParentType;
|
|
|
|
DbgType* mReturnType;
|
|
|
|
DbgMethodType mMethodType;
|
|
|
|
BfProtection mProtection;
|
|
|
|
SLIList<DbgVariable*> mParams;
|
|
|
|
|
|
|
|
DbgSubprogram* mNext;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgSubprogram()
|
|
|
|
{
|
|
|
|
mName = NULL;
|
|
|
|
mLinkName = NULL;
|
|
|
|
mHasThis = false;
|
|
|
|
mNeedLineDataFixup = true;
|
|
|
|
mWasHotReplaced = false;
|
|
|
|
mWasModuleHotReplaced = false;
|
|
|
|
mHasLineAddrGaps = false;
|
|
|
|
mPrologueSize = -1;
|
|
|
|
mParentType = NULL;
|
|
|
|
mDeclLine = 0;
|
|
|
|
//mInlinerData = NULL;
|
|
|
|
mInlineeInfo = NULL;
|
|
|
|
mFrameBaseData = NULL;
|
|
|
|
mFrameBaseLen = 0;
|
|
|
|
mReturnType = NULL;
|
|
|
|
mNext = NULL;
|
|
|
|
mMethodType = DbgMethodType_Normal;
|
|
|
|
mProtection = BfProtection_Public;
|
|
|
|
mVTableLoc = -1;
|
|
|
|
mStepFilterVersion = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
~DbgSubprogram();
|
|
|
|
|
|
|
|
String ToString();
|
|
|
|
DbgLineData* FindClosestLine(addr_target addr, DbgSubprogram** inlinedSubprogram = NULL, DbgSrcFile** srcFile = NULL, int* outLineIdx = NULL);
|
|
|
|
DbgType* GetParent();
|
|
|
|
DbgType* GetTargetType(); // usually mParentType except for closures
|
|
|
|
DbgLanguage GetLanguage();
|
|
|
|
bool Equals(DbgSubprogram* checkMethod);
|
|
|
|
int GetParamCount();
|
|
|
|
String GetParamName(int paramIdx);
|
|
|
|
bool IsGenericMethod();
|
|
|
|
bool ThisIsSplat();
|
|
|
|
|
|
|
|
DbgSubprogram* GetRootInlineParent()
|
|
|
|
{
|
|
|
|
if (mInlineeInfo == NULL)
|
|
|
|
return this;
|
|
|
|
return mInlineeInfo->mRootInliner;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetInlineDepth()
|
|
|
|
{
|
|
|
|
int inlineDepth = 0;
|
|
|
|
auto checkSubprogram = this;
|
|
|
|
while (checkSubprogram->mInlineeInfo != NULL)
|
|
|
|
{
|
|
|
|
checkSubprogram = checkSubprogram->mInlineeInfo->mInlineParent;
|
|
|
|
inlineDepth++;
|
|
|
|
}
|
|
|
|
if (mInlineeInfo != NULL)
|
|
|
|
BF_ASSERT(inlineDepth == mInlineeInfo->mInlineDepth);
|
|
|
|
return inlineDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr_target GetLineAddr(const DbgLineData& lineData);
|
|
|
|
DbgSubprogram* GetLineInlinee(const DbgLineData& lineData);
|
|
|
|
DbgSrcFile* GetLineSrcFile(const DbgLineData& lineData);
|
|
|
|
void PopulateSubprogram();
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgSubprogramMapEntry
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
addr_target mAddress;
|
|
|
|
DbgSubprogram* mEntry;
|
|
|
|
DbgSubprogramMapEntry* mNext;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgExceptionDirectoryEntry
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgExceptionDirectoryEntry* mNext;
|
|
|
|
DbgModule* mDbgModule;
|
|
|
|
addr_target mAddress;
|
|
|
|
int mOrigAddressOffset;
|
|
|
|
int mAddressLength;
|
|
|
|
int mExceptionPos;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgBaseTypeEntry
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgType* mBaseType;
|
|
|
|
DbgBaseTypeEntry* mNext;
|
|
|
|
int mThisOffset;
|
|
|
|
int mVTableOffset;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgBaseTypeEntry()
|
|
|
|
{
|
|
|
|
mVTableOffset = -1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
enum DbgTypePriority
|
|
|
|
{
|
|
|
|
DbgTypePriority_Normal,
|
|
|
|
DbgTypePriority_Unique,
|
|
|
|
DbgTypePriority_Primary_Implicit,
|
|
|
|
DbgTypePriority_Primary_Explicit
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DbgMethodNameEntry
|
|
|
|
{
|
|
|
|
const char* mName;
|
|
|
|
int mCompileUnitId;
|
|
|
|
DbgMethodNameEntry* mNext;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum DbgExtType : int8
|
|
|
|
{
|
|
|
|
DbgExtType_Unknown,
|
|
|
|
DbgExtType_Normal,
|
|
|
|
DbgExtType_BfObject,
|
|
|
|
DbgExtType_BfPayloadEnum,
|
|
|
|
DbgExtType_BfUnion,
|
|
|
|
DbgExtType_Interface
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgType : public DbgDebugData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const DbgClassType ClassType = DbgClassType_Type;
|
|
|
|
DbgType* mParent;
|
|
|
|
BumpList<DbgType*> mAlternates; // From other compile units
|
|
|
|
DbgType* mPrimaryType;
|
|
|
|
|
|
|
|
DbgTypeCode mTypeCode;
|
|
|
|
SLIList<DbgBaseTypeEntry*> mBaseTypes;
|
|
|
|
DbgType* mTypeParam;
|
|
|
|
SLIList<DbgVariable*> mMemberList;
|
|
|
|
|
|
|
|
DbgType* mPtrType;
|
|
|
|
|
|
|
|
DbgBlock* mBlockParam;
|
|
|
|
SLIList<DbgMethodNameEntry*> mMethodNameList;
|
|
|
|
SLIList<DbgSubprogram*> mMethodList;
|
|
|
|
SLIList<DbgType*> mSubTypeList;
|
|
|
|
BumpList<DbgType*> mUsingNamespaces;
|
|
|
|
SLIList<DbgSubprogram*> mHotReplacedMethodList; // Old methods
|
|
|
|
DbgType* mHotNewType; // Only non-null during actual hotloading
|
|
|
|
|
|
|
|
const char* mName;
|
|
|
|
const char* mTypeName;
|
|
|
|
int mTemplateNameIdx;
|
|
|
|
int mSize; // In bytes
|
|
|
|
int mAlign;
|
|
|
|
int mDeclFileIdx;
|
|
|
|
int mDeclLine;
|
|
|
|
int mTypeIdx;
|
|
|
|
uint16 mDefinedMembersCount; // For static members
|
|
|
|
uint16 mMethodsWithParamsCount;
|
|
|
|
bool mIsIncomplete; // Not fully loaded
|
|
|
|
bool mIsPacked;
|
|
|
|
bool mNeedsGlobalsPopulated;
|
|
|
|
bool mHasGlobalsPopulated;
|
|
|
|
bool mIsDeclaration;
|
|
|
|
bool mHasStaticMembers;
|
|
|
|
bool mHasVTable;
|
|
|
|
bool mFixedName;
|
|
|
|
DbgLanguage mLanguage;
|
|
|
|
DbgExtType mExtType;
|
|
|
|
DbgTypePriority mPriority; // Is the one stored in the type map
|
|
|
|
bool mSizeCalculated;
|
|
|
|
|
|
|
|
DbgType* mNext;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgType();
|
|
|
|
~DbgType();
|
|
|
|
|
|
|
|
//uint64 GetHash();
|
|
|
|
DbgType* ResolveTypeDef();
|
|
|
|
bool Equals(DbgType* dbgType);
|
|
|
|
|
|
|
|
bool IsRoot();
|
|
|
|
bool IsNull();
|
|
|
|
bool IsVoid();
|
|
|
|
bool IsValuelessType();
|
|
|
|
bool IsPrimitiveType();
|
|
|
|
bool IsStruct();
|
|
|
|
bool IsValueType();
|
|
|
|
bool IsTypedPrimitive();
|
|
|
|
bool IsBoolean();
|
|
|
|
bool IsInteger();
|
|
|
|
bool IsIntegral();
|
|
|
|
bool IsChar();
|
|
|
|
bool IsChar(DbgLanguage language);
|
|
|
|
bool IsNamespace();
|
|
|
|
bool IsFloat();
|
|
|
|
bool IsCompositeType();
|
|
|
|
bool WantsRefThis(); // Beef valuetypes want 'this' by ref, Objects and C++ want 'this' by pointer
|
|
|
|
bool IsBfObjectPtr();
|
|
|
|
bool IsBfObject();
|
|
|
|
bool IsBfPayloadEnum();
|
|
|
|
bool IsBfEnum();
|
|
|
|
bool IsBfTuple();
|
|
|
|
bool IsBfUnion();
|
|
|
|
bool HasCPPVTable();
|
|
|
|
bool IsBaseBfObject();
|
|
|
|
bool IsInterface();
|
|
|
|
bool IsEnum();
|
|
|
|
bool IsSigned();
|
|
|
|
bool IsRef();
|
|
|
|
bool IsConst();
|
|
|
|
bool IsPointer(bool includeBfObjectPointer = true);
|
|
|
|
bool HasPointer(bool includeBfObjectPointer = true);
|
|
|
|
bool IsPointerOrRef(bool includeBfObjectPointer = true);
|
|
|
|
bool IsSizedArray();
|
|
|
|
bool IsAnonymous();
|
|
|
|
bool IsGlobalsContainer();
|
|
|
|
|
|
|
|
DbgExtType CalcExtType();
|
|
|
|
DbgLanguage GetLanguage();
|
|
|
|
void FixName();
|
|
|
|
void PopulateType();
|
|
|
|
DbgModule* GetDbgModule();
|
|
|
|
DbgType* GetUnderlyingType();
|
|
|
|
DbgType* GetPrimaryType();
|
|
|
|
DbgType* GetBaseType();
|
|
|
|
DbgType* GetRootBaseType();
|
|
|
|
DbgType* RemoveModifiers(bool* hadRef = NULL);
|
|
|
|
String ToStringRaw(DbgLanguage language = DbgLanguage_Unknown);
|
|
|
|
String ToString(DbgLanguage language = DbgLanguage_Unknown, bool allowDirectBfObject = false);
|
|
|
|
int GetByteCount();
|
|
|
|
int GetStride();
|
|
|
|
int GetAlign();
|
|
|
|
void EnsureMethodsMapped();
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgBitfieldType : public DbgType
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
int mPosition;
|
|
|
|
int mLength;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*enum DbgDerivedTypeRefKind
|
|
|
|
{
|
|
|
|
DbgDerivedTypeRefKind_Ptr
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgDerivedTypeRef : public DbgType
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgType* mRefType;
|
|
|
|
};*/
|
|
|
|
|
|
|
|
class DbgLineDataBuilder
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
class SubprogramRecord
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Array<DbgLineInfoCtx, AllocatorBump<DbgLineInfoCtx> > mContexts;
|
|
|
|
Array<DbgLineData, AllocatorBump<DbgLineData> > mLines;
|
|
|
|
int mCurContext;
|
|
|
|
bool mHasInlinees;
|
|
|
|
};
|
|
|
|
|
|
|
|
BumpAllocator mAlloc;
|
|
|
|
DbgModule* mDbgModule;
|
|
|
|
Dictionary<DbgSubprogram*, SubprogramRecord*> mRecords;
|
|
|
|
DbgSubprogram* mCurSubprogram;
|
|
|
|
SubprogramRecord* mCurRecord;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgLineDataBuilder(DbgModule* dbgModule);
|
|
|
|
// The pointer returned is invalid after the next add
|
|
|
|
DbgLineData* Add(DbgCompileUnit* compileUnit, DbgLineData& lineData, DbgSrcFile* srcFile, DbgSubprogram* inlinee);
|
|
|
|
void Commit();
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgLineDataState : public DbgLineData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
int mOpIndex;
|
|
|
|
int mDiscriminator;
|
|
|
|
int mIsa;
|
|
|
|
bool mBasicBlock;
|
|
|
|
bool mIsStmt;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgSrcFileReference
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgCompileUnit* mCompileUnit;
|
|
|
|
DbgSrcFile* mSrcFile;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgDeferredSrcFileReference
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgModule* mDbgModule;
|
|
|
|
int mCompileUnitId;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Array<DbgLineData*> LineDataVector;
|
|
|
|
|
|
|
|
class DbgLineDataList
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LineDataVector mLineData;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum DbgHashKind
|
|
|
|
{
|
|
|
|
DbgHashKind_None,
|
|
|
|
DbgHashKind_MD5,
|
|
|
|
DbgHashKind_SHA256
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgSrcFile
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
String mFilePath;
|
|
|
|
String mLocalPath;
|
|
|
|
bool mHadLineData;
|
|
|
|
bool mHasLineDataFromMultipleModules;
|
|
|
|
DbgFileExistKind mFileExistKind;
|
|
|
|
int mStepFilterVersion;
|
|
|
|
DbgHashKind mHashKind;
|
|
|
|
uint8 mHash[32];
|
|
|
|
DbgModule* mFirstLineDataDbgModule; // Just used to detect mHasLineDataFromMultipleModules
|
|
|
|
Array<DbgDeferredSrcFileReference> mDeferredRefs;
|
|
|
|
Array<DbgSubprogram*> mLineDataRefs;
|
|
|
|
Array<HotReplacedLineInfo*> mHotReplacedDbgLineInfo; // Indexing starts at -1
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgSrcFile()
|
|
|
|
{
|
|
|
|
mHasLineDataFromMultipleModules = false;
|
|
|
|
mFirstLineDataDbgModule = NULL;
|
|
|
|
mHadLineData = false;
|
|
|
|
mHashKind = DbgHashKind_None;
|
|
|
|
mFileExistKind = DbgFileExistKind_NotChecked;
|
|
|
|
mStepFilterVersion = 0;
|
|
|
|
|
|
|
|
//mLineData.Reserve(64);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsBeef();
|
|
|
|
|
|
|
|
~DbgSrcFile();
|
|
|
|
|
|
|
|
void RemoveDeferredRefs(DbgModule* debugModule);
|
|
|
|
void RemoveLines(DbgModule* debugModule);
|
|
|
|
void RemoveLines(DbgModule* debugModule, DbgSubprogram* dbgSubprogram, bool isHotReplaced);
|
|
|
|
void RehupLineData();
|
|
|
|
const String& GetLocalPath();
|
|
|
|
};
|
|
|
|
|
|
|
|
class DwCommonFrameDescriptor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgModule* mDbgModule;
|
|
|
|
const char* mAugmentation;
|
|
|
|
int mAugmentationLength;
|
|
|
|
int mPointerSize;
|
|
|
|
int mSegmentSize;
|
|
|
|
int mCodeAlignmentFactor;
|
|
|
|
int mDataAlignmentFactor;
|
|
|
|
int mReturnAddressColumn;
|
|
|
|
const uint8* mInstData;
|
|
|
|
int mInstLen;
|
|
|
|
int mAddressPointerEncoding;
|
|
|
|
addr_target mLSDARoutine;
|
|
|
|
int mLSDAPointerEncodingFDE;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DwCommonFrameDescriptor()
|
|
|
|
{
|
|
|
|
mPointerSize = -1;
|
|
|
|
mSegmentSize = -1;
|
|
|
|
mDbgModule = NULL;
|
|
|
|
mAugmentationLength = 0;
|
|
|
|
mAddressPointerEncoding = 0;
|
|
|
|
mLSDARoutine = 0;
|
|
|
|
mLSDAPointerEncodingFDE = 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DwFrameDescriptor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
addr_target mLowPC;
|
|
|
|
addr_target mHighPC;
|
|
|
|
const uint8* mInstData;
|
|
|
|
int mInstLen;
|
|
|
|
DwCommonFrameDescriptor* mCommonFrameDescriptor;
|
|
|
|
int mAddressPointerEncoding;
|
|
|
|
addr_target mLSDARoutine;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DwFrameDescriptor()
|
|
|
|
{
|
|
|
|
mAddressPointerEncoding = 0;
|
|
|
|
mLSDARoutine = 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgModule;
|
|
|
|
|
|
|
|
class DbgCompileUnitContrib
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgCompileUnitContrib* mNext;
|
|
|
|
DbgModule* mDbgModule;
|
|
|
|
addr_target mAddress;
|
|
|
|
int mCompileUnitId;
|
|
|
|
int mLength;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgCompileUnit
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const DbgClassType ClassType = DbgClassType_CompileUnit;
|
|
|
|
|
|
|
|
DbgModule* mDbgModule;
|
|
|
|
DbgLanguage mLanguage;
|
|
|
|
DbgBlock* mGlobalBlock;
|
|
|
|
DbgType* mGlobalType;
|
|
|
|
Array<DbgSrcFileReference> mSrcFileRefs;
|
|
|
|
String mName;
|
|
|
|
String mProducer;
|
|
|
|
String mCompileDir;
|
|
|
|
addr_target mLowPC;
|
|
|
|
addr_target mHighPC;
|
|
|
|
bool mNeedsLineDataFixup;
|
|
|
|
bool mWasHotReplaced;
|
|
|
|
bool mIsMaster;
|
|
|
|
|
|
|
|
SLIList<DbgSubprogram*> mOrphanMethods;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgCompileUnit(DbgModule* dbgModule);
|
|
|
|
|
|
|
|
virtual ~DbgCompileUnit()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//static int gDbgSymbol_Idx = 0;
|
|
|
|
class DbgSymbol
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
//int mDbgIdx;
|
|
|
|
DbgSymbol()
|
|
|
|
{
|
|
|
|
//mDbgIdx = ++gDbgSymbol_Idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
const char* mName;
|
|
|
|
addr_target mAddress;
|
|
|
|
DbgModule* mDbgModule;
|
|
|
|
DbgSymbol* mNext;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgSection
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
addr_target mAddrStart;
|
|
|
|
addr_target mAddrLength;
|
|
|
|
bool mWritingEnabled;
|
|
|
|
bool mIsExecutable;
|
|
|
|
int mOldProt;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgSection()
|
|
|
|
{
|
|
|
|
mAddrStart = 0;
|
|
|
|
mAddrLength = 0;
|
|
|
|
mWritingEnabled = false;
|
|
|
|
mIsExecutable = false;
|
|
|
|
mOldProt = 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DbgCharPtrHash
|
|
|
|
{
|
|
|
|
size_t operator()(const char* val) const
|
|
|
|
{
|
|
|
|
int curHash = 0;
|
|
|
|
const char* curHashPtr = val;
|
|
|
|
while (*curHashPtr != 0)
|
|
|
|
{
|
|
|
|
curHash = ((curHash ^ *curHashPtr) << 5) - curHash;
|
|
|
|
curHashPtr++;
|
|
|
|
}
|
|
|
|
return curHash;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DbgCharPtrEquals
|
|
|
|
{
|
|
|
|
bool operator()(const char* lhs, const char* rhs) const
|
|
|
|
{
|
|
|
|
return strcmp(lhs, rhs) == 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DbgFileNameHash
|
|
|
|
{
|
|
|
|
size_t operator()(const char* val) const
|
|
|
|
{
|
|
|
|
int curHash = 0;
|
|
|
|
const char* curHashPtr = val;
|
|
|
|
while (*curHashPtr != 0)
|
|
|
|
{
|
|
|
|
char c = *curHashPtr;
|
|
|
|
#ifdef _WIN32
|
|
|
|
c = toupper((uint8)c);
|
|
|
|
if (c == '\\')
|
|
|
|
c = '/';
|
|
|
|
#endif
|
|
|
|
curHash = ((curHash ^ c) << 5) - curHash;
|
|
|
|
curHashPtr++;
|
|
|
|
}
|
|
|
|
return curHash;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DbgFileNameEquals
|
|
|
|
{
|
|
|
|
bool operator()(const char* lhs, const char* rhs) const
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
char lc = toupper((uint8)*(lhs++));
|
|
|
|
if (lc == '\\')
|
|
|
|
lc = '/';
|
|
|
|
char rc = toupper((uint8)*(rhs++));
|
|
|
|
if (rc == '\\')
|
|
|
|
rc = '/';
|
|
|
|
if (lc != rc)
|
|
|
|
return false;
|
|
|
|
if (lc == 0)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
return strcmp(lhs, rhs) == 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DbgAutoStaticEntry
|
|
|
|
{
|
|
|
|
String mFullName;
|
|
|
|
DbgVariable* mVariable;
|
|
|
|
uint64 mAddrStart;
|
|
|
|
uint64 mAddrLen;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgHotTargetSection
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
uint8* mData;
|
|
|
|
int mDataSize;
|
|
|
|
addr_target mTargetSectionAddr;
|
|
|
|
int mImageOffset;
|
|
|
|
int mTargetSectionSize;
|
|
|
|
int mPointerToRelocations;
|
|
|
|
int mNumberOfRelocations;
|
|
|
|
bool mNoTargetAlloc;
|
|
|
|
bool mCanExecute;
|
|
|
|
bool mCanWrite;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgHotTargetSection()
|
|
|
|
{
|
|
|
|
mData = NULL;
|
|
|
|
mDataSize = 0;
|
|
|
|
mImageOffset = 0;
|
|
|
|
mTargetSectionAddr = 0;
|
|
|
|
mTargetSectionSize = 0;
|
|
|
|
mPointerToRelocations = 0;
|
|
|
|
mNumberOfRelocations = 0;
|
|
|
|
mCanExecute = false;
|
|
|
|
mCanWrite = false;
|
|
|
|
mNoTargetAlloc = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
~DbgHotTargetSection()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Dictionary<String, DbgType*> DbgTypeMapType;
|
|
|
|
typedef Dictionary<String, std::pair<uint64, uint64> > DbgAutoValueMapType;
|
|
|
|
typedef Dictionary<addr_target, int> DbgAutoStaticEntryBucketMap;
|
|
|
|
|
|
|
|
struct DbgDeferredHotResolve
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DbgHotTargetSection* mHotTargetSection;
|
|
|
|
String mName;
|
|
|
|
addr_target mNewAddr;
|
|
|
|
COFFRelocation mReloc;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgDataMap
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// All entries we want to put in this map are at least 4 bytes apart
|
|
|
|
static const int IDX_DIV = 4;
|
|
|
|
DbgDebugData** mAddrs;
|
|
|
|
int mOffset;
|
|
|
|
int mSize;
|
|
|
|
|
|
|
|
DbgDataMap(int startIdx, int endIdx)
|
|
|
|
{
|
|
|
|
mOffset = startIdx;
|
|
|
|
mSize = (((endIdx - startIdx) + IDX_DIV - 1) / IDX_DIV) + 4; // Add a few extra at the end
|
|
|
|
mAddrs = new DbgDebugData*[mSize];
|
|
|
|
memset(mAddrs, 0, sizeof(DbgDebugData*)*mSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
~DbgDataMap()
|
|
|
|
{
|
|
|
|
delete mAddrs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Set(int tagIdx, DbgDebugData* debugData)
|
|
|
|
{
|
|
|
|
BF_ASSERT(debugData->mTagIdx == 0);
|
|
|
|
debugData->mTagIdx = tagIdx;
|
|
|
|
|
|
|
|
int mapIdx = (tagIdx - mOffset) / IDX_DIV;
|
|
|
|
BF_ASSERT(mapIdx < mSize);
|
|
|
|
|
|
|
|
// Search for empty slot
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
BF_ASSERT(mapIdx < mSize);
|
|
|
|
if (mAddrs[mapIdx] == NULL)
|
|
|
|
{
|
|
|
|
mAddrs[mapIdx] = debugData;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mapIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
T Get(int tagIdx)
|
|
|
|
{
|
|
|
|
int mapIdx = (tagIdx - mOffset) / IDX_DIV;
|
|
|
|
|
|
|
|
// Search for right slot
|
|
|
|
while (mapIdx < mSize)
|
|
|
|
{
|
|
|
|
DbgDebugData* checkData = mAddrs[mapIdx];
|
|
|
|
if (checkData == NULL)
|
|
|
|
return NULL;
|
|
|
|
if (checkData->mTagIdx == tagIdx)
|
|
|
|
return (T)checkData;
|
|
|
|
mapIdx++;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class WdStackFrame;
|
|
|
|
|
|
|
|
enum DbgModuleLoadState
|
|
|
|
{
|
|
|
|
DbgModuleLoadState_NotLoaded,
|
|
|
|
DbgModuleLoadState_Failed,
|
|
|
|
DbgModuleLoadState_Loaded
|
|
|
|
};
|
|
|
|
|
|
|
|
struct DbgSizedArrayEntry
|
|
|
|
{
|
|
|
|
DbgType* mElementType;
|
|
|
|
int mCount;
|
|
|
|
|
|
|
|
bool operator==(const DbgSizedArrayEntry& other) const
|
|
|
|
{
|
|
|
|
return (other.mElementType == mElementType) &&
|
|
|
|
(other.mCount == mCount);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DbgModule
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static const int ImageBlockSize = 4096;
|
|
|
|
|
|
|
|
WinDebugger* mDebugger;
|
|
|
|
DebugTarget* mDebugTarget;
|
|
|
|
DbgModuleLoadState mLoadState;
|
|
|
|
MappedFile* mMappedImageFile;
|
|
|
|
MemReporter* mMemReporter;
|
|
|
|
|
|
|
|
const uint8* mDebugLineData;
|
|
|
|
const uint8* mDebugInfoData;
|
|
|
|
const uint8* mDebugPubNames;
|
|
|
|
const uint8* mDebugFrameData;
|
|
|
|
const uint8* mDebugLocationData;
|
|
|
|
const uint8* mDebugRangesData;
|
|
|
|
addr_target mDebugFrameAddress;
|
|
|
|
addr_target mCodeAddress;
|
|
|
|
const uint8* mDebugAbbrevData;
|
|
|
|
const uint8* mDebugStrData;
|
2019-09-02 17:39:47 -07:00
|
|
|
const uint8** mDebugAbbrevPtrData;
|
|
|
|
Array<DbgSectionData> mExceptionDirectory;
|
2019-08-23 11:56:54 -07:00
|
|
|
const uint8* mEHFrameData;
|
|
|
|
const char* mStringTable;
|
|
|
|
const uint8* mSymbolData;
|
|
|
|
addr_target mEHFrameAddress;
|
|
|
|
addr_target mTLSAddr;
|
|
|
|
addr_target mTLSExtraAddr;
|
|
|
|
int mTLSSize;
|
|
|
|
int mTLSExtraSize;
|
|
|
|
addr_target mTLSIndexAddr;
|
|
|
|
DbgFlavor mDbgFlavor;
|
|
|
|
|
|
|
|
bool mParsedGlobalsData;
|
|
|
|
bool mParsedSymbolData;
|
|
|
|
bool mParsedTypeData;
|
|
|
|
bool mPopulatedStaticVariables;
|
|
|
|
bool mParsedFrameDescriptors;
|
|
|
|
|
|
|
|
bool mMayBeOld; // If we had to load debug info from the SymCache or a SymServer then it may be old
|
|
|
|
bool mDeleting;
|
|
|
|
bool mFailed;
|
|
|
|
int mHotIdx;
|
|
|
|
String mFilePath;
|
|
|
|
String mDisplayName;
|
|
|
|
uint32 mTimeStamp;
|
|
|
|
uint32 mExpectedFileSize;
|
|
|
|
int mStartSubprogramIdx;
|
|
|
|
int mEndSubprogramIdx;
|
|
|
|
int mStartTypeIdx;
|
|
|
|
int mEndTypeIdx;
|
|
|
|
uintptr mPreferredImageBase;
|
|
|
|
uintptr mImageBase;
|
|
|
|
uint32 mImageSize;
|
|
|
|
uintptr mEntryPoint;
|
|
|
|
String mVersion;
|
|
|
|
String* mFailMsgPtr;
|
|
|
|
|
|
|
|
DbgModuleMemoryCache* mOrigImageData;
|
|
|
|
DbgCompileUnit* mMasterCompileUnit;
|
|
|
|
StrHashMap<DbgVariable*> mGlobalVarMap; // Dedups entries into mMasterCompileUnit
|
|
|
|
|
|
|
|
BumpAllocator mAlloc;
|
|
|
|
|
|
|
|
std::list<DwAsmDebugLineMap> mAsmDebugLineMaps;
|
|
|
|
Array<DbgSection> mSections;
|
|
|
|
Dictionary<addr_target, int> mSecRelEncodingMap;
|
|
|
|
Array<addr_target> mSecRelEncodingVec;
|
|
|
|
bool mCheckedBfObject;
|
|
|
|
bool mBfObjectHasFlags;
|
|
|
|
bool mIsHotObjectFile;
|
|
|
|
bool mIsDwarf64;
|
|
|
|
|
|
|
|
HashSet<DbgSrcFile*> mSrcFileDeferredRefs;
|
|
|
|
Array<addr_target> mSectionRVAs;
|
|
|
|
SLIList<DbgSymbol*> mDeferredSymbols;
|
|
|
|
Beefy::OwnedVector<DbgDeferredHotResolve> mDeferredHotResolveList;
|
|
|
|
Array<DbgHotTargetSection*> mHotTargetSections;
|
|
|
|
HashSet<DbgType*> mHotPrimaryTypes; // List of types where we have entries in mHotReplacedMethodList
|
|
|
|
DbgCompileUnit mDefaultCompileUnit;
|
|
|
|
Dictionary<DbgType*, DbgType*> mConstTypes;
|
|
|
|
Dictionary<String, DbgFileExistKind> mFileExistsCache;
|
|
|
|
Dictionary<DbgSizedArrayEntry, DbgType*> mSizedArrayTypes;
|
|
|
|
|
|
|
|
int mAllocSizeData;
|
|
|
|
Array<const uint8*> mOwnedSectionData;
|
|
|
|
|
|
|
|
public:
|
|
|
|
Array<DbgSrcFile*> mEmptySrcFiles;
|
|
|
|
Array<DbgCompileUnit*> mCompileUnits;
|
|
|
|
Array<DbgVariable*> mStaticVariables;
|
|
|
|
|
|
|
|
DbgType* mCPrimitiveTypes[DbgType_COUNT];
|
|
|
|
DbgType* mBfPrimitiveTypes[DbgType_COUNT];
|
|
|
|
const char* mPrimitiveStructNames[DbgType_COUNT];
|
|
|
|
DbgTypeMap mTypeMap;
|
|
|
|
|
|
|
|
Array<DbgType*> mTypes;
|
|
|
|
Array<DbgSubprogram*> mSubprograms;
|
|
|
|
|
|
|
|
StrHashMap<DbgSymbol*> mSymbolNameMap;
|
|
|
|
std::unordered_map<const char*, DbgVariable*, DbgCharPtrHash, DbgCharPtrEquals> mStaticVariableMap;
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual void ParseGlobalsData();
|
|
|
|
virtual void ParseSymbolData();
|
|
|
|
virtual void ParseTypeData();
|
|
|
|
virtual DbgCompileUnit* ParseCompileUnit(int compileUnitId);
|
|
|
|
virtual void MapCompileUnitMethods(DbgCompileUnit* compileUnit);
|
|
|
|
virtual void MapCompileUnitMethods(int compileUnitId);
|
|
|
|
virtual void PopulateType(DbgType* dbgType);
|
|
|
|
virtual void PopulateTypeGlobals(DbgType* dbgType);
|
|
|
|
virtual void PopulateSubprogram(DbgSubprogram* dbgSubprogram) { }
|
|
|
|
virtual void FixupInlinee(DbgSubprogram* dbgSubprogram) {}
|
|
|
|
virtual void PopulateStaticVariableMap();
|
|
|
|
virtual void ProcessDebugInfo();
|
|
|
|
virtual bool CanGetOldSource() { return false; }
|
|
|
|
virtual String GetOldSourceCommand(const StringImpl& path) { return ""; }
|
|
|
|
virtual bool DbgIsStrMutable(const char* str) { return true; } // Always assume its a copy
|
|
|
|
virtual addr_target LocateSymbol(const StringImpl& name) { return 0; }
|
|
|
|
|
|
|
|
void Fail(const StringImpl& error);
|
|
|
|
void FindTemplateStr(const char*& name, int& templateNameIdx);
|
|
|
|
void TempRemoveTemplateStr(const char*& name, int& templateNameIdx);
|
|
|
|
void ReplaceTemplateStr(const char*& name, int& templateNameIdx);
|
|
|
|
|
|
|
|
char* DbgDupString(const char* str, const char* allocName = NULL);
|
|
|
|
DbgModule* GetLinkedModule();
|
|
|
|
addr_target GetTargetImageBase();
|
|
|
|
addr_target RemapAddr(addr_target addr);
|
|
|
|
template <typename T>
|
|
|
|
T GetOrCreate(int idx, DbgDataMap& dataMap);
|
|
|
|
DbgType* GetOrCreateType(int typeIdx, DbgDataMap& typeMap);
|
|
|
|
//void SplitName(const char* inName, const char*& outBaseName, const char*& outTemplateParams, bool alwaysDup = false);
|
|
|
|
void MapSubprogram(DbgSubprogram* dbgSubprogram);
|
|
|
|
bool ParseDWARF(const uint8*& dataPtr);
|
|
|
|
void ParseAbbrevData(const uint8* data);
|
|
|
|
void ParseExceptionData();
|
|
|
|
void ParseDebugFrameData();
|
|
|
|
void ParseEHFrameData();
|
|
|
|
void FlushLineData(DbgSubprogram* curSubprogram, std::list<DbgLineData>& queuedLineData);
|
|
|
|
DbgSrcFile* AddSrcFile(DbgCompileUnit* compileUnit, const String& srcFilePath);
|
|
|
|
void AddLineData(DbgCompileUnit* dwCompileUnit, DbgLineData& lineData, DbgSubprogram*& curSubProgram, std::list<DbgLineData>& queuedLineData);
|
|
|
|
bool ParseDebugLineInfo(const uint8*& data, int compileUnitIdx);
|
|
|
|
void FixupInnerTypes(int startingTypeIdx);
|
|
|
|
void MapTypes(int startingTypeIdx);
|
|
|
|
void CreateNamespaces();
|
|
|
|
bool IsHotSwapPreserve(const String& name);
|
|
|
|
addr_target GetHotTargetAddress(DbgHotTargetSection* hotTargetSection);
|
|
|
|
uint8* GetHotTargetData(addr_target address);
|
|
|
|
void DoReloc(DbgHotTargetSection* hotTargetSection, COFFRelocation& coffReloc, addr_target resolveSymbolAddr, PE_SymInfo* symInfo);
|
|
|
|
void ParseHotTargetSections(DataStream* stream, addr_target* resovledSymbolAddrs);
|
|
|
|
void CommitHotTargetSections();
|
|
|
|
void HotReplaceType(DbgType* newType);
|
|
|
|
void ProcessHotSwapVariables();
|
|
|
|
virtual bool LoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge) { return false; }
|
|
|
|
virtual bool CheckSection(const char* name, uint8* sectionData, int sectionSize) { return false; }
|
|
|
|
virtual void PreCacheImage() {}
|
|
|
|
virtual void PreCacheDebugInfo() {}
|
|
|
|
virtual bool RequestImage() { return false; }
|
|
|
|
virtual bool HasPendingDebugInfo() { return false; }
|
|
|
|
virtual bool RequestDebugInfo(bool allowRemote = true) { return false; }
|
|
|
|
virtual bool WantsAutoLoadDebugInfo() { return false; }
|
|
|
|
virtual DbgFileExistKind CheckSourceFileExist(const StringImpl& path);
|
|
|
|
virtual void ParseFrameDescriptors() {}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
T ReadValue(const uint8*& data, int form, int refOffset = 0, const uint8** extraData = NULL, const uint8* startData = NULL);
|
|
|
|
|
|
|
|
void EnableWriting(addr_target address);
|
|
|
|
void RevertWritingEnable();
|
|
|
|
|
|
|
|
public:
|
|
|
|
DbgModule(DebugTarget* debugTarget);
|
|
|
|
virtual ~DbgModule();
|
|
|
|
|
|
|
|
static bool CanRead(DataStream* stream, DebuggerResult* outResult);
|
|
|
|
|
|
|
|
bool ReadCOFF(DataStream* stream, bool isHotObjectFile);
|
|
|
|
void RemoveTargetData();
|
|
|
|
virtual void ReportMemory(MemReporter* memReporter);
|
|
|
|
|
|
|
|
int64 GetImageSize();
|
|
|
|
virtual void FinishHotSwap();
|
|
|
|
addr_target ExecuteOps(DbgSubprogram* dwSubprogram, const uint8* locData, int locDataLen, WdStackFrame* stackFrame, CPURegisters* registers, DbgAddrType* outAddrType, bool allowReg, addr_target* pushValue = NULL);
|
|
|
|
virtual addr_target EvaluateLocation(DbgSubprogram* dwSubprogram, const uint8* locData, int locDataLen, WdStackFrame* stackFrame, DbgAddrType* outAddrType, bool allowReg = true);
|
|
|
|
|
|
|
|
//const uint8* CopyOrigImageData(addr_target address, int length);
|
|
|
|
|
|
|
|
DbgType* FindTypeHelper(const String& typeName, DbgType* checkType);
|
|
|
|
DbgType* FindType(const String& typeName, DbgType* contextType = NULL, DbgLanguage language = DbgLanguage_Unknown);
|
|
|
|
DbgTypeMap::Entry* FindType(const char* typeName, DbgLanguage language);
|
|
|
|
|
|
|
|
DbgType* GetPointerType(DbgType* innerType);
|
|
|
|
DbgType* GetConstType(DbgType* innerType);
|
|
|
|
DbgType* GetPrimaryType(DbgType* dbgType);
|
|
|
|
DbgType* GetPrimitiveType(DbgTypeCode typeCode, DbgLanguage language);
|
|
|
|
DbgType* GetPrimitiveStructType(DbgTypeCode typeCode);
|
|
|
|
DbgType* GetInnerTypeOrVoid(DbgType* dbgType);
|
|
|
|
DbgType* GetSizedArrayType(DbgType* elementType, int count);
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_BF_END
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
template<>
|
|
|
|
struct hash<NS_BF_DBG::DbgSizedArrayEntry>
|
|
|
|
{
|
|
|
|
size_t operator()(const NS_BF_DBG::DbgSizedArrayEntry& val) const
|
|
|
|
{
|
|
|
|
return (size_t)val.mElementType ^ (val.mCount << 10);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|