DBG+BRIDGE+GUI: basics of type display GUI working
This commit is contained in:
parent
457b4bd68b
commit
f44c9fa705
|
|
@ -1057,6 +1057,7 @@ BRIDGE_IMPEXP void GuiUpdateAllViews()
|
|||
GuiUpdateSEHChain();
|
||||
GuiUpdateArgumentWidget();
|
||||
GuiUpdateGraphView();
|
||||
GuiUpdateTypeWidget();
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP void GuiUpdateRegisterView()
|
||||
|
|
@ -1523,6 +1524,21 @@ BRIDGE_IMPEXP void GuiProcessEvents()
|
|||
_gui_sendmessage(GUI_PROCESS_EVENTS, nullptr, nullptr);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP void* GuiTypeAddNode(void* parent, const TYPEDESCRIPTOR* type)
|
||||
{
|
||||
return _gui_sendmessage(GUI_TYPE_ADDNODE, parent, (void*)type);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP bool GuiTypeClear()
|
||||
{
|
||||
return !!_gui_sendmessage(GUI_TYPE_CLEAR, nullptr, nullptr);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP void GuiUpdateTypeWidget()
|
||||
{
|
||||
_gui_sendmessage(GUI_UPDATE_TYPE_WIDGET, nullptr, nullptr);
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
hInst = hinstDLL;
|
||||
|
|
|
|||
|
|
@ -975,12 +975,18 @@ typedef enum
|
|||
GUI_MENU_SET_ENTRY_CHECKED, // param1=int hEntry, param2=bool checked
|
||||
GUI_ADD_INFO_LINE, // param1=const char* infoline, param2=unused
|
||||
GUI_PROCESS_EVENTS, // param1=unused, param2=unused
|
||||
GUI_TYPE_ADDNODE, // param1=void* parent, param2=TYPEDESCRIPTOR* type
|
||||
GUI_TYPE_CLEAR, // param1=unused, param2=unused
|
||||
GUI_UPDATE_TYPE_WIDGET, // param1=unused, param2=unused
|
||||
} GUIMSG;
|
||||
|
||||
//GUI Typedefs
|
||||
struct _TYPEDESCRIPTOR;
|
||||
|
||||
typedef void (*GUICALLBACK)();
|
||||
typedef bool (*GUISCRIPTEXECUTE)(const char* text);
|
||||
typedef void (*GUISCRIPTCOMPLETER)(const char* text, char** entries, int* entryCount);
|
||||
typedef bool (*TYPETOSTRING)(const struct _TYPEDESCRIPTOR* type, char* dest, size_t* destCount); //don't change destCount for final failure
|
||||
|
||||
//GUI structures
|
||||
typedef struct
|
||||
|
|
@ -1018,6 +1024,17 @@ typedef struct
|
|||
char className[MAX_STRING_SIZE];
|
||||
} ACTIVEVIEW;
|
||||
|
||||
typedef struct _TYPEDESCRIPTOR
|
||||
{
|
||||
bool expanded; //is the type node expanded?
|
||||
const char* name; //type name (int b)
|
||||
duint addr; //virtual address
|
||||
int id; //type id
|
||||
int size; //sizeof(type)
|
||||
TYPETOSTRING callback; //convert to string
|
||||
void* userdata; //user data
|
||||
} TYPEDESCRIPTOR;
|
||||
|
||||
//GUI functions
|
||||
//code page is utf8
|
||||
BRIDGE_IMPEXP const char* GuiTranslateText(const char* Source);
|
||||
|
|
@ -1118,6 +1135,9 @@ BRIDGE_IMPEXP void GuiSelectInMemoryMap(duint addr);
|
|||
BRIDGE_IMPEXP void GuiGetActiveView(ACTIVEVIEW* activeView);
|
||||
BRIDGE_IMPEXP void GuiAddInfoLine(const char* infoLine);
|
||||
BRIDGE_IMPEXP void GuiProcessEvents();
|
||||
BRIDGE_IMPEXP void* GuiTypeAddNode(void* parent, const TYPEDESCRIPTOR* type);
|
||||
BRIDGE_IMPEXP bool GuiTypeClear();
|
||||
BRIDGE_IMPEXP void GuiUpdateTypeWidget();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace Types
|
|||
{
|
||||
enum Primitive
|
||||
{
|
||||
Unknown,
|
||||
Int8,
|
||||
Uint8,
|
||||
Int16,
|
||||
|
|
|
|||
|
|
@ -360,6 +360,82 @@ static void registercommands()
|
|||
dbgcmdnew("EnumTypes", cbInstrEnumTypes, false); //EnumTypes
|
||||
dbgcmdnew("LoadTypes", cbInstrLoadTypes, false); //LoadTypes
|
||||
dbgcmdnew("ParseTypes", cbInstrParseTypes, false); //ParseTypes
|
||||
dbgcmdnew("TestTypeGui", [](int argc, char* argv[])
|
||||
{
|
||||
TYPEDESCRIPTOR type;
|
||||
type.expanded = true;
|
||||
type.name = "struct TEST";
|
||||
type.addr = 0;
|
||||
type.id = 0;
|
||||
type.size = 19;
|
||||
type.callback = [](const TYPEDESCRIPTOR * type, char* dest, size_t* destCount)
|
||||
{
|
||||
if(type->id == -1)
|
||||
{
|
||||
*dest = '\0';
|
||||
return true;
|
||||
}
|
||||
auto value = StringUtils::sprintf("0x%X, %d (size: %d)", type->userdata, type->userdata, type->size);
|
||||
if(*destCount <= value.size())
|
||||
{
|
||||
*destCount = value.size() + 1;
|
||||
return false;
|
||||
}
|
||||
strcpy_s(dest, *destCount, value.c_str());
|
||||
return true;
|
||||
};
|
||||
type.userdata = 0;
|
||||
|
||||
auto t = GuiTypeAddNode(nullptr, &type);
|
||||
type.id = 1;
|
||||
type.addr = 0;
|
||||
type.size = 4;
|
||||
type.name = "int a";
|
||||
type.userdata = (void*)0xA;
|
||||
GuiTypeAddNode(t, &type);
|
||||
type.addr = 4;
|
||||
type.size = 1;
|
||||
type.name = "char b";
|
||||
type.userdata = (void*)0xB;
|
||||
GuiTypeAddNode(t, &type);
|
||||
type.id = 0;
|
||||
type.addr = 5;
|
||||
type.size = 10;
|
||||
type.name = "struct BLUB";
|
||||
type.userdata = 0;
|
||||
auto e = GuiTypeAddNode(t, &type);
|
||||
type.id = 1;
|
||||
type.size = 2;
|
||||
type.name = "short c";
|
||||
type.userdata = (void*)0xC;
|
||||
GuiTypeAddNode(e, &type);
|
||||
type.id = 0;
|
||||
type.addr = 7;
|
||||
type.size = 8;
|
||||
type.name = "int[2]";
|
||||
type.userdata = 0;
|
||||
type.expanded = false;
|
||||
auto d = GuiTypeAddNode(e, &type);
|
||||
type.id = 1;
|
||||
type.size = 4;
|
||||
type.name = "int d[0]";
|
||||
type.userdata = (void*)0xD0;
|
||||
GuiTypeAddNode(d, &type);
|
||||
type.addr = 11;
|
||||
type.size = 4;
|
||||
type.name = "int d[1]";
|
||||
type.userdata = (void*)0xD1;
|
||||
GuiTypeAddNode(d, &type);
|
||||
type.addr = 15;
|
||||
type.size = 4;
|
||||
type.name = "int f";
|
||||
type.userdata = (void*)0xF;
|
||||
type.expanded = true;
|
||||
GuiTypeAddNode(t, &type);
|
||||
|
||||
GuiUpdateAllViews();
|
||||
return true;
|
||||
}, false);
|
||||
|
||||
//plugins
|
||||
dbgcmdnew("StartScylla\1scylla\1imprec", cbDebugStartScylla, false); //start scylla
|
||||
|
|
|
|||
|
|
@ -696,6 +696,28 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
|||
QCoreApplication::processEvents();
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_TYPE_ADDNODE:
|
||||
{
|
||||
BridgeResult result;
|
||||
emit typeAddNode(param1, (const TYPEDESCRIPTOR*)param2);
|
||||
return (void*)result.Wait();
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_TYPE_CLEAR:
|
||||
{
|
||||
BridgeResult result;
|
||||
emit typeClear();
|
||||
result.Wait();
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_UPDATE_TYPE_WIDGET:
|
||||
{
|
||||
emit typeUpdateWidget();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ signals:
|
|||
void selectInMemoryMap(duint addr);
|
||||
void getActiveView(ACTIVEVIEW* activeView);
|
||||
void addInfoLine(const QString & text);
|
||||
void typeAddNode(void* parent, const TYPEDESCRIPTOR* type);
|
||||
void typeClear();
|
||||
void typeUpdateWidget();
|
||||
|
||||
private:
|
||||
QMutex* mBridgeMutex;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,23 @@
|
|||
#include "StructWidget.h"
|
||||
#include "ui_StructWidget.h"
|
||||
|
||||
struct TypeDescriptor
|
||||
{
|
||||
TYPEDESCRIPTOR type;
|
||||
QString name;
|
||||
};
|
||||
Q_DECLARE_METATYPE(TypeDescriptor)
|
||||
|
||||
StructWidget::StructWidget(QWidget* parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::StructWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->treeWidget->setStyleSheet("QTreeWidget { color: #000000; background-color: #FFF8F0; alternate-background-color: #DCD9CF; }");
|
||||
showTree();
|
||||
connect(Bridge::getBridge(), SIGNAL(typeAddNode(void*, const TYPEDESCRIPTOR*)), this, SLOT(typeAddNode(void*, const TYPEDESCRIPTOR*)));
|
||||
connect(Bridge::getBridge(), SIGNAL(typeClear()), this, SLOT(typeClear()));
|
||||
connect(Bridge::getBridge(), SIGNAL(typeUpdateWidget()), this, SLOT(typeUpdateWidget()));
|
||||
setupColumns();
|
||||
}
|
||||
|
||||
StructWidget::~StructWidget()
|
||||
|
|
@ -15,18 +25,68 @@ StructWidget::~StructWidget()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
void StructWidget::showTree()
|
||||
void StructWidget::typeAddNode(void* parent, const TYPEDESCRIPTOR* type)
|
||||
{
|
||||
TypeDescriptor dtype;
|
||||
dtype.type = *type;
|
||||
dtype.name = QString(dtype.type.name);
|
||||
dtype.type.name = nullptr;
|
||||
auto text = QStringList() << dtype.name << ToPtrString(dtype.type.addr) << "0x" + ToHexString(dtype.type.size);
|
||||
QTreeWidgetItem* item = parent ? new QTreeWidgetItem((QTreeWidgetItem*)parent, text) : new QTreeWidgetItem(ui->treeWidget, text);
|
||||
item->setExpanded(dtype.type.expanded);
|
||||
QVariant var;
|
||||
var.setValue(dtype);
|
||||
item->setData(0, Qt::UserRole, var);
|
||||
Bridge::getBridge()->setResult(dsint(item));
|
||||
}
|
||||
|
||||
void StructWidget::typeClear()
|
||||
{
|
||||
ui->treeWidget->clear();
|
||||
QTreeWidgetItem* t = new QTreeWidgetItem(ui->treeWidget, QStringList() << "struct TEST");
|
||||
new QTreeWidgetItem(t, QStringList() << "int a" << "00000000" << "0xA");
|
||||
new QTreeWidgetItem(t, QStringList() << "char b" << "00000004" << "0xB");
|
||||
QTreeWidgetItem* e = new QTreeWidgetItem(t, QStringList() << "struct BLUB");
|
||||
new QTreeWidgetItem(e, QStringList() << "short c" << "00000005" << "0xC");
|
||||
QTreeWidgetItem* d = new QTreeWidgetItem(e, QStringList() << "int[2]");
|
||||
new QTreeWidgetItem(d, QStringList() << "int d[0]" << "00000007" << "0xD0");
|
||||
new QTreeWidgetItem(d, QStringList() << "int d[1]" << "00000011" << "0xD1");
|
||||
new QTreeWidgetItem(t, QStringList() << "int f" << "00000015" << "0xF");
|
||||
ui->treeWidget->setColumnWidth(0, 200);
|
||||
ui->treeWidget->setColumnWidth(1, 80);
|
||||
Bridge::getBridge()->setResult();
|
||||
}
|
||||
|
||||
void StructWidget::typeUpdateWidget()
|
||||
{
|
||||
QTreeWidgetItemIterator it(ui->treeWidget);
|
||||
while(*it)
|
||||
{
|
||||
QString valueStr;
|
||||
QTreeWidgetItem* item = *it;
|
||||
auto type = item->data(0, Qt::UserRole).value<TypeDescriptor>();
|
||||
if(type.type.callback) //use the provided callback
|
||||
{
|
||||
char value[128] = "";
|
||||
size_t valueCount = _countof(value);
|
||||
if(!type.type.callback(&type.type, value, &valueCount) && valueCount && valueCount != _countof(value))
|
||||
{
|
||||
auto dest = new char[valueCount];
|
||||
if(type.type.callback(&type.type, dest, &valueCount))
|
||||
valueStr = value;
|
||||
else
|
||||
valueStr = "???";
|
||||
delete[] dest;
|
||||
}
|
||||
else
|
||||
valueStr = value;
|
||||
}
|
||||
else if(!item->childCount() && type.type.size > 0 && type.type.size <= sizeof(uint64_t)) //attempt to display small, non-parent values
|
||||
{
|
||||
uint64_t data;
|
||||
if(DbgMemRead(type.type.addr, &data, type.type.size))
|
||||
valueStr = QString().sprintf("0x%llX, %llu", data, data, data);
|
||||
else if(type.type.addr)
|
||||
valueStr = "???";
|
||||
}
|
||||
item->setText(3, valueStr);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void StructWidget::setupColumns()
|
||||
{
|
||||
ui->treeWidget->setColumnWidth(0, 200); //Name
|
||||
ui->treeWidget->setColumnWidth(1, 80); //Address
|
||||
ui->treeWidget->setColumnWidth(2, 80); //Size
|
||||
//ui->treeWidget->setColumnWidth(3, 80); //Value
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define STRUCTWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "Bridge.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
|
|
@ -16,10 +17,15 @@ public:
|
|||
explicit StructWidget(QWidget* parent = 0);
|
||||
~StructWidget();
|
||||
|
||||
public slots:
|
||||
void typeAddNode(void* parent, const TYPEDESCRIPTOR* type);
|
||||
void typeClear();
|
||||
void typeUpdateWidget();
|
||||
|
||||
private:
|
||||
Ui::StructWidget* ui;
|
||||
|
||||
void showTree();
|
||||
void setupColumns();
|
||||
};
|
||||
|
||||
#endif // STRUCTWIDGET_H
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@
|
|||
<string>Address</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
|
|
|
|||
|
|
@ -211,7 +211,8 @@ SOURCES += \
|
|||
dbg/commands/cmd-watch-control.cpp \
|
||||
gui/Src/Gui/CustomizeMenuDialog.cpp \
|
||||
gui/Src/Utils/MenuBuilder.cpp \
|
||||
gui/Src/Gui/SimpleTraceDialog.cpp
|
||||
gui/Src/Gui/SimpleTraceDialog.cpp \
|
||||
gui/Src/Gui/StructWidget.cpp
|
||||
|
||||
HEADERS += \
|
||||
gui/Src/Exports.h \
|
||||
|
|
@ -282,6 +283,7 @@ HEADERS += \
|
|||
gui/Src/Gui/YaraRuleSelectionDialog.h \
|
||||
gui/Src/Disassembler/capstone_gui.h \
|
||||
gui/Src/Disassembler/QBeaEngine.h \
|
||||
gui/Src/Gui/StructWidget.h \
|
||||
dbg/_dbgfunctions.h \
|
||||
dbg/_exports.h \
|
||||
dbg/_global.h \
|
||||
|
|
@ -471,7 +473,8 @@ FORMS += \
|
|||
gui/Src/Gui/XrefBrowseDialog.ui \
|
||||
gui/Src/Gui/YaraRuleSelectionDialog.ui \
|
||||
gui/Src/Gui/CustomizeMenuDialog.ui \
|
||||
gui/Src/Gui/SimpleTraceDialog.ui
|
||||
gui/Src/Gui/SimpleTraceDialog.ui \
|
||||
gui/Src/Gui/StructWidget.ui
|
||||
|
||||
TRANSLATIONS += \
|
||||
gui/Translations/x64dbg.ts
|
||||
Loading…
Reference in New Issue