2019-09-21 10:49:35 -07:00
# include "COFF.h"
# include "BeefySysLib/FileStream.h"
# include "BeefySysLib/MemStream.h"
# include "codeview/cvinfo.h"
# include "DebugTarget.h"
# include "DebugManager.h"
# include "DWARFInfo.h"
2022-04-16 06:27:54 -07:00
# include "BeefySysLib/util/PerfTimer.h"
# include "BeefySysLib/util/Dictionary.h"
# include "BeefySysLib/util/BeefPerf.h"
# include "BeefySysLib/util/BeefPerf.h"
# include "BeefySysLib/util/ZipFile.h"
# include "BeefySysLib/util/Hash.h"
2019-09-21 10:49:35 -07:00
# include "BeefySysLib/platform/PlatformHelper.h"
# include "WinDebugger.h"
# include "MiniDumpDebugger.h"
# include "Linker/BlHash.h"
# include "Backend/BeLibManger.h"
2022-04-16 06:27:54 -07:00
# include "Compiler/BfUtil.h"
2019-09-21 10:49:35 -07:00
# include <shlobj.h>
# include "BeefySysLib/util/AllocDebug.h"
2020-11-18 09:15:28 -08:00
# define LF_CLASS_EX 0x1608
# define LF_STRUCTURE_EX 0x1609
2019-09-21 10:49:35 -07:00
USING_NS_BF_DBG ;
# define MSF_SIGNATURE_700 "Microsoft C / C++ MSF 7.00\r\n\032DS\0\0"
static const int NUM_ROOT_DIRS = 73 ;
# pragma warning(default:4800)
# define ADDR_FLAG_ABS 0x8000000000000000L
# define GET(T) *((T*)(data += sizeof(T)) - 1)
# define GET_INTO(T, name) T name = GET(T)
# define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1)
# define PTR_ALIGN(ptr, origPtr, alignSize) ptr = ( (origPtr)+( ((ptr - origPtr) + (alignSize - 1)) & ~(alignSize - 1) ) )
static const char * DataGetString ( uint8 * & data )
{
const char * prevVal = ( const char * ) data ;
while ( * data ! = 0 )
data + + ;
data + + ;
return prevVal ;
}
# define CREATE_PRIMITIVE(pdbTypeCode, dwTypeCode, typeName, type) \
BP_ALLOC_T ( DbgType ) ; \
dbgType = mAlloc . Alloc < DbgType > ( ) ; \
dbgType - > mCompileUnit = mMasterCompileUnit ; \
dbgType - > mTypeName = typeName ; \
dbgType - > mName = typeName ; \
dbgType - > mTypeCode = dwTypeCode ; \
dbgType - > mSize = sizeof ( type ) ; \
dbgType - > mAlign = sizeof ( type ) ; \
mCvSystemTypes [ ( int ) pdbTypeCode ] = dbgType ; \
\
BP_ALLOC_T ( DbgType ) ; \
ptrType = mAlloc . Alloc < DbgType > ( ) ; \
ptrType - > mCompileUnit = mMasterCompileUnit ; \
ptrType - > mTypeCode = DbgType_Ptr ; \
ptrType - > mSize = sizeof ( addr_target ) ; \
ptrType - > mAlign = sizeof ( addr_target ) ; \
ptrType - > mTypeParam = dbgType ; \
dbgType - > mPtrType = ptrType ; \
mCvSystemTypes [ ( int ) pdbTypeCode | ptrMask ] = ptrType ;
# define REGISTER_PRIMITIVE() mTypeMap.Insert(dbgType)
static const char * GetLastDoubleColon ( const char * name )
{
int templateDepth = 0 ;
int parenDepth = 0 ;
const char * lastDblColon = NULL ;
for ( const char * checkPtr = name ; * checkPtr ! = ' \0 ' ; checkPtr + + )
{
char c = checkPtr [ 0 ] ;
if ( c = = ' < ' )
templateDepth + + ;
else if ( c = = ' > ' )
templateDepth - - ;
else if ( c = = ' ( ' )
parenDepth + + ;
else if ( c = = ' ) ' )
parenDepth - - ;
if ( ( templateDepth = = 0 ) & & ( parenDepth = = 0 ) & & ( c = = ' : ' ) & & ( checkPtr [ 1 ] = = ' : ' ) )
lastDblColon = checkPtr ;
if ( ( templateDepth = = 0 ) & & ( parenDepth = = 0 ) & & ( c = = ' ' ) )
{
// This catches cases like "Beefy::BfMethodRef::operator Beefy::BfMethodInstance*", where we want to match the :: right before "operator"
break ;
}
}
return lastDblColon ;
}
static const char * GetNamespaceEnd ( const char * name )
{
int templateDepth = 0 ;
const char * lastDblColon = NULL ;
for ( const char * checkPtr = name ; * checkPtr ! = ' \0 ' ; checkPtr + + )
{
char c = checkPtr [ 0 ] ;
if ( ( c = = ' < ' ) | | ( c = = ' ' ) )
return NULL ;
if ( ( c = = ' : ' ) & & ( checkPtr [ 1 ] = = ' : ' ) )
2022-07-30 09:08:49 -04:00
lastDblColon = checkPtr ;
2019-09-21 10:49:35 -07:00
}
return lastDblColon ;
}
// This version inserts namespaces that contain specialized methods, but since we don't (at the time of this comment) support
// calling specialized methods, we don't bother doing this -- it increases the scan time
#if 0
static const char * GetNamespaceEnd ( const char * name )
{
bool hadTemplate = false ;
int templateDepth = 0 ;
const char * lastDblColon = NULL ;
for ( const char * checkPtr = name ; * checkPtr ! = ' \0 ' ; checkPtr + + )
{
char c = checkPtr [ 0 ] ;
if ( c = = ' < ' )
{
hadTemplate = true ;
templateDepth + + ;
}
else if ( c = = ' > ' )
templateDepth - - ;
if ( ( templateDepth = = 0 ) & & ( c = = ' : ' ) & & ( checkPtr [ 1 ] = = ' : ' ) )
{
if ( hadTemplate )
{
// This is to reject cases like NameSpace::TypeName<int>::sField - since we know that there's a typename attached and we just want 'loose' namespaces,
// But this still allows NameSpace::Method<int>, where "NameSpace" is indeed a loose namespace we need to catch
return NULL ;
}
lastDblColon = checkPtr ;
}
if ( ( templateDepth = = 0 ) & & ( c = = ' ' ) )
{
// This catches cases like "Beefy::BfMethodRef::operator Beefy::BfMethodInstance*", where we want to match the :: right before "operator"
// In these cases we do know this is an operator method name so it's not in a loose namespace
return NULL ;
}
}
return lastDblColon ;
}
# endif
//////////////////////////////////////////////////////////////////////////
uint8 * CvStreamReader : : GetTempPtr ( int offset , int size , bool mayRecurse , bool * madeCopy )
{
int pageStart = offset > > mPageBits ;
int pageEnd = ( offset + size - 1 ) > > mPageBits ;
if ( pageStart > = pageEnd )
return mStreamPtrs . mVals [ pageStart ] + ( offset & ( ( 1 < < mPageBits ) - 1 ) ) ;
2022-07-30 09:08:49 -04:00
// Handle the relatively-rare case of spanning multiple pages
2019-09-21 10:49:35 -07:00
if ( madeCopy ! = NULL )
* madeCopy = true ;
uint8 * destPtr ;
if ( mayRecurse )
{
if ( mCOFF - > mTempBufIdx > = mCOFF - > mTempBufs . size ( ) )
mCOFF - > mTempBufs . push_back ( Array < uint8 > ( ) ) ;
auto & arr = mCOFF - > mTempBufs [ mCOFF - > mTempBufIdx + + ] ;
if ( arr . size ( ) < size )
arr . Resize ( size ) ;
destPtr = arr . mVals ;
}
else
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( mTempData . size ( ) < size )
mTempData . Resize ( size ) ;
destPtr = mTempData . mVals ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
uint8 * dest = destPtr ;
while ( size > 0 )
{
int copyPage = offset > > mPageBits ;
int pageOffset = offset & ( ( 1 < < mPageBits ) - 1 ) ;
int copyBytes = BF_MIN ( mCOFF - > mCvPageSize - pageOffset , size ) ;
memcpy ( destPtr , mStreamPtrs . mVals [ copyPage ] + pageOffset , copyBytes ) ;
destPtr + = copyBytes ;
offset + = copyBytes ;
2022-07-30 09:08:49 -04:00
size - = copyBytes ;
2019-09-21 10:49:35 -07:00
}
return dest ;
}
uint8 * CvStreamReader : : GetPermanentPtr ( int offset , int size , bool * madeCopy )
{
int pageStart = offset > > mPageBits ;
int pageEnd = ( offset + size - 1 ) > > mPageBits ;
2022-07-30 09:08:49 -04:00
if ( pageStart = = pageEnd )
return mStreamPtrs . mVals [ pageStart ] + ( offset & ( ( 1 < < mPageBits ) - 1 ) ) ;
// Handle the relatively-rare case of spanning multiple pages
2019-09-21 10:49:35 -07:00
BP_ALLOC ( " GetPermanentPtr " , size ) ;
uint8 * destData = mCOFF - > mAlloc . AllocBytes ( size , " GetPermanentPtr " ) ;
if ( madeCopy ! = NULL )
* madeCopy = true ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
uint8 * destPtr = destData ;
while ( size > 0 )
{
int copyPage = offset > > mPageBits ;
int pageOffset = offset & ( ( 1 < < mPageBits ) - 1 ) ;
int copyBytes = BF_MIN ( mCOFF - > mCvPageSize - pageOffset , size ) ;
memcpy ( destPtr , mStreamPtrs . mVals [ copyPage ] + pageOffset , copyBytes ) ;
destPtr + = copyBytes ;
offset + = copyBytes ;
size - = copyBytes ;
}
return destData ;
}
//////////////////////////////////////////////////////////////////////////
COFF : : COFF ( DebugTarget * debugTarget ) : DbgModule ( debugTarget )
{
mParseKind = ParseKind_Full ;
2022-07-30 09:08:49 -04:00
memset ( mWantPDBGuid , 0 , 16 ) ;
memset ( mPDBGuid , 0 , 16 ) ;
2019-09-27 13:05:39 -07:00
mWantAge = - 1 ;
2019-09-21 10:49:35 -07:00
mDebugAge = - 1 ;
mFileAge = - 1 ;
mCvMinTag = - 1 ;
2022-07-30 09:08:49 -04:00
mCvMaxTag = - 1 ;
2019-09-21 10:49:35 -07:00
mCvIPIMinTag = - 1 ;
mCvIPIMaxTag = - 1 ;
mMasterCompileUnit = NULL ;
mTempBufIdx = 0 ;
2020-08-11 09:26:21 -07:00
mIs64Bit = false ;
2019-09-21 10:49:35 -07:00
mCvPageSize = 0 ;
mCvPageBits = 31 ;
mCvDataStream = NULL ;
2022-07-30 09:08:49 -04:00
mCvHeaderData = NULL ;
mCvStrTableData = NULL ;
2019-09-21 10:49:35 -07:00
mCvPublicSymbolData = NULL ;
mCvGlobalSymbolData = NULL ;
mNewFPOData = NULL ;
mCvGlobalSymbolInfoStream = 0 ;
mCvPublicSymbolInfoStream = 0 ;
mCvSymbolRecordStream = 0 ;
mCvNewFPOStream = 0 ;
mCvMappedFile = INVALID_HANDLE_VALUE ;
mCvMappedFileMapping = INVALID_HANDLE_VALUE ;
mCvMappedViewOfFile = NULL ;
mCvMappedFileSize = 0 ;
//mParsedProcRecs = false;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
mGlobalsTargetType = NULL ;
mPrevScanName = NULL ;
2022-07-30 09:08:49 -04:00
mProcSymCount = 0 ;
2019-09-21 10:49:35 -07:00
mCvSrcSrvStream = - 1 ;
2022-04-16 06:27:54 -07:00
mCvEmitStream = - 1 ;
2019-09-21 10:49:35 -07:00
mIsFastLink = false ;
mHotThunkCurAddr = 0 ;
mHotThunkDataLeft = 0 ;
mTriedSymSrv = false ;
2022-07-30 09:08:49 -04:00
mDbgSymRequest = NULL ;
mWantsAutoLoadDebugInfo = false ;
2019-09-21 10:49:35 -07:00
mPDBLoaded = false ;
2022-04-16 06:27:54 -07:00
mEmitSourceFile = NULL ;
2019-09-21 10:49:35 -07:00
}
COFF : : ~ COFF ( )
{
BF_ASSERT ( mTempBufIdx = = 0 ) ;
ClosePDB ( ) ;
2022-07-30 09:08:49 -04:00
mDebugger - > mDbgSymSrv . ReleaseRequest ( mDbgSymRequest ) ;
2019-09-21 10:49:35 -07:00
}
const char * COFF : : CvCheckTargetMatch ( const char * name , bool & wasBeef )
2022-04-16 13:22:47 -07:00
{
if ( mGlobalsTargetType = = NULL )
return NULL ;
2019-09-21 10:49:35 -07:00
/*if (mGlobalsTargetType->IsGlobalsContainer())
{
wasBeef = true ;
}
else */ if ( mGlobalsTargetType - > mLanguage = = DbgLanguage_Beef )
{
if ( strncmp ( name , " _bf:: " , 5 ) ! = 0 )
return NULL ;
name + = 5 ;
wasBeef = true ;
}
else if ( mGlobalsTargetType - > mTypeCode = = DbgType_Root )
{
if ( strncmp ( name , " _bf:: " , 5 ) = = 0 )
{
wasBeef = true ;
name + = 5 ;
}
}
if ( mGlobalsTargetType - > mName = = NULL )
{
for ( const char * cPtr = name ; * cPtr ! = ' \0 ' ; cPtr + + )
{
if ( * cPtr = = ' : ' )
return NULL ;
if ( * cPtr = = ' < ' )
return NULL ;
}
return name ;
}
const char * memberNamePtr = name ;
const char * typeName = mGlobalsTargetType - > mName ;
while ( true )
{
char cm = * ( memberNamePtr + + ) ;
char ct = * ( typeName + + ) ;
if ( ct = = 0 )
{
if ( cm = = ' : ' )
{
const char * memberName = memberNamePtr + 1 ;
for ( const char * cPtr = memberName ; * cPtr ! = ' \0 ' ; cPtr + + )
{
if ( * cPtr = = ' : ' )
return NULL ;
if ( * cPtr = = ' < ' )
return NULL ;
}
return memberName ;
}
return NULL ;
}
if ( cm ! = ct )
{
if ( ( cm = = ' : ' ) & & ( ct = = ' . ' ) & & ( memberNamePtr [ 0 ] = = ' : ' ) )
{
memberNamePtr + + ;
continue ;
}
return NULL ;
}
}
}
int COFF : : CvGetStringHash ( const char * str )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( str = = NULL )
return 0 ;
int curHash = 0 ;
const char * curHashPtr = str ;
while ( * curHashPtr ! = 0 )
{
2022-07-30 09:08:49 -04:00
char c = * curHashPtr ;
2019-09-21 10:49:35 -07:00
curHash = ( ( curHash ^ * curHashPtr ) < < 5 ) - curHash ;
curHashPtr + + ;
}
return curHash & 0x3FFFFFFF ;
}
// Remove "__ptr64"
void COFF : : CvFixupName ( char * name )
{
char * cPtrOut = NULL ;
for ( char * cPtr = name ; * cPtr ! = ' \0 ' ; cPtr + + )
{
if ( ( cPtr [ 0 ] = = ' _ ' ) & & ( cPtr [ 1 ] = = ' _ ' ) )
{
if ( strncmp ( cPtr + 2 , " ptr64 " , 5 ) = = 0 )
{
if ( cPtrOut = = NULL )
cPtrOut = cPtr ;
cPtr + = 6 ;
}
}
else if ( cPtrOut ! = NULL )
{
* ( cPtrOut + + ) = * cPtr ;
}
}
2022-07-30 09:08:49 -04:00
if ( cPtrOut ! = NULL )
* ( cPtrOut + + ) = ' \0 ' ;
2019-09-21 10:49:35 -07:00
}
void COFF : : InitCvTypes ( )
{
if ( mMasterCompileUnit ! = NULL )
{
BF_ASSERT ( mCompileUnits . size ( ) = = 1 ) ;
return ;
}
mDbgFlavor = DbgFlavor_MS ;
mCvSystemTypes . Resize ( 0x700 ) ;
DbgType * dbgType ;
DbgType * ptrType ;
# ifdef BF_DBG_32
const int ptrMask = 0x0400 ; // T_32*
# else
const int ptrMask = 0x0600 ; // T_64*
# endif
2022-07-30 09:08:49 -04:00
mMasterCompileUnit = new DbgCompileUnit ( this ) ;
mMasterCompileUnit - > mDbgModule = this ;
2019-09-21 10:49:35 -07:00
mMasterCompileUnit - > mIsMaster = true ;
mCompileUnits . push_back ( mMasterCompileUnit ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
CREATE_PRIMITIVE ( T_NOTTRANS , DbgType_Void , " void " , void * ) ;
mCvSystemTypes [ T_NOTTRANS ] - > mSize = 0 ;
mCvSystemTypes [ T_NOTTRANS ] - > mAlign = 0 ;
CREATE_PRIMITIVE ( T_NOTYPE , DbgType_Void , " void " , void * ) ;
mCvSystemTypes [ T_NOTYPE ] - > mSize = 0 ;
mCvSystemTypes [ T_NOTYPE ] - > mAlign = 0 ;
2022-07-30 09:08:49 -04:00
CREATE_PRIMITIVE ( T_VOID , DbgType_Void , " void " , void * ) ;
2019-09-21 10:49:35 -07:00
mCvSystemTypes [ T_VOID ] - > mSize = 0 ;
mCvSystemTypes [ T_VOID ] - > mAlign = 0 ;
mCvSystemTypes [ T_PVOID ] = ptrType ;
2022-01-09 08:30:56 -05:00
# ifdef BF_DBG_32
BP_ALLOC_T ( DbgType ) ;
ptrType = mAlloc . Alloc < DbgType > ( ) ;
ptrType - > mCompileUnit = mMasterCompileUnit ;
ptrType - > mTypeCode = DbgType_Ptr ;
ptrType - > mSize = 8 ;
ptrType - > mAlign = 8 ;
ptrType - > mTypeParam = dbgType ;
dbgType - > mPtrType = ptrType ;
mCvSystemTypes [ ( int ) T_VOID | 0x0600 ] = ptrType ;
2022-07-30 09:08:49 -04:00
# endif
2022-01-09 08:30:56 -05:00
2019-09-21 10:49:35 -07:00
# ifdef BF_DBG_32
CREATE_PRIMITIVE ( T_HRESULT , DbgType_u32 , " HRESULT " , addr_target ) ;
# else
CREATE_PRIMITIVE ( T_HRESULT , DbgType_u64 , " HRESULT " , addr_target ) ;
# endif
CREATE_PRIMITIVE ( T_CHAR , DbgType_SChar , " char " , char ) ;
CREATE_PRIMITIVE ( T_RCHAR , DbgType_SChar , " char " , char ) ; REGISTER_PRIMITIVE ( ) ;
CREATE_PRIMITIVE ( T_UCHAR , DbgType_UChar , " char8 " , uint8 ) ; REGISTER_PRIMITIVE ( ) ;
CREATE_PRIMITIVE ( T_WCHAR , DbgType_SChar16 , " wchar " , uint16 ) ; REGISTER_PRIMITIVE ( ) ;
CREATE_PRIMITIVE ( T_CHAR16 , DbgType_UChar16 , " char16 " , uint16 ) ;
CREATE_PRIMITIVE ( T_CHAR32 , DbgType_UChar32 , " char32 " , uint32 ) ;
CREATE_PRIMITIVE ( T_INT1 , DbgType_i8 , " sbyte " , int8 ) ;
CREATE_PRIMITIVE ( T_UINT1 , DbgType_u8 , " byte " , uint8 ) ;
CREATE_PRIMITIVE ( T_SHORT , DbgType_i16 , " short " , int16 ) ;
CREATE_PRIMITIVE ( T_INT2 , DbgType_i16 , " short " , int16 ) ;
CREATE_PRIMITIVE ( T_USHORT , DbgType_u16 , " ushort " , uint16 ) ;
CREATE_PRIMITIVE ( T_UINT2 , DbgType_u16 , " ushort " , uint16 ) ;
CREATE_PRIMITIVE ( T_LONG , DbgType_i32 , " int " , int32 ) ;
CREATE_PRIMITIVE ( T_INT4 , DbgType_i32 , " int " , int32 ) ;
CREATE_PRIMITIVE ( T_ULONG , DbgType_i32 , " uint " , uint32 ) ;
CREATE_PRIMITIVE ( T_UINT4 , DbgType_u32 , " uint " , uint32 ) ;
CREATE_PRIMITIVE ( T_QUAD , DbgType_i64 , " int64 " , int64 ) ;
CREATE_PRIMITIVE ( T_INT8 , DbgType_i64 , " int64 " , int64 ) ; REGISTER_PRIMITIVE ( ) ;
CREATE_PRIMITIVE ( T_UQUAD , DbgType_u64 , " uint64 " , uint64 ) ;
CREATE_PRIMITIVE ( T_UINT8 , DbgType_u64 , " uint64 " , uint64 ) ; REGISTER_PRIMITIVE ( ) ;
CREATE_PRIMITIVE ( T_OCT , DbgType_i128 , " int128 " , uint128 ) ;
CREATE_PRIMITIVE ( T_INT16 , DbgType_i128 , " int128 " , uint128 ) ;
CREATE_PRIMITIVE ( T_UOCT , DbgType_u128 , " uint128 " , uint128 ) ;
CREATE_PRIMITIVE ( T_UINT16 , DbgType_u128 , " uint128 " , uint128 ) ;
CREATE_PRIMITIVE ( T_BOOL08 , DbgType_Bool , " bool " , bool ) ;
CREATE_PRIMITIVE ( T_BOOL32 , DbgType_Bool , " bool " , int32 ) ;
CREATE_PRIMITIVE ( T_REAL32 , DbgType_Single , " float " , float ) ;
CREATE_PRIMITIVE ( T_REAL64 , DbgType_Double , " double " , double ) ;
CREATE_PRIMITIVE ( T_REAL80 , DbgType_Double , " double80 " , double ) ; // This isn't correct
}
addr_target COFF : : GetSectionAddr ( uint16 section , uint32 offset )
{
if ( section = = 0 )
return offset ;
if ( ( section & 0x8000 ) ! = 0 )
{
auto linkedModule = GetLinkedModule ( ) ;
addr_target hiBase = linkedModule - > mSecRelEncodingVec [ section & 0x7FFF ] ;
return hiBase + offset ;
}
int rva = mSectionRVAs [ section - 1 ] ;
if ( rva = = 0 )
return ADDR_FLAG_ABS + offset ;
return ( addr_target ) mImageBase + rva + offset ;
}
DbgType * COFF : : CvGetType ( int typeId )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
//TODO: How do we handle types that have the high bit set?
if ( typeId < 0 )
return NULL ;
/*if (typeId == 0)
return NULL ; */
if ( typeId < 0x1000 )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
TYPE_ENUM_e typeEnum = ( TYPE_ENUM_e ) typeId ;
DbgType * type = mCvSystemTypes [ typeId ] ;
BF_ASSERT ( type ! = NULL ) ;
return type ;
}
DbgType * type = mCvTypeMap [ typeId - mCvMinTag ] ;
if ( type = = NULL )
type = CvParseType ( typeId ) ;
2022-07-30 09:08:49 -04:00
/*if ((!allowNull) || (type != NULL))
2019-09-21 10:49:35 -07:00
{
BF_ASSERT ( type - > mCompileUnit - > mDbgModule = = this ) ;
} */
return type ;
}
2020-11-16 10:02:54 -08:00
DbgType * COFF : : CvGetTypeSafe ( int typeId )
{
DbgType * type = CvGetType ( typeId ) ;
if ( type ! = NULL )
return type ;
return CvGetType ( T_VOID ) ;
}
2019-09-21 10:49:35 -07:00
DbgType * COFF : : CvGetType ( int typeId , CvCompileUnit * compileUnit )
{
if ( ( typeId & 0x80000000 ) ! = 0 )
{
return CvGetType ( MapImport ( compileUnit , typeId ) ) ;
}
return CvGetType ( typeId ) ;
}
int COFF : : CvGetTagStart ( int tagIdx , bool ipi )
{
if ( tagIdx = = 0 )
return NULL ;
if ( ipi )
return mCvIPITagStartMap [ tagIdx - mCvMinTag ] ;
else
2019-12-21 09:35:58 -08:00
return mCvTagStartMap [ tagIdx - mCvMinTag ] ;
}
int COFF : : CvGetTagSize ( int tagIdx , bool ipi )
{
if ( tagIdx = = 0 )
return 0 ;
if ( ipi )
return mCvIPITagStartMap [ tagIdx - mCvMinTag + 1 ] - mCvIPITagStartMap [ tagIdx - mCvMinTag ] ;
else
return mCvTagStartMap [ tagIdx - mCvMinTag + 1 ] - mCvTagStartMap [ tagIdx - mCvMinTag ] ;
2019-09-21 10:49:35 -07:00
}
uint8 * COFF : : CvGetTagData ( int tagIdx , bool ipi , int * outDataSize )
{
if ( tagIdx = = 0 )
return NULL ;
2020-11-16 10:02:54 -08:00
if ( ( ipi ) & & ( tagIdx < mCvIPIMinTag ) )
return NULL ;
if ( ( ! ipi ) & & ( tagIdx < mCvMinTag ) )
return NULL ;
2019-09-21 10:49:35 -07:00
auto & reader = ipi ? mCvIPIReader : mCvTypeSectionReader ;
int offset = ipi ? mCvIPITagStartMap [ tagIdx - mCvIPIMinTag ] : mCvTagStartMap [ tagIdx - mCvMinTag ] ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
uint8 * data = reader . GetTempPtr ( offset , 4 ) ;
uint16 trLength = * ( uint16 * ) data ;
data = reader . GetTempPtr ( offset + 2 , trLength , true ) ;
if ( outDataSize ! = NULL )
* outDataSize = trLength ;
return data ;
}
int64 COFF : : 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 COFF : : CvParseConstant ( uint8 * & data )
{
2022-07-30 09:08:49 -04:00
uint16 val = GET ( uint16 ) ;
return CvParseConstant ( val , data ) ;
2019-09-21 10:49:35 -07:00
}
const char * COFF : : CvParseString ( uint8 * & data )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
const char * strStart = ( const char * ) data ;
int strLen = strlen ( ( const char * ) data ) ;
if ( strLen = = 0 )
2022-07-30 09:08:49 -04:00
return NULL ;
2019-09-21 10:49:35 -07:00
data + = strLen + 1 ;
return strStart ;
}
const char * COFF : : CvParseAndDupString ( uint8 * & data )
{
int strLen = strlen ( ( const char * ) data ) ;
if ( strLen = = 0 )
{
data + + ;
return NULL ;
}
BP_ALLOC ( " CvParseAndDupString " , strLen + 1 ) ;
char * dupStr = ( char * ) mAlloc . AllocBytes ( strLen + 1 , " CvParseAndDupString " ) ;
memcpy ( dupStr , data , strLen ) ;
data + = strLen + 1 ;
return dupStr ;
}
2019-11-29 09:21:51 -08:00
const char * COFF : : CvDupString ( const char * str , int strLen )
2022-07-30 09:08:49 -04:00
{
2019-11-29 09:21:51 -08:00
BP_ALLOC ( " CvDupString " , strLen + 1 ) ;
char * dupStr = ( char * ) mAlloc . AllocBytes ( strLen + 1 , " CvParseAndDupString " ) ;
memcpy ( dupStr , str , strLen ) ;
dupStr [ strLen ] = 0 ;
return dupStr ;
}
2019-09-21 10:49:35 -07:00
void COFF : : CvParseArgList ( DbgSubprogram * subprogram , int tagIdx , bool ipi )
{
uint8 * data = CvGetTagData ( tagIdx , ipi ) ;
CvAutoReleaseTempData releaseTempData ( this , data ) ;
2022-07-30 09:08:49 -04:00
int16 trLeafType = GET ( int16 ) ;
2019-09-21 10:49:35 -07:00
BF_ASSERT ( trLeafType = = LF_ARGLIST ) ;
2022-07-30 09:08:49 -04:00
int argCount = GET ( int32 ) ;
2019-09-21 10:49:35 -07:00
for ( int argIdx = 0 ; argIdx < argCount ; argIdx + + )
{
CV_typ_t argTypeId = GET ( CV_typ_t ) ;
DbgType * argType = CvGetType ( argTypeId ) ;
BP_ALLOC_T ( DbgVariable ) ;
2022-07-30 09:08:49 -04:00
DbgVariable * arg = mAlloc . Alloc < DbgVariable > ( ) ;
2019-09-21 10:49:35 -07:00
arg - > mType = argType ;
arg - > mIsParam = true ;
subprogram - > mParams . PushBack ( arg ) ;
}
ReleaseTempBuf ( data ) ;
}
DbgSubprogram * COFF : : CvParseMethod ( DbgType * parentType , const char * methodName , int tagIdx , bool ipi , DbgSubprogram * subprogram )
{
BP_ZONE ( " COFF::CvParseMethod " ) ;
uint8 * data = CvGetTagData ( tagIdx , ipi ) ;
2020-11-16 10:02:54 -08:00
if ( data = = NULL )
return NULL ;
2019-09-21 10:49:35 -07:00
CvAutoReleaseTempData releaseTempData ( this , data ) ;
bool fromTypeSection = methodName ! = NULL ;
uint8 * dataStart = data ;
int16 trLeafType = GET ( int16 ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( trLeafType = = LF_FUNC_ID )
{
2022-07-30 09:08:49 -04:00
lfFuncId * funcData = ( lfFuncId * ) dataStart ;
2019-09-21 10:49:35 -07:00
subprogram = CvParseMethod ( NULL , ( const char * ) funcData - > name , funcData - > type , false , subprogram ) ;
return subprogram ;
}
if ( trLeafType = = LF_MFUNC_ID )
{
lfMFuncId * funcData = ( lfMFuncId * ) dataStart ;
2022-07-30 09:08:49 -04:00
auto parentType = CvGetType ( funcData - > parentType ) ;
2019-09-21 10:49:35 -07:00
//subprogram = CvParseMethod(parentType, (const char*)funcData->name, funcData->type, false, subprogram);
// We shouldn't pass parentType in there, because that would be the declType and not the actual primary type (ie: definition type)
subprogram = CvParseMethod ( NULL , ( const char * ) funcData - > name , funcData - > type , false , subprogram ) ;
return subprogram ;
}
2022-07-30 09:08:49 -04:00
//DbgSubprogram* subprogram = mAlloc.Alloc<DbgSubprogram>();
2019-09-21 10:49:35 -07:00
if ( subprogram = = NULL )
{
BP_ALLOC_T ( DbgSubprogram ) ;
subprogram = mAlloc . Alloc < DbgSubprogram > ( ) ;
}
subprogram - > mName = methodName ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int argListId = 0 ;
if ( trLeafType = = LF_MFUNCTION )
{
static int gMFuncIdx = 0 ;
gMFuncIdx + + ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
lfMFunc * funcData = ( lfMFunc * ) dataStart ;
argListId = funcData - > arglist ;
subprogram - > mReturnType = CvGetType ( funcData - > rvtype ) ;
//TODO:
if ( parentType = = NULL )
subprogram - > mParentType = CvGetType ( funcData - > classtype ) ;
DbgType * thisType = CvGetType ( funcData - > thistype ) ;
if ( ( thisType ! = NULL ) & & ( ! thisType - > IsVoid ( ) ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgVariable ) ;
2022-07-30 09:08:49 -04:00
DbgVariable * arg = mAlloc . Alloc < DbgVariable > ( ) ;
2019-09-21 10:49:35 -07:00
arg - > mType = thisType ;
arg - > mIsParam = true ;
arg - > mTagIdx = gMFuncIdx ;
subprogram - > mParams . PushBack ( arg ) ;
//TODO: Why did we have this "fromTypeSection" check? It caused non-static methods from S_GPROC32_ID to look like static methods in the autocomplete list
//if (fromTypeSection)
{
arg - > mType = thisType ;
subprogram - > mHasThis = true ;
arg - > mName = " this " ;
}
}
}
else if ( trLeafType = = LF_METHODLIST )
{
int32 flags = GET ( int32 ) ;
int methodIndex = GET ( int32 ) ;
return CvParseMethod ( parentType , methodName , methodIndex , ipi , subprogram ) ;
}
else if ( trLeafType = = LF_PROCEDURE )
{
lfProc * funcData = ( lfProc * ) dataStart ;
subprogram - > mReturnType = CvGetType ( funcData - > rvtype ) ;
argListId = funcData - > arglist ;
}
else if ( trLeafType = = LF_MFUNC_ID )
{
//
}
else
{
2022-07-30 09:08:49 -04:00
SoftFail ( StrFormat ( " Unhandled func type at tagId %d ipi %d " , tagIdx , ipi ) ) ;
2019-09-21 10:49:35 -07:00
}
2019-11-07 13:35:56 -08:00
if ( ( parentType ! = NULL ) & & ( ! IsObjectFile ( ) ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
subprogram - > mCompileUnit = parentType - > mCompileUnit ;
parentType - > mMethodList . PushBack ( subprogram ) ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
mSubprograms . push_back ( subprogram ) ;
CvParseArgList ( subprogram , argListId , ipi ) ;
return subprogram ;
}
void COFF : : CvParseMethodList ( DbgType * parentType , const char * methodName , int tagIdx , bool ipi )
{
int dataSize = 0 ;
uint8 * data = CvGetTagData ( tagIdx , ipi , & dataSize ) ;
CvAutoReleaseTempData releaseTempData ( this , data ) ;
uint8 * dataEnd = data + dataSize ;
int16 trLeafType = GET ( int16 ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
BF_ASSERT ( trLeafType = = LF_METHODLIST ) ;
while ( data < dataEnd )
{
int32 flags = GET ( int32 ) ;
int32 methodIndex = GET ( int32 ) ;
CvParseMethod ( parentType , methodName , methodIndex , ipi ) ;
}
}
void COFF : : CvParseMembers ( DbgType * parentType , int tagIdx , bool ipi )
{
if ( tagIdx = = NULL )
return ;
auto & reader = ipi ? mCvIPIReader : mCvTypeSectionReader ;
int offset = ipi ? mCvIPITagStartMap [ tagIdx - mCvIPIMinTag ] : mCvTagStartMap [ tagIdx - mCvMinTag ] ;
uint8 * data = reader . GetTempPtr ( offset , 4 ) ;
uint16 trLength = * ( uint16 * ) data ;
offset + = 2 ;
data = reader . GetTempPtr ( offset , trLength , true ) ;
CvAutoReleaseTempData releaseTempData ( this , data ) ;
2022-07-30 09:08:49 -04:00
uint8 * dataStart = data ;
2019-09-21 10:49:35 -07:00
uint8 * dataEnd = data + trLength ;
2022-07-30 09:08:49 -04:00
int16 trLeafType = GET ( int16 ) ;
2019-09-21 10:49:35 -07:00
bool strMadeCopy ;
auto _ParseString = [ & ] ( )
{
strMadeCopy = false ;
int nameLen = strlen ( ( const char * ) data ) ;
int nameOfs = data - dataStart ;
const char * name = ( const char * ) reader . GetPermanentPtr ( offset + nameOfs , nameLen + 1 , & strMadeCopy ) ;
data + = nameLen + 1 ;
return name ;
} ;
if ( trLeafType = = 0 )
return ;
switch ( trLeafType )
{
2022-07-30 09:08:49 -04:00
case LF_FIELDLIST :
2019-09-21 10:49:35 -07:00
{
uint8 * sectionStart = data ;
while ( data < dataEnd )
{
uint8 * leafDataStart = data ;
int leafType = ( int ) GET ( uint16 ) ;
switch ( leafType )
{
case LF_VFUNCTAB :
{
lfVFuncTab & vfuncTab = * ( lfVFuncTab * ) leafDataStart ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgType * vtableType = CvGetType ( vfuncTab . type ) ;
BP_ALLOC_T ( DbgVariable ) ;
DbgVariable * vtableMember = mAlloc . Alloc < DbgVariable > ( ) ;
vtableMember - > mType = vtableType ;
parentType - > mMemberList . PushFront ( vtableMember ) ;
data = ( uint8 * ) ( & vfuncTab + 1 ) ;
}
break ;
case LF_BCLASS :
2022-07-30 09:08:49 -04:00
{
lfBClass & baseClassInfo = * ( lfBClass * ) leafDataStart ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgBaseTypeEntry ) ;
DbgBaseTypeEntry * baseTypeEntry = mAlloc . Alloc < DbgBaseTypeEntry > ( ) ;
data = ( uint8 * ) & baseClassInfo . offset ;
baseTypeEntry - > mThisOffset = ( int ) CvParseConstant ( data ) ;
if ( baseClassInfo . index ! = 0 )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
baseTypeEntry - > mBaseType = CvGetType ( baseClassInfo . index ) ;
2019-11-02 06:04:51 -07:00
// if (parentType->mLanguage == DbgLanguage_Beef)
// {
// if (!parentType->mBaseTypes.IsEmpty())
// parentType->mTypeParam = baseTypeEntry->mBaseType;
// }
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
parentType - > mBaseTypes . PushBack ( baseTypeEntry ) ;
2022-07-30 09:08:49 -04:00
parentType - > mAlign = std : : max ( parentType - > mAlign , baseTypeEntry - > mBaseType - > GetAlign ( ) ) ;
2019-09-21 10:49:35 -07:00
if ( ! parentType - > mSizeCalculated )
2022-07-30 09:08:49 -04:00
{
2019-11-29 09:21:51 -08:00
if ( ( baseTypeEntry - > mBaseType - > GetByteCount ( ) = = 0 ) & & ( baseTypeEntry - > mBaseType - > IsBfObject ( ) ) )
2019-09-21 10:49:35 -07:00
{
parentType - > mExtType = DbgExtType_Interface ;
}
parentType - > mSize = BF_MAX ( parentType - > mSize , baseTypeEntry - > mBaseType - > GetByteCount ( ) ) ;
}
}
}
break ;
case LF_VBCLASS :
case LF_IVBCLASS :
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
lfVBClass & baseClassInfo = * ( lfVBClass * ) leafDataStart ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgBaseTypeEntry ) ;
DbgBaseTypeEntry * baseTypeEntry = mAlloc . Alloc < DbgBaseTypeEntry > ( ) ;
baseTypeEntry - > mBaseType = CvGetType ( baseClassInfo . index ) ;
data = ( uint8 * ) & baseClassInfo . vbpoff ;
baseTypeEntry - > mThisOffset = ( int ) CvParseConstant ( data ) ;
baseTypeEntry - > mVTableOffset = ( int ) CvParseConstant ( data ) ;
parentType - > mBaseTypes . PushBack ( baseTypeEntry ) ;
}
break ;
case LF_ENUMERATE :
{
CV_fldattr_t fieldAttr = GET ( CV_fldattr_t ) ;
int64 fieldVal = CvParseConstant ( data ) ;
2022-07-30 09:08:49 -04:00
const char * fieldName = _ParseString ( ) ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgVariable ) ;
DbgVariable * member = mAlloc . Alloc < DbgVariable > ( ) ;
member - > mCompileUnit = parentType - > mCompileUnit ;
member - > mConstValue = fieldVal ;
2022-07-30 09:08:49 -04:00
member - > mName = fieldName ;
2019-09-21 10:49:35 -07:00
member - > mIsStatic = true ;
member - > mIsConst = true ;
member - > mType = parentType - > mTypeParam ;
FixConstant ( member ) ;
parentType - > mMemberList . PushBack ( member ) ;
}
break ;
case LF_NESTTYPE :
{
// Resolve nested types at end through 'primary type'
// Nested types also include nested TypeDefs, so the embedded type index may even be a primitive type here
// Why did we have this check to avoid unnamed nested types?
// it seems we added this and removed it a couple times.
// Disallowing NULL nested types here breaks the "_BUF_SIZE" in String, which is
// an anonymous enum
/*int16 pad = GET(int16);
int32 nestedTypeId = GET ( int32 ) ;
const char * typeName = CvParseAndDupString ( data ) ;
if ( ( typeName ! = NULL ) & & ( typeName [ 0 ] ! = ' < ' ) )
{
DbgType * nestedType = CvCreateType ( ) ;
nestedType - > mTypeParam = CvGetType ( nestedTypeId ) ;
nestedType - > mTypeCode = DbgType_TypeDef ;
nestedType - > mName = typeName ;
2022-07-30 09:08:49 -04:00
nestedType - > mTypeName = typeName ;
2019-09-21 10:49:35 -07:00
nestedType - > mParent = parentType ;
parentType - > mSubTypeList . PushBack ( nestedType ) ;
} */
int16 pad = GET ( int16 ) ;
int32 nestedTypeId = GET ( int32 ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
const char * typeName = _ParseString ( ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgType * nestedType = CvCreateType ( ) ;
nestedType - > mTypeParam = CvGetType ( nestedTypeId ) ;
nestedType - > mTypeCode = DbgType_TypeDef ;
if ( ( typeName ! = NULL ) & & ( typeName [ 0 ] ! = ' < ' ) )
{
nestedType - > mName = typeName ;
nestedType - > mTypeName = typeName ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
nestedType - > mParent = parentType ;
2022-07-30 09:08:49 -04:00
parentType - > mSubTypeList . PushBack ( nestedType ) ;
2019-09-21 10:49:35 -07:00
}
break ;
case LF_ONEMETHOD :
{
CV_fldattr_t attr = GET ( CV_fldattr_t ) ;
CV_typ_t methodTypeId = GET ( CV_typ_t ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int virtOffset = - 1 ;
if ( ( attr . mprop = = CV_MTintro ) | | ( attr . mprop = = CV_MTpureintro ) )
virtOffset = GET ( int32 ) ;
2022-07-30 09:08:49 -04:00
const char * methodName = _ParseString ( ) ;
2019-09-21 10:49:35 -07:00
DbgSubprogram * subProgram = CvParseMethod ( parentType , methodName , methodTypeId , ipi ) ;
subProgram - > mVirtual = ( attr . mprop = = CV_MTintro ) | | ( attr . mprop = = CV_MTpureintro ) | | ( attr . mprop = = CV_MTvirtual ) ;
subProgram - > mVTableLoc = virtOffset ;
}
break ;
case LF_METHOD :
{
int count = ( int ) GET ( uint16 ) ;
int32 methodList = GET ( int32 ) ;
const char * methodName = _ParseString ( ) ;
uint8 * listData = CvGetTagData ( methodList , ipi ) ;
CvAutoReleaseTempData releaseTempData ( this , listData ) ;
int16 trLeafType = GET_FROM ( listData , int16 ) ;
2022-04-22 19:19:43 -07:00
if ( trLeafType ! = LF_METHODLIST )
{
SoftFail ( " Invalid LF_METHOD member " ) ;
return ;
}
2019-09-21 10:49:35 -07:00
BF_ASSERT ( trLeafType = = LF_METHODLIST ) ;
for ( int methodIdx = 0 ; methodIdx < count ; methodIdx + + )
{
2022-07-30 09:08:49 -04:00
CV_fldattr_t attr = GET_FROM ( listData , CV_fldattr_t ) ;
2019-09-21 10:49:35 -07:00
int16 unused = GET_FROM ( listData , int16 ) ;
CV_typ_t methodTypeId = GET_FROM ( listData , CV_typ_t ) ;
int virtOffset = - 1 ;
if ( ( attr . mprop = = CV_MTintro ) | | ( attr . mprop = = CV_MTpureintro ) )
virtOffset = GET_FROM ( listData , int32 ) ;
2022-07-30 09:08:49 -04:00
DbgSubprogram * subProgram = CvParseMethod ( parentType , methodName , methodTypeId , ipi ) ;
2019-09-21 10:49:35 -07:00
subProgram - > mVirtual = ( attr . mprop = = CV_MTintro ) | | ( attr . mprop = = CV_MTpureintro ) | | ( attr . mprop = = CV_MTvirtual ) ;
subProgram - > mVTableLoc = virtOffset ;
}
}
2022-07-30 09:08:49 -04:00
break ;
2019-09-21 10:49:35 -07:00
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 ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( parentType - > mTagIdx = = 29184 )
{
NOP ;
}
int memberOffset = - 1 ;
if ( isStatic )
{
2022-07-30 09:08:49 -04:00
//?
2019-09-21 10:49:35 -07:00
}
else
{
memberOffset = ( int ) CvParseConstant ( data ) ;
}
char * fieldName = ( char * ) _ParseString ( ) ;
2019-11-02 06:04:51 -07:00
if ( ( fieldName ! = NULL ) & & ( parentType - > mLanguage = = DbgLanguage_Beef ) )
2019-09-21 10:49:35 -07:00
{
2019-11-02 06:04:51 -07:00
if ( strcmp ( fieldName , " $prim " ) = = 0 )
{
parentType - > mTypeParam = CvGetType ( fieldTypeId ) ;
2019-11-29 09:21:51 -08:00
parentType - > mTypeParam = GetPrimitiveType ( parentType - > mTypeParam - > mTypeCode , DbgLanguage_Beef ) ;
2022-07-30 09:08:49 -04:00
2019-11-29 09:21:51 -08:00
parentType - > mSize = parentType - > mTypeParam - > mSize ;
parentType - > mAlign = parentType - > mTypeParam - > mAlign ;
2019-11-02 06:04:51 -07:00
if ( ( parentType - > mBaseTypes . mHead ! = NULL ) & & ( strcmp ( parentType - > mBaseTypes . mHead - > mBaseType - > mName , " System.Enum " ) = = 0 ) )
parentType - > mTypeCode = DbgType_Enum ;
2019-11-25 06:47:41 -08:00
break ;
2019-11-02 06:04:51 -07:00
}
2022-07-30 09:08:49 -04:00
if ( strncmp ( fieldName , " $using$ " , 7 ) = = 0 )
{
fieldName = NULL ;
}
2019-09-21 10:49:35 -07:00
}
int64 constVal = 0 ;
2022-07-30 09:08:49 -04:00
if ( ( fieldName ! = NULL ) & & ( parentType - > mLanguage = = DbgLanguage_Beef ) & & ( isStatic ) )
{
2019-09-21 10:49:35 -07:00
for ( char * cPtr = fieldName ; true ; cPtr + + )
{
char c = * cPtr ;
if ( c = = 0 )
break ;
if ( c = = ' $ ' )
{
if ( ! strMadeCopy )
{
int ofs = cPtr - fieldName ;
fieldName = DbgDupString ( fieldName , " CvParseMembers.LF_MEMBER " ) ;
cPtr = fieldName + ofs ;
}
isConst = true ;
if ( cPtr [ 1 ] = = ' _ ' )
2019-12-05 06:50:08 -08:00
{
cPtr [ 1 ] = ' - ' ;
constVal = atoll ( cPtr + 1 ) ;
}
2019-09-21 10:49:35 -07:00
else
constVal = atoll ( cPtr + 1 ) ;
* cPtr = 0 ;
break ;
}
}
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
2019-11-07 13:35:56 -08:00
if ( ( isStatic ) & & ( ! isConst ) & & ( IsObjectFile ( ) ) )
2019-09-21 10:49:35 -07:00
{
// Already has statics filled in
break ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgVariable ) ;
DbgVariable * member = mAlloc . Alloc < DbgVariable > ( ) ;
2022-07-30 09:08:49 -04:00
member - > mIsStatic = isStatic ;
2019-09-21 10:49:35 -07:00
DbgType * fieldType = CvGetType ( fieldTypeId ) ;
// if (fieldType == NULL)
2022-07-30 09:08:49 -04:00
// {
2019-09-21 10:49:35 -07:00
// uint8* fieldTypeData = CvGetTagData(fieldTypeId, ipi);
// CvAutoReleaseTempData releaseTempData(this, fieldTypeData);
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// // It's a section data ptr
// int16 memberLeafType = *((int16*)fieldTypeData);
// switch (memberLeafType)
// {
// case LF_BITFIELD:
2022-07-30 09:08:49 -04:00
// {
2019-09-21 10:49:35 -07:00
// lfBitfield& bitfield = *(lfBitfield*)fieldTypeData;
// fieldType = CvGetType(bitfield.type);
2022-07-30 09:08:49 -04:00
//
// // Bit offset is expressed in MSB form
2019-09-21 10:49:35 -07:00
// member->mBitOffset = (fieldType->mSize * 8) - bitfield.position - bitfield.length;
// member->mBitSize = bitfield.length;
// }
// break;
// default:
// BF_FATAL("Unhandled");
2022-07-30 09:08:49 -04:00
// }
// }
2019-09-21 10:49:35 -07:00
if ( fieldType = = NULL )
fieldType = CvGetType ( fieldTypeId ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ( fieldType - > mTypeCode = = DbgType_Enum ) & & ( fieldType - > GetByteCount ( ) = = 0 ) )
fieldType = fieldType - > GetPrimaryType ( ) ;
// if (fieldType->mTypeCode == DbgType_Bitfield)
// {
2022-07-30 09:08:49 -04:00
// auto bitfieldType = (DbgBitfieldType*)fieldType;
2019-09-21 10:49:35 -07:00
// member->mBitOffset = bitfieldType->mPosition;
// member->mBitSize = bitfieldType->mLength;
// fieldType = fieldType->mTypeParam;
// }
if ( isConst )
{
member - > mConstValue = constVal ;
member - > mIsConst = true ;
}
else if ( isStatic )
{
2022-07-30 09:08:49 -04:00
// NOP
2019-09-21 10:49:35 -07:00
}
else
member - > mMemberOffset = memberOffset ;
member - > mType = fieldType ;
2022-07-30 09:08:49 -04:00
member - > mCompileUnit = parentType - > mCompileUnit ;
member - > mName = fieldName ;
2019-09-21 10:49:35 -07:00
// Size should already be set, right? It gets set on 'dataSize' in the LF_STRUCT/LF_CLASS
//parentType->mSize = std::max(memberOffset + fieldType->mSize, parentType->mSize);
if ( ( ! isStatic ) & & ( member - > mMemberOffset > = 0 ) )
{
if ( ! parentType - > mIsPacked )
parentType - > mAlign = std : : max ( parentType - > mAlign , fieldType - > GetAlign ( ) ) ;
if ( ! parentType - > mSizeCalculated )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
parentType - > mSize = std : : max ( memberOffset + fieldType - > GetByteCount ( ) , parentType - > mSize ) ;
}
}
//if (parentType->mAlign > 1)
//parentType->mSize = (parentType->mSize + (parentType->mAlign - 1)) & ~(parentType->mAlign - 1);
//parentType->mSizeCalculated = true;
parentType - > mMemberList . PushBack ( member ) ;
if ( isStatic )
parentType - > mNeedsGlobalsPopulated = true ;
}
2022-07-30 09:08:49 -04:00
break ;
2019-09-21 10:49:35 -07:00
case LF_INDEX :
{
int _pad = ( int ) GET ( uint16 ) ;
int32 indexType = GET ( int32 ) ;
CvParseMembers ( parentType , indexType , ipi ) ;
}
break ;
default :
2022-04-22 19:19:43 -07:00
SoftFail ( StrFormat ( " Unhandled leaf id 0x%X " , leafType ) ) ;
return ;
2019-09-21 10:49:35 -07:00
}
PTR_ALIGN ( data , sectionStart , 4 ) ;
}
}
break ;
}
}
int COFF : : CvConvRegNum ( int regNum , int * outBits )
{
if ( ( regNum > = CV_AMD64_R8B ) & & ( regNum < = CV_AMD64_R15B ) )
{
if ( outBits ! = NULL )
* outBits = 8 ;
regNum - = CV_AMD64_R8B - CV_AMD64_R8 ;
}
else if ( ( regNum > = CV_AMD64_R8W ) & & ( regNum < = CV_AMD64_R15W ) )
{
if ( outBits ! = NULL )
* outBits = 16 ;
regNum - = CV_AMD64_R8W - CV_AMD64_R8 ;
}
else if ( ( regNum > = CV_AMD64_R8D ) & & ( regNum < = CV_AMD64_R15D ) )
{
if ( outBits ! = NULL )
* outBits = 32 ;
regNum - = CV_AMD64_R8D - CV_AMD64_R8 ;
}
switch ( regNum )
{
# ifdef BF_DBG_64
case CV_AMD64_RAX : return X64Reg_RAX ;
case CV_AMD64_RDX : return X64Reg_RDX ;
case CV_AMD64_RCX : return X64Reg_RCX ;
case CV_AMD64_RBX : return X64Reg_RBX ;
case CV_AMD64_RSI : return X64Reg_RSI ;
case CV_AMD64_RDI : return X64Reg_RDI ;
case CV_AMD64_RBP : return X64Reg_RBP ;
case CV_AMD64_RSP : return X64Reg_RSP ;
case CV_AMD64_R8 : return X64Reg_R8 ;
case CV_AMD64_R9 : return X64Reg_R9 ;
case CV_AMD64_R10 : return X64Reg_R10 ;
case CV_AMD64_R11 : return X64Reg_R11 ;
case CV_AMD64_R12 : return X64Reg_R12 ;
case CV_AMD64_R13 : return X64Reg_R13 ;
case CV_AMD64_R14 : return X64Reg_R14 ;
case CV_AMD64_R15 : return X64Reg_R15 ;
case CV_AMD64_RIP : return X64Reg_RIP ;
case CV_REG_AL : if ( outBits ! = NULL ) * outBits = 8 ; return X64Reg_RAX ;
case CV_REG_AX : if ( outBits ! = NULL ) * outBits = 16 ; return X64Reg_RAX ;
case CV_REG_EAX : if ( outBits ! = NULL ) * outBits = 32 ; return X64Reg_RAX ;
case CV_REG_CL : if ( outBits ! = NULL ) * outBits = 8 ; return X64Reg_RCX ;
case CV_REG_CX : if ( outBits ! = NULL ) * outBits = 16 ; return X64Reg_RCX ;
case CV_REG_ECX : if ( outBits ! = NULL ) * outBits = 32 ; return X64Reg_RCX ;
case CV_REG_DL : if ( outBits ! = NULL ) * outBits = 8 ; return X64Reg_RDX ;
case CV_REG_DX : if ( outBits ! = NULL ) * outBits = 16 ; return X64Reg_RDX ;
case CV_REG_EDX : if ( outBits ! = NULL ) * outBits = 32 ; return X64Reg_RDX ;
case CV_REG_BL : if ( outBits ! = NULL ) * outBits = 8 ; return X64Reg_RBX ;
case CV_REG_BX : if ( outBits ! = NULL ) * outBits = 16 ; return X64Reg_RBX ;
case CV_REG_EBX : if ( outBits ! = NULL ) * outBits = 32 ; return X64Reg_RBX ;
case CV_REG_ESP : if ( outBits ! = NULL ) * outBits = 32 ; return X64Reg_RSP ;
case CV_REG_EBP : if ( outBits ! = NULL ) * outBits = 32 ; return X64Reg_RBP ;
case CV_AMD64_SIL : if ( outBits ! = NULL ) * outBits = 8 ; return X64Reg_RSI ;
case CV_REG_SI : if ( outBits ! = NULL ) * outBits = 16 ; return X64Reg_RSI ;
case CV_REG_ESI : if ( outBits ! = NULL ) * outBits = 32 ; return X64Reg_RSI ;
case CV_AMD64_DIL : if ( outBits ! = NULL ) * outBits = 8 ; return X64Reg_RDI ;
case CV_REG_DI : if ( outBits ! = NULL ) * outBits = 16 ; return X64Reg_RDI ;
case CV_REG_EDI : if ( outBits ! = NULL ) * outBits = 32 ; return X64Reg_RDI ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
case CV_AMD64_R8B : * outBits = 8 ; return X64Reg_R8 ;
case CV_AMD64_R8W : * outBits = 16 ; return X64Reg_R8 ;
case CV_AMD64_R8D : * outBits = 32 ; return X64Reg_R8 ;
case CV_AMD64_R9B : * outBits = 8 ; return X64Reg_R9 ;
case CV_AMD64_R9W : * outBits = 16 ; return X64Reg_R9 ;
case CV_AMD64_R9D : * outBits = 32 ; return X64Reg_R9 ;
case CV_AMD64_R10B : * outBits = 8 ; return X64Reg_R10 ;
case CV_AMD64_R10W : * outBits = 16 ; return X64Reg_R10 ;
case CV_AMD64_R10D : * outBits = 32 ; return X64Reg_R10 ;
case CV_AMD64_R11B : * outBits = 8 ; return X64Reg_R11 ;
case CV_AMD64_R11W : * outBits = 16 ; return X64Reg_R11 ;
case CV_AMD64_R11D : * outBits = 32 ; return X64Reg_R11 ;
case CV_AMD64_R12B : * outBits = 8 ; return X64Reg_R12 ;
case CV_AMD64_R12W : * outBits = 16 ; return X64Reg_R12 ;
case CV_AMD64_R12D : * outBits = 32 ; return X64Reg_R12 ;
case CV_AMD64_R13B : * outBits = 8 ; return X64Reg_R13 ;
case CV_AMD64_R13W : * outBits = 16 ; return X64Reg_R13 ;
case CV_AMD64_R13D : * outBits = 32 ; return X64Reg_R13 ;
case CV_AMD64_R14B : * outBits = 8 ; return X64Reg_R14 ;
case CV_AMD64_R14W : * outBits = 16 ; return X64Reg_R14 ;
case CV_AMD64_R14D : * outBits = 32 ; return X64Reg_R14 ;
case CV_AMD64_R15B : * outBits = 8 ; return X64Reg_R15 ;
case CV_AMD64_R15W : * outBits = 16 ; return X64Reg_R15 ;
case CV_AMD64_R15D : * outBits = 32 ; return X64Reg_R15 ;
case CV_AMD64_XMM0_0 : return X64Reg_XMM00 ;
case CV_AMD64_XMM0_1 : return X64Reg_XMM01 ;
case CV_AMD64_XMM0_2 : return X64Reg_XMM02 ;
case CV_AMD64_XMM0_3 : return X64Reg_XMM03 ;
case CV_AMD64_XMM1_0 : return X64Reg_XMM10 ;
case CV_AMD64_XMM1_1 : return X64Reg_XMM11 ;
case CV_AMD64_XMM1_2 : return X64Reg_XMM12 ;
case CV_AMD64_XMM1_3 : return X64Reg_XMM13 ;
case CV_AMD64_XMM2_0 : return X64Reg_XMM20 ;
case CV_AMD64_XMM2_1 : return X64Reg_XMM21 ;
case CV_AMD64_XMM2_2 : return X64Reg_XMM22 ;
case CV_AMD64_XMM2_3 : return X64Reg_XMM23 ;
case CV_AMD64_XMM3_0 : return X64Reg_XMM30 ;
case CV_AMD64_XMM3_1 : return X64Reg_XMM31 ;
case CV_AMD64_XMM3_2 : return X64Reg_XMM32 ;
case CV_AMD64_XMM3_3 : return X64Reg_XMM33 ;
case CV_AMD64_XMM4_0 : return X64Reg_XMM40 ;
case CV_AMD64_XMM4_1 : return X64Reg_XMM41 ;
case CV_AMD64_XMM4_2 : return X64Reg_XMM42 ;
case CV_AMD64_XMM4_3 : return X64Reg_XMM43 ;
case CV_AMD64_XMM5_0 : return X64Reg_XMM50 ;
case CV_AMD64_XMM5_1 : return X64Reg_XMM51 ;
case CV_AMD64_XMM5_2 : return X64Reg_XMM52 ;
case CV_AMD64_XMM5_3 : return X64Reg_XMM53 ;
case CV_AMD64_XMM6_0 : return X64Reg_XMM60 ;
case CV_AMD64_XMM6_1 : return X64Reg_XMM61 ;
case CV_AMD64_XMM6_2 : return X64Reg_XMM62 ;
case CV_AMD64_XMM6_3 : return X64Reg_XMM63 ;
case CV_AMD64_XMM7_0 : return X64Reg_XMM70 ;
case CV_AMD64_XMM7_1 : return X64Reg_XMM71 ;
case CV_AMD64_XMM7_2 : return X64Reg_XMM72 ;
case CV_AMD64_XMM7_3 : return X64Reg_XMM73 ;
case CV_AMD64_XMM8_0 : return X64Reg_XMM80 ;
case CV_AMD64_XMM8_1 : return X64Reg_XMM81 ;
case CV_AMD64_XMM8_2 : return X64Reg_XMM82 ;
case CV_AMD64_XMM8_3 : return X64Reg_XMM83 ;
case CV_AMD64_XMM9_0 : return X64Reg_XMM90 ;
case CV_AMD64_XMM9_1 : return X64Reg_XMM91 ;
case CV_AMD64_XMM9_2 : return X64Reg_XMM92 ;
case CV_AMD64_XMM9_3 : return X64Reg_XMM93 ;
case CV_AMD64_XMM10_0 : return X64Reg_XMM10_0 ;
case CV_AMD64_XMM10_1 : return X64Reg_XMM10_1 ;
case CV_AMD64_XMM10_2 : return X64Reg_XMM10_2 ;
case CV_AMD64_XMM10_3 : return X64Reg_XMM10_3 ;
case CV_AMD64_XMM11_0 : return X64Reg_XMM11_0 ;
case CV_AMD64_XMM11_1 : return X64Reg_XMM11_1 ;
case CV_AMD64_XMM11_2 : return X64Reg_XMM11_2 ;
case CV_AMD64_XMM11_3 : return X64Reg_XMM11_3 ;
case CV_AMD64_XMM12_0 : return X64Reg_XMM12_0 ;
case CV_AMD64_XMM12_1 : return X64Reg_XMM12_1 ;
case CV_AMD64_XMM12_2 : return X64Reg_XMM12_2 ;
case CV_AMD64_XMM12_3 : return X64Reg_XMM12_3 ;
case CV_AMD64_XMM13_0 : return X64Reg_XMM13_0 ;
case CV_AMD64_XMM13_1 : return X64Reg_XMM13_1 ;
case CV_AMD64_XMM13_2 : return X64Reg_XMM13_2 ;
case CV_AMD64_XMM13_3 : return X64Reg_XMM13_3 ;
case CV_AMD64_XMM14_0 : return X64Reg_XMM14_0 ;
case CV_AMD64_XMM14_1 : return X64Reg_XMM14_1 ;
case CV_AMD64_XMM14_2 : return X64Reg_XMM14_2 ;
case CV_AMD64_XMM14_3 : return X64Reg_XMM14_3 ;
case CV_AMD64_XMM15_0 : return X64Reg_XMM15_0 ;
case CV_AMD64_XMM15_1 : return X64Reg_XMM15_1 ;
case CV_AMD64_XMM15_2 : return X64Reg_XMM15_2 ;
case CV_AMD64_XMM15_3 : return X64Reg_XMM15_3 ;
# else
case CV_REG_AL : return X86Reg_EAX ;
case CV_REG_CL : return X86Reg_ECX ;
case CV_REG_DL : return X86Reg_EDX ;
case CV_REG_BL : return X86Reg_EBX ;
case CV_REG_AH : return X86Reg_EAX ;
case CV_REG_AX : return X86Reg_EAX ;
case CV_REG_CX : return X86Reg_ECX ;
case CV_REG_DX : return X86Reg_EDX ;
case CV_REG_BX : return X86Reg_EBX ;
case CV_REG_SP : return X86Reg_ESP ;
case CV_REG_BP : return X86Reg_EBP ;
case CV_REG_SI : return X86Reg_ESI ;
case CV_REG_DI : return X86Reg_EDI ;
case CV_REG_EAX : return X86Reg_EAX ;
case CV_REG_ECX : return X86Reg_ECX ;
case CV_REG_EDX : return X86Reg_EDX ;
case CV_REG_EBX : return X86Reg_EBX ;
case CV_REG_ESP : return X86Reg_ESP ;
case CV_REG_EBP : return X86Reg_EBP ;
case CV_REG_ESI : return X86Reg_ESI ;
case CV_REG_EDI : return X86Reg_EDI ;
case CV_REG_IP : return X86Reg_EIP ;
// case CV_REG_XMM0: return X86Reg_XMM00;
// case CV_REG_XMM1: return X86Reg_XMM01;
// case CV_REG_XMM2: return X86Reg_XMM02;
// case CV_REG_XMM3: return X86Reg_XMM03;
// case CV_REG_XMM4: return X86Reg_XMM04;
// case CV_REG_XMM5: return X86Reg_XMM05;
// case CV_REG_XMM6: return X86Reg_XMM06;
// case CV_REG_XMM7: return X86Reg_XMM07;
2022-07-30 09:08:49 -04:00
# endif
2019-09-21 10:49:35 -07:00
}
return 0 ; // Nope
BF_FATAL ( " Invalid register " ) ;
return 0 ;
}
DbgType * COFF : : CvCreateType ( )
{
DbgModule * linkedModule = GetLinkedModule ( ) ;
BP_ALLOC_T ( DbgType ) ;
DbgType * dbgType = mAlloc . Alloc < DbgType > ( ) ;
dbgType - > mCompileUnit = mMasterCompileUnit ;
dbgType - > mTypeIdx = ( int ) linkedModule - > mTypes . size ( ) ;
2022-07-30 09:08:49 -04:00
linkedModule - > mTypes . push_back ( dbgType ) ;
2019-09-21 10:49:35 -07:00
return dbgType ;
}
DbgType * COFF : : CvParseType ( int tagIdx , bool ipi )
{
auto & reader = ipi ? mCvIPIReader : mCvTypeSectionReader ;
int offset = ipi ? mCvIPITagStartMap [ tagIdx - mCvIPIMinTag ] : mCvTagStartMap [ tagIdx - mCvMinTag ] ;
uint8 * data = reader . GetTempPtr ( offset , 4 ) ;
uint16 trLength = * ( uint16 * ) data ;
offset + = 2 ;
data = reader . GetTempPtr ( offset , trLength , true ) ;
CvAutoReleaseTempData releaseTempData ( this , data ) ;
uint8 * dataStart = data ;
uint8 * dataEnd = data + trLength ;
int16 trLeafType = GET ( int16 ) ;
bool strMadeCopy ;
auto _ParseString = [ & ] ( )
{
strMadeCopy = false ;
int nameLen = strlen ( ( const char * ) data ) ;
int nameOfs = data - dataStart ;
const char * name = ( const char * ) reader . GetPermanentPtr ( offset + nameOfs , nameLen + 1 , & strMadeCopy ) ;
data + = nameLen + 1 ;
return name ;
} ;
DbgType * dbgType = NULL ;
switch ( trLeafType )
2020-11-18 09:15:28 -08:00
{
2019-09-21 10:49:35 -07:00
case LF_ENUM :
{
int elemCount = ( int ) GET ( uint16 ) ;
int prop = ( int ) GET ( uint16 ) ;
int underlyingType = GET ( int32 ) ;
int typeIndex = GET ( int32 ) ;
const char * name = _ParseString ( ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
dbgType = CvCreateType ( ) ;
dbgType - > mCompileUnit = mMasterCompileUnit ;
dbgType - > mName = name ;
dbgType - > mTypeName = name ;
2022-07-30 09:08:49 -04:00
//SplitName(dbgType->mName, dbgType->mTypeName, dbgType->mTemplateParams);
2019-09-21 10:49:35 -07:00
dbgType - > mTypeCode = DbgType_Enum ;
2022-07-30 09:08:49 -04:00
dbgType - > mTypeParam = CvGetTypeSafe ( underlyingType ) ;
2019-09-21 10:49:35 -07:00
dbgType - > mIsIncomplete = true ;
if ( dbgType - > mTypeParam - > GetByteCount ( ) = = 0 )
dbgType - > mIsDeclaration = true ;
dbgType - > mSize = dbgType - > mTypeParam - > mSize ;
2022-07-30 09:08:49 -04:00
dbgType - > mAlign = dbgType - > mTypeParam - > mAlign ;
2019-09-21 10:49:35 -07:00
/*if (dbgType->mTypeParam->GetByteCount() == 0)
{
// Appears to be a bug where byte-sized enums come out as void (sometimes?)
dbgType - > mTypeParam = mBfPrimitiveTypes [ DbgType_u8 ] ;
} */
//dbgType->mIsDeclaration = typeIndex == 0;
//CvParseMembers(dbgType, typeIndex, sectionData);
}
break ;
case LF_VTSHAPE :
{
lfVTShape & vtShape = * ( lfVTShape * ) dataStart ;
dbgType = CvCreateType ( ) ;
dbgType - > mTypeCode = DbgType_VTable ;
dbgType - > mSize = vtShape . count * sizeof ( addr_target ) ;
dbgType - > mSizeCalculated = true ;
}
break ;
case LF_BITFIELD :
{
//DbgType
lfBitfield & bitfield = * ( lfBitfield * ) dataStart ;
//dbgType = CvCreateType();
DbgBitfieldType * bitfieldType = mAlloc . Alloc < DbgBitfieldType > ( ) ;
dbgType = bitfieldType ;
2020-11-17 07:52:51 -08:00
dbgType - > mTypeParam = CvGetTypeSafe ( bitfield . type ) ;
2019-09-21 10:49:35 -07:00
dbgType - > mTypeCode = DbgType_Bitfield ;
//bitfieldType->mPosition = (dbgType->mTypeParam->mSize * 8) - bitfield.position - bitfield.length;
bitfieldType - > mPosition = bitfield . position ;
2022-07-30 09:08:49 -04:00
bitfieldType - > mLength = bitfield . length ;
2019-09-21 10:49:35 -07:00
bitfieldType - > mSize = dbgType - > mTypeParam - > mSize ;
bitfieldType - > mAlign = dbgType - > mTypeParam - > mAlign ;
dbgType - > mSizeCalculated = true ;
dbgType - > mPriority = DbgTypePriority_Unique ;
}
break ;
2022-07-30 09:08:49 -04:00
2020-11-18 09:15:28 -08:00
case LF_CLASS :
2022-07-30 09:08:49 -04:00
case LF_STRUCTURE :
2020-11-18 09:15:28 -08:00
case LF_CLASS_EX :
case LF_STRUCTURE_EX :
2022-07-30 09:08:49 -04:00
{
2020-11-18 09:15:28 -08:00
unsigned short count ; // count of number of elements in class
CV_prop_t property ; // property attribute field (prop_t)
CV_typ_t field ; // type index of LF_FIELD descriptor list
CV_typ_t derived ; // type index of derived from list if not zero
CV_typ_t vshape ; // type index of vshape table for this class
int dataSize ;
int16 extra = 0 ;
if ( ( trLeafType = = 0x1608 ) | | ( trLeafType = = 0x1609 ) )
2022-07-30 09:08:49 -04:00
{
2020-11-18 09:15:28 -08:00
property = GET ( CV_prop_t ) ;
extra = GET ( int16 ) ;
field = GET ( CV_typ_t ) ;
derived = GET ( CV_typ_t ) ;
vshape = GET ( CV_typ_t ) ;
count = GET ( unsigned short ) ;
2022-07-30 09:08:49 -04:00
dataSize = ( int ) CvParseConstant ( data ) ;
2020-11-18 09:15:28 -08:00
}
else
{
count = GET ( unsigned short ) ;
property = GET ( CV_prop_t ) ;
field = GET ( CV_typ_t ) ;
derived = GET ( CV_typ_t ) ;
vshape = GET ( CV_typ_t ) ;
dataSize = ( int ) CvParseConstant ( data ) ;
}
2019-09-21 10:49:35 -07:00
const char * name = _ParseString ( ) ;
2019-11-29 09:21:51 -08:00
2020-11-18 09:15:28 -08:00
// if (strstr(name, "TestStruct") != NULL)
// {
// NOP;
// }
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
// if ((strstr(name, "`") != NULL) || (strstr(name, "::__l") != NULL))
// {
// OutputDebugStrF("Local type: %s\n", name);
// }
// Remove "enum " from type names
2019-12-21 11:27:50 -08:00
bool isPartialDef = false ;
2019-09-21 10:49:35 -07:00
for ( int i = 0 ; true ; i + + )
{
char c = name [ i ] ;
2022-07-30 11:05:03 -04:00
2019-09-21 10:49:35 -07:00
if ( c = = 0 )
2022-07-30 11:05:03 -04:00
break ;
if ( c = = ' $ ' )
2019-12-21 11:27:50 -08:00
{
2022-07-30 11:05:03 -04:00
if ( ( i > = 5 ) & & ( strncmp ( & name [ i - 5 ] , " $part$ " , 6 ) = = 0 ) )
2019-12-21 11:27:50 -08:00
{
if ( ! strMadeCopy )
name = DbgDupString ( name , " CvParseType.LF_CLASS " ) ;
2022-07-30 11:05:03 -04:00
strcpy ( ( char * ) & name [ i - 5 ] , & name [ i + 1 ] ) ;
if ( name [ i - 5 ] = = ' \0 ' )
{
isPartialDef = true ;
break ;
}
2019-12-21 11:27:50 -08:00
}
}
2022-07-30 11:05:03 -04:00
2019-09-21 10:49:35 -07:00
if ( ( c = = ' ' ) & & ( i > = 5 ) )
{
if ( ( name [ i - 4 ] = = ' e ' ) & &
( name [ i - 3 ] = = ' n ' ) & &
( name [ i - 2 ] = = ' u ' ) & &
( name [ i - 1 ] = = ' m ' ) )
{
char prevC = name [ i - 5 ] ;
if ( ( ! isalnum ( prevC ) ) & & ( prevC ! = ' _ ' ) )
{
if ( ! strMadeCopy )
name = DbgDupString ( name , " CvParseType.LF_CLASS " ) ;
memmove ( ( char * ) name + i - 4 , name + i + 1 , strlen ( name + i + 1 ) + 1 ) ;
i - = 5 ;
continue ;
}
}
}
}
dbgType = CvCreateType ( ) ;
dbgType - > mCompileUnit = mMasterCompileUnit ;
2020-11-18 09:15:28 -08:00
dbgType - > mIsDeclaration = property . fwdref ;
2019-12-21 11:27:50 -08:00
if ( isPartialDef )
dbgType - > mIsDeclaration = true ;
2019-09-21 10:49:35 -07:00
dbgType - > mName = name ;
dbgType - > mTypeName = name ;
//SplitName(dbgType->mName, dbgType->mTypeName, dbgType->mTemplateParams);
2020-11-18 09:15:28 -08:00
if ( ( trLeafType = = LF_CLASS ) | | ( trLeafType = = LF_CLASS_EX ) )
2019-09-21 10:49:35 -07:00
dbgType - > mTypeCode = DbgType_Class ;
else
dbgType - > mTypeCode = DbgType_Struct ;
DbgType * baseType = NULL ;
2020-11-18 09:15:28 -08:00
if ( derived ! = 0 )
2019-09-21 10:49:35 -07:00
{
2020-11-18 09:15:28 -08:00
baseType = CvGetTypeSafe ( derived ) ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgBaseTypeEntry ) ;
DbgBaseTypeEntry * baseTypeEntry = mAlloc . Alloc < DbgBaseTypeEntry > ( ) ;
2022-07-30 09:08:49 -04:00
baseTypeEntry - > mBaseType = baseType ;
2019-09-21 10:49:35 -07:00
dbgType - > mBaseTypes . PushBack ( baseTypeEntry ) ;
}
2020-11-18 09:15:28 -08:00
if ( property . packed )
2019-09-21 10:49:35 -07:00
{
dbgType - > mAlign = 1 ;
dbgType - > mIsPacked = true ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
if ( ! dbgType - > mIsDeclaration )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
dbgType - > mSizeCalculated = true ;
dbgType - > mSize = dataSize ;
if ( strncmp ( name , " _bf: " , 4 ) = = 0 )
{
2019-11-29 09:21:51 -08:00
// Beef types have different strides from size. Note we MUST set size to zero here, because there are
// some BF_MAX calculations we perform on it
2019-09-21 10:49:35 -07:00
dbgType - > mSizeCalculated = false ;
2019-11-29 09:21:51 -08:00
dbgType - > mSize = 0 ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
2022-07-30 09:08:49 -04:00
if ( vshape ! = 0 )
2019-09-21 10:49:35 -07:00
{
2020-11-18 09:15:28 -08:00
CvGetTypeSafe ( vshape ) ;
2022-07-30 09:08:49 -04:00
dbgType - > mHasVTable = true ;
2019-09-21 10:49:35 -07:00
}
dbgType - > mIsIncomplete = true ;
2019-12-21 09:35:58 -08:00
2022-07-30 09:08:49 -04:00
// if (classInfo.field != 0)
// dbgType->mDefinedMembersSize = CvGetTagSize(classInfo.field, ipi);
2019-09-21 10:49:35 -07:00
//CvParseMembers(dbgType, classInfo.field, sectionData);
}
break ;
case LF_UNION :
2022-07-30 09:08:49 -04:00
{
lfUnion & classInfo = * ( lfUnion * ) dataStart ;
2019-09-21 10:49:35 -07:00
data = ( uint8 * ) & classInfo . data ;
int dataSize = ( int ) CvParseConstant ( data ) ;
const char * name = _ParseString ( ) ;
dbgType = CvCreateType ( ) ;
dbgType - > mCompileUnit = mMasterCompileUnit ;
dbgType - > mIsDeclaration = classInfo . property . fwdref ;
dbgType - > mName = name ;
dbgType - > mTypeName = name ;
//SplitName(dbgType->mName, dbgType->mTypeName, dbgType->mTemplateParams);
2022-07-30 09:08:49 -04:00
dbgType - > mTypeCode = DbgType_Union ;
dbgType - > mSize = dataSize ;
2019-09-21 10:49:35 -07:00
dbgType - > mAlign = 1 ;
dbgType - > mSizeCalculated = ! dbgType - > mIsDeclaration ;
dbgType - > mIsIncomplete = true ;
//CvParseMembers(dbgType, classInfo.field, sectionData);
}
break ;
case LF_MODIFIER :
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
lfModifier & modifier = * ( lfModifier * ) dataStart ;
2020-11-17 07:52:51 -08:00
DbgType * outerType = CvGetTypeSafe ( modifier . type ) ;
2019-09-21 10:49:35 -07:00
dbgType = outerType ;
if ( modifier . attr . MOD_const )
{
DbgType * innerType = dbgType ;
2022-07-30 09:08:49 -04:00
dbgType = CvCreateType ( ) ;
2019-09-21 10:49:35 -07:00
dbgType - > mTypeParam = innerType ;
dbgType - > mTypeCode = DbgType_Const ;
dbgType - > mLanguage = innerType - > mLanguage ;
}
if ( modifier . attr . MOD_volatile )
{
DbgType * innerType = dbgType ;
dbgType = CvCreateType ( ) ;
dbgType - > mTypeParam = innerType ;
dbgType - > mTypeCode = DbgType_Volatile ;
dbgType - > mLanguage = innerType - > mLanguage ;
}
if ( modifier . attr . MOD_unaligned )
{
DbgType * innerType = dbgType ;
dbgType = CvCreateType ( ) ;
dbgType - > mTypeParam = innerType ;
dbgType - > mTypeCode = DbgType_Unaligned ;
dbgType - > mLanguage = innerType - > mLanguage ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
break ;
case LF_POINTER :
{
lfPointer * pointerInfo = ( lfPointer * ) dataStart ;
2022-07-30 09:08:49 -04:00
dbgType = CvCreateType ( ) ;
2020-11-16 10:02:54 -08:00
dbgType - > mTypeParam = CvGetTypeSafe ( pointerInfo - > utype ) ;
2019-09-21 10:49:35 -07:00
if ( pointerInfo - > attr . ptrmode = = CV_PTR_MODE_RVREF )
dbgType - > mTypeCode = DbgType_RValueReference ;
else if ( pointerInfo - > attr . ptrmode = = CV_PTR_MODE_LVREF )
dbgType - > mTypeCode = DbgType_Ref ;
else
{
dbgType - > mTypeCode = DbgType_Ptr ;
if ( ( dbgType - > mTypeParam ! = NULL ) & & ( dbgType - > mTypeParam - > mPtrType = = NULL ) )
dbgType - > mTypeParam - > mPtrType = dbgType ;
}
2022-07-30 09:08:49 -04:00
//dbgType->mSize = pointerInfo->attr.size;
2019-09-21 10:49:35 -07:00
dbgType - > mSize = sizeof ( addr_target ) ;
dbgType - > mAlign = dbgType - > mSize ;
dbgType - > mSizeCalculated = true ;
dbgType - > mLanguage = dbgType - > mTypeParam - > mLanguage ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
/*if (prop.isconst)
{
DbgType * innerType = dbgType ;
2022-07-30 09:08:49 -04:00
dbgType = CvCreateType ( ) ;
2019-09-21 10:49:35 -07:00
dbgType - > mTypeParam = innerType ;
dbgType - > mTypeCode = DbgType_Const ;
dbgType - > mSize = innerType - > mSize ;
} */
2022-07-30 09:08:49 -04:00
//TODO: Handle const, volatile, ref, restrict, etc
2019-09-21 10:49:35 -07:00
}
break ;
case LF_DIMARRAY :
{
}
break ;
case LF_ARRAY :
{
lfArray * array = ( lfArray * ) dataStart ;
2020-11-17 07:52:51 -08:00
DbgType * indexType = CvGetTypeSafe ( array - > idxtype ) ;
2019-09-21 10:49:35 -07:00
dbgType = CvCreateType ( ) ;
2020-11-17 07:52:51 -08:00
dbgType - > mTypeParam = CvGetTypeSafe ( array - > elemtype ) ;
2022-07-30 09:08:49 -04:00
dbgType - > mTypeCode = DbgType_SizedArray ;
2019-09-21 10:49:35 -07:00
dbgType - > mLanguage = dbgType - > mTypeParam - > mLanguage ;
data = ( uint8 * ) & array - > data ;
int size = ( int ) CvParseConstant ( data ) ;
const char * name = _ParseString ( ) ;
dbgType - > mName = name ;
dbgType - > mSize = size ;
2022-06-06 12:14:20 -07:00
dbgType - > mAlign = dbgType - > mTypeParam - > GetAlign ( ) ;
2019-09-21 10:49:35 -07:00
// Beef arrays do not necessarily have aligned sizes
dbgType - > mSizeCalculated = false ;
dbgType - > mLanguage = dbgType - > mTypeParam - > mLanguage ;
}
break ;
case LF_PROCEDURE :
{
dbgType = CvCreateType ( ) ;
//TODO: Calling convetion, etc
lfProc * proc = ( lfProc * ) dataStart ;
dbgType - > mTypeCode = DbgType_Subroutine ;
2020-11-17 07:52:51 -08:00
dbgType - > mTypeParam = CvGetTypeSafe ( proc - > rvtype ) ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgBlock ) ;
dbgType - > mBlockParam = mAlloc . Alloc < DbgBlock > ( ) ;
uint8 * argData = CvGetTagData ( proc - > arglist , ipi ) ;
CvAutoReleaseTempData releaseTempData ( this , argData ) ;
2022-07-30 09:08:49 -04:00
int16 argLeafType = GET_FROM ( argData , int16 ) ;
2019-09-21 10:49:35 -07:00
BF_ASSERT ( argLeafType = = LF_ARGLIST ) ;
int argCount = GET_FROM ( argData , int32 ) ;
CV_typ_t * argTypes = ( CV_typ_t * ) argData ;
for ( int paramIdx = 0 ; paramIdx < proc - > parmcount ; paramIdx + + )
{
BP_ALLOC_T ( DbgVariable ) ;
2022-07-30 09:08:49 -04:00
DbgVariable * arg = mAlloc . Alloc < DbgVariable > ( ) ;
2019-09-21 10:49:35 -07:00
arg - > mIsParam = true ;
2020-11-17 07:52:51 -08:00
arg - > mType = CvGetTypeSafe ( argTypes [ paramIdx ] ) ;
2019-09-21 10:49:35 -07:00
arg - > mName = " $arg " ;
dbgType - > mBlockParam - > mVariables . PushBack ( arg ) ;
}
}
break ;
case LF_MFUNCTION :
{
dbgType = CvCreateType ( ) ;
//TODO: Calling convetion, etc
lfMFunc * proc = ( lfMFunc * ) dataStart ;
dbgType - > mTypeCode = DbgType_Subroutine ;
2020-11-17 07:52:51 -08:00
dbgType - > mTypeParam = CvGetTypeSafe ( proc - > rvtype ) ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgBlock ) ;
dbgType - > mBlockParam = mAlloc . Alloc < DbgBlock > ( ) ;
uint8 * argData = CvGetTagData ( proc - > arglist , ipi ) ;
CvAutoReleaseTempData releaseTempData ( this , argData ) ;
2022-07-30 09:08:49 -04:00
int16 argLeafType = GET_FROM ( argData , int16 ) ;
2019-09-21 10:49:35 -07:00
BF_ASSERT ( argLeafType = = LF_ARGLIST ) ;
int argCount = GET_FROM ( argData , int32 ) ;
CV_typ_t * argTypes = ( CV_typ_t * ) argData ;
for ( int paramIdx = 0 ; paramIdx < proc - > parmcount ; paramIdx + + )
{
BP_ALLOC_T ( DbgVariable ) ;
2022-07-30 09:08:49 -04:00
DbgVariable * arg = mAlloc . Alloc < DbgVariable > ( ) ;
2019-09-21 10:49:35 -07:00
arg - > mIsParam = true ;
2020-11-17 07:52:51 -08:00
arg - > mType = CvGetTypeSafe ( argTypes [ paramIdx ] ) ;
2019-09-21 10:49:35 -07:00
arg - > mName = " $arg " ;
dbgType - > mBlockParam - > mVariables . PushBack ( arg ) ;
}
}
break ;
2020-11-18 09:15:28 -08:00
// case 0x1609:
// NOP;
// break;
default :
NOP ;
break ;
2019-09-21 10:49:35 -07:00
}
if ( dbgType ! = NULL )
{
if ( tagIdx = = 14709 )
{
NOP ;
}
dbgType - > mTagIdx = tagIdx ;
int wantIdx = tagIdx - mCvMinTag ;
mCvTypeMap [ wantIdx ] = dbgType ;
}
return dbgType ;
}
void COFF : : ParseTypeData ( CvStreamReader & reader , int dataOffset )
{
BP_ZONE ( " COFF::ParseTypeData " ) ;
//uint8* sectionEnd = sectionData + sectionSize;
//uint8* data = sectionData;
if ( mCvMinTag = = - 1 )
mCvMinTag = 0x1000 ;
int offset = dataOffset ;
bool isTagMapEmpty = mCvTagStartMap . empty ( ) ;
for ( int tagIdx = mCvMinTag ; true ; tagIdx + + )
{
if ( tagIdx = = mCvMaxTag )
break ;
if ( offset > = reader . mSize )
break ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
//OutputDebugStrF("%X %X\n", tagIdx, (int)(data - sectionData));
BF_ASSERT ( ( ( offset ) & 3 ) = = 0 ) ;
//PTR_ALIGN(data, sectionData, 4);
uint8 * data = reader . GetTempPtr ( offset , 4 ) ;
2022-07-30 09:08:49 -04:00
uint16 trLength = * ( uint16 * ) data ;
uint16 trLeafType = * ( uint16 * ) ( data + 2 ) ;
2019-09-21 10:49:35 -07:00
// uint16 trLength = GET(uint16);
// uint8* dataStart = data;
// uint16 trLeafType = GET(uint16);
// uint8* dataEnd = dataStart + trLength;
if ( isTagMapEmpty )
{
mCvTagStartMap . push_back ( offset ) ;
mCvTypeMap . push_back ( NULL ) ;
}
else
mCvTagStartMap [ tagIdx - mCvMinTag ] = offset ;
offset + = trLength + 2 ;
DbgType * dbgType = NULL ;
if ( trLeafType = = 0 )
continue ;
2020-11-18 09:15:28 -08:00
if ( ( trLeafType = = LF_ENUM ) | | ( trLeafType = = LF_CLASS ) | | ( trLeafType = = LF_STRUCTURE ) | | ( trLeafType = = LF_UNION ) | |
( trLeafType = = LF_CLASS_EX ) | | ( trLeafType = = LF_STRUCTURE_EX ) )
2019-09-21 10:49:35 -07:00
{
CvParseType ( tagIdx ) ;
}
}
2019-12-21 09:35:58 -08:00
if ( isTagMapEmpty )
mCvTagStartMap . Add ( offset ) ;
2019-09-21 10:49:35 -07:00
}
void COFF : : ParseTypeData ( int sectionNum , CvStreamReader & reader , int & sectionSize , int & dataOfs , int & hashStream , int & hashAdjOffset , int & hashAdjSize , int & minVal , int & maxVal )
{
BP_ZONE ( " COFF::ParseTypeData " ) ;
sectionSize = 0 ;
// sectionData = CvReadStream(sectionNum, §ionSize);
// if (sectionData == NULL)
// return;
2022-07-30 09:08:49 -04:00
// uint8* data = sectionData;
2019-09-21 10:49:35 -07:00
CvReadStream ( sectionNum , reader ) ;
uint8 * data = reader . GetTempPtr ( 0 , 0 ) ;
uint8 * sectionData = data ;
int32 ver = GET ( int32 ) ;
int32 headerSize = GET ( int32 ) ;
minVal = GET ( int32 ) ;
maxVal = GET ( int32 ) ;
int32 followSize = GET ( int32 ) ;
hashStream = GET ( int16 ) ;
int16 hashStreamPadding = GET ( int16 ) ; // -1
int32 hashKeySize = GET ( int32 ) ; // 4
int32 hashBucketsSize = GET ( int32 ) ; // 0x3ffff
int32 hashValsOffset = GET ( int32 ) ; // 0
int32 hashValsSize = GET ( int32 ) ;
int32 hashTypeIndexOffset = GET ( int32 ) ;
int32 hashTypeIndexSize = GET ( int32 ) ;
hashAdjOffset = GET ( int32 ) ;
hashAdjSize = GET ( int32 ) ;
dataOfs = 14 * 4 ;
uint8 * typeDataHead = data ;
bool validate = false ;
// Validate hash info - not necessary, just for debugging
if ( validate )
{
BF_FATAL ( " Fix validate stuff to work with new CvReader " ) ;
int hashStreamSize = 0 ;
uint8 * hashDataHead = CvReadStream ( hashStream , & hashStreamSize ) ;
int tagId = minVal ;
//////// Validate Type indices
int typeIndexCount = hashTypeIndexSize / 8 ;
2022-07-30 09:08:49 -04:00
// We expect a TypeIndexOffset for every 8k of data, plus the zero at the start
2019-09-21 10:49:35 -07:00
int expectedTypeIndices = ( sectionSize - ( int ) ( data - sectionData ) ) / 8192 + 1 ;
// Assert it's in some acceptable range...
BF_ASSERT ( ( typeIndexCount > expectedTypeIndices / 2 ) & & ( typeIndexCount < expectedTypeIndices * 2 ) ) ;
for ( int entryIdx = 0 ; entryIdx < typeIndexCount ; entryIdx + + )
{
data = hashDataHead + hashTypeIndexOffset + entryIdx * 8 ;
GET_INTO ( int , typeIdx ) ;
GET_INTO ( int , ofs ) ;
uint8 * dataEnd ;
int endTagId ;
if ( entryIdx < typeIndexCount - 1 )
{
endTagId = GET ( int ) ;
int endOfs = GET ( int ) ;
dataEnd = typeDataHead + endOfs ;
}
else
{
endTagId = maxVal ;
dataEnd = sectionData + sectionSize ;
}
data = typeDataHead + ofs ;
while ( data < dataEnd )
{
int tagSize = GET ( uint16 ) ;
data + = tagSize ;
tagId + + ;
}
BF_ASSERT ( data = = dataEnd ) ;
BF_ASSERT ( tagId = = endTagId ) ;
}
BF_ASSERT ( tagId = = maxVal ) ;
////// Validate hashes
int hashCount = hashValsSize / 4 ;
BF_ASSERT ( hashCount = = maxVal - minVal ) ;
tagId = minVal ;
int32 * hashVals = ( int32 * ) ( hashDataHead + hashValsOffset ) ;
data = typeDataHead ;
Array < int > tagStarts ;
tagStarts . Reserve ( maxVal - minVal ) ;
for ( int hashIdx = 0 ; hashIdx < hashCount ; hashIdx + + )
{
int32 expectHashVal = hashVals [ hashIdx ] ;
PTR_ALIGN ( data , sectionData , 4 ) ;
tagStarts . push_back ( ( int ) ( data - sectionData ) ) ;
int32 hashVal = BlHash : : GetTypeHash ( data ) % hashBucketsSize ;
BF_ASSERT ( hashVal = = expectHashVal ) ;
tagId + + ;
}
//////// Validate hash adjusters
if ( hashAdjSize > 0 )
{
data = hashDataHead + hashAdjOffset ;
uint8 * dataEnd = data + hashAdjSize ;
GET_INTO ( int32 , adjustCount ) ;
GET_INTO ( int32 , adjustCapacity ) ;
GET_INTO ( int32 , usedLen ) ;
uint32 * usedBitsArr = ( uint32 * ) data ;
data + = usedLen * sizeof ( int32 ) ;
GET_INTO ( int32 , deletedLen ) ;
uint32 * deletedBitsArr = ( uint32 * ) data ;
data + = deletedLen * sizeof ( int32 ) ;
int curAdjIdx = 0 ;
for ( int usedIdx = 0 ; usedIdx < usedLen ; usedIdx + + )
{
int usedBits = usedBitsArr [ usedIdx ] ;
for ( int i = 0 ; i < 32 ; i + + )
{
if ( ( usedBits & ( 1 < < i ) ) ! = 0 )
{
GET_INTO ( int32 , adjVal ) ;
GET_INTO ( CV_typ_t , typeId ) ;
uint8 * typeData = sectionData + tagStarts [ typeId - minVal ] ;
int32 hashVal = BlHash : : GetTypeHash ( typeData ) % hashBucketsSize ;
const char * strVal = mStringTable . mStrTable + adjVal ;
int32 strHashVal = BlHash : : HashStr_PdbV1 ( strVal ) % hashBucketsSize ;
BF_ASSERT ( hashVal = = strHashVal ) ;
curAdjIdx + + ;
}
}
}
BF_ASSERT ( curAdjIdx = = adjustCount ) ;
}
data = typeDataHead ;
}
}
void COFF : : ParseTypeData ( )
{
if ( ! mPDBLoaded )
return ;
if ( mParsedTypeData )
return ;
mParsedTypeData = true ;
auto linkedModule = GetLinkedModule ( ) ;
int startingTypeIdx = ( int ) linkedModule - > mTypes . size ( ) ;
//uint8* sectionData;
int sectionSize = 0 ;
int hashAdjOffset = 0 ;
int32 hashStream = - 1 ;
int32 hashAdjSize = 0 ;
2022-07-30 09:08:49 -04:00
int32 dataOffset = 0 ;
2019-09-21 10:49:35 -07:00
ParseTypeData ( 2 , mCvTypeSectionReader , sectionSize , dataOffset , hashStream , hashAdjOffset , hashAdjSize , mCvMinTag , mCvMaxTag ) ;
//mCvTypeSectionData = sectionData;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
mCvTypeMap . Clear ( ) ;
mCvTagStartMap . Clear ( ) ;
mCvTypeMap . Resize ( mCvMaxTag - mCvMinTag ) ;
mCvTagStartMap . Resize ( mCvMaxTag - mCvMinTag ) ;
//DbgDataMap dataMap(minVal, maxVal);
//uint8* data = sectionData + dataOffset;
ParseTypeData ( mCvTypeSectionReader , dataOffset ) ;
if ( hashAdjSize > 0 )
{
int sectionSize = 0 ;
uint8 * data = CvReadStream ( hashStream , & sectionSize ) ;
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 ) ;
}
2022-07-30 09:08:49 -04:00
// Types listed in the adjustment table are always primary types,
2019-09-21 10:49:35 -07:00
// 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 ) ;
DbgType * dbgType = CvGetType ( typeId ) ;
if ( dbgType ! = NULL )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
dbgType - > mPriority = DbgTypePriority_Primary_Explicit ;
}
}
2022-07-30 09:08:49 -04:00
delete [ ] sectionData ;
2019-09-21 10:49:35 -07:00
}
FixTypes ( startingTypeIdx ) ;
MapTypes ( startingTypeIdx ) ;
BF_ASSERT ( mTempBufIdx = = 0 ) ;
}
void COFF : : FixConstant ( DbgVariable * constVar )
{
if ( constVar - > mType - > mTypeCode = = DbgType_u8 )
constVar - > mConstValue & = 0xFF ;
else if ( constVar - > mType - > mTypeCode = = DbgType_u16 )
constVar - > mConstValue & = 0xFFFF ;
else if ( constVar - > mType - > mTypeCode = = DbgType_u32 )
constVar - > mConstValue & = 0xFFFFFFFF ;
}
void COFF : : MapRanges ( DbgVariable * variable , CV_LVAR_ADDR_RANGE * range , CV_LVAR_ADDR_GAP * gaps )
{
auto rangeStart = GetSectionAddr ( range - > isectStart , range - > offStart ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( variable - > mRangeStart = = 0 )
{
2022-07-30 09:08:49 -04:00
variable - > mRangeStart = rangeStart ;
2019-09-21 10:49:35 -07:00
variable - > mRangeLen = ( rangeStart + range - > cbRange ) - variable - > mRangeStart ;
}
else
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
addr_target maxEnd = BF_MAX ( variable - > mRangeStart + variable - > mRangeLen , rangeStart + range - > cbRange ) ;
variable - > mRangeStart = BF_MIN ( variable - > mRangeStart , rangeStart ) ;
variable - > mRangeLen = maxEnd - variable - > mRangeStart ;
}
}
void COFF : : MakeThis ( DbgSubprogram * curSubprogram , DbgVariable * & curParam )
{
if ( ( curParam ! = NULL ) | | ( curSubprogram - > mParams . mHead ! = NULL ) )
return ;
BP_ALLOC_T ( DbgVariable ) ;
curParam = mAlloc . Alloc < DbgVariable > ( ) ;
curParam - > mIsParam = true ;
curParam - > mName = " this " ;
curSubprogram - > mParams . mHead = curParam ;
}
static int gSymCount = 0 ;
void COFF : : ParseCompileUnit_Symbols ( DbgCompileUnit * compileUnit , uint8 * sectionData , uint8 * data , uint8 * symDataEnd , CvInlineInfoVec & inlineDataVec , bool wantDeferInternals , DbgSubprogram * useSubprogram )
{
bool isOptimized = false ;
uint8 * dataHead = data ;
CvCompileUnit * cvCompileUnit = ( CvCompileUnit * ) compileUnit ;
uint8 * symDataStart = data ;
2022-07-30 09:08:49 -04:00
DbgSubprogram * curSubprogram = NULL ;
2019-09-21 10:49:35 -07:00
DbgVariable * curRegRelVariable = NULL ;
DbgVariable * curParam = NULL ;
DbgVariable * localVar = NULL ;
bool inLocalVarRanged = false ;
SizedArray < DbgBlock * , 16 > blockStack ;
blockStack . push_back ( compileUnit - > mGlobalBlock ) ;
int deferBlockDepth = 0 ;
int deferInlineDepth = 0 ;
uint8 * newLocationDataStart = NULL ;
uint8 * locationDataStart = NULL ;
uint8 * locationDataEnd = NULL ;
int locationDataCount = 0 ;
struct _DeferredVariableLocation
{
DbgVariable * mVariable ;
uint8 * mRangedStart ;
int mRangedLength ;
_DeferredVariableLocation ( )
{
mVariable = NULL ;
mRangedStart = NULL ;
2022-07-30 09:08:49 -04:00
mRangedLength = 0 ;
2019-09-21 10:49:35 -07:00
}
} ;
2022-07-30 09:08:49 -04:00
SizedArray < _DeferredVariableLocation , 16 > deferredVariableLocations ;
2019-09-21 10:49:35 -07:00
int unrangedIdx = - 1 ;
auto _NextUnrangedLocalVar = [ & ] ( const char * name , DbgType * varType )
{
inLocalVarRanged = false ;
localVar = NULL ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
unrangedIdx + + ;
while ( unrangedIdx < deferredVariableLocations . size ( ) )
{
localVar = deferredVariableLocations [ unrangedIdx ] . mVariable ;
if ( strcmp ( localVar - > mName , name ) = = 0 )
break ;
localVar = NULL ;
unrangedIdx + + ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
bool isParam = false ;
if ( localVar = = NULL )
{
if ( curParam ! = NULL )
{
isParam = true ;
if ( curParam - > mType ! = varType )
{
// Type was different, probably from a 'ref' being added when we are passing composites
curParam - > mName = name ;
curParam = curParam - > mNext ;
}
else
{
localVar = curParam ;
curParam = curParam - > mNext ;
}
}
}
if ( localVar = = NULL )
{
BP_ALLOC_T ( DbgVariable ) ;
localVar = mAlloc . Alloc < DbgVariable > ( ) ;
if ( name ! = NULL )
blockStack . back ( ) - > mVariables . PushBack ( localVar ) ;
//return;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
localVar - > mName = name ;
if ( isParam )
localVar - > mIsParam = true ;
if ( strcmp ( name , " this " ) = = 0 )
{
MakeThis ( curSubprogram , localVar ) ;
2020-11-16 10:02:54 -08:00
//BF_ASSERT(varType->mTypeCode == DbgType_Ptr);
2019-09-21 10:49:35 -07:00
curSubprogram - > mParentType = varType - > mTypeParam ;
curSubprogram - > mHasThis = true ;
}
} ;
auto _FinishLocationData = [ & ] ( )
{
if ( locationDataStart = = NULL )
return ;
if ( inLocalVarRanged )
{
auto & deferredVariableLocation = deferredVariableLocations . back ( ) ;
BF_ASSERT ( deferredVariableLocation . mRangedLength = = 0 ) ;
deferredVariableLocation . mRangedStart = locationDataStart ;
deferredVariableLocation . mRangedLength = ( int ) ( locationDataEnd - locationDataStart ) ;
}
else
{
2020-01-22 12:37:44 -08:00
if ( localVar - > mLocationData ! = NULL )
{
// Already handled
NOP ;
}
else if ( unrangedIdx > = deferredVariableLocations . size ( ) )
2019-09-21 10:49:35 -07:00
{
// There was no ranged data, commit just the unranged entry
BF_ASSERT ( locationDataCount = = localVar - > mLocationLen ) ;
BP_ALLOC ( " DeferredVarLoc0 " , locationDataEnd - locationDataStart ) ;
localVar - > mLocationData = mAlloc . AllocBytes ( locationDataEnd - locationDataStart , " DeferredVarLoc0 " ) ;
memcpy ( ( uint8 * ) localVar - > mLocationData , locationDataStart , locationDataEnd - locationDataStart ) ;
}
else
{
// We have both ranged an unranged data. Merge them!
auto & deferredVariableLocation = deferredVariableLocations [ unrangedIdx ] ;
auto deferredVar = deferredVariableLocation . mVariable ;
BF_ASSERT ( deferredVar = = localVar ) ;
if ( deferredVariableLocation . mRangedLength = = 0 )
BF_ASSERT ( locationDataCount = = localVar - > mLocationLen ) ;
else
BF_ASSERT ( locationDataCount < localVar - > mLocationLen ) ;
BP_ALLOC ( " DeferredVarLoc1 " , deferredVariableLocation . mRangedLength + ( locationDataEnd - locationDataStart ) ) ;
localVar - > mLocationData = mAlloc . AllocBytes ( deferredVariableLocation . mRangedLength + ( locationDataEnd - locationDataStart ) , " DeferredVarLoc1 " ) ;
memcpy ( ( uint8 * ) localVar - > mLocationData , deferredVariableLocation . mRangedStart , deferredVariableLocation . mRangedLength ) ;
memcpy ( ( uint8 * ) localVar - > mLocationData + deferredVariableLocation . mRangedLength , locationDataStart , locationDataEnd - locationDataStart ) ;
deferredVariableLocation . mRangedLength = - 1 ; // Mark as 'handled'
}
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
locationDataStart = NULL ;
locationDataEnd = NULL ;
locationDataCount = 0 ;
} ;
auto _FlushDeferredVariableLocations = [ & ] ( )
{
for ( auto & deferredVariableLocation : deferredVariableLocations )
{
if ( deferredVariableLocation . mRangedLength = = - 1 )
2022-07-30 09:08:49 -04:00
continue ;
2019-09-21 10:49:35 -07:00
auto deferredVar = deferredVariableLocation . mVariable ;
2020-01-22 12:37:44 -08:00
if ( deferredVar - > mLocationData ! = NULL )
{
// Already handled
continue ;
}
2019-09-21 10:49:35 -07:00
BP_ALLOC ( " DeferredVarLoc2 " , deferredVariableLocation . mRangedLength ) ;
deferredVar - > mLocationData = mAlloc . AllocBytes ( deferredVariableLocation . mRangedLength , " DeferredVarLoc2 " ) ;
memcpy ( ( uint8 * ) deferredVar - > mLocationData , deferredVariableLocation . mRangedStart , deferredVariableLocation . mRangedLength ) ;
}
deferredVariableLocations . clear ( ) ;
unrangedIdx = - 1 ;
} ;
bool inlineDebugDump = false ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( useSubprogram ! = NULL )
{
curSubprogram = useSubprogram ;
blockStack . push_back ( & curSubprogram - > mBlock ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
curParam = curSubprogram - > mParams . mHead ;
curRegRelVariable = curParam ;
}
while ( data < symDataEnd )
{
bool deferInternals = ( wantDeferInternals ) | | ( deferInlineDepth > 0 ) ;
gSymCount + + ;
uint8 * dataStart = data ;
GET_INTO ( uint16 , symLen ) ;
uint8 * dataEnd = data + symLen ;
GET_INTO ( uint16 , symType ) ;
2019-11-07 13:35:56 -08:00
if ( ! IsObjectFile ( ) )
2019-09-21 10:49:35 -07:00
BF_ASSERT ( symLen % 4 = = 2 ) ;
bool newLocalVarHasLocData = false ;
DbgVariable * prevLocalVar = localVar ;
switch ( symType )
{
case S_LOCAL :
case S_BPREL32 :
case S_REGISTER :
case S_REGREL32 :
case S_GPROC32 :
case S_LPROC32 :
case S_GPROC32_ID :
case S_LPROC32_ID :
// Starting a new var or method
if ( ( ! deferInternals ) & & ( locationDataStart ! = NULL ) )
{
_FinishLocationData ( ) ;
}
break ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
/*if (handled)
{
data = dataEnd ;
continue ;
} */
if ( inlineDebugDump )
BfLogCv ( " SYMTYPE: %X \n " , symType ) ;
switch ( symType )
{
case S_UDT :
{
UDTSYM & udtSym = * ( UDTSYM * ) dataStart ;
DbgType * typeDefType = CvCreateType ( ) ;
typeDefType - > mTypeCode = DbgType_TypeDef ;
2020-11-17 07:52:51 -08:00
typeDefType - > mTypeParam = CvGetTypeSafe ( udtSym . typind ) ;
2022-07-30 09:08:49 -04:00
typeDefType - > mName = DbgDupString ( ( const char * ) udtSym . name , " DbgDupString.S_UDT " ) ;
2019-09-21 10:49:35 -07:00
if ( strncmp ( typeDefType - > mName , " _bf:: " , 5 ) = = 0 )
{
typeDefType - > mLanguage = DbgLanguage_Beef ;
typeDefType - > mName + = 5 ;
}
else
{
typeDefType - > mLanguage = DbgLanguage_C ;
}
typeDefType - > mTypeName = typeDefType - > mName ;
}
break ;
case S_OBJNAME :
{
GET_INTO ( int32 , objSig ) ;
2022-07-30 09:08:49 -04:00
const char * objName = CvParseAndDupString ( data ) ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_CONSTANT :
{
CONSTSYM & constSym = * ( CONSTSYM * ) dataStart ;
BP_ALLOC_T ( DbgVariable ) ;
DbgVariable * constVar = mAlloc . Alloc < DbgVariable > ( ) ;
constVar - > mName = DbgDupString ( ( const char * ) constSym . name , " DbgDupString.S_CONSTANT " ) ;
2020-11-17 07:52:51 -08:00
constVar - > mType = CvGetTypeSafe ( constSym . typind ) ;
2019-09-21 10:49:35 -07:00
constVar - > mIsConst = true ;
constVar - > mIsStatic = true ;
constVar - > mConstValue = constSym . value ;
data = constSym . name + strlen ( ( const char * ) constSym . name ) + 1 ;
constVar - > mConstValue = CvParseConstant ( constSym . value , data ) ;
FixConstant ( constVar ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( constVar - > mName ! = NULL )
blockStack . back ( ) - > mVariables . PushBack ( constVar ) ;
}
break ;
case S_EXPORT :
{
GET_INTO ( int16 , ord ) ;
struct ExpFlags
{
unsigned short fConstant : 1 ; // CONSTANT
unsigned short fData : 1 ; // DATA
unsigned short fPrivate : 1 ; // PRIVATE
unsigned short fNoName : 1 ; // NONAME
unsigned short fOrdinal : 1 ; // Ordinal was explicitly assigned
unsigned short fForwarder : 1 ; // This is a forwarder
unsigned short reserved : 10 ; // Reserved. Must be zero.
} ;
GET_INTO ( ExpFlags , flags ) ;
2022-07-30 09:08:49 -04:00
const char * symName = CvParseAndDupString ( data ) ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_GDATA32 :
case S_LDATA32 :
// In PDB reads we get this from the symbol stream
2019-11-07 13:35:56 -08:00
if ( ( IsObjectFile ( ) ) | | ( curSubprogram ! = NULL ) )
2019-09-21 10:49:35 -07:00
{
auto linkedModule = GetLinkedModule ( ) ;
DATASYM32 & dataSym = * ( DATASYM32 * ) dataStart ;
2022-07-30 09:08:49 -04:00
char * name = ( char * ) dataSym . name ;
2019-09-21 10:49:35 -07:00
char * targetName = NULL ;
DbgType * targetType = mMasterCompileUnit - > mGlobalType ;
bool overrideBeef = false ;
char * lastDblColon = ( char * ) GetLastDoubleColon ( name ) ;
if ( lastDblColon ! = NULL )
{
targetName = name ;
name = lastDblColon + 2 ;
* lastDblColon = 0 ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( strcmp ( targetName , " _bf " ) = = 0 )
{
overrideBeef = true ;
}
else
{
targetType = CvGetTypeOrNamespace ( targetName ) ;
}
}
2022-07-30 09:08:49 -04:00
2020-11-17 07:52:51 -08:00
DbgType * dbgType = CvGetTypeSafe ( dataSym . typind ) ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgVariable ) ;
DbgVariable * variable = mAlloc . Alloc < DbgVariable > ( ) ;
2022-07-30 09:08:49 -04:00
variable - > mType = dbgType ;
2019-09-21 10:49:35 -07:00
variable - > mLocationData = dataStart ;
variable - > mLocationLen = 1 ;
variable - > mIsStatic = true ;
variable - > mCompileUnit = mMasterCompileUnit ;
variable - > mName = name ;
if ( targetType = = mMasterCompileUnit - > mGlobalType )
variable - > mLinkName = name ;
variable - > mIsExtern = symType = = S_GDATA32 ;
if ( curSubprogram ! = NULL )
{
2019-11-07 13:35:56 -08:00
if ( ! IsObjectFile ( ) )
2019-09-21 10:49:35 -07:00
{
// Copy this, we free the source data
variable - > mName = DbgDupString ( name , " DbgDupString.S_GDATA32 " ) ;
BP_ALLOC_T ( DATASYM32 )
auto newPtr = mAlloc . Alloc < DATASYM32 > ( ) ;
memcpy ( newPtr , variable - > mLocationData , sizeof ( DATASYM32 ) ) ;
variable - > mLocationData = ( uint8 * ) newPtr ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
if ( variable - > mName ! = NULL )
blockStack . back ( ) - > mVariables . PushBack ( variable ) ;
break ;
}
2022-07-30 09:08:49 -04:00
//variable->mCompileUnit = m;
2019-09-21 10:49:35 -07:00
// Push front so we will find before the original static declaration (that has no memory associated with it)
2020-07-31 06:18:26 -07:00
if ( targetType ! = NULL )
targetType - > mMemberList . PushFront ( variable ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ( variable - > mIsExtern ) & & ( variable - > mLinkName ! = NULL ) )
2022-07-30 09:08:49 -04:00
mStaticVariables . push_back ( variable ) ;
}
break ;
2019-09-21 10:49:35 -07:00
case S_GTHREAD32 :
case S_LTHREAD32 :
{
2022-07-30 09:08:49 -04:00
if ( ( IsObjectFile ( ) ) | | ( curSubprogram ! = NULL ) )
2019-09-21 10:49:35 -07:00
{
auto linkedModule = GetLinkedModule ( ) ;
THREADSYM32 & dataSym = * ( THREADSYM32 * ) dataStart ;
char * name = ( char * ) dataSym . name ;
char * targetName = NULL ;
DbgType * targetType = mMasterCompileUnit - > mGlobalType ;
bool overrideBeef = false ;
char * lastDblColon = ( char * ) GetLastDoubleColon ( name ) ;
if ( lastDblColon ! = NULL )
{
targetName = name ;
name = lastDblColon + 2 ;
* lastDblColon = 0 ;
if ( strcmp ( targetName , " _bf " ) = = 0 )
{
overrideBeef = true ;
}
else
{
targetType = CvGetTypeOrNamespace ( targetName ) ;
}
}
2020-11-17 07:52:51 -08:00
DbgType * dbgType = CvGetTypeSafe ( dataSym . typind ) ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgVariable ) ;
DbgVariable * variable = mAlloc . Alloc < DbgVariable > ( ) ;
variable - > mType = dbgType ;
variable - > mLocationData = dataStart ;
variable - > mLocationLen = 1 ;
variable - > mIsStatic = true ;
variable - > mCompileUnit = mMasterCompileUnit ;
2022-07-30 09:08:49 -04:00
variable - > mName = name ;
2019-09-21 10:49:35 -07:00
if ( targetType = = mMasterCompileUnit - > mGlobalType )
variable - > mLinkName = name ;
variable - > mIsExtern = symType = = S_GTHREAD32 ;
if ( curSubprogram ! = NULL )
{
2019-11-07 13:35:56 -08:00
if ( ! IsObjectFile ( ) )
2019-09-21 10:49:35 -07:00
{
// Copy this, we free the source data
variable - > mName = DbgDupString ( name , " DbgDupString.S_GTHREAD32 " ) ;
BP_ALLOC_T ( DATASYM32 )
auto newPtr = mAlloc . Alloc < DATASYM32 > ( ) ;
memcpy ( newPtr , variable - > mLocationData , sizeof ( DATASYM32 ) ) ;
variable - > mLocationData = ( uint8 * ) newPtr ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
if ( variable - > mName ! = NULL )
blockStack . back ( ) - > mVariables . PushBack ( variable ) ;
break ;
}
2022-07-30 09:08:49 -04:00
//variable->mCompileUnit = m;
2019-09-21 10:49:35 -07:00
// Push front so we will find before the original static declaration (that has no memory associated with it)
targetType - > mMemberList . PushFront ( variable ) ;
if ( ( variable - > mIsExtern ) & & ( variable - > mLinkName ! = NULL ) )
mStaticVariables . push_back ( variable ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
break ;
case S_GPROC32 :
case S_LPROC32 :
case S_GPROC32_ID :
case S_LPROC32_ID :
{
BF_ASSERT ( curSubprogram = = NULL ) ;
2022-07-30 09:08:49 -04:00
PROCSYM32 * procSym = ( PROCSYM32 * ) dataStart ;
2019-09-21 10:49:35 -07:00
DbgType * parentType = NULL ;
auto addr = GetSectionAddr ( procSym - > seg , procSym - > off ) ;
2022-07-30 09:08:49 -04:00
2020-11-16 10:02:54 -08:00
DbgSubprogram * subprogram = NULL ;
2022-07-30 09:08:49 -04:00
if ( procSym - > typind ! = 0 )
{
2019-09-21 10:49:35 -07:00
bool ipi = false ;
2022-07-30 09:08:49 -04:00
if ( ( ! IsObjectFile ( ) ) & &
2019-09-21 10:49:35 -07:00
( ( symType = = S_GPROC32_ID ) | | ( symType = = S_LPROC32_ID ) ) )
{
if ( ! mCvIPIReader . IsSetup ( ) )
CvParseIPI ( ) ;
ipi = true ;
2022-07-30 09:08:49 -04:00
}
subprogram = CvParseMethod ( parentType , NULL , procSym - > typind , ipi ) ;
2019-09-21 10:49:35 -07:00
}
2020-11-16 10:02:54 -08:00
if ( subprogram = = NULL )
{
BP_ALLOC_T ( DbgSubprogram ) ;
subprogram = mAlloc . Alloc < DbgSubprogram > ( ) ;
}
2019-09-21 10:49:35 -07:00
subprogram - > mTagIdx = ( int ) ( dataEnd - sectionData ) ; // Position for method data
subprogram - > mIsOptimized = isOptimized ;
2022-07-30 09:08:49 -04:00
subprogram - > mCompileUnit = compileUnit ;
2019-11-29 09:21:51 -08:00
char * name = DbgDupString ( ( const char * ) procSym - > name , " DbgDupString.S_GPROC32 " ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( procSym - > flags . CV_PFLAG_OPTDBGINFO )
{
subprogram - > mIsOptimized = true ;
}
if ( ( name [ 0 ] = = ' _ ' ) & & ( name [ 1 ] = = ' _ ' ) )
{
// This matches things like "__chkstk" or other system (supposedly) functions
subprogram - > mIsStepFilteredDefault = true ;
}
if ( strncmp ( name , " _bf:: " , 5 ) = = 0 )
{
compileUnit - > mLanguage = DbgLanguage_Beef ;
}
localVar = NULL ;
bool hasColon = false ;
2019-11-29 09:21:51 -08:00
for ( char * cPtr = name ; * cPtr ! = 0 ; cPtr + + )
{
char c = * cPtr ;
hasColon | = c = = ' : ' ;
if ( c = = ' $ ' )
{
if ( strcmp ( cPtr , " $CHK " ) = = 0 )
{
subprogram - > mCheckedKind = BfCheckedKind_Checked ;
* cPtr = NULL ;
break ;
}
else if ( strcmp ( cPtr , " $UCHK " ) = = 0 )
{
subprogram - > mCheckedKind = BfCheckedKind_Unchecked ;
* cPtr = NULL ;
break ;
2022-07-30 09:08:49 -04:00
}
2019-11-29 09:21:51 -08:00
}
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
subprogram - > mPrologueSize = procSym - > DbgStart ;
subprogram - > mBlock . mLowPC = addr ;
subprogram - > mBlock . mHighPC = subprogram - > mBlock . mLowPC + ( int32 ) procSym - > len ;
BF_ASSERT ( procSym - > len > = 0 ) ;
MapSubprogram ( subprogram ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
curSubprogram = subprogram ;
curParam = subprogram - > mParams . mHead ;
curRegRelVariable = curParam ;
blockStack . push_back ( & subprogram - > mBlock ) ;
//OutputDebugStrF("Func: %s\n", subprogram->mName);
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( hasColon )
{
subprogram - > mName = name ;
subprogram - > mHasQualifiedName = true ;
compileUnit - > mOrphanMethods . PushBack ( curSubprogram ) ;
}
else
{
subprogram - > mName = name ;
compileUnit - > mGlobalType - > mMethodList . PushBack ( curSubprogram ) ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
BF_ASSERT ( unrangedIdx = = - 1 ) ;
}
break ;
case S_THUNK32 :
{
THUNKSYM32 & thunkSym = * ( THUNKSYM32 * ) dataStart ;
DbgType * parentType = NULL ;
2022-07-30 09:08:49 -04:00
DbgSubprogram * subprogram ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgSubprogram ) ;
2022-07-30 09:08:49 -04:00
subprogram = mAlloc . Alloc < DbgSubprogram > ( ) ;
2019-09-21 10:49:35 -07:00
subprogram - > mCompileUnit = compileUnit ;
subprogram - > mHasQualifiedName = true ;
subprogram - > mName = DbgDupString ( ( const char * ) thunkSym . name , " DbgDupString.S_THUNK32 " ) ;
subprogram - > mTagIdx = ( int ) ( dataEnd - sectionData ) ; // Position for method data
subprogram - > mBlock . mLowPC = GetSectionAddr ( thunkSym . seg , thunkSym . off ) ;
subprogram - > mBlock . mHighPC = subprogram - > mBlock . mLowPC + thunkSym . len ;
BF_ASSERT ( thunkSym . len > = 0 ) ;
MapSubprogram ( subprogram ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
curSubprogram = subprogram ;
curParam = subprogram - > mParams . mHead ;
blockStack . push_back ( & subprogram - > mBlock ) ;
BF_ASSERT ( unrangedIdx = = - 1 ) ;
//OutputDebugStrF("Func: %s\n", subprogram->mName);
}
break ;
case S_BLOCK32 :
{
if ( deferInternals )
{
deferBlockDepth + + ;
break ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgBlock ) ;
DbgBlock * block = mAlloc . Alloc < DbgBlock > ( ) ;
blockStack . back ( ) - > mSubBlocks . PushBack ( block ) ;
blockStack . push_back ( block ) ;
BLOCKSYM32 * blockSym = ( BLOCKSYM32 * ) dataStart ;
block - > mLowPC = GetSectionAddr ( blockSym - > seg , blockSym - > off ) ;
block - > mHighPC = block - > mLowPC + blockSym - > len ;
}
break ;
case S_FRAMEPROC :
{
2022-07-30 09:08:49 -04:00
FRAMEPROCSYM * frameProc = ( FRAMEPROCSYM * ) dataStart ;
2019-09-21 10:49:35 -07:00
if ( curSubprogram ! = NULL )
{
// if ((curSubprogram->mName != NULL) && (strcmp(curSubprogram->mName, "_bf::IDETest::HotTester::TestFuncs") == 0))
// {
// NOP;
// }
curSubprogram - > mFrameBaseLen = frameProc - > cbFrame + frameProc - > cbSaveRegs ;
2019-12-01 10:17:09 -08:00
curSubprogram - > mParamBaseReg = ( DbgSubprogram : : LocalBaseRegKind ) ( uint8 ) frameProc - > flags . encodedParamBasePointer ;
2019-09-21 10:49:35 -07:00
curSubprogram - > mLocalBaseReg = ( DbgSubprogram : : LocalBaseRegKind ) ( uint8 ) frameProc - > flags . encodedLocalBasePointer ;
}
}
break ;
case S_BPREL32 :
{
if ( deferInternals )
break ;
BPRELSYM32 * bpRel32 = ( BPRELSYM32 * ) dataStart ;
const char * name = DbgDupString ( ( const char * ) bpRel32 - > name , " DbgDupString.S_BPREL32 " ) ;
2020-11-17 07:52:51 -08:00
DbgType * varType = CvGetTypeSafe ( bpRel32 - > typind ) ;
2019-09-21 10:49:35 -07:00
_NextUnrangedLocalVar ( name , varType ) ;
localVar - > mName = name ;
2022-07-30 09:08:49 -04:00
localVar - > mCompileUnit = compileUnit ;
2019-09-21 10:49:35 -07:00
localVar - > mType = varType ;
// This is location data now, not just a S_LOCAL opener
//prevLocalVar = localVar;
newLocalVarHasLocData = true ;
}
break ;
case S_REGISTER :
{
if ( deferInternals )
break ;
2022-07-30 09:08:49 -04:00
REGSYM * regSym = ( REGSYM * ) dataStart ;
2019-09-21 10:49:35 -07:00
const char * name = DbgDupString ( ( const char * ) regSym - > name ) ;
2020-11-17 07:52:51 -08:00
DbgType * varType = CvGetTypeSafe ( regSym - > typind ) ;
2019-09-21 10:49:35 -07:00
_NextUnrangedLocalVar ( name , varType ) ;
localVar - > mName = name ;
2022-07-30 09:08:49 -04:00
localVar - > mCompileUnit = compileUnit ;
2019-09-21 10:49:35 -07:00
localVar - > mType = varType ;
// This is location data now, not just a S_LOCAL opener
//prevLocalVar = localVar;
newLocalVarHasLocData = true ;
}
break ;
case S_REGREL32 :
{
if ( deferInternals )
break ;
REGREL32 * regRel32 = ( REGREL32 * ) dataStart ;
const char * name = DbgDupString ( ( const char * ) regRel32 - > name ) ;
2022-07-30 09:08:49 -04:00
DbgType * varType = CvGetTypeSafe ( regRel32 - > typind ) ;
2019-09-21 10:49:35 -07:00
_NextUnrangedLocalVar ( name , varType ) ;
localVar - > mName = name ;
2022-07-30 09:08:49 -04:00
localVar - > mCompileUnit = compileUnit ;
2020-06-13 04:55:45 -07:00
if ( ( localVar - > mType ! = NULL ) & & ( ! localVar - > mType - > IsPointer ( ) ) & & ( varType ! = NULL ) & & ( varType - > IsPointer ( ) ) )
2019-09-21 10:49:35 -07:00
localVar - > mSigNoPointer = true ;
localVar - > mType = varType ;
// This is location data now, not just a S_LOCAL opener
//prevLocalVar = localVar;
newLocalVarHasLocData = true ;
}
break ;
2022-07-30 09:08:49 -04:00
case S_LOCAL :
2019-09-21 10:49:35 -07:00
{
if ( deferInternals )
break ;
inLocalVarRanged = true ;
LOCALSYM & localSym = * ( LOCALSYM * ) dataStart ;
char * name = DbgDupString ( ( const char * ) localSym . name ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
bool isConst = false ;
int64 constVal = 0 ;
2020-04-26 10:27:38 -07:00
if ( ( compileUnit - > mLanguage = = DbgLanguage_Beef ) & & ( name ! = NULL ) & & ( name [ 0 ] ! = ' $ ' ) )
2019-09-21 10:49:35 -07:00
{
for ( char * cPtr = name + 1 ; true ; cPtr + + )
{
char c = * cPtr ;
if ( c = = 0 )
break ;
if ( c = = ' $ ' )
{
if ( cPtr [ 1 ] = = ' _ ' )
{
2019-12-05 06:50:08 -08:00
cPtr [ 1 ] = ' - ' ;
2019-09-21 10:49:35 -07:00
isConst = true ;
2022-07-30 09:08:49 -04:00
constVal = atoll ( cPtr + 1 ) ;
2019-09-21 10:49:35 -07:00
* cPtr = 0 ;
}
else if ( ( cPtr [ 1 ] > = ' 0 ' ) & & ( cPtr [ 1 ] < = ' 9 ' ) )
{
isConst = true ;
constVal = atoll ( cPtr + 1 ) ;
* cPtr = 0 ;
}
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ( name ! = NULL ) & & ( name [ 0 ] = = ' # ' ) )
{
if ( strcmp ( name + 1 , " StepOver " ) = = 0 )
{
curSubprogram - > mIsStepFilteredDefault = true ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
localVar = NULL ;
break ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
2022-07-30 09:08:49 -04:00
DbgType * varType = CvGetType ( localSym . typind , cvCompileUnit ) ;
2020-05-15 06:26:59 -07:00
if ( varType = = NULL )
varType = CvGetType ( T_VOID ) ;
2019-09-21 10:49:35 -07:00
if ( name ! = NULL )
{
if ( ( localSym . flags . fIsOptimizedOut ) & & ( name [ 0 ] ! = ' $ ' ) )
{
if ( varType - > mSize > 0 )
curSubprogram - > mIsOptimized = true ;
}
if ( ( strcmp ( name , " this " ) = = 0 ) & & ( varType ! = NULL ) )
{
//BF_ASSERT(varType->mTypeCode == DbgType_Ptr);
MakeThis ( curSubprogram , curParam ) ;
curSubprogram - > mParentType = varType - > mTypeParam ;
curSubprogram - > mHasThis = true ;
}
}
bool handledLocalVar = false ;
if ( curParam ! = NULL )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( ( name ! = NULL ) & & ( name [ 0 ] = = ' $ ' ) )
{
int strLen = strlen ( name ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
// Splat head
const char * dollarPos = strchr ( name + 1 , ' $ ' ) ;
const char * nameStr = name + 1 ;
int nameLen = dollarPos - name - 1 ;
if ( ( dollarPos ! = NULL ) & &
( ( localVar = = NULL ) | | ( strncmp ( localVar - > mName , name , nameLen + 1 ) ! = 0 ) ) )
{
BP_ALLOC ( " ParamName " , nameLen + 1 ) ;
char * dupStr = ( char * ) mAlloc . AllocBytes ( nameLen + 1 , " ParamName " ) ;
memcpy ( dupStr , nameStr , nameLen ) ;
curParam - > mName = dupStr ;
curParam - > mIsConst = true ;
curParam = curParam - > mNext ;
if ( strcmp ( dupStr , " this " ) = = 0 )
curSubprogram - > mHasThis = true ;
}
}
else if ( ( curParam - > mType ! = varType ) & & ( varType - > mTypeCode ! = DbgType_Void ) )
{
// Type was different, probably from a 'ref' being added when we are passing composites
curParam - > mName = name ;
2022-07-30 09:08:49 -04:00
curParam = curParam - > mNext ;
2019-09-21 10:49:35 -07:00
}
else
{
localVar = curParam ;
curParam = curParam - > mNext ;
handledLocalVar = true ;
}
}
if ( ! handledLocalVar )
{
BP_ALLOC_T ( DbgVariable ) ;
2022-07-30 09:08:49 -04:00
localVar = mAlloc . Alloc < DbgVariable > ( ) ;
2019-09-21 10:49:35 -07:00
if ( name ! = NULL )
blockStack . back ( ) - > mVariables . PushBack ( localVar ) ;
}
localVar - > mName = name ;
2022-07-30 09:08:49 -04:00
localVar - > mCompileUnit = compileUnit ;
2019-09-21 10:49:35 -07:00
localVar - > mType = varType ;
localVar - > mIsConst = isConst ;
localVar - > mConstValue = constVal ;
_DeferredVariableLocation deferredLocation ;
deferredLocation . mVariable = localVar ;
deferredVariableLocations . Add ( deferredLocation ) ;
}
break ;
case S_DEFRANGE_REGISTER :
{
if ( deferInternals )
break ;
DEFRANGESYMREGISTER & defRangeReg = * ( DEFRANGESYMREGISTER * ) dataStart ;
if ( localVar ! = NULL )
2022-07-30 09:08:49 -04:00
MapRanges ( localVar , & defRangeReg . range , defRangeReg . gaps ) ;
2019-09-21 10:49:35 -07:00
}
2022-07-30 09:08:49 -04:00
break ;
2019-09-21 10:49:35 -07:00
case S_DEFRANGE_FRAMEPOINTER_REL :
{
if ( deferInternals )
break ;
2022-07-30 09:08:49 -04:00
DEFRANGESYMFRAMEPOINTERREL & defRangeFPRel = * ( DEFRANGESYMFRAMEPOINTERREL * ) dataStart ;
MapRanges ( localVar , & defRangeFPRel . range , defRangeFPRel . gaps ) ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_DEFRANGE_SUBFIELD_REGISTER :
{
if ( deferInternals )
break ;
2022-07-30 09:08:49 -04:00
DEFRANGESYMSUBFIELDREGISTER & defRangeSubFieldReg = * ( DEFRANGESYMSUBFIELDREGISTER * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE :
{
if ( deferInternals )
break ;
DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE & defRangeFPRel = * ( DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE * ) dataStart ;
}
break ;
case S_DEFRANGE_REGISTER_REL :
{
if ( deferInternals )
break ;
DEFRANGESYMREGISTERREL & defRangeRegRel = * ( DEFRANGESYMREGISTERREL * ) dataStart ;
if ( localVar ! = NULL )
2022-07-30 09:08:49 -04:00
MapRanges ( localVar , & defRangeRegRel . range , defRangeRegRel . gaps ) ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_ENDARG :
if ( deferInternals )
break ;
BF_ASSERT ( curParam = = NULL ) ;
break ;
case S_END :
case S_PROC_ID_END :
2022-07-30 09:08:49 -04:00
if ( deferBlockDepth > 0 )
- - deferBlockDepth ;
2019-09-21 10:49:35 -07:00
else
blockStack . pop_back ( ) ;
BF_ASSERT ( blockStack . size ( ) > 0 ) ;
if ( blockStack . size ( ) = = 1 )
{
_FinishLocationData ( ) ;
_FlushDeferredVariableLocations ( ) ;
// Done with forced subprogram?
if ( useSubprogram ! = NULL )
{
return ;
}
else if ( deferInternals )
{
if ( curSubprogram - > mTagIdx ! = - 1 )
{
int endOffset = ( int ) ( dataEnd - sectionData ) ;
curSubprogram - > mDeferredInternalsSize = endOffset - curSubprogram - > mTagIdx ;
}
}
inlineDebugDump = false ;
curSubprogram = NULL ;
2022-07-30 09:08:49 -04:00
curParam = NULL ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_COMPILE2 :
{
2022-07-30 09:08:49 -04:00
COMPILESYM * compileSym = ( COMPILESYM * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_COMPILE3 :
{
2022-07-30 09:08:49 -04:00
COMPILESYM3 * compileSym = ( COMPILESYM3 * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_ENVBLOCK :
{
GET_INTO ( uint8 , flags ) ;
while ( true )
{
const char * envKey = CvParseAndDupString ( data ) ;
if ( envKey = = NULL )
break ;
const char * envValue = CvParseAndDupString ( data ) ;
}
}
break ;
case S_BUILDINFO :
{
2022-07-30 09:08:49 -04:00
CV_ItemId buildInfoId = GET ( CV_ItemId ) ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_TRAMPOLINE :
break ;
case S_COFFGROUP :
break ;
case S_SECTION :
break ;
case S_FRAMECOOKIE :
{
2022-07-30 09:08:49 -04:00
FRAMECOOKIE & frameCookie = * ( FRAMECOOKIE * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_LABEL32 :
{
2022-07-30 09:08:49 -04:00
LABELSYM32 & labelSym = * ( LABELSYM32 * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_CALLSITEINFO :
{
2022-07-30 09:08:49 -04:00
CALLSITEINFO & callSiteInfo = * ( CALLSITEINFO * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_HEAPALLOCSITE :
{
2022-07-30 09:08:49 -04:00
HEAPALLOCSITE & heapAllocSite = * ( HEAPALLOCSITE * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_FILESTATIC :
{
2022-07-30 09:08:49 -04:00
FILESTATICSYM & fileStaticSym = * ( FILESTATICSYM * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_CALLEES :
{
2022-07-30 09:08:49 -04:00
FUNCTIONLIST & calleeList = * ( FUNCTIONLIST * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_CALLERS :
{
2022-07-30 09:08:49 -04:00
FUNCTIONLIST & calleeList = * ( FUNCTIONLIST * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_POGODATA :
{
2022-07-30 09:08:49 -04:00
POGOINFO & pogoInfo = * ( POGOINFO * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
case S_INLINESITE :
case S_INLINESITE2 :
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( useSubprogram ! = NULL )
{
deferInlineDepth + + ;
break ; // Already handled this
}
uint32 inlinee ;
uint8 * binaryAnnotations ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( symType = = S_INLINESITE )
{
INLINESITESYM & inlineSite = * ( INLINESITESYM * ) dataStart ;
inlinee = inlineSite . inlinee ;
binaryAnnotations = ( uint8 * ) & inlineSite . binaryAnnotations ;
}
else // S_INLINESITE2
{
INLINESITESYM2 & inlineSite = * ( INLINESITESYM2 * ) dataStart ;
inlinee = inlineSite . inlinee ;
binaryAnnotations = ( uint8 * ) & inlineSite . binaryAnnotations ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgSubprogram * inlineParent = curSubprogram ;
DbgSubprogram * subprogram = NULL ;
2019-11-07 13:35:56 -08:00
if ( IsObjectFile ( ) )
2019-09-21 10:49:35 -07:00
{
subprogram = CvParseMethod ( NULL , NULL , inlinee , false ) ;
2022-07-30 09:08:49 -04:00
subprogram - > mCompileUnit = compileUnit ;
2019-09-21 10:49:35 -07:00
curSubprogram = subprogram ;
}
else if ( ( inlinee & 0x80000000 ) ! = 0 )
{
BP_ALLOC_T ( DbgSubprogram ) ;
subprogram = mAlloc . Alloc < DbgSubprogram > ( ) ; // ??
subprogram - > mCompileUnit = compileUnit ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ! mCvIPIReader . IsSetup ( ) )
CvParseIPI ( ) ;
curSubprogram = subprogram ;
}
else
{
BP_ALLOC_T ( DbgSubprogram ) ;
subprogram = mAlloc . Alloc < DbgSubprogram > ( ) ;
2022-07-30 09:08:49 -04:00
subprogram - > mCompileUnit = compileUnit ;
2019-09-21 10:49:35 -07:00
curSubprogram = subprogram ;
FixupInlinee ( curSubprogram , inlinee ) ;
}
BF_ASSERT ( subprogram = = curSubprogram ) ;
curSubprogram - > mTagIdx = ( int ) ( dataEnd - sectionData ) ; // Position for method data
BP_ALLOC_T ( DbgInlineeInfo ) ;
curSubprogram - > mInlineeInfo = mAlloc . Alloc < DbgInlineeInfo > ( ) ;
curSubprogram - > mInlineeInfo - > mInlineParent = inlineParent ;
if ( inlineParent - > mInlineeInfo ! = NULL )
curSubprogram - > mInlineeInfo - > mInlineDepth = inlineParent - > mInlineeInfo - > mInlineDepth + 1 ;
else
curSubprogram - > mInlineeInfo - > mInlineDepth = 1 ;
curSubprogram - > mInlineeInfo - > mRootInliner = inlineParent - > GetRootInlineParent ( ) ;
curSubprogram - > mInlineeInfo - > mInlineeId = 0 ;
curSubprogram - > mFrameBaseData = inlineParent - > mFrameBaseData ;
curSubprogram - > mFrameBaseLen = inlineParent - > mFrameBaseLen ;
curSubprogram - > mLocalBaseReg = inlineParent - > mLocalBaseReg ;
if ( curSubprogram - > mName = = NULL )
{
/*curSubprogram->mName = "<Inline>";
String name = StrFormat ( " <Inline>@%@ " , curSubprogram ) ;
curSubprogram - > mName = DbgDupString ( name . c_str ( ) ) ; */
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
String name = StrFormat ( " <Inline>@%@ " , curSubprogram ) ;
curSubprogram - > mName = DbgDupString ( name . c_str ( ) ) ;
curSubprogram - > mInlineeInfo - > mInlineeId = inlinee ;
}
if ( inlineDebugDump )
{
2022-07-30 09:08:49 -04:00
int depth = curSubprogram - > GetInlineDepth ( ) ;
BfLogCv ( " S_INLINESITE Ofs:%d Depth:%d Inlinee:%X Subprogram:%@ %s \n Parent:%@ %s \n " , ( dataStart - symDataStart ) , depth , inlinee ,
2019-09-21 10:49:35 -07:00
curSubprogram , curSubprogram - > mName , curSubprogram - > mInlineeInfo - > mInlineParent , curSubprogram - > mInlineeInfo - > mInlineParent - > mName ) ;
}
2022-07-30 09:08:49 -04:00
CvInlineInfo inlineInfo ;
2019-09-21 10:49:35 -07:00
inlineInfo . mNext = NULL ;
inlineInfo . mTail = NULL ;
inlineInfo . mInlinee = inlinee ;
inlineInfo . mSubprogram = NULL ;
inlineInfo . mSubprogram = curSubprogram ;
inlineInfo . mData = binaryAnnotations ;
inlineInfo . mDataLen = dataEnd - inlineInfo . mData ;
inlineInfo . mDebugDump = inlineDebugDump ;
inlineDataVec . push_back ( inlineInfo ) ;
blockStack . push_back ( & curSubprogram - > mBlock ) ;
}
break ;
case S_INLINESITE_END :
{
if ( inlineDebugDump )
BfLogCv ( " S_INLINESITE_END \n " ) ;
if ( deferInlineDepth > 0 )
{
deferInlineDepth - - ;
}
else
{
if ( deferInternals )
{
int endOffset = ( int ) ( dataEnd - sectionData ) ;
curSubprogram - > mDeferredInternalsSize = endOffset - curSubprogram - > mTagIdx ;
}
2022-07-30 09:08:49 -04:00
curSubprogram = curSubprogram - > mInlineeInfo - > mInlineParent ;
2019-09-21 10:49:35 -07:00
blockStack . pop_back ( ) ;
}
}
break ;
case S_SSEARCH :
{
2022-07-30 09:08:49 -04:00
SEARCHSYM * searchSym = ( SEARCHSYM * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
2022-07-30 09:08:49 -04:00
case S_SEPCODE :
2019-09-21 10:49:35 -07:00
{
BP_ALLOC_T ( DbgSubprogram ) ;
curSubprogram = mAlloc . Alloc < DbgSubprogram > ( ) ;
curSubprogram - > mCompileUnit = compileUnit ;
blockStack . push_back ( & curSubprogram - > mBlock ) ;
SEPCODESYM * sepCodeSym = ( SEPCODESYM * ) dataStart ;
auto addr = GetSectionAddr ( sepCodeSym - > sect , sepCodeSym - > off ) ;
auto parentAddr = GetSectionAddr ( sepCodeSym - > sectParent , sepCodeSym - > offParent ) ;
curSubprogram - > mBlock . mLowPC = addr ;
curSubprogram - > mBlock . mHighPC = addr + sepCodeSym - > length ;
String name = StrFormat ( " SEPCODE@%p " , parentAddr ) ;
curSubprogram - > mName = DbgDupString ( name . c_str ( ) ) ;
curSubprogram - > mTagIdx = ( int ) ( dataEnd - sectionData ) ; // Position for method data
MapSubprogram ( curSubprogram ) ;
}
break ;
case S_COMPILE :
break ;
case S_ANNOTATION :
break ;
case S_UNAMESPACE :
break ;
2022-07-30 09:08:49 -04:00
case /*S_FASTLINK*/ 0x1167 :
2019-09-21 10:49:35 -07:00
break ;
2022-07-30 09:08:49 -04:00
case /*S_INLINEES*/ 0x1168 :
2019-09-21 10:49:35 -07:00
break ;
2022-07-30 09:08:49 -04:00
case 0x1176 :
2019-09-21 10:49:35 -07:00
break ;
2020-12-28 10:47:14 -08:00
case 0x1178 :
break ;
2020-10-27 12:28:23 -07:00
case 0x1179 :
break ;
2022-03-23 16:49:19 -07:00
case 7 :
// Unknown
break ;
2019-09-21 10:49:35 -07:00
default :
2020-04-30 10:24:16 -07:00
BF_DBG_FATAL ( " Unhandled " ) ;
2019-09-21 10:49:35 -07:00
break ;
}
bool hasNewLocalVar = ( localVar ! = prevLocalVar ) & & ( localVar ! = NULL ) ;
if ( newLocalVarHasLocData )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
prevLocalVar = localVar ;
}
if ( deferInlineDepth = = 0 )
{
switch ( symType )
{
case S_BPREL32 :
case S_REGISTER :
case S_REGREL32 :
case S_DEFRANGE_REGISTER :
case S_DEFRANGE_FRAMEPOINTER_REL :
case S_DEFRANGE_SUBFIELD_REGISTER :
case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE :
case S_DEFRANGE_REGISTER_REL :
{
if ( prevLocalVar ! = NULL )
{
2022-07-30 09:08:49 -04:00
/*if (localVar->mLocationData == NULL)
2019-09-21 10:49:35 -07:00
localVar - > mLocationData = dataStart ;
2022-07-30 09:08:49 -04:00
localVar - > mLocationLen + + ; */
2019-09-21 10:49:35 -07:00
if ( locationDataStart = = NULL )
locationDataStart = dataStart ;
locationDataEnd = dataEnd ;
locationDataCount + + ;
2020-01-22 12:37:44 -08:00
if ( localVar - > mLocationData = = NULL )
localVar - > mLocationLen + + ;
2019-09-21 10:49:35 -07:00
}
}
break ;
}
}
if ( hasNewLocalVar )
{
2020-01-22 12:37:44 -08:00
if ( ( localVar - > mName ! = NULL ) & & ( localVar - > mName [ 0 ] = = ' $ ' ) )
2019-09-21 10:49:35 -07:00
{
2020-01-22 12:37:44 -08:00
char * aliasPos = ( char * ) strstr ( localVar - > mName , " $alias$ " ) ;
2019-09-21 10:49:35 -07:00
// This $alias$ hack is unfortunate, but LLVM gets confused when we attempt to tie multiple debug variables
// to the same memory location, which can happen during mixin injection. The result is that the mixin gets
// some premature instructions attributed to it from the variable declaration. This fixes that.
2020-07-12 06:27:43 -07:00
if ( ( aliasPos ! = NULL ) & & ( aliasPos > localVar - > mName ) )
2022-07-30 09:08:49 -04:00
{
2020-01-22 12:37:44 -08:00
String findName = String ( aliasPos + 7 ) ;
localVar - > mName = CvDupString ( localVar - > mName + 1 , aliasPos - localVar - > mName - 1 ) ;
auto curBlock = blockStack . back ( ) ;
localVar - > mLocationData = ( uint8 * ) CvDupString ( aliasPos + 7 , strlen ( aliasPos + 7 ) ) ;
localVar - > mRangeStart = curBlock - > mLowPC ;
localVar - > mRangeLen = curBlock - > mHighPC - curBlock - > mLowPC ;
2019-09-21 10:49:35 -07:00
2020-01-22 12:37:44 -08:00
/*bool found = false;
auto _CheckBlock = [ & ] ( DbgBlock * block )
2022-07-30 09:08:49 -04:00
{
2020-01-22 12:37:44 -08:00
for ( auto checkVar : block - > mVariables )
2019-09-21 10:49:35 -07:00
{
2020-01-22 12:37:44 -08:00
if ( checkVar - > mName = = NULL )
continue ;
2019-09-21 10:49:35 -07:00
2020-01-22 12:37:44 -08:00
if ( findName = = checkVar - > mName )
{
localVar - > mConstValue = checkVar - > mConstValue ;
localVar - > mType = checkVar - > mType ;
localVar - > mLocationData = checkVar - > mLocationData ;
localVar - > mLocationLen = checkVar - > mLocationLen ;
found = true ;
return true ;
2019-09-21 10:49:35 -07:00
}
2020-01-22 12:37:44 -08:00
}
return false ;
} ;
for ( int blockIdx = ( int ) blockStack . size ( ) - 1 ; blockIdx > = 0 ; blockIdx - - )
{
2022-07-30 09:08:49 -04:00
DbgBlock * block = blockStack [ blockIdx ] ;
if ( _CheckBlock ( block ) )
break ;
}
2020-01-22 12:37:44 -08:00
if ( ! found )
{
addr_target checkAddr = 0 ;
DbgSubprogram * checkSubprogram = curSubprogram ;
2019-09-21 10:49:35 -07:00
2020-01-22 12:37:44 -08:00
while ( checkSubprogram ! = NULL )
{
auto checkAddr = checkSubprogram - > mBlock . mLowPC ;
if ( checkSubprogram - > mInlineeInfo = = NULL )
2019-09-21 10:49:35 -07:00
break ;
2020-01-22 12:37:44 -08:00
checkSubprogram = checkSubprogram - > mInlineeInfo - > mInlineParent ;
std : : function < void ( DbgBlock * ) > _RecurseBlock = [ & ] ( DbgBlock * block )
{
if ( ( checkAddr < block - > mLowPC ) | | ( checkAddr > = block - > mHighPC ) )
return ;
2022-07-30 09:08:49 -04:00
if ( _CheckBlock ( block ) )
2020-01-22 12:37:44 -08:00
return ;
for ( auto block : block - > mSubBlocks )
_RecurseBlock ( block ) ;
} ;
_RecurseBlock ( & checkSubprogram - > mBlock ) ;
2019-09-21 10:49:35 -07:00
}
2020-01-22 12:37:44 -08:00
} */
2022-07-30 09:08:49 -04:00
}
2020-05-15 06:26:59 -07:00
}
if ( ( compileUnit - > mLanguage ! = DbgLanguage_Beef ) & & ( localVar - > mName ! = NULL ) )
{
for ( char * cPtr = ( char * ) localVar - > mName ; true ; cPtr + + )
2019-09-21 10:49:35 -07:00
{
2020-05-15 06:26:59 -07:00
char c = * cPtr ;
if ( c = = 0 )
break ;
if ( ( c = = ' < ' ) | | ( c = = ' > ' ) )
* cPtr = ' $ ' ;
2019-09-21 10:49:35 -07:00
}
}
}
/*if (prevLocalVar != NULL)
{
BF_ASSERT ( locationDataCount = = prevLocalVar - > mLocationLen ) ;
} */
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
data = dataEnd ;
2022-07-30 09:08:49 -04:00
//PTR_ALIGN(data, sectionData, 4);
2019-09-21 10:49:35 -07:00
}
if ( localVar ! = NULL )
{
if ( locationDataStart ! = NULL )
{
_FinishLocationData ( ) ;
}
}
_FlushDeferredVariableLocations ( ) ;
}
CvCompileUnit * COFF : : ParseCompileUnit ( CvModuleInfo * moduleInfo , CvCompileUnit * compileUnit , uint8 * sectionData , int sectionSize )
{
BP_ZONE ( " COFF::ParseCompileUnit " ) ;
CvInlineInfoVec inlineDataVec ;
Dictionary < uint32 , CvInlineInfo * > inlineDataDict ;
if ( moduleInfo ! = NULL )
{
BfLogCv ( " ParseCompileUnit %s \n " , moduleInfo - > mModuleName ) ;
}
else
{
BfLogCv ( " ParseCompileUnit NULL \n " ) ;
}
int allocSizeStart = mAlloc . GetAllocSize ( ) ;
if ( compileUnit = = NULL )
{
compileUnit = new CvCompileUnit ( this ) ;
mCompileUnits . push_back ( compileUnit ) ;
}
compileUnit - > mDbgModule = this ;
if ( moduleInfo ! = NULL )
{
compileUnit - > mModuleIdx = moduleInfo - > mIdx ;
compileUnit - > mName = moduleInfo - > mModuleName ;
moduleInfo - > mCompileUnit = compileUnit ;
}
else
{
compileUnit - > mModuleIdx = NULL ;
compileUnit - > mName = mFilePath . c_str ( ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
uint8 * data = sectionData ;
uint8 * dataEnd = NULL ;
GET_INTO ( uint32 , infoType ) ;
BF_ASSERT ( infoType = = CV_SIGNATURE_C13 ) ;
int taggedSize = sectionSize ;
uint8 * debugSubSectionsStart = data ;
if ( moduleInfo ! = NULL )
2022-07-30 09:08:49 -04:00
{
taggedSize = moduleInfo - > mLinesBytes ;
2019-09-21 10:49:35 -07:00
debugSubSectionsStart = data + moduleInfo - > mSymbolBytes - sizeof ( uint32 ) ;
}
else
{
taggedSize = sectionSize - sizeof ( uint32 ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
if ( mStringTable . mStrTable = = NULL )
{
data = debugSubSectionsStart ;
dataEnd = data + taggedSize ;
while ( data < dataEnd )
{
PTR_ALIGN ( data , sectionData , 4 ) ;
GET_INTO ( int32 , lineInfoType ) ;
GET_INTO ( int32 , lineInfoLength ) ;
uint8 * dataStart = data ;
uint8 * dataEnd = data + lineInfoLength ;
if ( lineInfoType = = DEBUG_S_STRINGTABLE )
{
if ( mStringTable . mStrTable = = NULL )
mStringTable . mStrTable = ( const char * ) data ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
data = dataEnd ;
}
}
//
{
data = debugSubSectionsStart ;
dataEnd = data + taggedSize ;
while ( data < dataEnd )
{
PTR_ALIGN ( data , sectionData , 4 ) ;
GET_INTO ( int32 , lineInfoType ) ;
GET_INTO ( int32 , lineInfoLength ) ;
uint8 * dataStart = data ;
uint8 * dataEnd = data + lineInfoLength ;
if ( lineInfoType = = DEBUG_S_CROSSSCOPEIMPORTS )
{
while ( data < dataEnd )
{
compileUnit - > mImports . Add ( CvCrossScopeImport ( ) ) ;
auto & crossScopeImport = compileUnit - > mImports . back ( ) ;
crossScopeImport . mScopeCompileUnit = NULL ;
GET_INTO ( uint32 , externalScope ) ;
const char * fileName = mStringTable . mStrTable + externalScope ;
BfLogCv ( " DEBUG_S_CROSSSCOPEIMPORTS Scope:%s " , fileName ) ;
crossScopeImport . mScopeName = fileName ;
//
2022-07-30 09:08:49 -04:00
/*for (int checkIdx = 0; checkIdx < (int)mCvModuleInfo.size(); checkIdx++)
2019-09-21 10:49:35 -07:00
{
auto checkModuleInfo = mCvModuleInfo [ checkIdx ] ;
if ( ( checkModuleInfo ! = NULL ) & & ( checkModuleInfo - > mModuleName ! = NULL ) & & ( stricmp ( checkModuleInfo - > mModuleName , fileName ) = = 0 ) )
{
ParseCompileUnit ( checkIdx ) ;
}
} */
GET_INTO ( int32 , numRefs ) ;
for ( int i = 0 ; i < numRefs ; i + + )
{
GET_INTO ( uint32 , refId ) ;
BfLogCv ( " %X " , refId ) ;
crossScopeImport . mImports . Add ( refId ) ;
}
BfLogCv ( " \n " ) ;
}
}
else if ( lineInfoType = = DEBUG_S_CROSSSCOPEEXPORTS )
{
BfLogCv ( " DEBUG_S_CROSSSCOPEEXPORTS " ) ;
while ( data < dataEnd )
{
GET_INTO ( int32 , localId ) ;
GET_INTO ( int32 , globalId ) ;
BfLogCv ( " %X=%X " , globalId , localId ) ;
CvCrossScopeExportEntry entry ;
entry . mLocalId = localId ;
entry . mGlobalId = globalId ;
compileUnit - > mExports . Add ( entry ) ;
}
BfLogCv ( " \n " ) ;
}
else if ( lineInfoType = = DEBUG_S_FRAMEDATA )
{
uint8 * dataPtr = data ;
2022-07-30 09:08:49 -04:00
addr_target baseAddr = 0 ;
2019-09-21 10:49:35 -07:00
int relAddr = GET_FROM ( dataPtr , int32 ) ;
ParseFrameDescriptors ( dataPtr , dataEnd - dataPtr , GetLinkedModule ( ) - > mImageBase + relAddr ) ;
}
data = dataEnd ;
}
}
if ( moduleInfo ! = NULL )
{
data = sectionData + 4 ;
dataEnd = data + moduleInfo - > mSymbolBytes - sizeof ( uint32 ) ;
bool wantsDeferInternals = true ;
ParseCompileUnit_Symbols ( compileUnit , sectionData , data , dataEnd , inlineDataVec , wantsDeferInternals , NULL ) ;
//ParseCompileUnit_Symbols(compileUnit, sectionData, data, dataEnd, inlineDataVec, false, NULL);
data = dataEnd ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
// Scan debug subsections to find file checksum table, and to load symbol data for hotloads
Dictionary < int , int > checksumFileRefs ;
{
BP_ZONE ( " ParseCompileUnit_SrcFiles " ) ;
data = debugSubSectionsStart ;
dataEnd = data + taggedSize ;
while ( true )
{
PTR_ALIGN ( data , sectionData , 4 ) ;
if ( data > = dataEnd )
break ;
GET_INTO ( int32 , lineInfoType ) ;
GET_INTO ( int32 , lineInfoLength ) ;
uint8 * dataStart = data ;
uint8 * dataEnd = data + lineInfoLength ;
if ( lineInfoType < 0 )
{
// Ignore
}
else if ( lineInfoType = = DEBUG_S_SYMBOLS )
{
ParseCompileUnit_Symbols ( compileUnit , sectionData , data , dataEnd , inlineDataVec , false , NULL ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
else if ( lineInfoType = = DEBUG_S_FILECHKSMS )
{
BF_ASSERT ( checksumFileRefs . size ( ) = = 0 ) ;
while ( data < dataEnd )
{
int dataOfs = ( int ) ( data - dataStart ) ;
GET_INTO ( uint , fileTableOfs ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
const char * fileName = mStringTable . mStrTable + fileTableOfs ;
2022-04-16 06:27:54 -07:00
if ( ( fileName [ 0 ] = = ' \\ ' ) & & ( fileName [ 1 ] = = ' $ ' ) )
fileName + + ;
2019-09-21 10:49:35 -07:00
DbgSrcFile * srcFile = NULL ;
2022-04-16 06:27:54 -07:00
if ( fileName [ 0 ] = = ' $ ' )
{
srcFile = AddSrcFile ( compileUnit , fileName ) ;
2022-07-30 09:08:49 -04:00
}
2022-04-16 06:27:54 -07:00
else if ( ( fileName [ 0 ] = = ' / ' ) | | ( fileName [ 0 ] = = ' \\ ' ) | |
2022-07-30 09:08:49 -04:00
( ( fileName [ 0 ] ! = 0 ) & & ( fileName [ 1 ] = = ' : ' ) ) )
2019-09-21 10:49:35 -07:00
{
srcFile = AddSrcFile ( compileUnit , fileName ) ;
}
else
{
String fullDir = GetFileDir ( mFilePath ) ;
fullDir . Append ( " \\ " ) ;
fullDir . Append ( fileName ) ;
srcFile = AddSrcFile ( compileUnit , fullDir ) ;
}
if ( srcFile - > IsBeef ( ) )
compileUnit - > mLanguage = DbgLanguage_Beef ;
GET_INTO ( uint8 , hashLen ) ;
GET_INTO ( uint8 , hashType ) ;
if ( ( hashType = = 1 ) & & ( hashLen = = 16 ) )
{
srcFile - > mHashKind = DbgHashKind_MD5 ;
memcpy ( srcFile - > mHash , data , 16 ) ;
}
else if ( ( hashType = = 3 ) & & ( hashLen = = 32 ) )
{
srcFile - > mHashKind = DbgHashKind_SHA256 ;
memcpy ( srcFile - > mHash , data , 32 ) ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
data + = hashLen ;
checksumFileRefs . TryAdd ( dataOfs , ( int ) compileUnit - > mSrcFileRefs . size ( ) - 1 ) ;
PTR_ALIGN ( data , sectionData , 4 ) ;
}
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
else
{
BF_ASSERT ( ( lineInfoType > = DEBUG_S_SYMBOLS ) & & ( lineInfoType < = DEBUG_S_COFF_SYMBOL_RVA ) ) ;
}
data = dataEnd ;
}
}
if ( ! inlineDataVec . IsEmpty ( ) )
{
for ( auto & inlineData : inlineDataVec )
{
uint32 * keyPtr ;
CvInlineInfo * * valuePtr ;
if ( inlineDataDict . TryAdd ( inlineData . mInlinee , & keyPtr , & valuePtr ) )
{
inlineData . mTail = & inlineData ;
* valuePtr = & inlineData ;
}
else
{
( * valuePtr ) - > mTail - > mNext = & inlineData ;
( * valuePtr ) - > mTail = & inlineData ;
}
}
}
int inlineDataIdx = 0 ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgLineDataBuilder lineBuilder ( this ) ;
//
{
2022-07-30 09:08:49 -04:00
BP_ZONE ( " ParseCompileUnit_LineInfo " ) ;
2019-09-21 10:49:35 -07:00
//int totalLineCount = 0;
//int targetLineCount = 0;
int inlineIdx = 0 ;
// struct _InlinerData
// {
// bool mWantSummaryDump;
// Array<DbgInlinee> mInlinees;
// Array<DbgInlineLineData> mInlineLineData;
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// _InlinerData()
// {
// mWantSummaryDump = false;
// }
// };
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// Dictionary<DbgSubprogram*, _InlinerData> deferredInlinerDatas;
2022-07-30 09:08:49 -04:00
// Line info
2019-09-21 10:49:35 -07:00
data = debugSubSectionsStart ;
dataEnd = data + taggedSize ;
while ( data < dataEnd )
{
PTR_ALIGN ( data , sectionData , 4 ) ;
GET_INTO ( int32 , lineInfoType ) ;
GET_INTO ( int32 , lineInfoLength ) ;
uint8 * dataStart = data ;
uint8 * dataEnd = data + lineInfoLength ;
if ( lineInfoType = = DEBUG_S_FILECHKSMS )
{
// Already handled
}
else if ( lineInfoType = = DEBUG_S_LINES )
{
CV_DebugSLinesHeader_t & lineSec = GET ( CV_DebugSLinesHeader_t ) ;
Array < DbgLineData > lineDataVec ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
addr_target contribStartAddr = GetSectionAddr ( lineSec . segCon , lineSec . offCon ) ;
while ( data < dataEnd )
{
lineDataVec . Clear ( ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
CV_DebugSLinesFileBlockHeader_t & linesFileHeader = GET ( CV_DebugSLinesFileBlockHeader_t ) ;
DbgSrcFileReference * srcFileRef = & compileUnit - > mSrcFileRefs [ checksumFileRefs [ linesFileHeader . offFile ] ] ;
bool isBeef = srcFileRef - > mSrcFile - > IsBeef ( ) ;
int expectSize = ( int ) sizeof ( CV_DebugSLinesFileBlockHeader_t ) + ( int ) ( linesFileHeader . nLines * sizeof ( CV_Line_t ) ) ;
if ( ( lineSec . flags & CV_LINES_HAVE_COLUMNS ) ! = 0 )
expectSize + = ( int ) ( linesFileHeader . nLines * sizeof ( int16 ) * 2 ) ;
BF_ASSERT ( expectSize = = linesFileHeader . cbBlock ) ;
lineDataVec . Resize ( linesFileHeader . nLines ) ;
for ( int lineIdx = 0 ; lineIdx < linesFileHeader . nLines ; lineIdx + + )
{
CV_Line_t & srcLineData = GET ( CV_Line_t ) ;
DbgLineData & lineData = lineDataVec [ lineIdx ] ;
2022-07-30 09:08:49 -04:00
lineData . mRelAddress = ( uint32 ) ( ( contribStartAddr + srcLineData . offset ) - mImageBase ) ;
2019-09-21 10:49:35 -07:00
if ( srcLineData . linenumStart = = 0xf00f00 ) // Never step into
{
if ( lineIdx > 0 )
lineData . mLine = lineDataVec [ lineIdx - 1 ] . mLine ;
lineData . mColumn = - 2 ; // Never step into marker
}
else if ( srcLineData . linenumStart = = 0xfeefee ) // Always step into
{
if ( lineIdx > 0 )
lineData . mLine = lineDataVec [ lineIdx - 1 ] . mLine ;
lineData . mColumn = - 1 ; // Always step into marker
}
else
lineData . mLine = srcLineData . linenumStart - 1 ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
// In Beef we always set the column, so a section without CV_LINES_HAVE_COLUMNS indicates a block of invalid
// positions that we want to skip over
if ( isBeef )
lineData . mColumn = - 1 ;
}
if ( ( lineSec . flags & CV_LINES_HAVE_COLUMNS ) ! = 0 )
{
for ( int lineIdx = 0 ; lineIdx < linesFileHeader . nLines ; lineIdx + + )
{
CV_Column_t & srcColumnData = GET ( CV_Column_t ) ;
DbgLineData & lineData = lineDataVec [ lineIdx ] ;
lineData . mColumn = ( int ) srcColumnData . offColumnStart - 1 ;
}
}
DbgLineData * lastLineData = NULL ;
for ( int lineIdx = 0 ; lineIdx < linesFileHeader . nLines ; lineIdx + + )
{
2022-07-30 09:08:49 -04:00
DbgLineData & lineData = lineDataVec [ lineIdx ] ;
2019-09-21 10:49:35 -07:00
lastLineData = lineBuilder . Add ( compileUnit , lineData , srcFileRef - > mSrcFile , NULL ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
}
else if ( lineInfoType = = DEBUG_S_INLINEELINES )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
int linesType = GET ( int ) ;
while ( data < dataEnd )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
int inlinee = 0 ;
int srcFileIdx = - 1 ;
int startLine ;
DbgSrcFileReference * startSrcFileRef = NULL ;
if ( linesType = = 0 )
{
CodeViewInfo : : InlineeSourceLine & lineInfo = GET ( CodeViewInfo : : InlineeSourceLine ) ;
srcFileIdx = checksumFileRefs [ lineInfo . fileId ] ;
startSrcFileRef = & compileUnit - > mSrcFileRefs [ srcFileIdx ] ;
startLine = lineInfo . sourceLineNum ;
2022-07-30 09:08:49 -04:00
inlinee = lineInfo . inlinee ;
2019-09-21 10:49:35 -07:00
}
else if ( linesType = = 1 )
{
CodeViewInfo : : InlineeSourceLineEx & lineInfo = * ( CodeViewInfo : : InlineeSourceLineEx * ) data ;
srcFileIdx = checksumFileRefs [ lineInfo . fileId ] ;
startSrcFileRef = & compileUnit - > mSrcFileRefs [ srcFileIdx ] ;
startLine = lineInfo . sourceLineNum ;
inlinee = lineInfo . inlinee ;
data + = sizeof ( CodeViewInfo : : InlineeSourceLineEx ) ;
data + = ( int ) sizeof ( CV_off32_t ) * lineInfo . countOfExtraFiles ;
}
else
BF_FATAL ( " Invalid DEBUG_S_INLINEELINES lines type " ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
CvInlineInfo * inlineData = NULL ;
inlineDataDict . TryGetValue ( inlinee , & inlineData ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
while ( inlineData ! = NULL )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
bool inlineDebugDump = inlineData - > mDebugDump ;
if ( inlineData - > mInlinee = = - 1 )
{
if ( inlineDebugDump )
BfLogCv ( " Duplicate data: %X \n " , inlinee ) ;
break ;
}
// Mark as done
inlineData - > mInlinee = - 1 ;
2022-07-30 09:08:49 -04:00
int chunkNum = 0 ;
int curLine = startLine ;
int curValidLine = curLine ;
2019-09-21 10:49:35 -07:00
bool flushOnLineOffset = false ;
addr_target lastLineAddr = 0 ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgSrcFileReference * srcFileRef = startSrcFileRef ;
DbgSubprogram * curSubprogram = inlineData - > mSubprogram ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgSubprogram * inlineParent = inlineData - > mSubprogram - > GetRootInlineParent ( ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
addr_target curAddr = inlineParent - > mBlock . mLowPC ;
lastLineAddr = 0 ;
if ( inlineDebugDump )
{
//inlinerData->mWantSummaryDump = true;
2022-07-30 09:08:49 -04:00
BfLogCv ( " ------------------------------------------------ \n INLINE DATA:%X Idx:%d CurAddr:%@ Line:%d \n SubProgram:%@ %s \n File:%s \n " , inlinee , inlineIdx , curAddr , curLine ,
2019-09-21 10:49:35 -07:00
curSubprogram , curSubprogram - > mName , srcFileRef - > mSrcFile - > mFilePath . c_str ( ) ) ;
}
uint8 * annData = inlineData - > mData ;
2022-07-30 09:08:49 -04:00
uint8 * annDataEnd = inlineData - > mData + inlineData - > mDataLen ;
2019-09-21 10:49:35 -07:00
DbgLineData * curLineData = NULL ;
auto _AddLine = [ & ] ( )
{
if ( chunkNum ! = 0 )
{
curLineData = NULL ;
return ;
}
2022-07-30 09:08:49 -04:00
DbgLineData lineData ;
lineData . mLine = curValidLine - 1 ;
2019-09-21 10:49:35 -07:00
lineData . mRelAddress = ( uint32 ) ( curAddr - mImageBase ) ;
lineData . mColumn = 0 ;
if ( curLine < = 0 ) // Negative lines mean "invalid position" for inlining
2022-07-30 09:08:49 -04:00
lineData . mColumn = - 1 ;
2019-09-21 10:49:35 -07:00
lineData . mContribSize = 0 ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ( curSubprogram - > mBlock . mLowPC = = 0 ) & & ( curLineData ! = NULL ) )
2022-07-30 09:08:49 -04:00
curSubprogram - > mBlock . mLowPC = mImageBase + curLineData - > mRelAddress ;
2019-09-21 10:49:35 -07:00
if ( inlineDebugDump )
BfLogCv ( " Adding Line:%d Addr:%@ \n " , lineData . mLine + 1 , lineData . mRelAddress + mImageBase ) ;
curLineData = lineBuilder . Add ( compileUnit , lineData , srcFileRef - > mSrcFile , curSubprogram ) ;
} ;
int codeIdx = 0 ;
while ( annData < annDataEnd )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
auto annVal = CodeViewInfo : : CVUncompressData ( annData ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
switch ( annVal )
{
case CodeViewInfo : : BA_OP_Invalid : // link time pdb contains PADDINGs
break ;
2022-07-30 09:08:49 -04:00
case CodeViewInfo : : BA_OP_CodeOffset : // param : start offset
2019-09-21 10:49:35 -07:00
{
int32 offset = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
curAddr = inlineParent - > mBlock . mLowPC + offset ;
if ( inlineDebugDump )
BfLogCv ( " BA_OP_CodeOffset(%d) CurAddr:%@ Line:%d \n " , offset , curAddr , curLine ) ;
}
break ;
case CodeViewInfo : : BA_OP_ChangeCodeOffsetBase : // param : nth separated code chunk (main code chunk == 0)
{
2022-07-30 09:08:49 -04:00
chunkNum = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
2019-09-21 10:49:35 -07:00
if ( inlineDebugDump )
2022-07-30 09:08:49 -04:00
BfLogCv ( " xxxxxxxxx BA_OP_ChangeCodeOffsetBase(%d) CurAddr:%@ Line:%d \n " , chunkNum , curAddr , curLine ) ;
2019-09-21 10:49:35 -07:00
}
break ;
case CodeViewInfo : : BA_OP_ChangeCodeOffset : // param : delta of offset
{
int32 offset = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
2022-07-30 09:08:49 -04:00
curAddr + = offset ;
2019-09-21 10:49:35 -07:00
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeCodeOffset(%d) CurAddr:%@ Line:%d \n " , offset , curAddr , curLine ) ;
if ( ( curLineData ! = NULL ) & & ( curLineData - > mContribSize = = 0 ) )
{
curLineData - > mRelAddress = ( uint32 ) ( curAddr - mImageBase ) ;
if ( inlineDebugDump )
BfLogCv ( " Setting addr on previous entry \n " ) ;
}
else
_AddLine ( ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
flushOnLineOffset = true ;
}
break ;
case CodeViewInfo : : BA_OP_ChangeCodeLength : // param : length of code, default next start
{
int newCodeLen = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
curAddr + = newCodeLen ;
if ( curLineData ! = NULL )
curLineData - > mContribSize = newCodeLen ;
if ( inlineDebugDump )
2022-07-30 09:08:49 -04:00
BfLogCv ( " BA_OP_ChangeCodeLength(%d) Addr:%@ EndAddr:%@ \n " , newCodeLen , curLineData - > mRelAddress + mImageBase , curLineData - > mRelAddress + mImageBase + curLineData - > mContribSize ) ;
2019-09-21 10:49:35 -07:00
}
break ;
2022-07-30 09:08:49 -04:00
case CodeViewInfo : : BA_OP_ChangeFile : // param : fileId
2019-09-21 10:49:35 -07:00
{
uint32 newFileId = CodeViewInfo : : CVUncompressData ( annData ) ;
srcFileRef = & compileUnit - > mSrcFileRefs [ checksumFileRefs [ newFileId ] ] ;
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeFile(%s) CurAddr:%@ Line:%d \n " , srcFileRef - > mSrcFile - > mFilePath . c_str ( ) , curAddr , curLine ) ;
}
break ;
case CodeViewInfo : : BA_OP_ChangeLineOffset : // param : line offset (signed)
{
int32 lineOfs = ( int32 ) CodeViewInfo : : DecodeSignedInt32 ( CodeViewInfo : : CVUncompressData ( annData ) ) ;
curLine + = lineOfs ;
if ( curLine > 0 )
2022-07-30 09:08:49 -04:00
curValidLine = curLine ;
2019-09-21 10:49:35 -07:00
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeLineOffset(%d) CurAddr:%@ Line:%d \n " , lineOfs , curAddr , curLine ) ;
_AddLine ( ) ;
}
break ;
case CodeViewInfo : : BA_OP_ChangeLineEndDelta : // param : how many lines, default 1
{
int numLines = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeLineEndDelta(%d) CurAddr:%@ Line:%d \n " , numLines , curAddr , curLine ) ;
}
break ;
2022-07-30 09:08:49 -04:00
case CodeViewInfo : : BA_OP_ChangeRangeKind : // param : either 1 (default, for statement) or 0 (for expression)
2019-09-21 10:49:35 -07:00
{
int32 readKind = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeRangeKind(%d) CurAddr:%@ Line:%d \n " , readKind , curAddr , curLine ) ;
}
break ;
case CodeViewInfo : : BA_OP_ChangeColumnStart : // param : start column number, 0 means no column info
{
int column = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
if ( curLineData ! = NULL )
curLineData - > mColumn = column ;
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeColumnStart(%d) CurAddr:%@ Line:%d \n " , column , curAddr , curLine ) ;
}
break ;
case CodeViewInfo : : BA_OP_ChangeColumnEndDelta : // param : end column number delta (signed)
{
int columnEndDelta = ( int32 ) CodeViewInfo : : DecodeSignedInt32 ( CodeViewInfo : : CVUncompressData ( annData ) ) ;
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeColumnEndDelta(%d) CurAddr:%@ Line:%d \n " , columnEndDelta , curAddr , curLine ) ;
}
break ;
// Combo opcodes for smaller encoding size.
case CodeViewInfo : : BA_OP_ChangeCodeOffsetAndLineOffset : // param : ((sourceDelta << 4) | CodeDelta)
{
int offsetData = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
int codeDelta = offsetData & 0xF ;
int sourceDelta = CodeViewInfo : : DecodeSignedInt32 ( offsetData > > 4 ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
curAddr + = codeDelta ;
curLine + = sourceDelta ;
if ( curLine > 0 )
2022-07-30 09:08:49 -04:00
curValidLine = curLine ;
2019-09-21 10:49:35 -07:00
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeCodeOffsetAndLineOffset(%d, %d) CurAddr:%@ Line:%d \n " , codeDelta , sourceDelta , curAddr , curLine ) ;
_AddLine ( ) ;
}
break ;
case CodeViewInfo : : BA_OP_ChangeCodeLengthAndCodeOffset : // param : codeLength, codeOffset
{
curValidLine = curLine ;
int codeLen = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
int codeOffset = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
curAddr + = codeOffset ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeCodeLengthAndCodeOffset(%d, %d) CurAddr:%@ Line:%d \n " , codeLen , codeOffset , curAddr , curLine ) ;
_AddLine ( ) ;
if ( curLineData ! = NULL )
{
if ( inlineDebugDump )
BfLogCv ( " ContribSize:%d \n " , codeLen ) ;
curLineData - > mContribSize = codeLen ;
}
}
break ;
case CodeViewInfo : : BA_OP_ChangeColumnEnd : // param : end column number
{
int columnEnd = ( int32 ) CodeViewInfo : : CVUncompressData ( annData ) ;
if ( inlineDebugDump )
BfLogCv ( " BA_OP_ChangeColumnEnd(%d) CurAddr:%@ Line:%d \n " , columnEnd , curAddr , curLine ) ;
}
break ;
}
codeIdx + + ;
}
if ( curLineData ! = NULL )
{
if ( curSubprogram - > mBlock . mLowPC = = 0 )
curSubprogram - > mBlock . mLowPC = mImageBase + curLineData - > mRelAddress ;
curSubprogram - > mBlock . mHighPC = mImageBase + curLineData - > mRelAddress + curLineData - > mContribSize ;
}
inlineData = inlineData - > mNext ;
}
}
}
data = dataEnd ;
}
// for (auto& deferredInlinerDataKV : deferredInlinerDatas)
// {
// auto inlinerParent = deferredInlinerDataKV.mKey;
// auto deferredInlinerData = &deferredInlinerDataKV.mValue;
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// inlinerParent->mInlinerData = mAlloc.Alloc<DbgInlinerData>();
// inlinerParent->mInlinerData->mInlinees.CopyFrom(deferredInlinerData->mInlinees.mVals, deferredInlinerData->mInlinees.mSize, mAlloc);
// inlinerParent->mInlinerData->mInlineLineData.CopyFrom(deferredInlinerData->mInlineLineData.mVals, deferredInlinerData->mInlineLineData.mSize, mAlloc);
// //deferredInlinerData->
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// if (deferredInlinerData->mWantSummaryDump)
// {
// BfLogCv("------------------------------\nSUMMARY FOR: %s\n", inlinerParent->mName);
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// for (auto& inlineLine : inlinerParent->mInlinerData->mInlineLineData)
2022-07-30 09:08:49 -04:00
// {
// BfLogCv("Addr:%@ EndAddr:%@ Line:%d Column:%d Inlinee:%d\n", inlineLine.mAddress, inlineLine.mAddress + inlineLine.mContribSize,
2019-09-21 10:49:35 -07:00
// inlineLine.mLine + 1, inlineLine.mColumn + 1, inlineLine.mInlineIdx);
// }
// }
// }
}
lineBuilder . Commit ( ) ;
2022-07-30 09:08:49 -04:00
//OutputDebugStrF("Module loaded, AllocSize added: %d\n", (mAlloc.GetAllocSize() - allocSizeStart) / 1024);
2019-09-21 10:49:35 -07:00
return compileUnit ;
}
CvCompileUnit * COFF : : ParseCompileUnit ( int compileUnitId )
{
CvModuleInfo * moduleInfo = mCvModuleInfo [ compileUnitId ] ;
if ( moduleInfo - > mCompileUnit ! = NULL )
return moduleInfo - > mCompileUnit ;
BP_ZONE ( " ParseCompileUnit " ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
ParseTypeData ( ) ;
if ( moduleInfo - > mStream = = - 1 )
return NULL ;
int sectionSize = 0 ;
uint8 * sectionData = CvReadStream ( moduleInfo - > mStream , & sectionSize ) ;
ParseCompileUnit ( moduleInfo , NULL , sectionData , sectionSize ) ;
delete sectionData ;
return moduleInfo - > mCompileUnit ;
}
2020-11-18 09:31:52 -08:00
void COFF : : ParseCompileUnits ( )
{
for ( int i = 0 ; i < ( int ) mCvModuleInfo . size ( ) ; i + + )
ParseCompileUnit ( i ) ;
}
2019-09-21 10:49:35 -07:00
DbgType * COFF : : CvGetTypeOrNamespace ( char * name , DbgLanguage language )
2020-11-17 07:52:51 -08:00
{
2019-09-21 10:49:35 -07:00
if ( language = = DbgLanguage_Unknown )
{
if ( strncmp ( name , " _bf:: " , 5 ) = = 0 )
{
language = DbgLanguage_Beef ;
name + = 5 ;
}
else if ( ( name [ 0 ] = = ' G ' ) & & ( name [ 1 ] = = ' $ ' ) )
{
language = DbgLanguage_Beef ;
}
else
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
language = DbgLanguage_C ;
// Check for a primitive array type like 'double[]'
for ( int i = 0 ; i < 10 ; i + + )
{
char c = name [ i ] ;
if ( c = = 0 )
break ;
if ( c = = ' [ ' )
language = DbgLanguage_Beef ;
}
}
}
auto linkedModule = GetLinkedModule ( ) ;
auto dbgTypeEntry = linkedModule - > mTypeMap . Find ( name , language ) ;
if ( dbgTypeEntry ! = NULL )
{
auto dbgType = dbgTypeEntry - > mValue ;
if ( dbgType - > mHotNewType ! = NULL )
return dbgType - > mHotNewType ;
return dbgType ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
// It's possible that we get a reference to a template name that isn't actually in our type database
// These may indicate VS compiler bugs or anonymous namespaces
bool isValidName = true ;
for ( const char * cPtr = name ; * cPtr ! = ' \0 ' ; cPtr + + )
if ( ( * cPtr = = ' < ' ) | | ( * cPtr = = ' ` ' ) | | ( * cPtr = = ' $ ' ) )
isValidName = false ;
if ( ! isValidName )
return NULL ;
//OutputDebugStrF("CvGetTypeOrNamespace Creating: %s\n", name);
char * lastDblColon = ( char * ) GetLastDoubleColon ( name ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgType * dbgType = CvCreateType ( ) ;
DbgType * parentType = mMasterCompileUnit - > mGlobalType ;
if ( lastDblColon ! = NULL )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
* lastDblColon = 0 ;
parentType = CvGetTypeOrNamespace ( name , language ) ;
dbgType - > mTypeName = DbgDupString ( lastDblColon + 2 , " DbgDupString.TypeOrNamespace0 " ) ;
* lastDblColon = ' : ' ;
dbgType - > mName = DbgDupString ( name , " DbgDupString.TypeOrNamespace1 " ) ;
}
else
{
dbgType - > mTypeName = DbgDupString ( name , " DbgDupString.TypeOrNamespace2 " ) ;
2022-07-30 09:08:49 -04:00
dbgType - > mName = dbgType - > mTypeName ;
}
2019-09-21 10:49:35 -07:00
parentType - > mSubTypeList . PushBack ( dbgType ) ;
dbgType - > mTypeCode = DbgType_Namespace ;
dbgType - > mLanguage = language ;
linkedModule - > mTypeMap . Insert ( dbgType ) ;
return dbgType ;
}
void COFF : : MapCompileUnitMethods ( DbgCompileUnit * compileUnit )
{
2019-11-07 13:35:56 -08:00
bool addHotTypes = ( IsObjectFile ( ) ) & & ( mHotPrimaryTypes . size ( ) = = 0 ) ;
2019-09-21 10:49:35 -07:00
DbgSubprogram * prevDbgMethod = NULL ;
DbgSubprogram * dbgMethod = compileUnit - > mOrphanMethods . mHead ;
while ( dbgMethod ! = NULL )
2022-07-30 09:08:49 -04:00
{
auto nextDbgMethod = dbgMethod - > mNext ;
2019-09-21 10:49:35 -07:00
bool movedMethod = false ;
if ( dbgMethod - > mHasQualifiedName )
{
char * name = ( char * ) dbgMethod - > mName ;
char * lastDblColon = ( char * ) GetLastDoubleColon ( name ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( lastDblColon ! = NULL )
{
dbgMethod - > mName = lastDblColon + 2 ;
dbgMethod - > mHasQualifiedName = false ;
const char * typeName = name ;
* lastDblColon = 0 ;
DbgType * parentType = CvGetTypeOrNamespace ( name ) ;
if ( parentType ! = NULL )
{
if ( addHotTypes )
{
mHotPrimaryTypes . Add ( parentType ) ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
compileUnit - > mOrphanMethods . Remove ( dbgMethod , prevDbgMethod ) ;
parentType - > mMethodList . PushBack ( dbgMethod ) ;
dbgMethod - > mParentType = parentType ;
movedMethod = true ;
}
}
}
if ( ! movedMethod )
prevDbgMethod = dbgMethod ;
dbgMethod = nextDbgMethod ;
}
}
void COFF : : MapCompileUnitMethods ( int compileUnitId )
{
CvModuleInfo * moduleInfo = mCvModuleInfo [ compileUnitId ] ;
if ( moduleInfo - > mHasMappedMethods )
return ;
ParseCompileUnit ( compileUnitId ) ;
auto compileUnit = moduleInfo - > mCompileUnit ;
//for (auto dbgMethod : compileUnit->mGlobalType.mMethodList)
MapCompileUnitMethods ( compileUnit ) ;
moduleInfo - > mHasMappedMethods = true ;
}
void COFF : : PopulateType ( DbgType * dbgType )
{
uint8 * data = CvGetTagData ( dbgType - > mTagIdx , false ) ;
CvAutoReleaseTempData releaseTempData ( this , data ) ;
uint8 * dataStart = data ;
2022-07-30 09:08:49 -04:00
uint16 trLeafType = GET ( uint16 ) ;
2019-09-21 10:49:35 -07:00
switch ( trLeafType )
{
case LF_ENUM :
{
lfEnum & enumInfo = * ( lfEnum * ) dataStart ;
CvParseMembers ( dbgType , enumInfo . field , false ) ;
}
break ;
case LF_CLASS :
2022-07-30 09:08:49 -04:00
case LF_STRUCTURE :
2019-09-21 10:49:35 -07:00
{
lfClass & classInfo = * ( lfClass * ) dataStart ;
CvParseMembers ( dbgType , classInfo . field , false ) ;
}
break ;
2020-11-18 09:15:28 -08:00
case LF_CLASS_EX :
case LF_STRUCTURE_EX :
{
auto property = GET ( CV_prop_t ) ;
auto extra = GET ( int16 ) ;
auto field = GET ( CV_typ_t ) ;
CvParseMembers ( dbgType , field , false ) ;
}
break ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
case LF_UNION :
{
2022-07-30 09:08:49 -04:00
lfUnion & classInfo = * ( lfUnion * ) dataStart ;
2019-09-21 10:49:35 -07:00
CvParseMembers ( dbgType , classInfo . field , false ) ;
}
break ;
default :
BF_FATAL ( " Invalid type " ) ;
}
}
void COFF : : PopulateTypeGlobals ( DbgType * dbgType )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
//gDbgPerfManager->StartRecording();
{
BP_ZONE_F ( " COFF::PopulateTypeGlobals %s " , ( dbgType - > mName ! = NULL ) ? dbgType - > mName : " ? " ) ;
ParseTypeData ( ) ;
dbgType - > mNeedsGlobalsPopulated = false ;
dbgType - > mHasGlobalsPopulated = true ;
mGlobalsTargetType = dbgType ;
ParseSymbolStream ( CvSymStreamType_Globals_Targeted ) ;
mGlobalsTargetType = NULL ;
}
//gDbgPerfManager->StopRecording(true);
}
void COFF : : PopulateSubprogram ( DbgSubprogram * dbgSubprogram )
{
if ( dbgSubprogram - > mDeferredInternalsSize = = 0 )
return ;
BP_ZONE ( " COFF::PopulateSubprogram " ) ;
auto compileUnit = ( CvCompileUnit * ) dbgSubprogram - > mCompileUnit ;
2022-07-30 09:08:49 -04:00
CvModuleInfo * moduleInfo = mCvModuleInfo [ compileUnit - > mModuleIdx ] ;
2019-09-21 10:49:35 -07:00
int sectionSize = 0 ;
uint8 * sectionData = CvReadStreamSegment ( moduleInfo - > mStream , dbgSubprogram - > mTagIdx , dbgSubprogram - > mDeferredInternalsSize ) ;
CvInlineInfoVec inlineDataVec ;
ParseCompileUnit_Symbols ( compileUnit , NULL , sectionData , sectionData + dbgSubprogram - > mDeferredInternalsSize , inlineDataVec , false , dbgSubprogram ) ;
2022-07-30 09:08:49 -04:00
delete sectionData ;
2019-09-21 10:49:35 -07:00
dbgSubprogram - > mDeferredInternalsSize = 0 ;
}
2019-11-29 09:21:51 -08:00
void COFF : : FixSubprogramName ( DbgSubprogram * dbgSubprogram )
{
const char * name = dbgSubprogram - > mName ;
for ( const char * cPtr = name ; * cPtr ! = 0 ; cPtr + + )
{
2022-07-30 09:08:49 -04:00
char c = * cPtr ;
2019-11-29 09:21:51 -08:00
if ( c = = ' $ ' )
{
bool isChecked = strcmp ( cPtr , " $CHK " ) = = 0 ;
bool isUnchecked = strcmp ( cPtr , " $UCHK " ) = = 0 ;
if ( isChecked | | isUnchecked )
{
dbgSubprogram - > mCheckedKind = isChecked ? BfCheckedKind_Checked : BfCheckedKind_Unchecked ;
dbgSubprogram - > mName = CvDupString ( name , cPtr - name ) ;
return ;
2022-07-30 09:08:49 -04:00
}
2019-11-29 09:21:51 -08:00
}
}
}
2019-09-21 10:49:35 -07:00
void COFF : : FixupInlinee ( DbgSubprogram * dbgSubprogram , uint32 ipiTag )
{
if ( ! mCvIPIReader . IsSetup ( ) )
CvParseIPI ( ) ;
//int idx = (ipiTag & 0x7FFFFFFF) - mCvIPIMinTag;
//uint8* dataStart = mCvIPIData + mCvIPITagStartMap[idx];
uint8 * dataStart = CvGetTagData ( ipiTag & 0x7FFFFFFF , true ) ;
CvAutoReleaseTempData releaseTempData ( this , dataStart ) ;
lfEasy & funcLeaf = * ( lfEasy * ) dataStart ;
switch ( funcLeaf . leaf )
{
case LF_FUNC_ID :
{
lfFuncId * funcData = ( lfFuncId * ) dataStart ;
CvParseMethod ( NULL , NULL , funcData - > type , false , dbgSubprogram ) ;
dbgSubprogram - > mName = ( const char * ) funcData - > name ;
bool doScope = true ;
if ( ( funcData - > scopeId ! = 0 ) & & ( doScope ) )
{
uint8 * data = CvGetTagData ( funcData - > scopeId , true ) ;
CvAutoReleaseTempData releaseTempData ( this , data ) ;
lfEasy & leaf = * ( lfEasy * ) data ;
switch ( leaf . leaf )
{
case LF_STRING_ID :
{
lfStringId & str = * ( lfStringId * ) data ;
const char * parentStr = ( const char * ) str . name ;
int allocLen = strlen ( parentStr ) + 2 + strlen ( dbgSubprogram - > mName ) + 1 ;
BP_ALLOC ( " String " , allocLen ) ;
char * dupStr = ( char * ) mAlloc . AllocBytes ( allocLen , " String " ) ;
strcpy ( dupStr , parentStr ) ;
strcat ( dupStr , " :: " ) ;
strcat ( dupStr , dbgSubprogram - > mName ) ;
dbgSubprogram - > mName = dupStr ;
}
break ;
case LF_UDT_MOD_SRC_LINE :
{
/*auto udtModSrcLine = *(lfUdtModSrcLine*)data;
auto parentType = CvGetType ( udtModSrcLine . type ) ;
curSubprogram - > mParentType = parentType ; */
}
break ;
}
}
break ;
}
case LF_MFUNC_ID :
{
lfMFuncId * funcData = ( lfMFuncId * ) dataStart ;
2022-07-30 09:08:49 -04:00
CvParseMethod ( NULL , NULL , funcData - > type , false , dbgSubprogram ) ;
2019-09-21 10:49:35 -07:00
dbgSubprogram - > mName = ( const char * ) funcData - > name ;
2020-06-20 17:25:37 -07:00
if ( dbgSubprogram - > mName ! = NULL )
{
for ( const char * cPtr = dbgSubprogram - > mName + 1 ; true ; cPtr + + )
{
char c = * cPtr ;
if ( c = = 0 )
break ;
// For removing the mangled name from the mixins
if ( c = = ' ? ' )
{
int nameLen = cPtr - dbgSubprogram - > mName ;
char * dupStr = ( char * ) mAlloc . AllocBytes ( nameLen + 1 ) ;
memcpy ( dupStr , dbgSubprogram - > mName , nameLen ) ;
dupStr [ nameLen ] = 0 ;
dbgSubprogram - > mName = dupStr ;
break ;
}
}
}
2019-11-29 09:21:51 -08:00
FixSubprogramName ( dbgSubprogram ) ;
2019-09-21 10:49:35 -07:00
dbgSubprogram - > mParentType = CvGetType ( funcData - > parentType ) ;
}
break ;
}
}
int COFF : : MapImport ( CvCompileUnit * compileUnit , int id )
{
BF_ASSERT ( ( id & 0x80000000 ) ! = 0 ) ;
int scopeIdx = ( id & 0x7FFF0000 ) > > 20 ;
int itemId = ( id & 0x0000FFFF ) ;
if ( mModuleNameSet . IsEmpty ( ) )
{
for ( auto moduleInfo : mCvModuleInfo )
{
String name = moduleInfo - > mModuleName ;
name = ToUpper ( name ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
CvModuleInfoNameEntry entry ;
entry . mModuleInfo = moduleInfo ;
mModuleNameSet . Add ( entry ) ;
}
}
if ( scopeIdx < ( int ) compileUnit - > mImports . size ( ) )
{
auto & importSection = compileUnit - > mImports [ scopeIdx ] ;
if ( itemId < ( int ) importSection . mImports . size ( ) )
{
auto importId = importSection . mImports [ itemId ] ;
if ( importSection . mScopeCompileUnit = = NULL )
{
CvModuleInfo * moduleInfo = NULL ;
size_t nameHash = CvModuleInfoNameEntry : : GetHashCode ( importSection . mScopeName ) ;
for ( auto & nameEntry : mModuleNameSet . SelectHashes ( nameHash ) )
{
String checkModuleName = nameEntry . mModuleInfo - > mModuleName ;
checkModuleName . Replace ( " \\ " , " / " ) ;
checkModuleName = ToUpper ( checkModuleName ) ;
String checkScopeName = importSection . mScopeName ;
checkScopeName . Replace ( " \\ " , " / " ) ;
checkScopeName = ToUpper ( checkScopeName ) ;
bool matches = false ;
if ( checkModuleName = = checkScopeName )
matches = true ;
else if ( checkScopeName . EndsWith ( " / " + checkModuleName ) )
matches = true ;
if ( matches )
{
ParseCompileUnit ( nameEntry . mModuleInfo - > mIdx ) ;
auto externCompileUnit = nameEntry . mModuleInfo - > mCompileUnit ;
if ( externCompileUnit - > mExportMap . IsEmpty ( ) )
{
for ( auto & exportEntry : externCompileUnit - > mExports )
externCompileUnit - > mExportMap [ exportEntry . mLocalId ] = exportEntry . mGlobalId ;
}
if ( externCompileUnit - > mExportMap . ContainsKey ( importId ) )
{
importSection . mScopeCompileUnit = nameEntry . mModuleInfo - > mCompileUnit ;
break ;
}
}
}
}
if ( importSection . mScopeCompileUnit ! = NULL )
{
uint32 exportId ;
if ( importSection . mScopeCompileUnit - > mExportMap . TryGetValue ( importId , & exportId ) )
{
if ( ( exportId & 0x80000000 ) ! = 0 )
{
// Does this mean a recursive lookup?
return exportId & 0x7FFFFFFF ;
}
else
{
return exportId ;
}
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
}
}
return 0 ;
}
void COFF : : FixupInlinee ( DbgSubprogram * dbgSubprogram )
{
BF_ASSERT ( dbgSubprogram - > mInlineeInfo ! = NULL ) ;
BF_ASSERT ( ( dbgSubprogram - > mInlineeInfo - > mInlineeId & 0x80000000 ) ! = 0 ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int scopeIdx = ( dbgSubprogram - > mInlineeInfo - > mInlineeId & 0x7FFF0000 ) > > 20 ;
int itemId = ( dbgSubprogram - > mInlineeInfo - > mInlineeId & 0x0000FFFF ) ;
if ( mModuleNameMap . IsEmpty ( ) )
{
for ( auto moduleInfo : mCvModuleInfo )
{
mModuleNameMap [ CaseInsensitiveString ( moduleInfo - > mModuleName ) ] = moduleInfo ;
}
}
auto compileUnit = ( CvCompileUnit * ) dbgSubprogram - > mCompileUnit ;
if ( scopeIdx < ( int ) compileUnit - > mImports . size ( ) )
{
auto & importSection = compileUnit - > mImports [ scopeIdx ] ;
if ( itemId < ( int ) importSection . mImports . size ( ) )
{
auto importId = importSection . mImports [ itemId ] ;
if ( importSection . mScopeCompileUnit = = NULL )
{
CvModuleInfo * moduleInfo = NULL ;
mModuleNameMap . TryGetValue ( CaseInsensitiveString ( importSection . mScopeName ) , & moduleInfo ) ;
if ( moduleInfo ! = NULL )
{
ParseCompileUnit ( moduleInfo - > mIdx ) ;
importSection . mScopeCompileUnit = moduleInfo - > mCompileUnit ;
}
if ( importSection . mScopeCompileUnit ! = NULL )
{
for ( auto & exportEntry : importSection . mScopeCompileUnit - > mExports )
{
if ( exportEntry . mLocalId = = importId )
{
if ( exportEntry . mGlobalId < mCvIPITagStartMap . size ( ) )
{
FixupInlinee ( dbgSubprogram , exportEntry . mGlobalId ) ;
}
}
}
}
}
}
}
dbgSubprogram - > mInlineeInfo - > mInlineeId = 0 ;
}
void COFF : : PopulateStaticVariableMap ( )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( mPopulatedStaticVariables )
return ;
BP_ZONE ( " COFF::PopulateStaticVariableMap " ) ;
if ( mMasterCompileUnit ! = NULL )
{
PopulateTypeGlobals ( mMasterCompileUnit - > mGlobalType ) ;
for ( auto variable : mMasterCompileUnit - > mGlobalType - > mMemberList )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( ( variable - > mIsExtern ) & & ( variable - > mLinkName ! = NULL ) )
mStaticVariables . push_back ( variable ) ;
}
}
DbgModule : : PopulateStaticVariableMap ( ) ;
}
void COFF : : ScanCompileUnit ( int compileUnitId )
{
BP_ZONE ( " COFF::ScanCompileUnit " ) ;
CvModuleInfo * moduleInfo = mCvModuleInfo [ compileUnitId ] ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( moduleInfo - > mStream < 0 )
return ;
BF_ASSERT ( moduleInfo - > mSymbolBytes % 4 = = 0 ) ;
2022-07-30 09:08:49 -04:00
uint8 * sectionData = CvReadStreamSegment ( moduleInfo - > mStream , moduleInfo - > mSymbolBytes , moduleInfo - > mLinesBytes ) ;
2019-09-21 10:49:35 -07:00
uint8 * data = sectionData ;
2022-07-30 09:08:49 -04:00
uint8 * dataEnd = sectionData + moduleInfo - > mLinesBytes ;
2019-09-21 10:49:35 -07:00
while ( data < dataEnd )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
GET_INTO ( int32 , lineInfoType ) ;
2022-07-30 09:08:49 -04:00
GET_INTO ( int32 , lineInfoLength ) ;
2019-09-21 10:49:35 -07:00
uint8 * dataEnd = data + lineInfoLength ;
if ( lineInfoType = = DEBUG_S_FILECHKSMS )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
while ( data < dataEnd )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
GET_INTO ( uint , fileTableOfs ) ;
DbgSrcFile * srcFile ;
DbgSrcFile * * srcFilePtr = NULL ;
if ( ! mCVSrcFileRefCache . TryAdd ( fileTableOfs , NULL , & srcFilePtr ) )
{
srcFile = * srcFilePtr ;
}
else
{
const char * fileName = mStringTable . mStrTable + fileTableOfs ;
2022-04-16 06:27:54 -07:00
if ( ( fileName [ 0 ] = = ' \\ ' ) & & ( fileName [ 1 ] = = ' $ ' ) )
fileName + + ;
2019-09-21 10:49:35 -07:00
srcFile = AddSrcFile ( NULL , fileName ) ;
mSrcFileDeferredRefs . Add ( srcFile ) ;
* srcFilePtr = srcFile ;
//mCVSrcFileRefCache[fileTableOfs] = srcFile;
}
DbgDeferredSrcFileReference dbgDeferredSrcFileReference ;
dbgDeferredSrcFileReference . mDbgModule = this ;
dbgDeferredSrcFileReference . mCompileUnitId = compileUnitId ;
srcFile - > mDeferredRefs . push_back ( dbgDeferredSrcFileReference ) ;
srcFile - > mHadLineData = true ;
GET_INTO ( uint8 , hashLen ) ;
GET_INTO ( uint8 , hashType ) ;
data + = hashLen ;
PTR_ALIGN ( data , sectionData , 4 ) ;
}
break ; // Stop once we handle the file checksums
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
data = dataEnd ;
}
delete [ ] sectionData ;
}
void COFF : : FixTypes ( int startingIdx )
{
BP_ZONE ( " COFF::FixTypes " ) ;
//std::unordered_map<String, DbgType*> namespaceMap;
auto linkedModule = GetLinkedModule ( ) ;
String wholeNamespace ;
for ( int typeIdx = startingIdx ; typeIdx < ( int ) linkedModule - > mTypes . size ( ) ; typeIdx + + )
{
DbgType * dbgType = linkedModule - > mTypes [ typeIdx ] ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgType * prevNamespaceType = NULL ;
if ( dbgType - > mName = = NULL )
{
// Internal typedef
continue ;
}
if ( dbgType - > mLanguage = = DbgLanguage_Unknown )
{
if ( strncmp ( dbgType - > mName , " _bf:: " , 5 ) = = 0 )
{
dbgType - > mLanguage = DbgLanguage_Beef ;
dbgType - > mName + = 5 ;
dbgType - > mTypeName + = 5 ;
}
else if ( ( dbgType - > mName [ 0 ] = = ' G ' ) & & ( dbgType - > mName [ 1 ] = = ' $ ' ) )
{
dbgType - > mLanguage = DbgLanguage_Beef ;
}
else
{
dbgType - > mLanguage = DbgLanguage_C ;
// Check for a primitive array type like 'double[]'
for ( int i = 0 ; i < 10 ; i + + )
{
char c = dbgType - > mName [ i ] ;
if ( c = = 0 )
break ;
if ( c = = ' [ ' )
dbgType - > mLanguage = DbgLanguage_Beef ;
}
}
}
if ( dbgType - > mIsDeclaration )
continue ;
2019-11-07 13:35:56 -08:00
if ( IsObjectFile ( ) )
2019-09-21 10:49:35 -07:00
{
auto entry = linkedModule - > mTypeMap . Find ( dbgType - > mName , dbgType - > mLanguage ) ;
if ( entry ! = NULL )
{
// Just do hot replacing unless this type is new
continue ;
}
}
// This never happens anymore - nested types are always handled as "internal typedefs"
2022-07-30 09:08:49 -04:00
//TODO: Check the 'isnested' flag on the leaf instead of counting on parent to be specified?
2019-09-21 10:49:35 -07:00
bool hadParent = dbgType - > mParent ! = NULL ;
int chevronDepth = 0 ;
2022-07-30 09:08:49 -04:00
if ( ( dbgType - > mTypeCode = = DbgType_Class ) | | ( dbgType - > mTypeCode = = DbgType_Struct ) | | ( dbgType - > mTypeCode = = DbgType_Union ) | |
2019-09-21 10:49:35 -07:00
( dbgType - > mTypeCode = = DbgType_Enum ) | | ( dbgType - > mTypeCode = = DbgType_TypeDef ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
int startIdx = - 1 ;
const char * name = dbgType - > mTypeName ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
for ( int i = 0 ; true ; i + + )
{
char c = name [ i ] ;
if ( c = = ' < ' )
chevronDepth + + ;
else if ( c = = ' > ' )
chevronDepth - - ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ( chevronDepth = = 0 ) & & ( ( c = = ' : ' ) | | ( c = = ' . ' ) ) )
{
if ( ( ! hadParent ) & & ( i - startIdx > 1 ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
//String wholeNamespace = String(name, name + i);
wholeNamespace . clear ( ) ;
wholeNamespace . Insert ( 0 , name , i ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
auto entry = linkedModule - > mTypeMap . Find ( wholeNamespace . c_str ( ) , dbgType - > mLanguage ) ;
if ( entry = = NULL )
{
DbgType * namespaceType = CvCreateType ( ) ;
namespaceType - > mTypeCode = DbgType_Namespace ;
namespaceType - > mName = DbgDupString ( wholeNamespace . c_str ( ) , " DbgDupString.FixTypes " ) ;
namespaceType - > mTypeName = namespaceType - > mName + startIdx + 1 ;
namespaceType - > mPriority = DbgTypePriority_Primary_Implicit ;
namespaceType - > mLanguage = dbgType - > mLanguage ;
linkedModule - > mTypeMap . Insert ( namespaceType ) ;
if ( prevNamespaceType ! = NULL )
{
namespaceType - > mParent = prevNamespaceType ;
prevNamespaceType - > mSubTypeList . PushBack ( namespaceType ) ;
}
prevNamespaceType = namespaceType ;
}
else
{
prevNamespaceType = entry - > mValue ;
}
}
startIdx = i ;
}
else if ( ( c = = 0 ) /*|| (c == '<')*/ | | ( c = = ' ( ' ) )
break ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
if ( prevNamespaceType ! = NULL )
{
dbgType - > mParent = prevNamespaceType ;
prevNamespaceType - > mSubTypeList . PushBack ( dbgType ) ;
}
dbgType - > mTypeName = dbgType - > mTypeName + startIdx + 1 ; // Just take last part of name
}
if ( dbgType - > mParent = = NULL )
dbgType - > mCompileUnit - > mGlobalType - > mSubTypeList . PushBack ( dbgType ) ;
}
}
void COFF : : CvReadStream ( int streamIdx , CvStreamReader & streamReader )
{
BF_ASSERT ( streamReader . mCOFF = = NULL ) ;
streamReader . mCOFF = this ;
streamReader . mPageBits = mCvPageBits ;
int streamSize = mCvStreamSizes [ streamIdx ] ;
int streamPageCount = ( streamSize + mCvPageSize - 1 ) / mCvPageSize ;
streamReader . mStreamPtrs . Resize ( streamPageCount ) ;
streamReader . mSize = streamSize ;
int streamPtrIdx = mCvStreamPtrStartIdxs [ streamIdx ] ;
for ( int streamPageIdx = 0 ; streamPageIdx < streamPageCount ; streamPageIdx + + )
{
streamReader . mStreamPtrs [ streamPageIdx ] = ( uint8 * ) mCvMappedViewOfFile + mCvStreamPtrs [ streamPtrIdx ] * mCvPageSize ;
streamPtrIdx + + ;
}
}
void COFF : : CvInitStreamRaw ( CvStreamReader & streamReader , uint8 * data , int size )
{
BF_ASSERT ( streamReader . mCOFF = = NULL ) ;
streamReader . mCOFF = this ;
streamReader . mPageBits = 31 ;
streamReader . mStreamPtrs . Add ( data ) ;
streamReader . mSize = size ;
}
uint8 * COFF : : CvReadStream ( int streamIdx , int * outSize )
{
BP_ZONE ( " ReadCvSection " ) ;
if ( streamIdx > = mCvStreamSizes . size ( ) )
return NULL ;
2020-12-28 09:10:25 -08:00
if ( ( streamIdx < 0 ) | | ( streamIdx > = mCvStreamSizes . mSize ) )
{
Fail ( StrFormat ( " Invalid PDB stream index: %d " , streamIdx ) ) ;
return NULL ;
}
2019-09-21 10:49:35 -07:00
int streamSize = mCvStreamSizes [ streamIdx ] ;
if ( outSize ! = NULL )
* outSize = streamSize ;
if ( streamSize < = 0 )
return NULL ;
2022-07-30 09:08:49 -04:00
int streamPageCount = ( streamSize + mCvPageSize - 1 ) / mCvPageSize ;
2019-09-21 10:49:35 -07:00
uint8 * sectionData = new uint8 [ streamSize ] ;
bool deferDeleteSectionData = false ;
int streamPtrIdx = mCvStreamPtrStartIdxs [ streamIdx ] ;
for ( int streamPageIdx = 0 ; streamPageIdx < streamPageCount ; streamPageIdx + + )
{
mCvDataStream - > SetPos ( mCvStreamPtrs [ streamPtrIdx ] * mCvPageSize ) ;
mCvDataStream - > Read ( sectionData + streamPageIdx * mCvPageSize , std : : min ( streamSize - ( streamPageIdx * mCvPageSize ) , mCvPageSize ) ) ;
streamPtrIdx + + ;
}
return sectionData ;
}
uint8 * COFF : : CvReadStreamSegment ( int streamIdx , int offset , int size )
{
BP_ZONE ( " ReadCvSection " ) ;
//int streamSize = mCvStreamSizes[streamIdx];
//int streamPageCount = (streamSize + mCvPageSize - 1) / mCvPageSize;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
uint8 * sectionData = new uint8 [ size ] ;
//delete [] sectionData;
bool deferDeleteSectionData = false ;
uint8 * data = sectionData ;
int curOffset = offset ;
int sizeLeft = size ;
2022-07-30 09:08:49 -04:00
int streamPtrIdx = mCvStreamPtrStartIdxs [ streamIdx ] ;
2019-09-21 10:49:35 -07:00
streamPtrIdx + = offset / mCvPageSize ;
curOffset = offset - ( offset / mCvPageSize ) * mCvPageSize ;
//for (int streamPageIdx = 0; streamPageIdx < streamPageCount; streamPageIdx++)
while ( sizeLeft > 0 )
{
mCvDataStream - > SetPos ( mCvStreamPtrs [ streamPtrIdx ] * mCvPageSize + curOffset ) ;
int readSize = std : : min ( mCvPageSize - curOffset , sizeLeft ) ;
mCvDataStream - > Read ( data , readSize ) ;
data + = readSize ;
sizeLeft - = readSize ;
curOffset = 0 ;
streamPtrIdx + + ;
}
return sectionData ;
}
void COFF : : ReleaseTempBuf ( uint8 * buf )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( ( mTempBufIdx > 0 ) & & ( mTempBufs . mVals [ mTempBufIdx - 1 ] . mVals = = buf ) )
2022-07-30 09:08:49 -04:00
mTempBufIdx - - ;
2019-09-21 10:49:35 -07:00
}
bool COFF : : CvParseHeader ( uint8 wantGuid [ 16 ] , int32 wantAge )
{
int streamSize = 0 ;
uint8 * data = CvReadStream ( 1 , & streamSize ) ;
mCvHeaderData = data ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int32 pdbVersion = GET ( int32 ) ;
int32 timestamp = GET ( int32 ) ;
2022-07-30 09:08:49 -04:00
int32 pdbAge = GET ( int32 ) ;
2019-09-21 10:49:35 -07:00
for ( int i = 0 ; i < 16 ; i + + )
mPDBGuid [ i ] = GET ( int8 ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ( wantAge ! = - 1 ) & &
( /*(pdbAge != wantAge) ||*/ ( memcmp ( mPDBGuid , wantGuid , 16 ) ! = 0 ) ) )
{
if ( mDebugger ! = NULL )
{
String msg = " PDB GUID did not match requested version \n " ;
msg + = StrFormat ( " Module GUID: " ) ;
for ( int i = 0 ; i < 16 ; i + + )
msg + = StrFormat ( " %02X " , ( uint8 ) wantGuid [ i ] ) ;
msg + = " \n " ;
msg + = StrFormat ( " PDB GUID : " ) ;
for ( int i = 0 ; i < 16 ; i + + )
2022-07-30 09:08:49 -04:00
msg + = StrFormat ( " %02X " , ( uint8 ) mPDBGuid [ i ] ) ;
2019-09-21 10:49:35 -07:00
Fail ( msg ) ;
}
return false ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
if ( mParseKind = = ParseKind_Header )
return true ;
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 ;
if ( strcmp ( tableName , " srcsrv " ) = = 0 )
mCvSrcSrvStream = streamNum ;
2022-04-16 06:27:54 -07:00
if ( strcmp ( tableName , " emit " ) = = 0 )
mCvEmitStream = streamNum ;
2019-09-21 10:49:35 -07:00
/*if (tableIdx == nameTableIdx)
{
nameStringTable . mStream = streamNum ;
nameStringTable . mStreamOffset = strOfs ;
} */
}
return true ;
}
bool COFF : : CvParseDBI ( int wantAge )
{
BP_ZONE ( " CvParseDBI " ) ;
2022-07-30 09:08:49 -04:00
uint8 * data = CvReadStream ( 3 ) ;
2020-08-11 09:26:21 -07:00
if ( data = = NULL )
return false ;
2019-09-21 10:49:35 -07:00
uint8 * sectionData = data ;
defer
2019-10-15 12:28:21 -07:00
(
2019-09-21 10:49:35 -07:00
delete sectionData ;
2019-10-15 12:28:21 -07:00
) ;
2019-09-21 10:49:35 -07:00
// Header
GET_INTO ( int32 , signature ) ;
GET_INTO ( uint32 , version ) ;
GET_INTO ( uint32 , age ) ;
mDebugAge = ( int32 ) age ;
if ( ( wantAge ! = - 1 ) & & ( wantAge ! = age ) )
{
if ( mDebugger ! = NULL )
{
String msg = " PDB age did not match requested age \n " ;
msg + = StrFormat ( " Module Age: %d PDB Age: %d " , wantAge , age ) ;
Fail ( msg ) ;
}
return false ;
}
if ( mParseKind = = ParseKind_Header )
return true ;
mCvGlobalSymbolInfoStream = GET ( int16 ) ; // hash1_file, snGSSyms
GET_INTO ( uint16 , pdb_dll_version ) ;
mCvPublicSymbolInfoStream = GET ( int16 ) ; // hash2_file, snPSSyms
GET_INTO ( uint16 , pdb_dll_build_major ) ;
mCvSymbolRecordStream = GET ( int16 ) ; // gsym_file, snSymRecs
GET_INTO ( uint16 , pdb_dll_build_minor ) ;
GET_INTO ( uint32 , gp_modi_size ) ; //module_size
GET_INTO ( uint32 , section_contribution_size ) ; //offset_size
GET_INTO ( uint32 , section_map_size ) ; //hash_size
GET_INTO ( uint32 , file_info_size ) ; //srcmodule_size
GET_INTO ( uint32 , ts_map_size ) ; //pdb_import_size
GET_INTO ( uint32 , mfc_index ) ; //resvd0
GET_INTO ( uint32 , dbg_header_size ) ; // stream_index_size
GET_INTO ( uint32 , ec_info_size ) ; //unknown_size
GET_INTO ( uint16 , flags ) ; //resvd3
GET_INTO ( uint16 , machine ) ;
GET_INTO ( uint32 , reserved ) ; //resvd4
2020-08-11 09:26:21 -07:00
if ( machine = = 0x8664 )
mIs64Bit = true ;
else if ( machine = = 0x014C )
mIs64Bit = false ;
else // Unknown machine
2022-07-30 09:08:49 -04:00
return false ;
2020-08-11 09:26:21 -07:00
2019-09-21 10:49:35 -07:00
uint8 * headerEnd = data ;
// Skip to debug header
data + = gp_modi_size ;
data + = section_contribution_size ;
data + = section_map_size ;
data + = file_info_size ;
data + = ts_map_size ;
data + = ec_info_size ;
// Debug header
GET_INTO ( int16 , fpo ) ;
GET_INTO ( int16 , exception ) ;
GET_INTO ( int16 , fixup ) ;
GET_INTO ( int16 , omap_to_src ) ;
GET_INTO ( int16 , omap_from_src ) ;
GET_INTO ( int16 , section_header ) ; // 0x0a, all others are -1 (segments)
GET_INTO ( int16 , token_rid_map ) ;
GET_INTO ( int16 , x_data ) ;
GET_INTO ( int16 , p_data ) ;
mCvNewFPOStream = GET ( int16 ) ;
GET_INTO ( int16 , section_header_origin ) ;
if ( section_header ! = - 1 )
ParseSectionHeader ( section_header ) ;
// Module info
data = headerEnd ;
uint8 * dataEnd = data + gp_modi_size ;
while ( data < dataEnd )
{
BP_ALLOC_T ( CvModuleInfo ) ;
CvModuleInfo * moduleInfo = mAlloc . Alloc < CvModuleInfo > ( ) ;
memcpy ( moduleInfo , data , sizeof ( CvModuleInfoBase ) ) ;
data + = sizeof ( CvModuleInfoBase ) ;
moduleInfo - > mModuleName = CvParseAndDupString ( data ) ; //DataGetString(data);
moduleInfo - > mObjectName = CvParseAndDupString ( data ) ; //DataGetString(data);
moduleInfo - > mIdx = ( int ) mCvModuleInfo . size ( ) ;
//BfLogCv("Module %d: %s Obj: %s\n", mCvModuleInfo.size(), moduleInfo->mModuleName, moduleInfo->mObjectName);
mCvModuleInfo . push_back ( moduleInfo ) ;
/*if (moduleInfo->mStream != -1)
{
if ( moduleInfo - > mStream > = mDeferredModuleInfo . size ( ) )
mDeferredModuleInfo . resize ( moduleInfo - > mStream + 1 ) ;
mDeferredModuleInfo [ moduleInfo - > mStream ] . push_back ( moduleInfo ) ;
} */
PTR_ALIGN ( data , sectionData , 4 ) ;
}
// Section contrib
{
BP_ZONE ( " CvParseDBI_Contrib " ) ;
dataEnd = data + section_contribution_size ;
int32 sig = GET ( int32 ) ;
BF_ASSERT ( ( sig = = 0xF12EBA2D ) | | ( sig = = 0xf13151e4 ) ) ;
bool isV2 = sig = = 0xf13151e4 ;
if ( isV2 )
{
2019-12-21 05:44:01 -08:00
Fail ( " FastLink PDBs are not supported. Consider adding full debug info (/DEBUG:FULL). " ) ;
2019-09-21 10:49:35 -07:00
mIsFastLink = true ;
}
while ( data < dataEnd )
{
CvSectionContrib & contrib = GET ( CvSectionContrib ) ;
if ( isV2 )
{
uint32_t isectCoff = GET ( uint32_t ) ;
}
for ( int contribOffset = 0 ; true ; contribOffset + = DBG_MAX_LOOKBACK )
{
int curSize = contrib . mSize - contribOffset ;
if ( curSize < = 0 )
break ;
BP_ALLOC_T ( DbgCompileUnitContrib ) ;
auto contribEntry = mAlloc . Alloc < DbgCompileUnitContrib > ( ) ;
contribEntry - > mAddress = GetSectionAddr ( contrib . mSection , contrib . mOffset ) + contribOffset ;
2020-08-11 09:26:21 -07:00
if ( ( contribEntry - > mAddress & 0xFFFF0000'00000000 ) ! = 0 )
continue ;
2019-09-21 10:49:35 -07:00
contribEntry - > mLength = curSize ;
contribEntry - > mDbgModule = this ;
contribEntry - > mCompileUnitId = contrib . mModule ;
mDebugTarget - > mContribMap . Insert ( contribEntry ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
}
// Dbi section map
dataEnd = data + section_map_size ;
GET_INTO ( int16 , numSections ) ;
GET_INTO ( int16 , numSectionsCopy ) ;
while ( data < dataEnd )
{
GET_INTO ( uint8 , flags ) ;
GET_INTO ( uint8 , section_type ) ;
// This field hasn't been deciphered but it is always 0x00000000 or 0xFFFFFFFF
// and modifying it doesn't seem to invalidate the Cv.
GET_INTO ( int32 , unknownData ) ;
GET_INTO ( uint16 , section_number ) ;
// Same thing as for unknown_data_1.
GET_INTO ( int32 , unknownData2 ) ;
// Value added to the address offset when calculating the RVA.
GET_INTO ( uint32 , rva_offset ) ;
2022-07-30 09:08:49 -04:00
GET_INTO ( uint32 , section_length ) ;
2019-09-21 10:49:35 -07:00
}
// Dbi File info
dataEnd = data + file_info_size ;
GET_INTO ( uint16 , fileInfoNumModules ) ;
GET_INTO ( uint16 , bad_fileInfoNumSourceFiles ) ;
int fileInfoNumSourceFiles = 0 ;
2022-07-30 09:08:49 -04:00
uint16 * modIndices = ( uint16 * ) data ;
2019-09-21 10:49:35 -07:00
data + = fileInfoNumModules * sizeof ( uint16 ) ;
uint16 * modFileCounts = ( uint16 * ) data ;
data + = fileInfoNumModules * sizeof ( uint16 ) ;
2022-07-30 09:08:49 -04:00
for ( int moduleIdx = 0 ; moduleIdx < fileInfoNumModules ; moduleIdx + + )
2019-09-21 10:49:35 -07:00
fileInfoNumSourceFiles + = modFileCounts [ moduleIdx ] ;
int32 * fileNameOffsets = ( int32 * ) data ;
data + = fileInfoNumSourceFiles * sizeof ( int32 ) ;
char * nameBuffer = ( char * ) data ;
char * namePtr = nameBuffer ;
int curFileOfs = 0 ;
for ( int moduleIdx = 0 ; moduleIdx < fileInfoNumModules ; moduleIdx + + )
{
//TODO: LLD-LINK does not emit this properly
//BF_ASSERT((modIndices[moduleIdx] == curFileOfs) || (moduleIdx >= 32));
for ( int fileIdx = 0 ; fileIdx < modFileCounts [ moduleIdx ] ; fileIdx + + )
{
2022-07-30 09:08:49 -04:00
char * fileName = namePtr + * fileNameOffsets ;
2019-09-21 10:49:35 -07:00
curFileOfs + + ;
fileNameOffsets + + ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
//int blockStart = fileBlockTable[i];
//int blockLength = fileBlockTable[fileInfoNumModules + i];
2022-07-30 09:08:49 -04:00
//int offset = offsetTable[blockStart]; through blockLength...
2019-09-21 10:49:35 -07:00
}
// File name table
/*uint8* dataStart = data;
while ( data < dataEnd )
{
int offset = ( int ) ( data - dataStart ) ;
2022-07-30 09:08:49 -04:00
const char * fileName = DataGetString ( data ) ;
2019-09-21 10:49:35 -07:00
//DbgSrcFile* srcFile = AddSrcFile(mMasterCompileUnit, fileName);
//fileTable.insert(std::make_pair(offset, srcFile));
} */
data = dataEnd ;
BF_ASSERT ( ts_map_size = = 0 ) ;
// EC Info
dataEnd = data + ec_info_size ;
GET_INTO ( uint32 , strTabSig ) ;
GET_INTO ( uint32 , strTabVer ) ;
BF_ASSERT ( strTabSig = = 0xEFFEEFFE ) ;
GET_INTO ( int32 , strTabSize ) ;
uint8 * strTabData = data ;
data + = strTabSize ;
GET_INTO ( int32 , strTabEntryCount ) ;
for ( int entryIdx = 0 ; entryIdx < strTabEntryCount ; entryIdx + + )
{
GET_INTO ( int32 , strOffset ) ;
2022-07-30 09:08:49 -04:00
const char * str = ( const char * ) strTabData + strOffset ;
}
2019-09-21 10:49:35 -07:00
return true ;
}
void COFF : : ParseSectionHeader ( int sectionIdx )
{
bool fakeRVAS = mSectionRVAs . empty ( ) ;
int sectionSize = 0 ;
uint8 * sectionData = CvReadStream ( sectionIdx , & sectionSize ) ;
uint8 * data = sectionData ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
uint8 * dataEnd = data + sectionSize ;
while ( data < dataEnd )
{
auto & sectionHeader = GET ( PESectionHeader ) ;
if ( fakeRVAS )
{
mSectionRVAs . push_back ( sectionHeader . mVirtualAddress ) ;
}
}
if ( fakeRVAS )
mSectionRVAs . push_back ( 0 ) ;
delete sectionData ;
}
void COFF : : CvParseIPI ( )
{
BF_ASSERT ( ! mCvIPIReader . IsSetup ( ) ) ;
//uint8* sectionData;
int sectionSize = 0 ;
int hashAdjOffset = 0 ;
int32 hashStream = - 1 ;
int32 hashAdjSize = 0 ;
2022-07-30 09:08:49 -04:00
int32 dataOffset = 0 ;
2019-09-21 10:49:35 -07:00
ParseTypeData ( 4 , mCvIPIReader , sectionSize , dataOffset , hashStream , hashAdjOffset , hashAdjSize , mCvIPIMinTag , mCvIPIMaxTag ) ;
//mCvIPIData = sectionData;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int recordCount = mCvIPIMaxTag - mCvIPIMinTag ;
2019-12-21 09:35:58 -08:00
mCvIPITagStartMap . Resize ( recordCount + 1 ) ;
2019-09-21 10:49:35 -07:00
//uint8* data = sectionData + dataOffset;
int offset = dataOffset ;
for ( int idx = 0 ; idx < recordCount ; idx + + )
2022-07-30 09:08:49 -04:00
{
2019-09-24 08:58:04 -07:00
//BF_ASSERT(((offset) & 3) == 0);
2022-07-30 09:08:49 -04:00
uint8 * data = mCvIPIReader . GetTempPtr ( offset , 4 ) ;
2019-09-21 10:49:35 -07:00
uint16 trLength = GET ( uint16 ) ;
int offsetStart = offset ;
offset + = 2 ;
data = mCvIPIReader . GetTempPtr ( offset , trLength ) ;
2022-07-30 09:08:49 -04:00
uint8 * dataStart = data ;
2019-09-21 10:49:35 -07:00
uint16 trLeafType = GET ( uint16 ) ;
//uint8* dataEnd = dataStart + trLength;
offset + = trLength ;
/*
*/
lfEasy & funcLeaf = * ( lfEasy * ) dataStart ;
switch ( funcLeaf . leaf )
{
case LF_FUNC_ID :
{
2022-07-30 09:08:49 -04:00
lfFuncId * funcData = ( lfFuncId * ) dataStart ;
2019-09-21 10:49:35 -07:00
//subprogram->mName = (const char*)funcData->name;
bool doScope = true ;
/*if (strcmp(curSubprogram->mName, "DispatchToMethod") == 0)
{
2022-07-30 09:08:49 -04:00
doScope = true ;
2019-09-21 10:49:35 -07:00
} */
if ( ( funcData - > scopeId ! = 0 ) & & ( doScope ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
uint8 * data = CvGetTagData ( funcData - > scopeId , true ) ;
CvAutoReleaseTempData releaseTempData ( this , data ) ;
lfEasy & leaf = * ( lfEasy * ) data ;
switch ( leaf . leaf )
{
case LF_STRING_ID :
{
lfStringId & str = * ( lfStringId * ) data ;
const char * parentStr = ( const char * ) str . name ;
}
break ;
case LF_UDT_MOD_SRC_LINE :
{
/*auto udtModSrcLine = *(lfUdtModSrcLine*)data;
auto parentType = CvGetType ( udtModSrcLine . type ) ;
curSubprogram - > mParentType = parentType ; */
}
break ;
}
}
break ;
}
case LF_MFUNC_ID :
{
lfMFuncId * funcData = ( lfMFuncId * ) dataStart ;
auto parentType = CvGetType ( funcData - > parentType ) ;
}
break ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
mCvIPITagStartMap [ idx ] = offsetStart ;
}
2022-07-30 09:08:49 -04:00
2019-12-21 09:35:58 -08:00
mCvIPITagStartMap [ recordCount ] = offset ;
2019-09-21 10:49:35 -07:00
}
const char * COFF : : CvParseSymbol ( int offset , CvSymStreamType symStreamType , addr_target & outAddr )
{
const char * retName = NULL ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int offsetStart = offset ;
2022-07-30 09:08:49 -04:00
uint8 * data = mCvSymbolRecordReader . GetTempPtr ( offset , 4 ) ;
2019-09-21 10:49:35 -07:00
uint16 symLen = * ( uint16 * ) data ;
bool madeCopy = false ;
data = mCvSymbolRecordReader . GetTempPtr ( offset , symLen + 2 , false , & madeCopy ) ;
2022-07-30 09:08:49 -04:00
uint8 * dataStart = data ;
2019-09-21 10:49:35 -07:00
uint16 symType = * ( uint16 * ) ( data + 2 ) ;
BF_ASSERT ( symLen % 4 = = 2 ) ;
BF_ASSERT ( ( intptr ) data % 4 = = 0 ) ;
char * scanName = NULL ;
switch ( symType )
{
case S_UDT :
{
UDTSYM & udt = * ( UDTSYM * ) dataStart ;
const char * name = ( const char * ) udt . name ;
# ifdef _DEBUG
ParseTypeData ( ) ;
2022-07-30 09:08:49 -04:00
auto type = CvGetType ( udt . typind ) ;
# endif
2019-09-21 10:49:35 -07:00
retName = name ;
}
break ;
case S_PUB32 :
{
PUBSYM32 & pubSym = * ( PUBSYM32 * ) dataStart ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( symStreamType ! = CvSymStreamType_Symbols )
2022-07-30 09:08:49 -04:00
break ;
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgSymbol ) ;
DbgSymbol * dbgSymbol = mAlloc . Alloc < DbgSymbol > ( ) ;
const char * name = ( const char * ) mCvSymbolRecordReader . GetPermanentPtr ( offsetStart + offsetof ( PUBSYM32 , name ) , symLen - offsetof ( PUBSYM32 , name ) + 2 ) ; // pubSym.name;
2022-07-30 09:08:49 -04:00
//OutputDebugStrF("Sym: %s\n", name);
2019-09-21 10:49:35 -07:00
# ifdef BF_DBG_32
if ( ( name ! = NULL ) & & ( name [ 0 ] = = ' _ ' ) )
name + + ;
# endif
dbgSymbol - > mName = name ;
dbgSymbol - > mAddress = GetSectionAddr ( pubSym . seg , pubSym . off ) ;
dbgSymbol - > mDbgModule = this ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ( dbgSymbol - > mAddress > = mImageBase ) & & ( dbgSymbol - > mAddress < mImageBase + mImageSize ) )
{
if ( ( dbgSymbol - > mAddress & 0xFFFF'0000'0000'0000 ) = = 0 )
mDebugTarget - > mSymbolMap . Insert ( dbgSymbol ) ;
}
else
{
NOP ;
}
mSymbolNameMap . Insert ( dbgSymbol ) ;
outAddr = dbgSymbol - > mAddress ;
retName = name ;
}
break ;
case S_CONSTANT :
{
2022-07-30 09:08:49 -04:00
CONSTSYM & constSym = * ( CONSTSYM * ) dataStart ;
2019-09-21 10:49:35 -07:00
}
break ;
case S_GDATA32 :
case S_LDATA32 :
{
uint8 * permDataPtr = madeCopy ? mCvSymbolRecordReader . GetPermanentPtr ( offsetStart , symLen + 2 ) : dataStart ;
DATASYM32 & dataSym = * ( DATASYM32 * ) permDataPtr ;
if ( strcmp ( ( const char * ) dataSym . name , " _tls_index " ) = = 0 )
{
mTLSIndexAddr = GetSectionAddr ( dataSym . seg , dataSym . off ) ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
char * name = ( char * ) dataSym . name ;
retName = name ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( symStreamType = = CvSymStreamType_Globals_Scan )
{
scanName = ( char * ) dataSym . name ;
2022-07-30 09:08:49 -04:00
break ;
2019-09-21 10:49:35 -07:00
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
bool wasBeef = false ;
const char * memberName = CvCheckTargetMatch ( name , wasBeef ) ;
if ( memberName = = NULL )
break ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
DbgType * dbgType = CvGetType ( dataSym . typind ) ;
BP_ALLOC_T ( DbgVariable ) ;
DbgVariable * variable = mAlloc . Alloc < DbgVariable > ( ) ;
2022-07-30 09:08:49 -04:00
variable - > mType = dbgType ;
2019-09-21 10:49:35 -07:00
variable - > mLocationData = permDataPtr ;
variable - > mLocationLen = 1 ;
variable - > mIsStatic = true ;
variable - > mCompileUnit = mMasterCompileUnit ;
2022-07-30 09:08:49 -04:00
variable - > mName = memberName ;
2019-09-21 10:49:35 -07:00
variable - > mLinkName = name ;
if ( strcmp ( ( const char * ) dataSym . name , " __ImageBase " ) = = 0 )
variable - > mLinkName = NULL ; // Avoid adding to map
variable - > mIsExtern = symType = = S_GDATA32 ;
2022-07-30 09:08:49 -04:00
variable - > mCompileUnit = mGlobalsTargetType - > mCompileUnit ;
2019-09-21 10:49:35 -07:00
// Push front so we will find before the original static declaration (that has no memory associated with it)
2022-07-30 09:08:49 -04:00
mGlobalsTargetType - > mMemberList . PushFront ( variable ) ;
2019-09-21 10:49:35 -07:00
2019-11-07 13:35:56 -08:00
if ( IsObjectFile ( ) )
2019-09-21 10:49:35 -07:00
{
if ( ( variable - > mIsExtern ) & & ( variable - > mLinkName ! = NULL ) )
mStaticVariables . push_back ( variable ) ;
}
}
break ;
case S_GTHREAD32 :
case S_LTHREAD32 :
{
uint8 * permDataPtr = madeCopy ? mCvSymbolRecordReader . GetPermanentPtr ( offsetStart , symLen + 2 ) : dataStart ;
THREADSYM32 & threadSym = * ( THREADSYM32 * ) permDataPtr ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( symStreamType = = CvSymStreamType_Globals_Scan )
{
scanName = ( char * ) threadSym . name ;
break ;
}
char * name = ( char * ) threadSym . name ;
retName = name ;
bool wasBeef = false ;
const char * memberName = CvCheckTargetMatch ( name , wasBeef ) ;
if ( memberName = = NULL )
break ;
addr_target addr = GetSectionAddr ( threadSym . seg , threadSym . off ) ;
DbgType * dbgType = CvGetType ( threadSym . typind ) ;
BP_ALLOC_T ( DbgVariable ) ;
DbgVariable * variable = mAlloc . Alloc < DbgVariable > ( ) ;
2022-07-30 09:08:49 -04:00
variable - > mType = dbgType ;
2019-09-21 10:49:35 -07:00
variable - > mLocationData = permDataPtr ;
variable - > mLocationLen = 1 ;
variable - > mIsStatic = true ;
variable - > mCompileUnit = mMasterCompileUnit ;
variable - > mName = memberName ;
variable - > mLinkName = name ;
variable - > mIsExtern = symType = = S_GTHREAD32 ;
variable - > mCompileUnit = mGlobalsTargetType - > mCompileUnit ;
// Push front so we will find before the original static declaration (that has no memory associated with it)
mGlobalsTargetType - > mMemberList . PushFront ( variable ) ;
}
break ;
case S_PROCREF :
{
REFSYM2 & refSym = * ( REFSYM2 * ) dataStart ;
if ( refSym . imod = = 0 )
break ;
char * name = ( char * ) refSym . name ;
retName = name ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( symStreamType = = CvSymStreamType_Globals_Scan )
{
scanName = ( char * ) refSym . name ;
break ;
2022-07-30 09:08:49 -04:00
}
int moduleId = refSym . imod - 1 ;
2019-09-21 10:49:35 -07:00
bool wasBeef = false ;
2019-11-29 09:21:51 -08:00
char * memberName = ( char * ) CvCheckTargetMatch ( name , wasBeef ) ;
2022-07-30 09:08:49 -04:00
if ( memberName = = NULL )
2019-09-21 10:49:35 -07:00
break ;
2022-07-30 09:08:49 -04:00
2019-11-29 09:21:51 -08:00
bool wantsCopy = madeCopy ;
2019-09-21 10:49:35 -07:00
bool isIllegal = false ;
for ( const char * cPtr = memberName ; * cPtr ! = 0 ; cPtr + + )
{
char c = * cPtr ;
2019-11-29 09:21:51 -08:00
if ( c = = ' $ ' )
{
if ( ( strcmp ( cPtr , " $CHK " ) = = 0 ) | | ( strcmp ( cPtr , " $UCHK " ) = = 0 ) )
{
auto prevName = memberName ;
memberName = DbgDupString ( prevName ) ;
memberName [ cPtr - prevName ] = 0 ;
wantsCopy = false ;
break ;
2022-07-30 09:08:49 -04:00
}
2019-11-29 09:21:51 -08:00
else
isIllegal = true ;
}
if ( ( c = = ' < ' ) | | ( c = = ' ` ' ) )
2019-09-21 10:49:35 -07:00
isIllegal = true ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
if ( ! isIllegal )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
BP_ALLOC_T ( DbgMethodNameEntry ) ;
auto methodNameEntry = mAlloc . Alloc < DbgMethodNameEntry > ( ) ;
methodNameEntry - > mCompileUnitId = moduleId ;
2019-11-29 09:21:51 -08:00
methodNameEntry - > mName = wantsCopy ? DbgDupString ( memberName ) : memberName ;
2019-09-21 10:49:35 -07:00
mGlobalsTargetType - > mMethodNameList . PushBack ( methodNameEntry ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
break ;
default :
//BF_FATAL("Unhandled");
break ;
}
if ( scanName ! = NULL )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
//TODO: Remove
//String origName = name;
//CvFixupName(name);
char * lastDblColon = ( char * ) GetNamespaceEnd ( scanName ) ;
if ( lastDblColon ! = NULL )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( mPrevScanName ! = NULL )
{
int namespaceLen = lastDblColon - scanName ;
if ( strncmp ( scanName , mPrevScanName , namespaceLen + 2 ) = = 0 ) // +2 includes the ending '::'
{
// We've already inserted this namespace
2022-07-30 09:08:49 -04:00
return retName ;
2019-09-21 10:49:35 -07:00
}
}
StringT < 256 > tempName ;
2022-07-30 09:08:49 -04:00
tempName = String ( scanName , lastDblColon - scanName ) ;
2020-12-06 05:53:32 -08:00
2019-09-21 10:49:35 -07:00
DbgType * dbgType = CvGetTypeOrNamespace ( ( char * ) tempName . c_str ( ) ) ;
2022-07-30 09:08:49 -04:00
// *lastDblColon = '\0';
2019-09-21 10:49:35 -07:00
// DbgType* dbgType = CvGetTypeOrNamespace(scanName);
// *lastDblColon = ':';
/*if (strcmp(lastDblColon, "::this") == 0)
{
dbgType - > mLanguage = DbgLanguage_Beef ;
} */
if ( dbgType ! = NULL )
dbgType - > mNeedsGlobalsPopulated = true ;
mPrevScanName = scanName ;
/*const char* methodName = NULL;
DbgType * dbgParent = NULL ;
if ( lastDblColon ! = NULL )
{
* lastDblColon = 0 ;
const char * namespaceName = name ;
dbgParent = CvGetTypeOrNamespace ( namespaceName ) ;
methodName = lastDblColon + 2 ;
}
else
{
dbgParent = & mMasterCompileUnit - > mGlobalType ;
//mStaticVariables.push_back(variable);
methodName = name ;
}
if ( dbgParent ! = NULL )
{
auto methodNameEntry = mAlloc . Alloc < DbgMethodNameEntry > ( ) ;
methodNameEntry - > mCompileUnitId = moduleId ;
methodNameEntry - > mName = methodName ;
dbgParent - > mMethodNameList . PushBack ( methodNameEntry ) ;
2022-07-30 09:08:49 -04:00
} */
2019-09-21 10:49:35 -07:00
}
else
{
mMasterCompileUnit - > mGlobalType - > mNeedsGlobalsPopulated = true ;
}
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
return retName ;
}
uint8 * COFF : : HandleSymStreamEntries ( CvSymStreamType symStreamType , uint8 * data , uint8 * addrMap )
{
uint32 tickStart = BFTickCount ( ) ;
GET_INTO ( uint32 , verSig ) ;
GET_INTO ( uint32 , verHdr ) ;
GET_INTO ( int32 , sizeHr ) ;
GET_INTO ( int32 , sizeBuckets ) ;
BF_ASSERT ( verSig = = 0xffffffff ) ;
BF_ASSERT ( verHdr = = 0xf12f091a ) ;
uint8 * dataEnd = data + sizeHr ;
uint8 * refDataHead = data ;
int entryIdxMax = sizeHr / 8 ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
data = dataEnd ;
dataEnd = data + sizeBuckets ;
int32 * hashBucketHead = ( int32 * ) ( data + 0x81 * 4 ) ;
int32 * hashBucketPtr = hashBucketHead ;
int numRecordsRead = 0 ;
# ifdef _DEBUG
bool verify = false ;
# endif
if ( mIsFastLink )
2020-08-11 09:26:21 -07:00
return dataEnd ; // Format changed
if ( sizeBuckets = = 0 )
return dataEnd ; // No hash
2019-09-21 10:49:35 -07:00
std : : multimap < addr_target , int > checkAddrMap ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int bitCount = 0 ;
for ( int blockIdx = 0 ; blockIdx < 0x81 ; blockIdx + + )
{
GET_INTO ( uint32 , bits ) ;
for ( int i = 0 ; i < 32 ; i + + )
{
if ( ( bits & ( 1 < < i ) ) ! = 0 )
{
bitCount + + ;
int32 entryStart = * ( hashBucketPtr + + ) / 12 ;
int32 entryEnd ;
if ( ( uint8 * ) hashBucketPtr ! = ( uint8 * ) dataEnd )
entryEnd = * ( hashBucketPtr ) / 12 ;
else
entryEnd = entryIdxMax ;
BF_ASSERT ( entryStart < = entryEnd ) ;
for ( int entryIdx = entryStart ; entryIdx < entryEnd ; entryIdx + + )
{
int32 symDataPtr = * ( int32 * ) ( refDataHead + entryIdx * 8 ) ;
if ( symDataPtr = = 0 )
continue ;
addr_target addr = 0 ;
2022-07-30 09:08:49 -04:00
const char * symName = CvParseSymbol ( symDataPtr - 1 , symStreamType , addr ) ;
2019-09-21 10:49:35 -07:00
# ifdef _DEBUG
if ( ( verify ) & & ( addrMap ! = NULL ) )
{
checkAddrMap . insert ( std : : make_pair ( addr , symDataPtr - 1 ) ) ;
}
if ( ( verify ) & & ( symName ! = NULL ) )
{
int hashIdx = ( blockIdx * 32 ) + i ;
int wantHash = BlHash : : HashStr_PdbV1 ( symName ) % 4096 ;
BF_ASSERT ( hashIdx = = wantHash ) ;
}
# endif
numRecordsRead + + ;
}
}
}
}
# ifdef _DEBUG
if ( ( verify ) & & ( addrMap ! = NULL ) )
{
auto itr = checkAddrMap . begin ( ) ;
data = addrMap ;
for ( int entryIdx = 0 ; entryIdx < numRecordsRead ; entryIdx + + )
{
2022-07-30 09:08:49 -04:00
int verifyIdx = GET ( int32 ) ;
2019-09-21 10:49:35 -07:00
int actualIdx = itr - > second ;
if ( actualIdx ! = verifyIdx )
{
OutputDebugStrF ( " Mismatch #%X %X %X %08X \n " , entryIdx , verifyIdx , actualIdx , itr - > first ) ;
}
+ + itr ;
2022-07-30 09:08:49 -04:00
}
}
2019-09-21 10:49:35 -07:00
# endif
BF_ASSERT ( numRecordsRead = = entryIdxMax ) ;
2020-07-31 06:18:26 -07:00
//OutputDebugStrF("HandleSymStreamEntries Ticks: %d\n", BFTickCount() - tickStart);
2019-09-21 10:49:35 -07:00
return dataEnd ;
}
void COFF : : ParseSymbolStream ( CvSymStreamType symStreamType )
{
2022-07-30 09:08:49 -04:00
if ( mCvSymbolRecordStream = = 0 )
return ;
2019-09-21 10:49:35 -07:00
BP_ZONE ( " COFF::ParseSymbolStream " ) ;
if ( ! mCvSymbolRecordReader . IsSetup ( ) )
CvReadStream ( mCvSymbolRecordStream , mCvSymbolRecordReader ) ;
if ( ( symStreamType = = CvSymStreamType_Globals_Scan ) | | ( symStreamType = = CvSymStreamType_Globals_Targeted ) )
{
int streamSize = 0 ;
uint8 * data ;
if ( mCvGlobalSymbolData = = NULL )
mCvGlobalSymbolData = CvReadStream ( mCvGlobalSymbolInfoStream , & streamSize ) ;
data = mCvGlobalSymbolData ;
HandleSymStreamEntries ( symStreamType , data , NULL ) ;
}
else
{
int streamSize = 0 ;
uint8 * data ;
if ( mCvPublicSymbolData = = NULL )
mCvPublicSymbolData = CvReadStream ( mCvPublicSymbolInfoStream , & streamSize ) ; // psgsi
2022-07-30 09:08:49 -04:00
data = mCvPublicSymbolData ;
uint8 * sectionData = data ;
2019-09-21 10:49:35 -07:00
GET_INTO ( int32 , symHashSize ) ;
2022-07-30 09:08:49 -04:00
GET_INTO ( int32 , addrMapSize ) ;
2019-09-21 10:49:35 -07:00
GET_INTO ( int32 , thunkCount ) ;
GET_INTO ( int32 , thunkSize ) ;
2022-07-30 09:08:49 -04:00
GET_INTO ( int32 , thunkTableStream ) ;
2019-09-21 10:49:35 -07:00
GET_INTO ( int32 , thunkTableOfs ) ;
GET_INTO ( int32 , thunkSectCount ) ;
data = HandleSymStreamEntries ( symStreamType , data , data + symHashSize ) ;
//TODO: Hm, not quite right?
/*int addrMapEntryCount = addrMapSize / 4;
for ( int addrIdx = 0 ; addrIdx < addrMapEntryCount ; addrIdx + + )
{
2022-07-30 09:08:49 -04:00
GET_INTO ( int32 , addrVal ) ;
2019-09-21 10:49:35 -07:00
}
for ( int thunkIdx = 0 ; thunkIdx < thunkCount ; thunkIdx + + )
{
2022-07-30 09:08:49 -04:00
GET_INTO ( int32 , thunkVal ) ;
2019-09-21 10:49:35 -07:00
}
for ( int sectionIdx = 0 ; sectionIdx < thunkSectCount ; sectionIdx + + )
{
GET_INTO ( int32 , ofs ) ;
2022-07-30 09:08:49 -04:00
GET_INTO ( int32 , sectNum ) ;
2019-09-21 10:49:35 -07:00
} */
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
2022-01-18 10:34:51 -05:00
void COFF : : Fail ( const StringImpl & error )
2022-07-30 09:08:49 -04:00
{
2022-01-18 10:34:51 -05:00
DbgModule : : Fail ( StrFormat ( " %s in %s " , error . c_str ( ) , mPDBPath . c_str ( ) ) ) ;
}
2022-04-22 19:19:43 -07:00
void COFF : : SoftFail ( const StringImpl & error )
{
DbgModule : : SoftFail ( StrFormat ( " %s in %s " , error . c_str ( ) , mPDBPath . c_str ( ) ) ) ;
}
2022-01-18 10:34:51 -05:00
void COFF : : HardFail ( const StringImpl & error )
{
DbgModule : : HardFail ( StrFormat ( " %s in %s " , error . c_str ( ) , mPDBPath . c_str ( ) ) ) ;
}
2019-09-21 10:49:35 -07:00
void COFF : : ParseGlobalsData ( )
{
if ( ! mPDBLoaded )
return ;
if ( mParsedGlobalsData )
return ;
2020-12-06 05:53:32 -08:00
ParseTypeData ( ) ;
2022-07-30 09:08:49 -04:00
mParsedGlobalsData = true ;
2019-09-21 10:49:35 -07:00
//gDbgPerfManager->StartRecording();
int startTypeIdx = ( int ) mTypes . size ( ) ;
ParseSymbolStream ( CvSymStreamType_Globals_Scan ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
//gDbgPerfManager->StopRecording(true);
//int addedTypes = (int)mTypes.size() - startTypeIdx;
//OutputDebugStrF("Types Added: %d ProcSymCount: %d\n", addedTypes, mProcSymCount);
}
void COFF : : ParseSymbolData ( )
{
if ( ! mPDBLoaded )
return ;
if ( mParsedSymbolData )
return ;
2020-11-19 09:34:48 -08:00
ParseGlobalsData ( ) ;
2019-09-21 10:49:35 -07:00
mParsedSymbolData = true ;
ParseSymbolStream ( CvSymStreamType_Symbols ) ;
}
bool COFF : : ParseCv ( DataStream & pdbFS , uint8 * rootDirData , int pageSize , uint8 wantGuid [ 16 ] , int32 wantAge )
{
BP_ZONE ( " ParseCv " ) ;
mParsedGlobalsData = false ;
mParsedSymbolData = false ;
mParsedTypeData = false ;
mPopulatedStaticVariables = false ;
InitCvTypes ( ) ;
2022-07-30 09:08:49 -04:00
int startingTypeIdx = mTypes . size ( ) ;
2019-09-21 10:49:35 -07:00
uint8 * data = rootDirData ;
bool failed = false ;
int numStreams = GET ( int32 ) ;
2022-07-30 09:08:49 -04:00
if ( numStreams = = 0 )
2019-09-21 10:49:35 -07:00
return true ;
mCvStreamSizes . Resize ( numStreams ) ;
mCvStreamPtrStartIdxs . Resize ( numStreams ) ;
2022-07-30 09:08:49 -04:00
int streamPages = 0 ;
2019-09-21 10:49:35 -07:00
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 ] + pageSize - 1 ) / pageSize ;
}
mCvStreamPtrs . Resize ( streamPages ) ;
for ( int i = 0 ; i < ( int ) mCvStreamPtrs . size ( ) ; i + + )
2022-07-30 09:08:49 -04:00
mCvStreamPtrs [ i ] = GET ( int32 ) ;
2019-09-21 10:49:35 -07:00
//////////////////////////////////////////////////////////////////////////
if ( ! CvParseHeader ( wantGuid , wantAge ) )
return false ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( ! CvParseDBI ( wantAge ) )
return false ;
if ( mParseKind = = ParseKind_Header )
return true ;
2019-10-15 12:28:21 -07:00
///
2019-09-21 10:49:35 -07:00
{
BP_ZONE ( " COFF::ParseCv_ReadStrTable " ) ;
if ( mStringTable . mStream ! = - 1 )
{
mCvStrTableData = CvReadStream ( mStringTable . mStream ) ;
mStringTable . mStrTable = ( const char * ) mCvStrTableData + 12 ;
}
}
for ( int compileUnitId = 0 ; compileUnitId < ( int ) mCvModuleInfo . size ( ) ; compileUnitId + + )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
ScanCompileUnit ( compileUnitId ) ;
}
//////////////////////////////////////////////////////////////////////////
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
return true ;
}
void COFF : : ReportMemory ( MemReporter * memReporter )
{
DbgModule : : ReportMemory ( memReporter ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
memReporter - > AddVec ( " mCvTypeMap " , mCvTypeMap ) ;
memReporter - > AddVec ( " mCvTagStartMap " , mCvTagStartMap ) ;
memReporter - > AddVec ( " mCvIPITagStartMap " , mCvIPITagStartMap ) ;
memReporter - > AddVec ( mCvStreamSizes ) ;
memReporter - > AddVec ( mCvStreamPtrStartIdxs ) ;
memReporter - > AddVec ( mCvStreamPtrs ) ;
memReporter - > AddVec ( mCvModuleInfo ) ;
memReporter - > AddVec ( mCVSrcFileRefCache ) ;
if ( mCvHeaderData ! = NULL )
2022-07-30 09:08:49 -04:00
memReporter - > Add ( " mCvHeaderData " , mCvStreamSizes [ 1 ] ) ;
for ( auto & entry : mCvTypeSectionData )
2019-09-21 10:49:35 -07:00
{
if ( entry . mSize ! = - 1 )
memReporter - > Add ( " mCvTypeSectionData " , entry . mSize ) ;
else
memReporter - > Add ( " mCvTypeSectionData " , mCvStreamSizes [ 2 ] ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
if ( mCvStrTableData ! = NULL )
memReporter - > Add ( " mCvStrTableData " , mCvStreamSizes [ mStringTable . mStream ] ) ;
if ( mCvPublicSymbolData ! = NULL )
memReporter - > Add ( " mCvPublicSymbolData " , mCvStreamSizes [ mCvPublicSymbolInfoStream ] ) ;
if ( mCvGlobalSymbolData ! = NULL )
memReporter - > Add ( " mCvGlobalSymbolData " , mCvStreamSizes [ mCvGlobalSymbolInfoStream ] ) ;
//memReporter->AddVec(mCvNamespaceStaticEntries);
}
bool COFF : : TryLoadPDB ( const String & pdbPath , uint8 wantGuid [ 16 ] , int32 wantAge )
{
bool isVerifyOnly = mDebugger = = NULL ;
if ( ! mPDBPath . IsEmpty ( ) )
return false ; // Already have a PDB loaded
mCvMappedFile = CreateFileA ( pdbPath . c_str ( ) , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , NULL , NULL ) ;
if ( mCvMappedFile = = INVALID_HANDLE_VALUE )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
return false ;
}
BP_ZONE ( " COFF::TryLoadPDB " ) ;
if ( ! isVerifyOnly )
mDebugger - > OutputMessage ( StrFormat ( " Loading PDB %s \n " , pdbPath . c_str ( ) ) ) ;
DWORD highFileSize = 0 ;
int fileSize = ( int ) GetFileSize ( mCvMappedFile , & highFileSize ) ;
mCvMappedFileMapping = CreateFileMapping ( mCvMappedFile , NULL , PAGE_READONLY , 0 , fileSize , NULL ) ;
mCvMappedViewOfFile = MapViewOfFile ( mCvMappedFileMapping , FILE_MAP_READ , 0 , 0 , fileSize ) ;
mCvMappedFileSize = fileSize ;
//FileStream pdbFS;
//if (!pdbFS.Open(pdbPath, "rb"))
//return false;
mPDBPath = pdbPath ;
mCvDataStream = new SafeMemStream ( mCvMappedViewOfFile , fileSize , false ) ;
//Cv_HEADER
//pdbFS.Read
char sig [ 32 ] ;
mCvDataStream - > Read ( sig , 32 ) ;
if ( memcmp ( sig , MSF_SIGNATURE_700 , 32 ) ! = 0 )
{
if ( ! isVerifyOnly )
Fail ( " PDB signature error " ) ;
return false ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
BfLogDbg ( " Loading PDB %s \n " , pdbPath . c_str ( ) ) ;
BP_ZONE_F ( " LoadCv %s " , pdbPath . c_str ( ) ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int pageSize = mCvDataStream - > ReadInt32 ( ) ;
int fpmPageNum = mCvDataStream - > ReadInt32 ( ) ;
int totalPageCount = mCvDataStream - > ReadInt32 ( ) ;
int rootDirSize = mCvDataStream - > ReadInt32 ( ) ;
int unknown = mCvDataStream - > ReadInt32 ( ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int rootDirPtrs [ NUM_ROOT_DIRS ] ;
mCvDataStream - > ReadT ( rootDirPtrs ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
bool failed = false ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
mCvPageSize = pageSize ;
for ( int i = 0 ; i < 31 ; i + + )
{
if ( mCvPageSize < ( 1 < < i ) )
break ;
mCvPageBits = i ;
}
int rootPageCount = ( rootDirSize + pageSize - 1 ) / pageSize ;
int rootPointersPages = ( rootPageCount * sizeof ( int32 ) + pageSize - 1 ) / pageSize ;
int rootPageIdx = 0 ;
Array < uint8 > rootDirData ;
rootDirData . Resize ( rootPageCount * pageSize ) ;
for ( int rootDirIdx = 0 ; rootDirIdx < rootPointersPages ; rootDirIdx + + )
{
int rootDirPtr = rootDirPtrs [ rootDirIdx ] ;
if ( rootDirPtr = = 0 )
continue ;
mCvDataStream - > SetPos ( rootDirPtr * pageSize ) ;
int32 rootPages [ 1024 ] ;
mCvDataStream - > Read ( rootPages , pageSize ) ;
for ( int subRootPageIdx = 0 ; subRootPageIdx < pageSize / 4 ; subRootPageIdx + + , rootPageIdx + + )
{
if ( rootPageIdx > = rootPageCount )
break ;
int rootPagePtr = rootPages [ subRootPageIdx ] ;
if ( rootPagePtr = = 0 )
break ;
mCvDataStream - > SetPos ( rootPagePtr * pageSize ) ;
mCvDataStream - > Read ( & rootDirData [ rootPageIdx * pageSize ] , pageSize ) ;
}
}
2022-07-30 09:08:49 -04:00
int startingTypeIdx = mTypes . size ( ) ;
2019-09-21 10:49:35 -07:00
if ( ! ParseCv ( * mCvDataStream , & rootDirData [ 0 ] , pageSize , wantGuid , wantAge ) )
{
//mDebugger->OutputMessage("Failed to parse PDB\n");
2022-07-30 09:08:49 -04:00
return false ;
2019-09-21 10:49:35 -07:00
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( mCvDataStream - > mFailed )
return false ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
//OutputDebugStrF("COFF::TryLoadPDB %s\n", pdbPath.c_str());
if ( ! isVerifyOnly )
mDebugger - > ModuleChanged ( this ) ;
mPDBLoaded = true ;
return true ;
}
void COFF : : ClosePDB ( )
{
delete mCvDataStream ;
mCvDataStream = NULL ;
delete mCvHeaderData ;
2022-07-30 09:08:49 -04:00
mCvHeaderData = NULL ;
2019-09-21 10:49:35 -07:00
delete mCvStrTableData ;
mCvStrTableData = 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 ;
mCvGlobalSymbolData = NULL ;
delete mNewFPOData ;
mNewFPOData = NULL ;
if ( mCvMappedViewOfFile ! = NULL )
: : UnmapViewOfFile ( mCvMappedViewOfFile ) ;
mCvMappedViewOfFile = NULL ;
if ( mCvMappedFileMapping ! = INVALID_HANDLE_VALUE )
: : CloseHandle ( mCvMappedFileMapping ) ;
mCvMappedFileMapping = NULL ;
if ( mCvMappedFile ! = INVALID_HANDLE_VALUE )
: : CloseHandle ( mCvMappedFile ) ;
mCvMappedFile = NULL ;
for ( auto kv : mHotLibMap )
delete kv . mValue ;
2022-07-30 09:08:49 -04:00
mHotLibMap . Clear ( ) ;
2019-09-21 10:49:35 -07:00
mHotLibSymMap . Clear ( ) ;
2022-04-16 06:27:54 -07:00
delete mEmitSourceFile ;
mEmitSourceFile = NULL ;
2019-09-21 10:49:35 -07:00
}
bool COFF : : LoadPDB ( const String & pdbPath , uint8 wantGuid [ 16 ] , int32 wantAge )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( mDebugTarget - > mTargetBinary = = this )
{
// If we don't have to load the debug symbols from a remote source or the cache
// then we assume we were locally built, meaning we don't attempt to auto-load
// any symbols since we assume we already have what we built for all referenced
// dlls
mDebugTarget - > mWasLocallyBuilt = FileExists ( pdbPath ) ;
}
2019-09-27 13:05:39 -07:00
memcpy ( mWantPDBGuid , wantGuid , 16 ) ;
mWantAge = wantAge ;
2022-07-30 09:08:49 -04:00
mDbgSymRequest = mDebugger - > mDbgSymSrv . CreateRequest ( mFilePath , pdbPath , wantGuid , wantAge ) ;
2019-09-21 10:49:35 -07:00
mDbgSymRequest - > SearchLocal ( ) ;
if ( ! mDbgSymRequest - > mFinalPDBPath . IsEmpty ( ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
TryLoadPDB ( mDbgSymRequest - > mFinalPDBPath , wantGuid , wantAge ) ;
mDebugger - > mDbgSymSrv . ReleaseRequest ( mDbgSymRequest ) ;
mDbgSymRequest = NULL ;
}
else
mMayBeOld = true ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
String fileName = GetFileName ( mFilePath ) ;
2022-07-30 09:08:49 -04:00
mWantsAutoLoadDebugInfo = ! mDebugTarget - > mWasLocallyBuilt ;
2019-09-21 10:49:35 -07:00
if ( ( fileName . Equals ( " KERNEL32.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " KERNELBASE.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " USER32.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " SHELL32.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " GDI32.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " GDI32FULL.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " NTDLL.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " COMDLG32.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " MSVCRT.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " COMBASE.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " UCRTBASE.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " RPCRT4.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " BCRYPTPRIMITIVES.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " SHCORE.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " WIN32U.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) | |
( fileName . Equals ( " MSWSOCK.DLL " , String : : CompareKind_OrdinalIgnoreCase ) ) )
{
mWantsAutoLoadDebugInfo = false ;
}
/*if (pdbPath.IndexOf('\\') != -1) // Do we have an absolute path at all?
{
if ( TryLoadPDB ( pdbPath , wantGuid , wantAge ) )
return true ;
ClosePDB ( ) ;
} */
//char exePath[MAX_PATH];
//GetModuleFileNameA(NULL, exePath, sizeof(exePath));
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
/*String checkPath = ::GetFileDir(mFilePath);
checkPath + = " / " ;
checkPath + = GetFileName ( pdbPath ) ;
if ( ! FileNameEquals ( checkPath , pdbPath ) )
{
if ( TryLoadPDB ( checkPath , wantGuid , wantAge ) )
return true ;
} */
return false ;
}
bool COFF : : CheckSection ( const char * name , uint8 * sectionData , int sectionSize )
{
if ( strcmp ( name , " .debug$T " ) = = 0 )
{
mDbgFlavor = DbgFlavor_MS ;
DbgSectionData entry ;
entry . mData = sectionData ;
entry . mSize = sectionSize ;
2022-07-30 09:08:49 -04:00
mCvTypeSectionData . Add ( entry ) ;
2019-09-21 10:49:35 -07:00
return true ;
}
if ( strcmp ( name , " .debug$S " ) = = 0 )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
DbgSectionData entry ;
entry . mData = sectionData ;
entry . mSize = sectionSize ;
mCvCompileUnitData . Add ( entry ) ;
return true ;
}
return false ;
}
void COFF : : ProcessDebugInfo ( )
{
BP_ZONE ( " COFF::ProcessDebugInfo " ) ;
if ( ( ! mCvTypeSectionData . IsEmpty ( ) ) & & ( ! mCvCompileUnitData . IsEmpty ( ) ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
auto linkedModule = ( COFF * ) GetLinkedModule ( ) ;
int startingTypeIdx = ( int ) linkedModule - > mTypes . size ( ) ;
InitCvTypes ( ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
for ( auto entry : mCvTypeSectionData )
{
uint8 * data = entry . mData ;
GET_INTO ( uint32 , infoType ) ;
BF_ASSERT ( infoType = = CV_SIGNATURE_C13 ) ;
2022-07-30 09:08:49 -04:00
CvInitStreamRaw ( mCvTypeSectionReader , entry . mData + 4 , entry . mSize - 4 ) ;
2019-09-21 10:49:35 -07:00
ParseTypeData ( mCvTypeSectionReader , 0 ) ;
}
FixTypes ( startingTypeIdx ) ;
linkedModule - > MapTypes ( startingTypeIdx ) ;
CvCompileUnit * compileUnit = NULL ;
for ( auto entry : mCvCompileUnitData )
{
2022-07-30 09:08:49 -04:00
compileUnit = ParseCompileUnit ( NULL , compileUnit , entry . mData , entry . mSize ) ;
2019-09-21 10:49:35 -07:00
}
compileUnit - > mLanguage = DbgLanguage_Beef ;
mMasterCompileUnit - > mLanguage = DbgLanguage_Beef ;
MapCompileUnitMethods ( compileUnit ) ;
mEndTypeIdx = ( int ) linkedModule - > mTypes . size ( ) ;
}
}
void COFF : : FinishHotSwap ( )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
DbgModule : : FinishHotSwap ( ) ;
2022-07-30 09:08:49 -04:00
mTypeMap . Clear ( ) ;
2019-09-21 10:49:35 -07:00
}
2020-01-22 12:37:44 -08:00
intptr COFF : : EvaluateLocation ( DbgSubprogram * dwSubprogram , const uint8 * locData , int locDataLen , WdStackFrame * stackFrame , DbgAddrType * outAddrType , DbgEvalLocFlags flags )
2019-09-21 10:49:35 -07:00
{
if ( mDbgFlavor = = DbgFlavor_GNU )
2019-12-01 10:17:09 -08:00
return DbgModule : : EvaluateLocation ( dwSubprogram , locData , locDataLen , stackFrame , outAddrType , flags ) ;
2019-09-21 10:49:35 -07:00
2020-01-22 12:37:44 -08:00
if ( ( locDataLen = = 0 ) & & ( locData ! = NULL ) )
{
// locData is actually a string, the aliased name
* outAddrType = DbgAddrType_Alias ;
return ( intptr ) locData ;
}
2019-09-21 10:49:35 -07:00
addr_target pc = 0 ;
if ( stackFrame ! = NULL )
{
2022-07-30 09:08:49 -04:00
// Use 'GetSourcePC', which will offset the RSP when we're not at the top position of the call stack, since RSP will be the
2019-09-21 10:49:35 -07:00
// return address in those cases
pc = stackFrame - > GetSourcePC ( ) ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int inlineDepth = 0 ;
uint8 * data = ( uint8 * ) locData ;
for ( int locIdx = 0 ; locIdx < locDataLen ; locIdx + + )
{
uint8 * dataStart = data ;
GET_INTO ( uint16 , symLen ) ;
uint8 * dataEnd = data + symLen ;
GET_INTO ( uint16 , symType ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
CV_LVAR_ADDR_RANGE * rangeInfo = NULL ;
CV_LVAR_ADDR_GAP * gapsInfo = NULL ;
addr_target result = 0 ;
if ( inlineDepth > 0 )
{
if ( symType = = S_INLINESITE )
inlineDepth + + ;
else if ( symType = = S_INLINESITE_END )
inlineDepth - - ;
data = dataEnd ;
continue ;
}
bool handled = false ;
switch ( symType )
{
case S_GDATA32 :
case S_LDATA32 :
{
2022-07-30 09:08:49 -04:00
DATASYM32 & dataSym = * ( DATASYM32 * ) dataStart ;
2019-09-21 10:49:35 -07:00
* outAddrType = DbgAddrType_Target ;
return GetSectionAddr ( dataSym . seg , dataSym . off ) ;
}
break ;
case S_BPREL32 :
{
BPRELSYM32 * bpRel32 = ( BPRELSYM32 * ) dataStart ;
# if BF_DBG_32
* outAddrType = DbgAddrType_Target ;
return stackFrame - > mRegisters . mIntRegs . ebp + ( int ) bpRel32 - > off ;
# else
* outAddrType = DbgAddrType_Target ;
return stackFrame - > mRegisters . mIntRegs . rbp + ( int ) bpRel32 - > off ;
# endif
}
break ;
case S_LTHREAD32 :
case S_GTHREAD32 :
{
THREADSYM32 & threadSym = * ( THREADSYM32 * ) dataStart ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int tlsIndex = mDebugger - > ReadMemory < int > ( mTLSIndexAddr ) ;
addr_target tlsEntry = mDebugger - > GetTLSOffset ( tlsIndex ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
* outAddrType = DbgAddrType_Target ;
return threadSym . off + tlsEntry ;
}
break ;
case S_REGISTER :
{
REGSYM * regSym = ( REGSYM * ) dataStart ;
* outAddrType = DbgAddrType_Register ;
int regNum = CvConvRegNum ( regSym - > reg ) ;
return regNum ;
}
break ;
case S_REGREL32 :
{
REGREL32 * regRel32 = ( REGREL32 * ) dataStart ;
* outAddrType = DbgAddrType_Target ;
2022-07-30 09:08:49 -04:00
int regNum = CvConvRegNum ( regRel32 - > reg ) ;
2019-09-21 10:49:35 -07:00
return stackFrame - > mRegisters . mIntRegsArray [ regNum ] + regRel32 - > off ;
}
break ;
case S_DEFRANGE_REGISTER :
{
DEFRANGESYMREGISTER & defRangeReg = * ( DEFRANGESYMREGISTER * ) dataStart ;
* outAddrType = DbgAddrType_Register ;
result = CvConvRegNum ( defRangeReg . reg ) ;
rangeInfo = & defRangeReg . range ;
gapsInfo = & defRangeReg . gaps [ 0 ] ;
}
break ;
case S_DEFRANGE_FRAMEPOINTER_REL :
{
DEFRANGESYMFRAMEPOINTERREL & defRangeFPRel = * ( DEFRANGESYMFRAMEPOINTERREL * ) dataStart ;
2022-07-30 09:08:49 -04:00
2019-12-01 10:17:09 -08:00
DbgSubprogram : : LocalBaseRegKind baseReg = ( ( flags & DbgEvalLocFlag_IsParam ) ! = 0 ) ? dwSubprogram - > mParamBaseReg : dwSubprogram - > mLocalBaseReg ;
2019-09-21 10:49:35 -07:00
* outAddrType = DbgAddrType_Target ;
2022-07-30 09:08:49 -04:00
# ifdef BF_DBG_64
2019-12-01 10:17:09 -08:00
if ( baseReg = = DbgSubprogram : : LocalBaseRegKind_RSP )
2019-09-21 10:49:35 -07:00
result = stackFrame - > mRegisters . mIntRegsArray [ X64Reg_RSP ] + defRangeFPRel . offFramePointer ;
2019-12-01 10:17:09 -08:00
else if ( baseReg = = DbgSubprogram : : LocalBaseRegKind_R13 )
2019-09-21 10:49:35 -07:00
result = stackFrame - > mRegisters . mIntRegsArray [ X64Reg_R13 ] + defRangeFPRel . offFramePointer ;
else
result = stackFrame - > mRegisters . mIntRegsArray [ X64Reg_RBP ] + defRangeFPRel . offFramePointer ;
2022-07-30 09:08:49 -04:00
# else
2019-12-01 10:17:09 -08:00
if ( baseReg = = DbgSubprogram : : LocalBaseRegKind_VFRAME )
2022-07-30 09:08:49 -04:00
result = stackFrame - > mRegisters . mIntRegsArray [ X86Reg_ESP ] + dwSubprogram - > mFrameBaseLen + defRangeFPRel . offFramePointer ;
2019-12-01 10:17:09 -08:00
else if ( baseReg = = DbgSubprogram : : LocalBaseRegKind_EBX )
2019-09-21 10:49:35 -07:00
result = stackFrame - > mRegisters . mIntRegsArray [ X86Reg_EBX ] + defRangeFPRel . offFramePointer ;
else
result = stackFrame - > mRegisters . mIntRegsArray [ X86Reg_EBP ] + defRangeFPRel . offFramePointer ;
2022-07-30 09:08:49 -04:00
# endif
2019-09-21 10:49:35 -07:00
rangeInfo = & defRangeFPRel . range ;
gapsInfo = & defRangeFPRel . gaps [ 0 ] ;
}
break ;
case S_DEFRANGE_SUBFIELD_REGISTER :
{
2022-07-30 09:08:49 -04:00
DEFRANGESYMSUBFIELDREGISTER & defRangeSubfieldReg = * ( DEFRANGESYMSUBFIELDREGISTER * ) dataStart ;
2019-09-21 10:49:35 -07:00
* outAddrType = DbgAddrType_Target ;
2022-07-30 09:08:49 -04:00
int regNum = CvConvRegNum ( defRangeSubfieldReg . reg ) ;
2019-09-21 10:49:35 -07:00
result = stackFrame - > mRegisters . mIntRegsArray [ regNum ] + defRangeSubfieldReg . offParent ;
rangeInfo = & defRangeSubfieldReg . range ;
gapsInfo = & defRangeSubfieldReg . gaps [ 0 ] ;
}
break ;
case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE :
{
DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE & defFPRel = * ( DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE * ) dataStart ;
# ifdef BF_DBG_64
int regNum = X64Reg_RSP ;
# else
int regNum = X86Reg_ESP ;
2022-07-30 09:08:49 -04:00
# endif
2019-09-21 10:49:35 -07:00
* outAddrType = DbgAddrType_Target ;
result = stackFrame - > mRegisters . mIntRegsArray [ regNum ] + defFPRel . offFramePointer ;
return result ;
}
break ;
case S_DEFRANGE_REGISTER_REL :
{
DEFRANGESYMREGISTERREL & defRangeRegRel = * ( DEFRANGESYMREGISTERREL * ) dataStart ;
* outAddrType = DbgAddrType_Target ;
int regNum = CvConvRegNum ( defRangeRegRel . baseReg ) ;
result = stackFrame - > mRegisters . mIntRegsArray [ regNum ] + defRangeRegRel . offBasePointer ;
rangeInfo = & defRangeRegRel . range ;
gapsInfo = & defRangeRegRel . gaps [ 0 ] ;
}
break ;
case S_PROCREF :
{
// Not currently handled.
}
break ;
case S_INLINESITE :
{
inlineDepth + + ;
}
2022-07-30 09:08:49 -04:00
break ;
2022-01-04 10:59:27 -05:00
case S_FILESTATIC :
{
FILESTATICSYM & fileStaticSym = * ( FILESTATICSYM * ) dataStart ;
}
break ;
2019-09-21 10:49:35 -07:00
default :
2022-01-04 10:29:30 -05:00
if ( ! mFailed )
2022-04-22 19:19:43 -07:00
SoftFail ( StrFormat ( " Unknown symbol type '0x%X' in EvaluateLocation " , symType ) ) ;
2022-01-04 10:29:30 -05:00
return 0 ;
2019-09-21 10:49:35 -07:00
}
if ( rangeInfo ! = NULL )
2022-07-30 09:08:49 -04:00
{
auto rangeStart = GetSectionAddr ( rangeInfo - > isectStart , rangeInfo - > offStart ) ;
2019-09-21 10:49:35 -07:00
if ( ( pc > = rangeStart ) & & ( pc < rangeStart + rangeInfo - > cbRange ) )
{
bool inRange = true ;
while ( ( uint8 * ) gapsInfo < ( uint8 * ) dataEnd )
{
if ( ( pc > = rangeStart + gapsInfo - > gapStartOffset ) & & ( pc < rangeStart + gapsInfo - > gapStartOffset + gapsInfo - > cbRange ) )
{
inRange = false ;
2022-07-30 09:08:49 -04:00
break ;
2019-09-21 10:49:35 -07:00
}
gapsInfo + + ;
}
if ( inRange )
return result ;
}
}
data = dataEnd ;
}
if ( ( dwSubprogram ! = NULL ) & & ( dwSubprogram - > mIsOptimized ) )
* outAddrType = DbgAddrType_OptimizedOut ;
else
* outAddrType = DbgAddrType_NoValue ;
return 0 ;
}
bool COFF : : CanGetOldSource ( )
{
return mCvSrcSrvStream ! = - 1 ;
}
String COFF : : GetOldSourceCommand ( const StringImpl & path )
{
if ( mCvSrcSrvStream = = - 1 )
return " " ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
int outSize ;
uint8 * data = CvReadStream ( mCvSrcSrvStream , & outSize ) ;
String cmdBlock = String ( ( char * ) data , outSize ) ;
delete data ;
bool inFileSection = false ;
Dictionary < String , String > defs ;
enum _SectType
{
_SectType_None ,
_SectType_Ini ,
_SectType_Variables ,
_SectType_SourceFiles
} ;
_SectType sectType = _SectType_None ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
//
{
AutoCrit autoCrit ( gDebugManager - > mCritSect ) ;
defs [ " TARG " ] = gDebugManager - > mSymSrvOptions . mSourceServerCacheDir ;
}
std : : function < void ( String & ) > _Expand = [ & ] ( String & str )
{
for ( int i = 0 ; i < str . length ( ) ; i + + )
{
if ( str [ i ] = = ' % ' )
{
int endIdx = str . IndexOf ( ' % ' , i + 1 ) ;
if ( endIdx ! = - 1 )
{
2022-07-30 09:08:49 -04:00
String varName = ToUpper ( str . Substring ( i + 1 , endIdx - i - 1 ) ) ;
2019-09-21 10:49:35 -07:00
if ( ( ( endIdx < str . length ( ) - 1 ) & & ( str [ endIdx + 1 ] = = ' ( ' ) ) & &
( ( varName = = " FNVAR " ) | | ( varName = = " FNBKSL " ) | | ( varName = = " FNFILE " ) ) )
{
int closePos = str . IndexOf ( ' ) ' , endIdx + 2 ) ;
if ( closePos ! = - 1 )
{
String paramStr = str . Substring ( endIdx + 2 , closePos - endIdx - 2 ) ;
_Expand ( paramStr ) ;
if ( varName = = " FNVAR " )
{
paramStr = defs [ paramStr ] ;
}
else
{
if ( varName = = " FNBKSL " )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
paramStr . Replace ( " / " , " \\ " ) ;
}
else if ( varName = = " FNFILE " )
{
paramStr = GetFileName ( paramStr ) ;
}
}
str . Remove ( i , closePos - i + 1 ) ;
str . Insert ( i , paramStr ) ;
i - - ;
}
}
else
{
auto replaceStr = defs [ varName ] ;
if ( ! replaceStr . IsEmpty ( ) )
{
str . Remove ( i , endIdx - i + 1 ) ;
str . Insert ( i , replaceStr ) ;
i - - ;
}
}
}
}
}
} ;
int linePos = 0 ;
while ( true )
{
int crPos = cmdBlock . IndexOf ( ' \n ' , linePos ) ;
if ( crPos = = - 1 )
break ;
int lineEndPos = crPos ;
if ( cmdBlock [ lineEndPos - 1 ] = = ' \r ' )
lineEndPos - - ;
String line = cmdBlock . Substring ( linePos , lineEndPos - linePos ) ;
if ( line . StartsWith ( " SRCSRV: ini - " ) )
{
sectType = _SectType_Ini ;
}
else if ( line . StartsWith ( " SRCSRV: variables - " ) )
{
sectType = _SectType_Variables ;
}
else if ( line . StartsWith ( " SRCSRV: source files - " ) )
{
sectType = _SectType_SourceFiles ;
}
else if ( line . StartsWith ( " SRCSRV: end - " ) )
{
break ;
}
else
{
switch ( sectType )
{
case _SectType_Ini :
case _SectType_Variables :
{
int eqPos = line . IndexOf ( ' = ' ) ;
if ( eqPos ! = - 1 )
{
defs [ ToUpper ( line . Substring ( 0 , eqPos ) ) ] = line . Substring ( eqPos + 1 ) ;
}
break ;
}
case _SectType_SourceFiles :
{
int curStrIdx = 0 ;
int curStrPos = 0 ;
StringT < 256 > var ;
bool matches = false ;
while ( curStrPos < ( int ) line . length ( ) )
{
int starPos = line . IndexOf ( ' * ' , curStrPos ) ;
if ( starPos = = - 1 )
starPos = line . length ( ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
//var = line.Substring(curStrPos, starPos - curStrPos);
var . Clear ( ) ;
var . Insert ( 0 , line . c_str ( ) + curStrPos , starPos - curStrPos ) ;
if ( curStrIdx = = 0 )
{
matches = FileNameEquals ( var , path ) ;
if ( ! matches )
break ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
defs [ StrFormat ( " VAR%d " , curStrIdx + 1 ) ] = var ;
curStrIdx + + ;
curStrPos = starPos + 1 ;
}
if ( ! matches )
break ;
String target = defs [ " SRCSRVTRG " ] ;
String cmd = defs [ " SRCSRVCMD " ] ;
String env = defs [ " SRCSRVENV " ] ;
_Expand ( target ) ;
_Expand ( cmd ) ;
_Expand ( env ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
String retVal ;
if ( ( cmd . IsEmpty ( ) ) & & ( target . StartsWith ( " HTTP " , StringImpl : : CompareKind_OrdinalIgnoreCase ) ) )
{
String localFile ;
BfpFileResult result ;
BFP_GETSTR_HELPER ( localFile , result , BfpFile_GetTempPath ( __STR , __STRLEN , & result ) ) ;
int dotPos = target . IndexOf ( " :// " ) ;
if ( dotPos ! = - 1 )
{
localFile . Append ( " SymbolCache \\ src \\ " ) ;
localFile . Append ( StringView ( target , dotPos + 3 ) ) ;
localFile . Replace ( " / " , " \\ " ) ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
retVal = localFile ;
retVal + = " \n " ;
retVal + = target ;
retVal + = " \n " ;
retVal + = env ;
}
else if ( ! cmd . IsWhitespace ( ) )
{
retVal = target ;
retVal + = " \n " ;
retVal + = cmd ;
retVal + = " \n " ;
retVal + = env ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
return retVal ;
}
break ;
2022-07-30 09:08:49 -04:00
}
2019-09-21 10:49:35 -07:00
}
linePos = crPos + 1 ;
}
return " " ;
}
2022-04-16 06:27:54 -07:00
bool COFF : : GetEmitSource ( const StringImpl & filePath , String & outText )
{
if ( ! filePath . StartsWith ( " $Emit " ) )
return false ;
2022-07-30 09:08:49 -04:00
2022-04-16 06:27:54 -07:00
if ( mEmitSourceFile = = NULL )
{
mEmitSourceFile = new ZipFile ( ) ;
String zipPath = mPDBPath ;
int dotPos = zipPath . LastIndexOf ( ' . ' ) ;
zipPath . RemoveToEnd ( dotPos ) ;
zipPath . Append ( " __emit.zip " ) ;
if ( ! mEmitSourceFile - > Open ( zipPath ) )
{
if ( mCvEmitStream = = - 1 )
return " " ;
2022-07-30 09:08:49 -04:00
2022-04-16 06:27:54 -07:00
int outSize ;
uint8 * data = CvReadStream ( mCvEmitStream , & outSize ) ;
2022-07-30 09:08:49 -04:00
2022-04-16 06:27:54 -07:00
FileStream fileStream ;
fileStream . Open ( zipPath , " wb " ) ;
fileStream . Write ( data , outSize ) ;
fileStream . Close ( ) ;
delete data ;
mEmitSourceFile - > Open ( zipPath ) ;
}
}
if ( mEmitSourceFile - > IsOpen ( ) )
{
String usePath = filePath ;
if ( usePath . StartsWith ( " $Emit " ) )
{
int dollarPos = usePath . IndexOf ( ' $ ' , 1 ) ;
usePath . Remove ( 0 , dollarPos + 1 ) ;
2022-07-30 09:08:49 -04:00
}
2022-04-16 06:27:54 -07:00
usePath = EncodeFileName ( usePath ) ;
usePath . Append ( " .bf " ) ;
Array < uint8 > data ;
if ( mEmitSourceFile - > Get ( usePath , data ) )
{
outText . Insert ( outText . mLength , ( char * ) data . mVals , data . mSize ) ;
return true ;
}
}
return false ;
}
2019-09-21 10:49:35 -07:00
bool COFF : : HasPendingDebugInfo ( )
{
if ( mDbgSymRequest = = NULL )
return false ;
return true ;
}
void COFF : : PreCacheImage ( )
{
if ( ! mDebugger - > IsMiniDumpDebugger ( ) )
return ;
if ( mLoadState ! = DbgModuleLoadState_NotLoaded )
return ;
auto miniDumpDebugger = ( MiniDumpDebugger * ) mDebugger ;
if ( mOrigImageData ! = NULL )
return ;
mDebugger - > mDbgSymSrv . PreCacheImage ( mFilePath , mTimeStamp , mImageSize ) ;
}
void COFF : : PreCacheDebugInfo ( )
{
if ( mDbgSymRequest = = NULL )
return ;
if ( mDbgSymRequest - > mInProcess )
return ;
bool hasDebugInfo = false ;
mDbgSymRequest - > SearchCache ( ) ;
if ( mDbgSymRequest - > mFinalPDBPath . IsEmpty ( ) )
{
if ( GetCurrentThreadId ( ) = = mDebugger - > mDebuggerThreadId )
{
mDbgSymRequest - > mIsPreCache = true ;
mDbgSymRequest - > SearchSymSrv ( ) ;
mDbgSymRequest - > mIsPreCache = false ;
mDbgSymRequest - > mFailed = false ;
}
}
}
2019-09-27 13:05:39 -07:00
bool COFF : : LoadModuleImage ( const StringImpl & imagePath )
{
if ( ! mDebugger - > IsMiniDumpDebugger ( ) )
return false ;
auto miniDumpDebugger = ( MiniDumpDebugger * ) mDebugger ;
if ( ! imagePath . IsEmpty ( ) )
{
MappedFile * mappedFile = miniDumpDebugger - > MapModule ( this , imagePath ) ;
mMappedImageFile = mappedFile ;
if ( mappedFile ! = NULL )
{
MemStream memStream ( mappedFile - > mData , mappedFile - > mFileSize , false ) ;
2019-11-07 13:35:56 -08:00
ReadCOFF ( & memStream , DbgModuleKind_Module ) ;
2019-09-27 13:05:39 -07:00
mOrigImageData = new DbgModuleMemoryCache ( mImageBase , mImageSize ) ;
}
}
if ( mOrigImageData = = NULL ) // Failed?
{
mLoadState = DbgModuleLoadState_Failed ;
return false ;
}
return true ;
}
2019-09-21 10:49:35 -07:00
bool COFF : : RequestImage ( )
{
if ( ! mDebugger - > IsMiniDumpDebugger ( ) )
return false ;
if ( mLoadState ! = DbgModuleLoadState_NotLoaded )
return false ;
auto miniDumpDebugger = ( MiniDumpDebugger * ) mDebugger ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
if ( mOrigImageData ! = NULL )
return false ;
if ( GetCurrentThreadId ( ) = = mDebugger - > mDebuggerThreadId )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
auto prevRunState = mDebugger - > mRunState ;
mDebugger - > mRunState = RunState_SearchingSymSrv ;
mDebugger - > mDebugManager - > mOutMessages . push_back ( StrFormat ( " symsrv Searching for image '%s' " , mFilePath . c_str ( ) ) ) ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
auto dbgSymRequest = mDebugger - > mDbgSymSrv . CreateRequest ( ) ;
mDebugger - > mActiveSymSrvRequest = dbgSymRequest ;
BF_ASSERT ( mDebugger - > mDebugManager - > mCritSect . mLockCount = = 1 ) ;
2022-07-30 09:08:49 -04:00
mDebugger - > mDebugManager - > mCritSect . Unlock ( ) ;
2019-09-21 10:49:35 -07:00
// We unlock to allow the IDE to continue updating while we search
String imagePath = dbgSymRequest - > SearchForImage ( mFilePath , mTimeStamp , mImageSize ) ;
mDebugger - > mDebugManager - > mCritSect . Lock ( ) ;
delete mDebugger - > mActiveSymSrvRequest ;
mDebugger - > mActiveSymSrvRequest = NULL ;
mDebugger - > mRunState = prevRunState ;
2022-07-30 09:08:49 -04:00
return LoadModuleImage ( imagePath ) ;
2019-09-21 10:49:35 -07:00
}
else
{
return false ;
}
return false ;
}
bool COFF : : RequestDebugInfo ( bool allowRemote )
{
if ( mDbgSymRequest = = NULL )
return false ;
if ( mDbgSymRequest - > mInProcess )
return false ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
bool hasDebugInfo = false ;
mDbgSymRequest - > SearchCache ( ) ;
if ( mDbgSymRequest - > mFinalPDBPath . IsEmpty ( ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
if ( ! allowRemote )
return false ;
if ( GetCurrentThreadId ( ) = = mDebugger - > mDebuggerThreadId )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
auto prevRunState = mDebugger - > mRunState ;
mDebugger - > mRunState = RunState_SearchingSymSrv ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
mDbgSymRequest - > mInProcess = true ;
mDebugger - > mActiveSymSrvRequest = mDbgSymRequest ;
BF_ASSERT ( mDebugger - > mDebugManager - > mCritSect . mLockCount = = 1 ) ;
2022-07-30 09:08:49 -04:00
mDebugger - > mDebugManager - > mCritSect . Unlock ( ) ;
2019-09-21 10:49:35 -07:00
mDbgSymRequest - > SearchSymSrv ( ) ;
mDebugger - > mDebugManager - > mCritSect . Lock ( ) ;
mDebugger - > mActiveSymSrvRequest = NULL ;
mDbgSymRequest - > mInProcess = false ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
mDebugger - > mRunState = prevRunState ;
}
else
{
return false ;
}
}
if ( ! mDbgSymRequest - > mFinalPDBPath . IsEmpty ( ) )
hasDebugInfo = TryLoadPDB ( mDbgSymRequest - > mFinalPDBPath , mDbgSymRequest - > mWantGuid , mDbgSymRequest - > mWantAge ) ;
mDebugger - > mDbgSymSrv . ReleaseRequest ( mDbgSymRequest ) ;
mDbgSymRequest = NULL ;
return hasDebugInfo ;
}
bool COFF : : WantsAutoLoadDebugInfo ( )
{
return mWantsAutoLoadDebugInfo ;
}
bool COFF : : DbgIsStrMutable ( const char * str )
{
2019-11-07 13:35:56 -08:00
if ( IsObjectFile ( ) )
2019-09-21 10:49:35 -07:00
{
return GetLinkedModule ( ) - > DbgIsStrMutable ( str ) ;
}
if ( mCvMappedViewOfFile = = NULL )
return true ;
if ( ( str > = ( const char * ) mCvMappedViewOfFile ) & & ( str < ( const char * ) mCvMappedViewOfFile + mCvMappedFileSize ) )
return false ;
return true ;
}
// We don't need this for Beef linkining because of "FORCELINK_", but we DO need it for
// libraries we linked to, either in the DLL or in the LIB
addr_target COFF : : LocateSymbol ( const StringImpl & name )
{
BP_ZONE ( " COFF::LocateSymbol " ) ;
BfLogDbg ( " COFF:LocateSymbol '%s' \n " , name . c_str ( ) ) ;
if ( mHotLibMap . IsEmpty ( ) )
{
for ( auto moduleInfo : mCvModuleInfo )
{
if ( moduleInfo - > mObjectName = = NULL )
continue ;
String libName = moduleInfo - > mObjectName ;
if ( ! libName . EndsWith ( " .lib " , StringImpl : : CompareKind_OrdinalIgnoreCase ) )
continue ;
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
CvLibInfo * * libInfoPtr ;
if ( ! mHotLibMap . TryAdd ( libName , NULL , & libInfoPtr ) )
continue ;
CvLibInfo * libInfo = new CvLibInfo ( ) ;
* libInfoPtr = libInfo ;
2022-07-30 09:08:49 -04:00
if ( ! libInfo - > mLibFile . Init ( libName , false ) )
2019-09-21 10:49:35 -07:00
continue ;
for ( auto kv : libInfo - > mLibFile . mOldEntries )
{
auto libEntry = kv . mValue ;
while ( libEntry ! = NULL )
{
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 ;
}
}
}
}
BeLibEntry * libEntry ;
if ( ! mHotLibSymMap . TryGetValue ( name , & libEntry ) )
return 0 ;
if ( libEntry - > mLength = = - 1 )
{
BfLogDbg ( " Already loaded obj '%s' in '%s' \n " , libEntry - > mName . c_str ( ) , libEntry - > mLibFile - > mFilePath . c_str ( ) ) ;
// We already tried to load this
return 0 ;
}
2022-07-30 09:08:49 -04:00
2019-09-21 10:49:35 -07:00
auto fileExt = GetFileExtension ( libEntry - > mName ) ;
if ( String : : Equals ( fileExt , " .dll " , StringImpl : : CompareKind_OrdinalIgnoreCase ) )
{
for ( auto dbgModule : mDebugTarget - > mDbgModules )
{
if ( String : : Equals ( libEntry - > mName , dbgModule - > mDisplayName ) )
2022-07-30 09:08:49 -04:00
{
2019-09-21 10:49:35 -07:00
dbgModule - > ParseSymbolData ( ) ;
auto entry = dbgModule - > mSymbolNameMap . Find ( name . c_str ( ) ) ;
if ( entry = = NULL )
continue ;
addr_target callTarget ;
# ifdef BF_DBG_32
callTarget = entry - > mValue - > mAddress ;
# else
BfLogDbg ( " Setting up DLL thunk for '%s' in '%s' \n " , name . c_str ( ) , dbgModule - > mFilePath . c_str ( ) ) ;
int wantHotSize = 16 ;
if ( mHotThunkDataLeft < wantHotSize )
{
int allocSize = 4096 ;
mDebugger - > ReserveHotTargetMemory ( allocSize ) ;
int outAllocSize = 0 ;
mHotThunkCurAddr = mDebugger - > AllocHotTargetMemory ( allocSize , true , false , & outAllocSize ) ;
mHotThunkDataLeft = outAllocSize ;
}
int outAllocSize = 0 ;
addr_target hotAddr = mHotThunkCurAddr ;
mHotThunkCurAddr + = wantHotSize ;
mHotThunkDataLeft - = wantHotSize ;
# pragma pack(push, 1)
struct HotLongJmpOp
{
uint8 mOpCode0 ;
uint8 mOpCode1 ;
2022-07-30 09:08:49 -04:00
int32 mRIPRel ;
2019-09-21 10:49:35 -07:00
uint64 mTarget ;
} ;
# pragma pack(pop)
HotLongJmpOp jumpOp ;
jumpOp . mOpCode0 = 0xFF ;
jumpOp . mOpCode1 = 0x25 ;
jumpOp . mRIPRel = 0 ;
jumpOp . mTarget = entry - > mValue - > mAddress ;
mDebugger - > WriteMemory ( hotAddr , jumpOp ) ;
callTarget = hotAddr ;
# endif
char * dupStr = ( char * ) mAlloc . AllocBytes ( name . length ( ) + 1 ) ;
memcpy ( dupStr , name . c_str ( ) , name . length ( ) ) ;
DbgSymbol * dwSymbol = mAlloc . Alloc < DbgSymbol > ( ) ;
dwSymbol - > mDbgModule = this ;
dwSymbol - > mName = dupStr ;
dwSymbol - > mAddress = callTarget ;
mSymbolNameMap . Insert ( dwSymbol ) ;
return callTarget ;
}
}
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");
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// uint8* data = new uint8[libEntry->mLength];
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// 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 ;
2019-11-07 13:35:56 -08:00
bool success = dbgModule - > ReadCOFF ( & fileStream , DbgModuleKind_FromLocateSymbol ) ;
2019-09-21 10:49:35 -07:00
fileStream . mFP = NULL ;
// Mark as loaded
libEntry - > mLength = - 1 ;
if ( ! success )
{
BfLogDbg ( " Failed \n " ) ;
Fail ( StrFormat ( " Debugger failed to read binary '%s' in '%s' " , libEntry - > mName . c_str ( ) , libEntry - > mLibFile - > mFilePath . c_str ( ) ) ) ;
delete dbgModule ;
return 0 ;
2022-07-30 09:08:49 -04:00
}
2022-04-16 06:27:54 -07:00
mDebugger - > mDebugTarget - > AddDbgModule ( dbgModule ) ;
2019-09-21 10:49:35 -07:00
auto symbolEntry = mSymbolNameMap . Find ( name . c_str ( ) ) ;
if ( symbolEntry ! = NULL )
return symbolEntry - > mValue - > mAddress ;
return 0 ;
}
void COFF : : ParseFrameDescriptors ( uint8 * data , int size , addr_target baseAddr )
{
uint8 * ptr = data ;
uint8 * endPtr = data + size ;
Dictionary < int , COFFFrameProgram > programMap ;
Array < COFFFrameProgram : : Command > cmds ;
while ( ptr < endPtr )
{
COFFFrameDescriptor * frame = ( COFFFrameDescriptor * ) ptr ;
ptr + = sizeof ( COFFFrameDescriptor ) ;
COFFFrameDescriptorEntry entry ;
entry . mFrameDescriptor = frame ;
bool failed = false ;
COFFFrameProgram * programPtr = NULL ;
if ( programMap . TryAdd ( frame - > mFrameFunc , NULL , & programPtr ) )
{
COFFFrameProgram program ;
cmds . Clear ( ) ;
String curCmd ;
const char * ptr = mStringTable . mStrTable + frame - > mFrameFunc ;
while ( true )
{
char c = * ( ptr + + ) ;
if ( ( c = = ' ' ) | | ( c = = 0 ) )
{
if ( curCmd = = " $eip " )
cmds . Add ( COFFFrameProgram : : Command_EIP ) ;
else if ( ( curCmd = = " $esp " ) | | ( curCmd = = " $21 " ) )
cmds . Add ( COFFFrameProgram : : Command_ESP ) ;
else if ( ( curCmd = = " $ebp " ) | | ( curCmd = = " $22 " ) )
cmds . Add ( COFFFrameProgram : : Command_EBP ) ;
else if ( ( curCmd = = " $eax " ) | | ( curCmd = = " $17 " ) )
cmds . Add ( COFFFrameProgram : : Command_EAX ) ;
else if ( ( curCmd = = " $ebx " ) | | ( curCmd = = " $20 " ) )
cmds . Add ( COFFFrameProgram : : Command_EBX ) ;
else if ( ( curCmd = = " $ecx " ) | | ( curCmd = = " $18 " ) )
cmds . Add ( COFFFrameProgram : : Command_ECX ) ;
else if ( ( curCmd = = " $edx " ) | | ( curCmd = = " $19 " ) )
cmds . Add ( COFFFrameProgram : : Command_EDX ) ;
else if ( ( curCmd = = " $esi " ) | | ( curCmd = = " $23 " ) )
cmds . Add ( COFFFrameProgram : : Command_ESI ) ;
else if ( ( curCmd = = " $edi " ) | | ( curCmd = = " $24 " ) )
cmds . Add ( COFFFrameProgram : : Command_EDI ) ;
else if ( curCmd = = " $T0 " )
cmds . Add ( COFFFrameProgram : : Command_T0 ) ;
else if ( curCmd = = " $T1 " )
cmds . Add ( COFFFrameProgram : : Command_T1 ) ;
else if ( curCmd = = " $T2 " )
cmds . Add ( COFFFrameProgram : : Command_T2 ) ;
else if ( curCmd = = " $T3 " )
cmds . Add ( COFFFrameProgram : : Command_T3 ) ;
else if ( ( curCmd = = " .raSearch " ) | | ( curCmd = = " .raSearchStart " ) )
cmds . Add ( COFFFrameProgram : : Command_RASearch ) ;
else if ( curCmd = = " + " )
cmds . Add ( COFFFrameProgram : : Command_Add ) ;
else if ( curCmd = = " - " )
cmds . Add ( COFFFrameProgram : : Command_Subtract ) ;
else if ( curCmd = = " @ " )
cmds . Add ( COFFFrameProgram : : Command_Align ) ;
else if ( curCmd = = " = " )
cmds . Add ( COFFFrameProgram : : Command_Set ) ;
else if ( curCmd = = " ^ " )
cmds . Add ( COFFFrameProgram : : Command_Deref ) ;
else if ( ! curCmd . IsEmpty ( ) )
{
if ( ( curCmd [ 0 ] > = ' 0 ' ) & & ( curCmd [ 0 ] < = ' 9 ' ) )
{
int val = atoi ( curCmd . c_str ( ) ) ;
if ( ( val > = 0 ) & & ( val < = 255 ) )
{
cmds . Add ( COFFFrameProgram : : Command_Value8 ) ;
cmds . Add ( ( COFFFrameProgram : : Command ) val ) ;
}
else
{
cmds . Add ( COFFFrameProgram : : Command_Value ) ;
cmds . Insert ( cmds . size ( ) , ( COFFFrameProgram : : Command * ) & val , 4 ) ;
}
}
else
{
failed = true ;
2022-04-22 19:19:43 -07:00
SoftFail ( StrFormat ( " Invalid COFF frame program: %s " , curCmd . c_str ( ) ) ) ;
2019-09-21 10:49:35 -07:00
}
}
if ( c = = 0 )
break ;
curCmd . Clear ( ) ;
}
else
curCmd . Append ( c ) ;
}
if ( failed )
cmds . Clear ( ) ;
cmds . Add ( COFFFrameProgram : : Command_None ) ;
program . mCommands = ( COFFFrameProgram : : Command * ) mAlloc . AllocBytes ( cmds . size ( ) ) ;
memcpy ( program . mCommands , & cmds [ 0 ] , cmds . size ( ) ) ;
* programPtr = program ;
}
entry . mProgram = * programPtr ;
mDebugTarget - > mCOFFFrameDescriptorMap . insert ( std : : make_pair ( baseAddr + frame - > mRvaStart , entry ) ) ;
}
mParsedFrameDescriptors = true ;
}
void COFF : : ParseFrameDescriptors ( )
{
if ( mParsedFrameDescriptors )
return ;
if ( mCvNewFPOStream = = 0 )
return ;
int streamSize = 0 ;
mNewFPOData = CvReadStream ( mCvNewFPOStream , & streamSize ) ;
ParseFrameDescriptors ( mNewFPOData , streamSize , mImageBase ) ;
}
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;
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// coff.mCvCompileUnitData = (uint8*)cuData;
// coff.mCvCompileUnitDataSize = cuDataSize;
2022-07-30 09:08:49 -04:00
//
2019-09-21 10:49:35 -07:00
// coff.ProcessDebugInfo();
// }
// delete debugTarget;
// }
2020-11-17 07:52:51 -08:00
void TestPDB ( const StringImpl & fileName , WinDebugger * debugger )
2019-09-21 10:49:35 -07:00
{
DebugTarget * debugTarget = new DebugTarget ( NULL ) ;
2022-07-30 09:08:49 -04:00
COFF coff ( debugTarget ) ;
2020-11-17 07:52:51 -08:00
coff . mDebugger = debugger ;
2019-09-21 10:49:35 -07:00
uint8 wantGuid [ 16 ] ;
2022-03-15 16:33:30 -07:00
coff . TryLoadPDB ( fileName , wantGuid , - 1 ) ;
2020-11-17 07:52:51 -08:00
coff . ParseTypeData ( ) ;
2019-09-21 10:49:35 -07:00
coff . CvParseIPI ( ) ;
coff . ParseGlobalsData ( ) ;
coff . ParseSymbolData ( ) ;
for ( int compileUnitId = 0 ; compileUnitId < ( int ) coff . mCvModuleInfo . size ( ) ; compileUnitId + + )
coff . ParseCompileUnit ( compileUnitId ) ;
}
2022-07-30 09:11:38 -04:00
NS_BF_DBG_END