Skip to content

Commit

Permalink
Refactor symbol handling and introduce DbgSymbolEnumRange
Browse files Browse the repository at this point in the history
This allows enumerating multiple symbols at the same address efficiently
  • Loading branch information
mrexodia committed Jun 10, 2023
1 parent 165b0d3 commit 97ff1ec
Show file tree
Hide file tree
Showing 15 changed files with 390 additions and 342 deletions.
24 changes: 18 additions & 6 deletions src/bridge/bridgemain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ BRIDGE_IMPEXP void* BridgeAlloc(size_t size)

BRIDGE_IMPEXP void BridgeFree(void* ptr)
{
if(ptr)
if(ptr != nullptr)
GlobalFree(ptr);
}

Expand Down Expand Up @@ -838,23 +838,35 @@ BRIDGE_IMPEXP bool DbgScriptGetBranchInfo(int line, SCRIPTBRANCH* info)
}

// FIXME all
BRIDGE_IMPEXP void DbgSymbolEnum(duint base, CBSYMBOLENUM cbSymbolEnum, void* user)
BRIDGE_IMPEXP bool DbgSymbolEnum(duint base, CBSYMBOLENUM cbSymbolEnum, void* user)
{
SYMBOLCBINFO cbInfo;
cbInfo.base = base;
cbInfo.cbSymbolEnum = cbSymbolEnum;
cbInfo.user = user;
_dbg_sendmessage(DBG_SYMBOL_ENUM, &cbInfo, 0);
// These fields are ignored if base != -1, but set them anyway to be safe
cbInfo.start = 0;
cbInfo.end = -1;
cbInfo.symbolMask = SYMBOL_MASK_ALL;
return !!_dbg_sendmessage(DBG_SYMBOL_ENUM, &cbInfo, 0);
}

// FIXME all
BRIDGE_IMPEXP void DbgSymbolEnumFromCache(duint base, CBSYMBOLENUM cbSymbolEnum, void* user)
BRIDGE_IMPEXP bool DbgSymbolEnumFromCache(duint base, CBSYMBOLENUM cbSymbolEnum, void* user)
{
return DbgSymbolEnum(base, cbSymbolEnum, user);
}

BRIDGE_IMPEXP bool DbgSymbolEnumRange(duint start, duint end, unsigned int symbolMask, CBSYMBOLENUM cbSymbolEnum, void* user)
{
SYMBOLCBINFO cbInfo;
cbInfo.base = base;
cbInfo.base = -1; // This indicates that start/end/mask is used
cbInfo.cbSymbolEnum = cbSymbolEnum;
cbInfo.user = user;
_dbg_sendmessage(DBG_SYMBOL_ENUM_FROMCACHE, &cbInfo, 0);
cbInfo.start = start;
cbInfo.end = end;
cbInfo.symbolMask = symbolMask;
return !!_dbg_sendmessage(DBG_SYMBOL_ENUM, &cbInfo, 0);
}

BRIDGE_IMPEXP bool DbgAssembleAt(duint addr, const char* instruction)
Expand Down
50 changes: 48 additions & 2 deletions src/bridge/bridgemain.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,11 @@ typedef enum
sym_symbol
} SYMBOLTYPE;

#define SYMBOL_MASK_IMPORT (1u << sym_import)
#define SYMBOL_MASK_EXPORT (1u << sym_export)
#define SYMBOL_MASK_SYMBOL (1u << sym_symbol)
#define SYMBOL_MASK_ALL (SYMBOL_MASK_IMPORT | SYMBOL_MASK_EXPORT | SYMBOL_MASK_SYMBOL)

typedef enum
{
mod_user,
Expand All @@ -549,6 +554,13 @@ typedef MEMORY_SIZE VALUE_SIZE;

typedef struct DBGFUNCTIONS_ DBGFUNCTIONS;

// Callback declaration:
// bool cbSymbolEnum(const SYMBOLPTR* symbol, void* user);
// To get the data from the opaque pointer:
// SYMBOLINFO info;
// DbgGetSymbolInfo(symbol, &info);
// The SYMBOLPTR* becomes invalid when the module is unloaded
// DO NOT STORE unless you are absolutely certain you handle it correctly
typedef bool (*CBSYMBOLENUM)(const struct SYMBOLPTR_* symbol, void* user);

//Debugger structs
Expand Down Expand Up @@ -638,11 +650,41 @@ typedef struct SYMBOLINFO_
char* decoratedSymbol;
char* undecoratedSymbol;
SYMBOLTYPE type;

// If true: Use BridgeFree(decoratedSymbol) to deallocate
// Else: The decoratedSymbol pointer is valid until the module unloads
bool freeDecorated;

// If true: Use BridgeFree(undecoratedSymbol) to deallcoate
// Else: The undecoratedSymbol pointer is valid until the module unloads
bool freeUndecorated;

// The entry point pseudo-export has ordinal == 0 (invalid ordinal value)
DWORD ordinal;
} SYMBOLINFO;

