Skip to content

Commit

Permalink
Merge pull request #3091 from m417z/xref-multi-api
Browse files Browse the repository at this point in the history
Add the DbgXrefAddMulti API
  • Loading branch information
mrexodia committed May 12, 2023
2 parents b64fa53 + 205b21a commit 17584fc
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 51 deletions.
5 changes: 5 additions & 0 deletions src/bridge/bridgemain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,11 @@ BRIDGE_IMPEXP bool DbgGetSymbolInfoAt(duint addr, SYMBOLINFO* info)
return !!_dbg_sendmessage(DBG_GET_SYMBOL_INFO_AT, (void*)addr, info);
}

BRIDGE_IMPEXP duint DbgXrefAddMulti(const XREF_EDGE* edges, duint count)
{
return (duint)_dbg_sendmessage(DBG_XREF_ADD_MULTI, (void*)edges, (void*)count);
}

BRIDGE_IMPEXP const char* GuiTranslateText(const char* Source)
{
EnterCriticalSection(&csTranslate);
Expand Down
10 changes: 9 additions & 1 deletion src/bridge/bridgemain.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ extern "C"
#define MAX_WATCH_NAME_SIZE 256
#define MAX_STRING_SIZE 512
#define MAX_ERROR_SIZE 512
#define RIGHTS_STRING_SIZE (sizeof("ERWCG") + 1)
#define RIGHTS_STRING_SIZE (sizeof("ERWCG"))
#define MAX_SECTION_SIZE 10
#define MAX_COMMAND_LINE_SIZE 256
#define MAX_MNEMONIC_SIZE 64
Expand Down Expand Up @@ -336,6 +336,7 @@ typedef enum
DBG_GET_SYMBOL_INFO, // param1=void* symbol, param2=SYMBOLINFO* info
DBG_GET_DEBUG_ENGINE, // param1=unused, param2-unused
DBG_GET_SYMBOL_INFO_AT, // param1=duint addr, param2=SYMBOLINFO* info
DBG_XREF_ADD_MULTI, // param1=const XREF_EDGE* edges, param2=duint count
} DBGMSG;

typedef enum
Expand Down Expand Up @@ -940,6 +941,12 @@ typedef struct
XREF_RECORD* references;
} XREF_INFO;

typedef struct
{
duint address;
duint from;
} XREF_EDGE;

typedef struct SYMBOLPTR_
{
duint modbase;
Expand Down Expand Up @@ -1072,6 +1079,7 @@ BRIDGE_IMPEXP duint DbgEval(const char* expression, bool* DEFAULT_PARAM(success,
BRIDGE_IMPEXP void DbgGetSymbolInfo(const SYMBOLPTR* symbolptr, SYMBOLINFO* info);
BRIDGE_IMPEXP DEBUG_ENGINE DbgGetDebugEngine();
BRIDGE_IMPEXP bool DbgGetSymbolInfoAt(duint addr, SYMBOLINFO* info);
BRIDGE_IMPEXP duint DbgXrefAddMulti(const XREF_EDGE* edges, duint count);

//Gui defines
typedef enum
Expand Down
8 changes: 8 additions & 0 deletions src/dbg/_exports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,8 @@ 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;
Expand All @@ -1679,6 +1681,12 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa
return true;
}
break;

case DBG_XREF_ADD_MULTI:
{
return XrefAddMulti((const XREF_EDGE*)param1, (duint)param2);
}
break;
}
return 0;
}
129 changes: 98 additions & 31 deletions src/dbg/xrefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct XrefSerializer : AddrInfoSerializer<XREFSINFO>
record.addr = duint(json_hex_value(json_object_get(reference, "addr")));
record.type = XREFTYPE(json_hex_value(json_object_get(reference, "type")));
value.type = max(record.type, value.type);
value.references.insert({ record.addr, record });
value.references.emplace(record.addr, record);
}
return true;
}
Expand All @@ -58,43 +58,110 @@ static Xrefs xrefs;

