1
0
Fork 0

Refactor symbol handling and introduce DbgSymbolEnumRange

This allows enumerating multiple symbols at the same address efficiently
This commit is contained in:
Duncan Ogilvie 2023-06-10 18:00:16 +02:00
parent 165b0d3bc5
commit 97ff1ec98a
15 changed files with 392 additions and 344 deletions

View File

@ -291,7 +291,7 @@ BRIDGE_IMPEXP void* BridgeAlloc(size_t size)
BRIDGE_IMPEXP void BridgeFree(void* ptr)
{
if(ptr)
if(ptr != nullptr)
GlobalFree(ptr);
}
@ -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)

View File

@ -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,
@ -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
@ -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;
@ -654,6 +696,9 @@ typedef struct
duint base;
CBSYMBOLENUM cbSymbolEnum;
void* user;
duint start;
duint end;
unsigned int symbolMask;
} SYMBOLCBINFO;
typedef struct
@ -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);

View File

@ -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;
@ -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;
@ -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)
{
@ -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;
@ -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;

View File

@ -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"";

View File

@ -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;
};

View File

@ -20,63 +20,128 @@ struct SYMBOLCBDATA
{
CBSYMBOLENUM cbSymbolEnum;
void* user = nullptr;
std::vector<char> decoratedSymbol;
std::vector<char> undecoratedSymbol;
};
void SymEnum(duint Base, CBSYMBOLENUM EnumCallback, void* UserData)
bool SymEnum(duint Base, CBSYMBOLENUM EnumCallback, void* UserData, duint BeginRva, duint EndRva, unsigned int SymbolMask)
{
SYMBOLCBDATA cbData;
cbData.cbSymbolEnum = EnumCallback;
cbData.user = UserData;
cbData.decoratedSymbol.resize(MAX_SYM_NAME + 1);
cbData.undecoratedSymbol.resize(MAX_SYM_NAME + 1);
SHARED_ACQUIRE(LockModules);
MODINFO* modInfo = ModInfoFromAddr(Base);
if(modInfo == nullptr)
return false;
if(SymbolMask & SYMBOL_MASK_SYMBOL && modInfo->symbols->isOpen())
{
SHARED_ACQUIRE(LockModules);
MODINFO* modInfo = ModInfoFromAddr(Base);
if(modInfo)
modInfo->symbols->enumSymbols([&cbData, Base](const SymbolInfo & info)
{
for(size_t i = 0; i < modInfo->exports.size(); i++)
{
SYMBOLPTR symbolptr;
symbolptr.modbase = Base;
symbolptr.symbol = &modInfo->exports.at(i);
cbData.cbSymbolEnum(&symbolptr, cbData.user);
}
SYMBOLPTR symbolptr;
symbolptr.modbase = Base;
symbolptr.symbol = &info;
return cbData.cbSymbolEnum(&symbolptr, cbData.user);
}, BeginRva, EndRva);
}
// Emit pseudo entry point symbol
{
SYMBOLPTR symbolptr;
symbolptr.modbase = Base;
symbolptr.symbol = &modInfo->entrySymbol;
cbData.cbSymbolEnum(&symbolptr, cbData.user);
}
if(SymbolMask & SYMBOL_MASK_EXPORT)
{
auto entry = &modInfo->entrySymbol;
for(size_t i = 0; i < modInfo->imports.size(); i++)
// There is a pseudo-export for the entry point function
auto emitEntryExport = [&]()
{
if(entry->rva >= BeginRva && entry->rva <= EndRva)
{
SYMBOLPTR symbolptr;
symbolptr.modbase = Base;
symbolptr.symbol = &modInfo->imports.at(i);
cbData.cbSymbolEnum(&symbolptr, cbData.user);
symbolptr.symbol = entry;
entry = nullptr;
return cbData.cbSymbolEnum(&symbolptr, cbData.user);
}
if(modInfo->symbols->isOpen())
entry = nullptr;
return true;
};
if(!modInfo->exportsByRva.empty())
{
auto it = modInfo->exportsByRva.begin();
if(BeginRva > modInfo->exports[*it].rva)
{
modInfo->symbols->enumSymbols([&cbData, Base](const SymbolInfo & info)
it = std::lower_bound(modInfo->exportsByRva.begin(), modInfo->exportsByRva.end(), BeginRva, [&modInfo](size_t index, duint rva)
{
return modInfo->exports[index].rva < rva;
});
}
if(it != modInfo->exportsByRva.end())
{
for(; it != modInfo->exportsByRva.end(); it++)
{
const auto & symbol = modInfo->exports[*it];
if(symbol.rva > EndRva)
break;
// This is only executed if there is another export after the entry
if(entry != nullptr && symbol.rva >= entry->rva)
{
if(!emitEntryExport())
return true;
}
SYMBOLPTR symbolptr;
symbolptr.modbase = Base;
symbolptr.symbol = &info;
return cbData.cbSymbolEnum(&symbolptr, cbData.user);
});
symbolptr.symbol = &symbol;
if(!cbData.cbSymbolEnum(&symbolptr, cbData.user))
return true;
}
// This is executed if the entry is the last 'export'
if(entry != nullptr)
{
emitEntryExport();
}
}
else
{
// This is executed if there are exports, but the range doesn't include any real ones
emitEntryExport();
}
}
else
{
// This is executed if there are no exports
emitEntryExport();
}
}
if(SymbolMask & SYMBOL_MASK_IMPORT && !modInfo->importsByRva.empty())
{
auto it = modInfo->importsByRva.begin();
if(BeginRva > modInfo->imports[*it].iatRva)
{
it = std::lower_bound(modInfo->importsByRva.begin(), modInfo->importsByRva.end(), BeginRva, [&modInfo](size_t index, duint rva)
{
return modInfo->imports[index].iatRva < rva;
});
}
if(it != modInfo->importsByRva.end())
{
for(; it != modInfo->importsByRva.end(); it++)
{
const auto & symbol = modInfo->imports[*it];
if(symbol.iatRva > EndRva)
break;
SYMBOLPTR symbolptr;
symbolptr.modbase = Base;
symbolptr.symbol = &symbol;
if(!cbData.cbSymbolEnum(&symbolptr, cbData.user))
return true;
}
}
}
}
void SymEnumFromCache(duint Base, CBSYMBOLENUM EnumCallback, void* UserData)
{
SymEnum(Base, EnumCallback, UserData);
return true;
}
bool SymGetModuleList(std::vector<SYMBOLMODULEINFO>* List)
@ -349,6 +414,112 @@ String SymGetSymbolicName(duint Address, bool IncludeAddress)
}
}
bool SymbolFromAddressExact(duint address, SYMBOLINFO* info)
{
if(address == 0)
return false;
SHARED_ACQUIRE(LockModules);
MODINFO* modInfo = ModInfoFromAddr(address);
if(modInfo == nullptr)
return false;
duint base = modInfo->base;
duint rva = address - base;
// search in symbols
if(modInfo->symbols->isOpen())
{
SymbolInfo symInfo;
if(modInfo->symbols->findSymbolExact(rva, symInfo))
{
symInfo.copyToGuiSymbol(base, info);
return true;
}
}
// search in module exports
{
auto modExport = modInfo->findExport(rva);
if(modExport != nullptr)
{
modExport->copyToGuiSymbol(base, info);
return true;
}
}
if(modInfo->entrySymbol.rva == rva)
{
modInfo->entrySymbol.convertToGuiSymbol(base, info);
return true;
}
// search in module imports
{
auto modImport = modInfo->findImport(rva);
if(modImport != nullptr)
{
modImport->copyToGuiSymbol(base, info);
return true;
}
}
return false;
}
bool SymbolFromAddressExactOrLower(duint address, SYMBOLINFO* info)
{
if(address == 0)
return false;
SHARED_ACQUIRE(LockModules);
MODINFO* modInfo = ModInfoFromAddr(address);
if(modInfo == nullptr)
return false;
duint rva = address - modInfo->base;
// search in module symbols
if(modInfo->symbols->isOpen())
{
SymbolInfo symInfo;
if(modInfo->symbols->findSymbolExactOrLower(rva, symInfo))
{
symInfo.copyToGuiSymbol(modInfo->base, info);
return true;
}
}
// search in module exports
if(!modInfo->exports.empty())
{
auto it = [&]()
{
auto it = std::lower_bound(modInfo->exportsByRva.begin(), modInfo->exportsByRva.end(), rva, [&modInfo](size_t index, duint rva)
{
return modInfo->exports.at(index).rva < rva;
});
// not found
if(it == modInfo->exportsByRva.end())
return --it;
// exact match
if(modInfo->exports[*it].rva == rva)
return it;
// right now 'it' points to the first element bigger than rva
return it == modInfo->exportsByRva.begin() ? modInfo->exportsByRva.end() : --it;
}();
if(it != modInfo->exportsByRva.end())
{
const auto & symbol = modInfo->exports[*it];
symbol.copyToGuiSymbol(modInfo->base, info);
return true;
}
}
return false;
}
bool SymGetSourceLine(duint Cip, char* FileName, int* Line, duint* disp)
{
SHARED_ACQUIRE(LockModules);

View File

@ -1,18 +1,18 @@
#ifndef _SYMBOLINFO_H
#define _SYMBOLINFO_H
#pragma once
#include "_global.h"
extern duint symbolDownloadingBase;
void SymEnum(duint Base, CBSYMBOLENUM EnumCallback, void* UserData);
void SymEnumFromCache(duint Base, CBSYMBOLENUM EnumCallback, void* UserData);
bool SymEnum(duint Base, CBSYMBOLENUM EnumCallback, void* UserData, duint BeginRva, duint EndRva, unsigned int SymbolMask);
bool SymGetModuleList(std::vector<SYMBOLMODULEINFO>* List);
void SymUpdateModuleList();
bool SymDownloadSymbol(duint Base, const char* SymbolStore);
void SymDownloadAllSymbols(const char* SymbolStore);
bool SymAddrFromName(const char* Name, duint* Address);
String SymGetSymbolicName(duint Address, bool IncludeAddress = true);
bool SymbolFromAddressExact(duint address, SYMBOLINFO* info);
bool SymbolFromAddressExactOrLower(duint address, SYMBOLINFO* info);
/**
\brief Gets the source code file name and line from an address.
@ -24,5 +24,3 @@ String SymGetSymbolicName(duint Address, bool IncludeAddress = true);
bool SymGetSourceLine(duint Cip, char* FileName, int* Line, duint* displacement = nullptr);
bool SymGetSourceAddr(duint Module, const char* FileName, int Line, duint* Address);
#endif // _SYMBOLINFO_H

View File

@ -175,19 +175,19 @@ bool SymbolSourceDIA::loadSymbolsAsync()
for(size_t i = 0; i < _symData.size(); i++)
{
AddrIndex addrIndex;
addrIndex.addr = _symData[i].rva;
addrIndex.rva = _symData[i].rva;
addrIndex.index = i;
_symAddrMap[i] = addrIndex;
}
std::sort(_symAddrMap.begin(), _symAddrMap.end(), [this](const AddrIndex & a, const AddrIndex & b)
{
// smaller
if(a.addr < b.addr)
if(a.rva < b.rva)
{
return true;
}
// bigger
else if(a.addr > b.addr)
else if(a.rva > b.rva)
{
return false;
}
@ -345,7 +345,7 @@ bool SymbolSourceDIA::loadSourceLinesAsync()
lineInfo.sourceFileIndex = found->second.sourceFileIndex;
AddrIndex lineIndex;
lineIndex.addr = lineInfo.rva;
lineIndex.rva = lineInfo.rva;
lineIndex.index = _linesData.size() - 1;
_lineAddrMap.push_back(lineIndex);
}
@ -420,7 +420,7 @@ bool SymbolSourceDIA::findSymbolExact(duint rva, SymbolInfo & symInfo)
return false;
AddrIndex find;
find.addr = rva;
find.rva = rva;
find.index = -1;
auto it = binary_find(_symAddrMap.begin(), _symAddrMap.end(), find);
@ -445,7 +445,7 @@ bool SymbolSourceDIA::findSymbolExactOrLower(duint rva, SymbolInfo & symInfo)
return false;
AddrIndex find;
find.addr = rva;
find.rva = rva;
find.index = -1;
auto it = [&]()
{
@ -454,7 +454,7 @@ bool SymbolSourceDIA::findSymbolExactOrLower(duint rva, SymbolInfo & symInfo)
if(it == _symAddrMap.end())
return --it;
// exact match
if(it->addr == rva)
if(it->rva == rva)
return it;
// right now 'it' points to the first element bigger than rva
return it == _symAddrMap.begin() ? _symAddrMap.end() : --it;
@ -482,11 +482,15 @@ void SymbolSourceDIA::enumSymbols(const CbEnumSymbol & cbEnum, duint beginRva, d
return;
AddrIndex find;
find.addr = beginRva;
find.rva = beginRva;
find.index = -1;
auto it = std::lower_bound(_symAddrMap.begin(), _symAddrMap.end(), find);
if(it == _symAddrMap.end())
return;
auto it = _symAddrMap.begin();
if(beginRva > it->rva)
{
it = std::lower_bound(_symAddrMap.begin(), _symAddrMap.end(), find);
if(it == _symAddrMap.end())
return;
}
for(; it != _symAddrMap.end(); it++)
{
@ -509,7 +513,7 @@ bool SymbolSourceDIA::findSourceLineInfo(duint rva, LineInfo & lineInfo)
return false;
AddrIndex find;
find.addr = rva;
find.rva = rva;
find.index = -1;
auto it = binary_find(_lineAddrMap.begin(), _lineAddrMap.end(), find);
if(it == _lineAddrMap.end())

View File

@ -35,12 +35,12 @@ private: //symbols
struct AddrIndex
{
duint addr;
duint rva;
size_t index;
bool operator<(const AddrIndex & b) const
{
return addr < b.addr;
return rva < b.rva;
}
};

View File

@ -1,193 +0,0 @@
#include "symcache.h"
#include "dbghelp_safe.h"
#include "addrinfo.h"
#include "threading.h"
#include <algorithm>
/*template<typename T>
using RangeMap = std::map<Range, T, RangeCompare>;
static RangeMap<RangeMap<SymbolInfo>> symbolRange;
static std::unordered_map<duint, duint> symbolName;*/
bool SymbolFromAddressExact(duint address, SymbolInfo & symInfo)
{
if(address == 0)
return false;
SHARED_ACQUIRE(LockModules);
MODINFO* modInfo = ModInfoFromAddr(address);
if(modInfo)
{
duint rva = address - modInfo->base;
// search in symbols
if(modInfo->symbols->isOpen())
{
if(modInfo->symbols->findSymbolExact(rva, symInfo))
return true;
}
// search in module exports
{
auto modExport = modInfo->findExport(rva);
if(modExport)
{
symInfo.rva = modExport->rva;
symInfo.size = 0;
symInfo.disp = 0;
symInfo.decoratedName = modExport->name;
symInfo.undecoratedName = modExport->undecoratedName;
symInfo.publicSymbol = true;
return true;
}
}
}
return false;
}
bool SymbolFromAddressExactOrLower(duint address, SymbolInfo & symInfo)
{
if(address == 0)
return false;
SHARED_ACQUIRE(LockModules);
MODINFO* modInfo = ModInfoFromAddr(address);
if(modInfo)
{
if(modInfo->symbols->isOpen() == false)
return false;
duint rva = address - modInfo->base;
return modInfo->symbols->findSymbolExactOrLower(rva, symInfo);
}
return false;
}
/*bool SymbolFromAddr(duint addr, SymbolInfo & symbol)
{
SHARED_ACQUIRE(LockSymbolCache);
auto foundR = symbolRange.find(Range(addr, addr));
if(foundR == symbolRange.end())
return false;
auto foundS = foundR->second.find(Range(addr, addr));
if(foundS == foundR->second.end())
return false;
symbol = foundS->second;
return true;
}
bool SymbolFromName(const char* name, SymbolInfo & symbol)
{
if(!name)
return false;
auto hash = ModHashFromName(name);
SHARED_ACQUIRE(LockSymbolCache);
auto found = symbolName.find(hash);
if(found == symbolName.end())
return false;
return SymbolFromAddr(found->second, symbol);
}
bool SymbolAdd(const SymbolInfo & symbol)
{
EXCLUSIVE_ACQUIRE(LockSymbolCache);
auto foundR = symbolRange.find(Range(symbol.addr, symbol.addr));
if(foundR == symbolRange.end())
return false;
auto foundS = foundR->second.find(Range(symbol.addr, symbol.addr));
if(foundS != foundR->second.end())
return false;
auto dec = symbol.size ? 1 : 0;
foundR->second.insert({ Range(symbol.addr, symbol.addr + symbol.size - dec), symbol });
auto hash = ModHashFromName(symbol.decoratedName.c_str());
symbolName.insert({ hash, symbol.addr });
return true;
}
bool SymbolAddRange(duint start, duint size)
{
EXCLUSIVE_ACQUIRE(LockSymbolCache);
auto foundR = symbolRange.find(Range(start, start + size - 1));
if(foundR != symbolRange.end())
return false;
symbolRange.insert({ Range(start, start + size - 1), RangeMap<SymbolInfo>() });
return true;
}
bool SymbolDelRange(duint addr)
{
EXCLUSIVE_ACQUIRE(LockSymbolCache);
auto foundR = symbolRange.find(Range(addr, addr));
if(foundR == symbolRange.end())
return false;
symbolRange.erase(foundR);
return true;
}
static RangeMap<RangeMap<LineInfo>> lineRange;
static std::unordered_map<duint, duint> lineName;
bool LineFromAddr(duint addr, LineInfo & line)
{
SHARED_ACQUIRE(LockLineCache);
auto foundR = lineRange.find(Range(addr, addr));
if(foundR == lineRange.end())
return false;
auto foundL = foundR->second.find(Range(addr, addr));
if(foundL == foundR->second.end())
return false;
line = foundL->second;
return true;
}
bool LineFromName(const char* sourceFile, int lineNumber, LineInfo & line)
{
if(!sourceFile)
return false;
auto hash = ModHashFromName(sourceFile) + lineNumber;
SHARED_ACQUIRE(LockLineCache);
auto found = lineName.find(hash);
if(found == lineName.end())
return false;
return LineFromAddr(found->second, line);
}
bool LineAdd(const LineInfo & line)
{
EXCLUSIVE_ACQUIRE(LockLineCache);
auto foundR = lineRange.find(Range(line.addr, line.addr));
if(foundR == lineRange.end())
return false;
auto foundL = foundR->second.find(Range(line.addr, line.addr));
if(foundL != foundR->second.end())
return false;
auto dec = line.size ? 1 : 0;
foundR->second.insert({ Range(line.addr, line.addr + line.size - dec), line });
auto hash = ModHashFromName(line.sourceFile.c_str()) + line.lineNumber;
lineName.insert({ hash, line.addr });
return true;
}
bool LineAddRange(duint start, duint size)
{
EXCLUSIVE_ACQUIRE(LockLineCache);
auto foundR = lineRange.find(Range(start, start + size - 1));
if(foundR != lineRange.end())
return false;
lineRange.insert({ Range(start, start + size - 1), RangeMap<LineInfo>() });
return true;
}
bool LineDelRange(duint addr)
{
EXCLUSIVE_ACQUIRE(LockLineCache);
auto foundR = lineRange.find(Range(addr, addr));
if(foundR == lineRange.end())
return false;
lineRange.erase(foundR);
return true;
}
*/

View File

@ -1,20 +0,0 @@
#pragma once
#include "_global.h"
#include "symbolsourcebase.h"
bool SymbolFromAddressExact(duint address, SymbolInfo & symInfo);
bool SymbolFromAddressExactOrLower(duint address, SymbolInfo & symInfo);
/*bool SymbolFromAddr(duint addr, SymbolInfo & symbol);
bool SymbolFromName(const char* name, SymbolInfo & symbol);
bool SymbolAdd(const SymbolInfo & symbol);
bool SymbolAddRange(duint start, duint size);
bool SymbolDelRange(duint addr);
bool LineFromAddr(duint addr, LineInfo & line);
bool LineFromName(const char* sourceFile, int lineNumber, LineInfo & line);
bool LineAdd(const LineInfo & line);
bool LineAddRange(duint start, duint size);
bool LineDelRange(duint addr);*/

View File

@ -51,10 +51,10 @@ void waitdeinitialize()
bool SectionLockerGlobal::m_Initialized = false;
bool SectionLockerGlobal::m_SRWLocks = false;
SRWLOCK SectionLockerGlobal::m_srwLocks[SectionLock::LockLast];
SectionLockerGlobal::owner_info SectionLockerGlobal::m_owner[SectionLock::LockLast];
CacheAligned<SRWLOCK> SectionLockerGlobal::m_srwLocks[SectionLock::LockLast];
SectionLockerGlobal::owner_info SectionLockerGlobal::m_exclusiveOwner[SectionLock::LockLast];
CRITICAL_SECTION SectionLockerGlobal::m_crLocks[SectionLock::LockLast];
CacheAligned<CRITICAL_SECTION> SectionLockerGlobal::m_crLocks[SectionLock::LockLast];
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_InitializeSRWLock;
SectionLockerGlobal::SRWLOCKFUNCTION SectionLockerGlobal::m_AcquireSRWLockShared;
SectionLockerGlobal::TRYSRWLOCKFUNCTION SectionLockerGlobal::m_TryAcquireSRWLockShared;

View File

@ -81,6 +81,14 @@ enum SectionLock
LockLast
};
template<typename T>
struct __declspec(align(64)) CacheAligned
{
T value;
T* operator&() { return &value; }
};
class SectionLockerGlobal
{
template<SectionLock LockIndex, bool Shared, bool ProcessGuiEvents>
@ -101,7 +109,7 @@ private:
if(Shared)
{
if(m_owner[LockIndex].thread == threadId)
if(m_exclusiveOwner[LockIndex].threadId == threadId)
return;
if(ProcessGuiEvents && threadId == m_guiMainThreadId)
@ -116,10 +124,10 @@ private:
return;
}
if(m_owner[LockIndex].thread == threadId)
if(m_exclusiveOwner[LockIndex].threadId == threadId)
{
assert(m_owner[LockIndex].count > 0);
m_owner[LockIndex].count++;
assert(m_exclusiveOwner[LockIndex].count > 0);
m_exclusiveOwner[LockIndex].count++;
return;
}
@ -133,10 +141,10 @@ private:
m_AcquireSRWLockExclusive(srwLock);
}
assert(m_owner[LockIndex].thread == 0);
assert(m_owner[LockIndex].count == 0);
m_owner[LockIndex].thread = threadId;
m_owner[LockIndex].count = 1;
assert(m_exclusiveOwner[LockIndex].threadId == 0);
assert(m_exclusiveOwner[LockIndex].count == 0);
m_exclusiveOwner[LockIndex].threadId = threadId;
m_exclusiveOwner[LockIndex].count = 1;
}
else
{
@ -160,19 +168,19 @@ private:
{
if(Shared)
{
if(m_owner[LockIndex].thread == GetCurrentThreadId())
if(m_exclusiveOwner[LockIndex].threadId == GetCurrentThreadId())
return;
m_ReleaseSRWLockShared(&m_srwLocks[LockIndex]);
return;
}
assert(m_owner[LockIndex].count && m_owner[LockIndex].thread);
m_owner[LockIndex].count--;
assert(m_exclusiveOwner[LockIndex].count && m_exclusiveOwner[LockIndex].threadId);
m_exclusiveOwner[LockIndex].count--;
if(m_owner[LockIndex].count == 0)
if(m_exclusiveOwner[LockIndex].count == 0)
{
m_owner[LockIndex].thread = 0;
m_exclusiveOwner[LockIndex].threadId = 0;
m_ReleaseSRWLockExclusive(&m_srwLocks[LockIndex]);
}
}
@ -187,10 +195,11 @@ private:
static bool m_Initialized;
static bool m_SRWLocks;
struct owner_info { DWORD thread; size_t count; };
static owner_info m_owner[SectionLock::LockLast];
static SRWLOCK m_srwLocks[SectionLock::LockLast];
static CRITICAL_SECTION m_crLocks[SectionLock::LockLast];
struct __declspec(align(64)) owner_info { DWORD threadId; size_t count; };
static owner_info m_exclusiveOwner[SectionLock::LockLast];
static CacheAligned<SRWLOCK> m_srwLocks[SectionLock::LockLast];
static CacheAligned<CRITICAL_SECTION> m_crLocks[SectionLock::LockLast];
static SRWLOCKFUNCTION m_InitializeSRWLock;
static SRWLOCKFUNCTION m_AcquireSRWLockShared;
static TRYSRWLOCKFUNCTION m_TryAcquireSRWLockShared;

View File

@ -102,7 +102,6 @@
<ClCompile Include="symbolinfo.cpp" />
<ClCompile Include="symbolsourcebase.cpp" />
<ClCompile Include="symbolsourcedia.cpp" />
<ClCompile Include="symcache.cpp" />
<ClCompile Include="tcpconnections.cpp" />
<ClCompile Include="thread.cpp" />
<ClCompile Include="threading.cpp" />
@ -240,7 +239,6 @@
<ClInclude Include="symbolsourcebase.h" />
<ClInclude Include="symbolsourcedia.h" />
<ClInclude Include="symbolundecorator.h" />
<ClInclude Include="symcache.h" />
<ClInclude Include="syscalls.h" />
<ClInclude Include="taskthread.h" />
<ClInclude Include="tcpconnections.h" />

View File

@ -440,9 +440,6 @@
<ClCompile Include="formatfunctions.cpp">
<Filter>Source Files\Core</Filter>
</ClCompile>
<ClCompile Include="symcache.cpp">
<Filter>Source Files\Symbols</Filter>
</ClCompile>
<ClCompile Include="symbolinfo.cpp">
<Filter>Source Files\Symbols</Filter>
</ClCompile>
@ -877,9 +874,6 @@
<ClInclude Include="symbolsourcebase.h">
<Filter>Header Files\Symbols</Filter>
</ClInclude>
<ClInclude Include="symcache.h">
<Filter>Header Files\Symbols</Filter>
</ClInclude>
<ClInclude Include="symbolinfo.h">
<Filter>Header Files\Symbols</Filter>
</ClInclude>