#ifdef __cplusplus
struct SYMBOLINFOCPP : SYMBOLINFO
{
SYMBOLINFOCPP(const SYMBOLINFOCPP &) = delete;
SYMBOLINFOCPP(SYMBOLINFOCPP &&) = delete;

SYMBOLINFOCPP()
{
memset(this, 0, sizeof(SYMBOLINFO));
}

~SYMBOLINFOCPP()
{
if(freeDecorated)
BridgeFree(decoratedSymbol);
if(freeUndecorated)
BridgeFree(undecoratedSymbol);
}
};
static_assert(sizeof(SYMBOLINFOCPP) == sizeof(SYMBOLINFO), "");
#endif // __cplusplus

typedef struct
{
duint base;
Expand All @@ -654,6 +696,9 @@ typedef struct
duint base;
CBSYMBOLENUM cbSymbolEnum;
void* user;
duint start;
duint end;
unsigned int symbolMask;
} SYMBOLCBINFO;

typedef struct
Expand Down Expand Up @@ -1015,8 +1060,9 @@ BRIDGE_IMPEXP void DbgScriptAbort();
BRIDGE_IMPEXP SCRIPTLINETYPE DbgScriptGetLineType(int line);
BRIDGE_IMPEXP void DbgScriptSetIp(int line);
BRIDGE_IMPEXP bool DbgScriptGetBranchInfo(int line, SCRIPTBRANCH* info);
BRIDGE_IMPEXP void DbgSymbolEnum(duint base, CBSYMBOLENUM cbSymbolEnum, void* user);
BRIDGE_IMPEXP void DbgSymbolEnumFromCache(duint base, CBSYMBOLENUM cbSymbolEnum, void* user);
BRIDGE_IMPEXP bool DbgSymbolEnum(duint base, CBSYMBOLENUM cbSymbolEnum, void* user);
BRIDGE_IMPEXP bool DbgSymbolEnumFromCache(duint base, CBSYMBOLENUM cbSymbolEnum, void* user);
BRIDGE_IMPEXP bool DbgSymbolEnumRange(duint start, duint end, unsigned int symbolMask, CBSYMBOLENUM cbSymbolEnum, void* user);
BRIDGE_IMPEXP bool DbgAssembleAt(duint addr, const char* instruction);
BRIDGE_IMPEXP duint DbgModBaseFromName(const char* name);
BRIDGE_IMPEXP void DbgDisasmAt(duint addr, DISASM_INSTR* instr);
Expand Down
95 changes: 54 additions & 41 deletions src/dbg/_exports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "TraceRecord.h"
#include "recursiveanalysis.h"
#include "dbghelp_safe.h"
#include "symcache.h"
#include "symbolinfo.h"