bool XrefAdd(duint Address, duint From)
{
XREFSINFO info;
if(!MemIsValidReadPtr(From) || !xrefs.PrepareValue(info, Address, false))
return false;
XREF_EDGE edge = { Address, From };
return XrefAddMulti(&edge, 1) == 1;
}

// Fail if boundary exceeds module size
auto moduleBase = ModBaseFromAddr(Address);
if(moduleBase != ModBaseFromAddr(From))
return false;
duint XrefAddMulti(const XREF_EDGE* Edges, duint Count)
{
// These types are used in a cache to improve performance
struct FromInfo
{
bool valid = false;
duint moduleBase = 0;
duint moduleSize = 0;
XREF_RECORD xrefRecord{};

BASIC_INSTRUCTION_INFO instInfo;
DbgDisasmFastAt(From, &instInfo);
explicit FromInfo(duint from)
{
if(!MemIsValidReadPtr(from))
return;

XREF_RECORD xrefRecord;
xrefRecord.addr = From - moduleBase;
if(instInfo.call)
xrefRecord.type = XREF_CALL;
else if(instInfo.branch)
xrefRecord.type = XREF_JMP;
else
xrefRecord.type = XREF_DATA;
{
SHARED_ACQUIRE(LockModules);

EXCLUSIVE_ACQUIRE(LockCrossReferences);
auto & mapData = xrefs.GetDataUnsafe();
auto key = Xrefs::VaKey(Address);
auto found = mapData.find(key);
if(found == mapData.end())
auto module = ModInfoFromAddr(from);
if(!module)
return;

moduleBase = module->base;
moduleSize = module->size;
}

BASIC_INSTRUCTION_INFO instInfo;
DbgDisasmFastAt(from, &instInfo);

xrefRecord.addr = from - moduleBase;
if(instInfo.call)
xrefRecord.type = XREF_CALL;
else if(instInfo.branch)
xrefRecord.type = XREF_JMP;
else
xrefRecord.type = XREF_DATA;

valid = true;
}
};

struct AddressInfo
{
info.type = xrefRecord.type;
info.references.insert({ xrefRecord.addr, xrefRecord });
mapData.insert({ key, info });
}
else
bool valid = false;
XREFSINFO* info = nullptr;

explicit AddressInfo(duint address)
{
XREFSINFO preparedInfo;
if(!xrefs.PrepareValue(preparedInfo, address, false))
return;

auto key = Xrefs::VaKey(address);
auto & mapData = xrefs.GetDataUnsafe();
auto insertResult = mapData.emplace(key, preparedInfo);

info = &insertResult.first->second;

valid = true;
}
};

EXCLUSIVE_ACQUIRE(LockCrossReferences);

std::unordered_map<duint, FromInfo> fromCache;
std::unordered_map<duint, AddressInfo> addressCache;
duint succeeded = 0;

for(duint i = 0; i < Count; i++)
{
found->second.references.insert({ xrefRecord.addr, xrefRecord });
found->second.type = max(found->second.type, xrefRecord.type);
duint address = Edges[i].address;
duint from = Edges[i].from;

auto fromCacheIt = fromCache.find(from);
if(fromCacheIt == fromCache.end())
fromCacheIt = fromCache.emplace(from, FromInfo(from)).first;

const auto & fromInfo = fromCacheIt->second;
if(!fromInfo.valid)
continue;
if(address < fromInfo.moduleBase || address >= fromInfo.moduleBase + fromInfo.moduleSize)
continue;

auto addressCacheIt = addressCache.find(address);
if(addressCacheIt == addressCache.end())
addressCacheIt = addressCache.emplace(address, AddressInfo(address)).first;

const auto & addressInfo = addressCacheIt->second;
if(!addressInfo.valid)
continue;

auto & info = *addressInfo.info;
auto & xrefRecord = fromInfo.xrefRecord;
info.references.emplace(xrefRecord.addr, xrefRecord);
info.type = max(info.type, xrefRecord.type);

succeeded++;
}
return true;

return succeeded;
}

bool XrefGet(duint Address, XREF_INFO* List)
Expand Down
1 change: 1 addition & 0 deletions src/dbg/xrefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "jansson/jansson_x64dbg.h"

bool XrefAdd(duint Address, duint From);
duint XrefAddMulti(const XREF_EDGE* Edges, duint Count);
bool XrefGet(duint Address, XREF_INFO* List);
duint XrefGetCount(duint Address);
XREFTYPE XrefGetType(duint Address);
Expand Down
2 changes: 1 addition & 1 deletion src/gui/Src/Gui/MemoryMapView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ void MemoryMapView::contextMenuSlot(const QPoint & pos)

static QString getProtectionString(DWORD Protect)
{
#define RIGHTS_STRING (sizeof("ERWCG") + 1)
#define RIGHTS_STRING (sizeof("ERWCG"))
char rights[RIGHTS_STRING];

if(!DbgFunctions()->PageRightsToString(Protect, rights))
Expand Down
47 changes: 29 additions & 18 deletions src/gui/Src/Gui/ZehSymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,35 @@

class SymbolInfoWrapper
{
SYMBOLINFO info;

public:
SymbolInfoWrapper()
{
memset(&info, 0, sizeof(SYMBOLINFO));
}

~SymbolInfoWrapper()
void free()
{
if(info.freeDecorated)
BridgeFree(info.decoratedSymbol);
if(info.freeUndecorated)
BridgeFree(info.undecoratedSymbol);
}

SYMBOLINFO* operator&() { return &info; }
SYMBOLINFO info{};

public:
SymbolInfoWrapper() = default;
~SymbolInfoWrapper() { free(); }

SymbolInfoWrapper(const SymbolInfoWrapper &) = delete;
SymbolInfoWrapper & operator=(const SymbolInfoWrapper &) = delete;

SYMBOLINFO* put()
{
free();
memset(&info, 0, sizeof(info));
return &info;
}

SYMBOLINFO* get() { return &info; }
const SYMBOLINFO* get() const { return &info; }

SYMBOLINFO* operator->() { return &info; }
const SYMBOLINFO* operator->() const { return &info; }
};

ZehSymbolTable::ZehSymbolTable(QWidget* parent)
Expand Down Expand Up @@ -51,8 +62,8 @@ QString ZehSymbolTable::getCellContent(int r, int c)
if(!isValidIndex(r, c))
return QString();
SymbolInfoWrapper info;
DbgGetSymbolInfo(&mData.at(r), &info);
return symbolInfoString(&info, c);
DbgGetSymbolInfo(&mData.at(r), info.put());
return symbolInfoString(info.get(), c);
}

bool ZehSymbolTable::isValidIndex(int r, int c)
Expand All @@ -67,8 +78,8 @@ void ZehSymbolTable::sortRows(int column, bool ascending)
std::stable_sort(mData.begin(), mData.end(), [this, column, ascending](const SYMBOLPTR & a, const SYMBOLPTR & b)
{
SymbolInfoWrapper ainfo, binfo;
DbgGetSymbolInfo(&a, &ainfo);
DbgGetSymbolInfo(&b, &binfo);
DbgGetSymbolInfo(&a, ainfo.put());
DbgGetSymbolInfo(&b, binfo.put());
switch(column)
{
case ColAddr:
Expand All @@ -88,16 +99,16 @@ void ZehSymbolTable::sortRows(int column, bool ascending)

case ColDecorated:
{
auto acell = symbolInfoString(&ainfo, ColDecorated);
auto bcell = symbolInfoString(&binfo, ColDecorated);
auto acell = symbolInfoString(ainfo.get(), ColDecorated);
auto bcell = symbolInfoString(binfo.get(), ColDecorated);
int result = QString::compare(acell, bcell);
return ascending ? result < 0 : result > 0;
}

case ColUndecorated:
{
auto acell = symbolInfoString(&ainfo, ColUndecorated);
auto bcell = symbolInfoString(&binfo, ColUndecorated);
auto acell = symbolInfoString(ainfo.get(), ColUndecorated);
auto bcell = symbolInfoString(binfo.get(), ColUndecorated);
int result = QString::compare(acell, bcell);
return ascending ? result < 0 : result > 0;
}
Expand Down

0 comments on commit 17584fc

Please sign in to comment.