static bool bOnlyCipAutoComments = false;
static bool bNoSourceLineAutoComments = false;
Expand Down Expand Up @@ -190,31 +190,35 @@ static bool getLabel(duint addr, char* label, bool noFuncOffset)
else //no user labels
{
DWORD64 displacement = 0;
SymbolInfo symInfo;

bool res;
if(noFuncOffset)
res = SymbolFromAddressExact(addr, symInfo);
else
res = SymbolFromAddressExactOrLower(addr, symInfo);

if(res)
{
displacement = (DWORD64)symInfo.disp;
SYMBOLINFOCPP symInfo;

//auto name = demanglePE32ExternCFunc(symInfo.decoratedName.c_str());
if(bUndecorateSymbolNames && !symInfo.undecoratedName.empty())
strncpy_s(label, MAX_LABEL_SIZE, symInfo.undecoratedName.c_str(), _TRUNCATE);
bool res;
if(noFuncOffset)
res = SymbolFromAddressExact(addr, &symInfo);
else
strncpy_s(label, MAX_LABEL_SIZE, symInfo.decoratedName.c_str(), _TRUNCATE);
retval = !shouldFilterSymbol(label);
if(retval && displacement)
res = SymbolFromAddressExactOrLower(addr, &symInfo);

if(res)
{
char temp[32];
sprintf_s(temp, "+%llX", displacement);
strncat_s(label, MAX_LABEL_SIZE, temp, _TRUNCATE);
displacement = (int32_t)(addr - symInfo.addr);

//auto name = demanglePE32ExternCFunc(symInfo.decoratedName.c_str());
if(bUndecorateSymbolNames && *symInfo.undecoratedSymbol != '\0')
strncpy_s(label, MAX_LABEL_SIZE, symInfo.undecoratedSymbol, _TRUNCATE);
else
strncpy_s(label, MAX_LABEL_SIZE, symInfo.decoratedSymbol, _TRUNCATE);

retval = !shouldFilterSymbol(label);
if(retval && displacement != 0)
{
char temp[32];
sprintf_s(temp, "+%llX", displacement);
strncat_s(label, MAX_LABEL_SIZE, temp, _TRUNCATE);
}
}
}

if(!retval) //search for CALL <jmp.&user32.MessageBoxA>
{
BASIC_INSTRUCTION_INFO basicinfo;
Expand All @@ -224,21 +228,22 @@ static bool getLabel(duint addr, char* label, bool noFuncOffset)
duint val = 0;
if(MemRead(basicinfo.memory.value, &val, sizeof(val), nullptr, true))
{
SYMBOLINFOCPP symInfo;
bool res;
if(noFuncOffset)
res = SymbolFromAddressExact(val, symInfo);
res = SymbolFromAddressExact(val, &symInfo);
else
res = SymbolFromAddressExactOrLower(val, symInfo);
res = SymbolFromAddressExactOrLower(val, &symInfo);

if(res)
{
//pSymbol->Name[pSymbol->MaxNameLen - 1] = '\0';

//auto name = demanglePE32ExternCFunc(pSymbol->Name);
if(bUndecorateSymbolNames && !symInfo.undecoratedName.empty())
_snprintf_s(label, MAX_LABEL_SIZE, _TRUNCATE, "JMP.&%s", symInfo.undecoratedName.c_str());
if(bUndecorateSymbolNames && *symInfo.undecoratedSymbol != '\0')
_snprintf_s(label, MAX_LABEL_SIZE, _TRUNCATE, "JMP.&%s", symInfo.undecoratedSymbol);
else
_snprintf_s(label, MAX_LABEL_SIZE, _TRUNCATE, "JMP.&%s", symInfo.decoratedName.c_str());
_snprintf_s(label, MAX_LABEL_SIZE, _TRUNCATE, "JMP.&%s", symInfo.decoratedSymbol);
retval = !shouldFilterSymbol(label);
if(retval && displacement)
{
Expand Down Expand Up @@ -1062,16 +1067,32 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa
break;

case DBG_SYMBOL_ENUM:
{
SYMBOLCBINFO* cbInfo = (SYMBOLCBINFO*)param1;
SymEnum(cbInfo->base, cbInfo->cbSymbolEnum, cbInfo->user);
}
break;

case DBG_SYMBOL_ENUM_FROMCACHE:
{
SYMBOLCBINFO* cbInfo = (SYMBOLCBINFO*)param1;
SymEnumFromCache(cbInfo->base, cbInfo->cbSymbolEnum, cbInfo->user);
if(cbInfo->base == -1)
{
SHARED_ACQUIRE(LockModules);
auto info = ModInfoFromAddr(cbInfo->start);
if(info != nullptr && cbInfo->end >= info->base && cbInfo->end < info->base + info->size)
{
auto beginRva = cbInfo->start - info->base;
auto endRva = cbInfo->end - info->base;
if(beginRva > endRva)
{
return false;
}
return SymEnum(info->base, cbInfo->cbSymbolEnum, cbInfo->user, beginRva, endRva, cbInfo->symbolMask);
}
else
{
return false;
}
}
else
{
return SymEnum(cbInfo->base, cbInfo->cbSymbolEnum, cbInfo->user, 0, -1, SYMBOL_MASK_ALL);
}
}
break;

Expand Down Expand Up @@ -1670,15 +1691,7 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa

case DBG_GET_SYMBOL_INFO_AT:
{
SHARED_ACQUIRE(LockModules);

SymbolInfo symInfo;
if(!SymbolFromAddressExact((duint)param1, symInfo))
return false;

auto modbase = ModBaseFromAddr((duint)param1);
symInfo.copyToGuiSymbol(modbase, (SYMBOLINFO*)param2);
return true;
return SymbolFromAddressExact((duint)param1, (SYMBOLINFO*)param2);
}
break;

Expand Down
15 changes: 15 additions & 0 deletions src/dbg/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,21 @@ const MODEXPORT* MODINFO::findExport(duint rva) const
return nullptr;
}

const MODIMPORT* MODINFO::findImport(duint rva) const
{
if(imports.size())
{
auto found = std::lower_bound(importsByRva.begin(), importsByRva.end(), rva, [this](size_t index, duint rva)
{
return imports.at(index).iatRva < rva;
});
found = found != importsByRva.end() && rva >= imports.at(*found).iatRva ? found : importsByRva.end();
if(found != importsByRva.end())
return &imports[*found];
}
return nullptr;
}

static bool resolveApiSetForward(const String & originatingDll, String & forwardDll, String & forwardExport)
{
wchar_t szApiSetDllPath[MAX_PATH] = L"";
Expand Down
1 change: 1 addition & 0 deletions src/dbg/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ struct MODINFO
void unloadSymbols();
void unmapFile();
const MODEXPORT* findExport(duint rva) const;
const MODIMPORT* findImport(duint iatRva) const;
duint getProcAddress(const String & name, int maxForwardDepth = 10) const;
};

Expand Down

0 comments on commit 97ff1ec

Please sign in to comment.