1
0
Fork 0

DBG+BRIDGE+GUI: initial version of struct viewer

This commit is contained in:
mrexodia 2016-11-27 00:51:24 +01:00
parent 59f944a090
commit de1951e9ca
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
14 changed files with 365 additions and 203 deletions

View File

@ -1029,6 +1029,7 @@ typedef struct _TYPEDESCRIPTOR
bool expanded; //is the type node expanded?
const char* name; //type name (int b)
duint addr; //virtual address
duint offset; //offset to addr for the actual location
int id; //type id
int size; //sizeof(type)
TYPETOSTRING callback; //convert to string

View File

@ -331,108 +331,134 @@ struct PrintVisitor : TypeManager::Visitor
return StringUtils::sprintf(format, *(T*)data);
}
static bool cbPrintPrimitive(const TYPEDESCRIPTOR* type, char* dest, size_t* destCount)
{
if(!type->addr)
{
*dest = '\0';
return true;
}
String valueStr;
Memory<unsigned char*> data(type->size);
if(MemRead(type->addr + type->offset, data(), data.size()))
{
switch(Primitive(type->id))
{
case Void:
valueStr.clear();
break;
case Int8:
valueStr += basicPrint<char>(data(), "%c");
break;
case Uint8:
valueStr += basicPrint<unsigned char>(data(), "0x%02X");
break;
case Int16:
valueStr += basicPrint<short>(data(), "%d");
break;
case Uint16:
valueStr += basicPrint<short>(data(), "%u");
break;
case Int32:
valueStr += basicPrint<int>(data(), "%d");
break;
case Uint32:
valueStr += basicPrint<unsigned int>(data(), "%u");
break;
case Int64:
valueStr += basicPrint<long long>(data(), "%lld");
break;
case Uint64:
valueStr += basicPrint<unsigned long long>(data(), "%llu");
break;
case Dsint:
#ifdef _WIN64
valueStr += basicPrint<dsint>(data(), "%lld");
#else
valueStr += basicPrint<dsint>(data(), "%d");
#endif //_WIN64
break;
case Duint:
#ifdef _WIN64
valueStr += basicPrint<duint>(data(), "%llu");
#else
valueStr += basicPrint<duint>(data(), "%u");
#endif //_WIN64
break;
case Float:
valueStr += basicPrint<float>(data(), "%f");
break;
case Double:
valueStr += basicPrint<double>(data(), "%f");
break;
case Pointer:
valueStr += basicPrint<void*>(data(), "0x%p");
break;
case PtrString:
{
valueStr += basicPrint<char*>(data(), "0x%p");
Memory<char*> strdata(MAX_STRING_SIZE + 1);
if(MemRead(*(duint*)data(), strdata(), strdata.size() - 1))
{
valueStr += "\"";
valueStr += strdata();
valueStr.push_back('\"');
}
else
valueStr += "???";
}
break;
case PtrWString:
{
valueStr += basicPrint<wchar_t*>(data(), "0x%p");
Memory<wchar_t*> strdata(MAX_STRING_SIZE * 2 + 2);
if(MemRead(*(duint*)data(), strdata(), strdata.size() - 2))
{
valueStr += "L\"";
valueStr += StringUtils::Utf16ToUtf8(strdata());
valueStr.push_back('\"');
}
else
valueStr += "???";
}
break;
default:
return false;
}
}
else
valueStr = "???";
if(*destCount <= valueStr.size())
{
*destCount = valueStr.size() + 1;
return false;
}
strcpy_s(dest, *destCount, valueStr.c_str());
return true;
}
bool visitType(const Member & member, const Type & type) override
{
String valueStr;
Memory<unsigned char*> data(type.size);
if(mAddr)
{
if(MemRead(mAddr + mOffset, data(), data.size()))
{
valueStr.assign(" = ");
switch(type.primitive)
{
case Int8:
valueStr += basicPrint<char>(data(), "%c");
break;
case Uint8:
valueStr += basicPrint<unsigned char>(data(), "0x%02X");
break;
case Int16:
valueStr += basicPrint<short>(data(), "%d");
break;
case Uint16:
valueStr += basicPrint<short>(data(), "%u");
break;
case Int32:
valueStr += basicPrint<int>(data(), "%d");
break;
case Uint32:
valueStr += basicPrint<unsigned int>(data(), "%u");
break;
case Int64:
valueStr += basicPrint<long long>(data(), "%lld");
break;
case Uint64:
valueStr += basicPrint<unsigned long long>(data(), "%llu");
break;
case Dsint:
#ifdef _WIN64
valueStr += basicPrint<dsint>(data(), "%lld");
#else
valueStr += basicPrint<dsint>(data(), "%d");
#endif //_WIN64
break;
case Duint:
#ifdef _WIN64
valueStr += basicPrint<duint>(data(), "%llu");
#else
valueStr += basicPrint<duint>(data(), "%u");
#endif //_WIN64
break;
case Float:
valueStr += basicPrint<float>(data(), "%f");
break;
case Double:
valueStr += basicPrint<double>(data(), "%f");
break;
case Pointer:
valueStr += basicPrint<void*>(data(), "0x%p");
break;
case PtrString:
{
valueStr += basicPrint<char*>(data(), "0x%p");
Memory<char*> strdata(MAX_STRING_SIZE + 1);
if(MemRead(*(duint*)data(), strdata(), strdata.size() - 1))
{
valueStr += " \"";
valueStr += strdata();
valueStr.push_back('\"');
}
else
valueStr += " ???";
}
break;
case PtrWString:
{
valueStr += basicPrint<wchar_t*>(data(), "0x%p");
Memory<wchar_t*> strdata(MAX_STRING_SIZE * 2 + 2);
if(MemRead(*(duint*)data(), strdata(), strdata.size() - 2))
{
valueStr += " L\"";
valueStr += StringUtils::Utf16ToUtf8(strdata());
valueStr.push_back('\"');
}
else
valueStr += " ???";
}
break;
default:
return false;
}
}
else
valueStr = " ???";
}
indent();
String tname;
auto ptype = mParents.empty() ? Parent::Struct : parent().type;
if(ptype == Parent::Array)
dprintf_untranslated("%s[%u]%s;", member.name.c_str(), parent().index++, valueStr.c_str());
tname = StringUtils::sprintf("%s[%u]", member.name.c_str(), parent().index++);
else
dprintf_untranslated("%s %s%s;", type.name.c_str(), member.name.c_str(), valueStr.c_str());
dputs_untranslated(type.pointto.empty() || mPtrDepth >= mMaxPtrDepth ? "" : " {");
tname = StringUtils::sprintf("%s %s", type.name.c_str(), member.name.c_str());
TYPEDESCRIPTOR td;
td.expanded = false;
td.name = tname.c_str();
td.addr = mAddr;
td.offset = mOffset;
td.id = type.primitive;
td.size = type.size;
td.callback = cbPrintPrimitive;
td.userdata = nullptr;
mNode = GuiTypeAddNode(mParents.empty() ? nullptr : parent().node, &td);
if(ptype != Parent::Union)
mOffset += type.size;
return true;
@ -440,17 +466,41 @@ struct PrintVisitor : TypeManager::Visitor
bool visitStructUnion(const Member & member, const StructUnion & type) override
{
indent();
dprintf_untranslated("%s %s {\n", type.isunion ? "union" : "struct", type.name.c_str());
String tname = StringUtils::sprintf("%s %s", type.isunion ? "union" : "struct", type.name.c_str());
TYPEDESCRIPTOR td;
td.expanded = true;
td.name = tname.c_str();
td.addr = mAddr;
td.offset = mOffset;
td.id = Void;
td.size = type.size;
td.callback = nullptr;
td.userdata = nullptr;
auto node = GuiTypeAddNode(mParents.empty() ? nullptr : parent().node, &td);
mParents.push_back(Parent(type.isunion ? Parent::Union : Parent::Struct));
parent().node = node;
return true;
}
bool visitArray(const Member & member) override
{
indent();
dprintf_untranslated("%s %s[%d] {\n", member.type.c_str(), member.name.c_str(), member.arrsize);
String tname = StringUtils::sprintf("%s %s[%d]", member.type.c_str(), member.name.c_str(), member.arrsize);
TYPEDESCRIPTOR td;
td.expanded = member.arrsize <= 5;
td.name = tname.c_str();
td.addr = mAddr;
td.offset = mOffset;
td.id = Void;
td.size = member.arrsize * SizeofType(member.type);
td.callback = nullptr;
td.userdata = nullptr;
auto node = GuiTypeAddNode(mParents.empty() ? nullptr : parent().node, &td);
mParents.push_back(Parent(Parent::Array));
parent().node = node;
return true;
}
@ -460,12 +510,15 @@ struct PrintVisitor : TypeManager::Visitor
auto res = visitType(member, type); //print the pointer value
if(mPtrDepth >= mMaxPtrDepth)
return false;
duint value = 0;
if(!mAddr || !MemRead(mAddr + offset, &value, sizeof(value)))
return false;
mParents.push_back(Parent(Parent::Pointer));
parent().offset = mOffset;
parent().addr = mAddr;
parent().node = mNode;
mOffset = 0;
mAddr = value;
mPtrDepth++;
@ -481,11 +534,6 @@ struct PrintVisitor : TypeManager::Visitor
mPtrDepth--;
}
mParents.pop_back();
indent();
if(parent().type == Parent::Array)
dprintf_untranslated("};\n");
else
dprintf_untranslated("} %s;\n", member.name.c_str());
return true;
}
@ -504,6 +552,7 @@ private:
unsigned int index = 0;
duint addr = 0;
duint offset = 0;
void* node = nullptr;
explicit Parent(Type type)
: type(type) { }
@ -514,19 +563,12 @@ private:
return mParents[mParents.size() - 1];
}
void indent() const
{
if(mAddr)
dprintf_untranslated("%p ", mAddr + mOffset);
for(auto i = 0; i < int(mParents.size()) * 2; i++)
dprintf_untranslated(" ");
}
std::vector<Parent> mParents;
duint mOffset = 0;
duint mAddr = 0;
int mPtrDepth = 0;
int mMaxPtrDepth = 0;
void* mNode = nullptr;
};
bool cbInstrVisitType(int argc, char* argv[])
@ -557,6 +599,8 @@ bool cbInstrVisitType(int argc, char* argv[])
dputs(QT_TRANSLATE_NOOP("DBG", "VisitType failed"));
return false;
}
GuiUpdateTypeWidget();
dputs(QT_TRANSLATE_NOOP("DBG", "Done!"));
return true;
}

View File

@ -8,7 +8,7 @@ namespace Types
{
enum Primitive
{
Unknown,
Void,
Int8,
Uint8,
Int16,

View File

@ -360,82 +360,6 @@ 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

View File

@ -543,6 +543,8 @@ void AppearanceDialog::colorInfoListInit()
colorInfoListAppend(tr("Memory Map %1").arg(ArchValue(tr("EIP"), tr("RIP"))), "MemoryMapCipColor", "MemoryMapCipBackgroundColor");
colorInfoListAppend(tr("Memory Map Section Text"), "MemoryMapSectionTextColor", "");
colorInfoListAppend(tr("Search Highlight Color"), "SearchListViewHighlightColor", "");
colorInfoListAppend(tr("Struct primary background"), "StructBackgroundColor", "");
colorInfoListAppend(tr("Struct secondary background"), "StructAlternateBackgroundColor", "");
//dev helper
const QMap<QString, QColor>* Colors = &Config()->defaultColors;

View File

@ -1,5 +1,10 @@
#include "StructWidget.h"
#include "ui_StructWidget.h"
#include "Configuration.h"
#include "MenuBuilder.h"
#include "LineEditDialog.h"
#include "GotoDialog.h"
#include <QFileDialog>
struct TypeDescriptor
{
@ -17,6 +22,12 @@ StructWidget::StructWidget(QWidget* parent) :
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()));
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(shortcutsUpdatedSlot()));
colorsUpdatedSlot();
fontsUpdatedSlot();
setupContextMenu();
setupColumns();
}
@ -25,13 +36,36 @@ StructWidget::~StructWidget()
delete ui;
}
void StructWidget::colorsUpdatedSlot()
{
auto color = ConfigColor("AbstractTableViewTextColor");
auto background = ConfigColor("StructBackgroundColor");
auto altBackground = ConfigColor("StructAlternateBackgroundColor");
auto style = QString("QTreeWidget { color: %1; background-color: %2; alternate-background-color: %3; }").arg(color.name(), background.name(), altBackground.name());
ui->treeWidget->setStyleSheet(style);
}
void StructWidget::fontsUpdatedSlot()
{
auto font = ConfigFont("AbstractTableView");
setFont(font);
ui->treeWidget->setFont(font);
ui->treeWidget->header()->setFont(font);
}
void StructWidget::shortcutsUpdatedSlot()
{
for(const auto & actionShortcut : actionShortcutPairs)
actionShortcut.action->setShortcut(ConfigShortcut(actionShortcut.shortcut));
}
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);
auto text = QStringList() << dtype.name << ToPtrString(dtype.type.addr + dtype.type.offset) << "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;
@ -48,12 +82,13 @@ void StructWidget::typeClear()
void StructWidget::typeUpdateWidget()
{
QTreeWidgetItemIterator it(ui->treeWidget);
while(*it)
for(QTreeWidgetItemIterator it(ui->treeWidget); *it; ++it)
{
QString valueStr;
QTreeWidgetItem* item = *it;
auto type = item->data(0, Qt::UserRole).value<TypeDescriptor>();
auto addr = type.type.addr + type.type.offset;
item->setText(1, ToPtrString(addr));
QString valueStr;
if(type.type.callback) //use the provided callback
{
char value[128] = "";
@ -73,20 +108,138 @@ void StructWidget::typeUpdateWidget()
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))
if(DbgMemRead(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(0, 300); //Name
ui->treeWidget->setColumnWidth(1, 80); //Address
ui->treeWidget->setColumnWidth(2, 80); //Size
//ui->treeWidget->setColumnWidth(3, 80); //Value
}
#define hasSelection !!ui->treeWidget->selectedItems().count()
#define selectedItem ui->treeWidget->selectedItems()[0]
#define selectedType selectedItem->data(0, Qt::UserRole).value<TypeDescriptor>().type
void StructWidget::setupContextMenu()
{
mMenuBuilder = new MenuBuilder(this);
mMenuBuilder->addAction(makeAction(DIcon("dump.png"), tr("&Follow in Dump"), SLOT(followDumpSlot())), [this](QMenu*)
{
return hasSelection && DbgMemIsValidReadPtr(selectedType.addr + selectedType.offset);
});
mMenuBuilder->addAction(makeAction(DIcon("structaddr.png"), tr("Change address"), SLOT(changeAddrSlot())), [this](QMenu*)
{
return hasSelection && !selectedItem->parent() && DbgIsDebugging();
});
mMenuBuilder->addAction(makeAction(DIcon("visitstruct.png"), tr("Visit type"), SLOT(visitSlot())));
mMenuBuilder->addAction(makeAction(DIcon("database-import.png"), tr("Load JSON"), SLOT(loadJsonSlot())));
mMenuBuilder->addAction(makeAction(DIcon("source.png"), tr("Parse header"), SLOT(parseFileSlot())));
mMenuBuilder->addAction(makeAction(DIcon("removestruct.png"), tr("Remove"), SLOT(removeSlot())), [this](QMenu*)
{
return hasSelection && !selectedItem->parent();
});
mMenuBuilder->addAction(makeAction(DIcon("eraser.png"), tr("Clear"), SLOT(clearSlot())));
mMenuBuilder->addAction(makeShortcutAction(DIcon("sync.png"), tr("&Refresh"), SLOT(refreshSlot()), "ActionRefresh"));
}
void StructWidget::on_treeWidget_customContextMenuRequested(const QPoint & pos)
{
QMenu wMenu;
mMenuBuilder->build(&wMenu);
if(wMenu.actions().count())
wMenu.exec(ui->treeWidget->viewport()->mapToGlobal(pos));
}
void StructWidget::followDumpSlot()
{
if(!hasSelection)
return;
DbgCmdExec(QString("dump %1").arg(ToPtrString(selectedType.addr + selectedType.offset)).toUtf8().constData());
}
void StructWidget::clearSlot()
{
ui->treeWidget->clear();
}
void StructWidget::removeSlot()
{
if(!hasSelection)
return;
delete selectedItem;
}
void StructWidget::visitSlot()
{
//TODO: replace with a list to pick from
LineEditDialog mLineEdit(this);
mLineEdit.setWindowTitle(tr("Type to visit"));
if(mLineEdit.exec() != QDialog::Accepted || !mLineEdit.editText.length())
return;
if(!mGotoDialog)
mGotoDialog = new GotoDialog(this);
duint addr = 0;
mGotoDialog->setWindowTitle(tr("Address to visit"));
if(DbgIsDebugging() && mGotoDialog->exec() == QDialog::Accepted)
addr = DbgValFromString(mGotoDialog->expressionText.toUtf8().constData());
DbgCmdExec(QString("VisitType %1, %2").arg(mLineEdit.editText, ToPtrString(addr)).toUtf8().constData());
}
void StructWidget::loadJsonSlot()
{
auto filename = QFileDialog::getOpenFileName(this, tr("Load JSON"), QString(), tr("JSON files (*.json);;All files (*.*)"));
if(!filename.length())
return;
filename = QDir::toNativeSeparators(filename);
DbgCmdExec(QString("LoadTypes \"%1\"").arg(filename).toUtf8().constData());
}
void StructWidget::parseFileSlot()
{
auto filename = QFileDialog::getOpenFileName(this, tr("Parse header"), QString(), tr("Header files (*.h *.hpp);;All files (*.*)"));
if(!filename.length())
return;
filename = QDir::toNativeSeparators(filename);
DbgCmdExec(QString("ParseTypes \"%1\"").arg(filename).toUtf8().constData());
}
static void changeTypeAddr(QTreeWidgetItem* item, duint addr)
{
auto changeAddr = item->data(0, Qt::UserRole).value<TypeDescriptor>().type.addr;
for(QTreeWidgetItemIterator it(item); *it; ++it)
{
QTreeWidgetItem* item = *it;
auto type = item->data(0, Qt::UserRole).value<TypeDescriptor>();
type.type.addr = type.type.addr == changeAddr ? addr : 0; //invalidate pointers (requires revisit)
QVariant var;
var.setValue(type);
item->setData(0, Qt::UserRole, var);
}
}
void StructWidget::changeAddrSlot()
{
if(!hasSelection || !DbgIsDebugging())
return;
if(!mGotoDialog)
mGotoDialog = new GotoDialog(this);
mGotoDialog->setWindowTitle(tr("Change address"));
if(mGotoDialog->exec() != QDialog::Accepted)
return;
changeTypeAddr(selectedItem, DbgValFromString(mGotoDialog->expressionText.toUtf8().constData()));
refreshSlot();
}
void StructWidget::refreshSlot()
{
typeUpdateWidget();
}

View File

@ -4,6 +4,9 @@
#include <QWidget>
#include "Bridge.h"
class MenuBuilder;
class GotoDialog;
namespace Ui
{
class StructWidget;
@ -18,14 +21,36 @@ public:
~StructWidget();
public slots:
void colorsUpdatedSlot();
void fontsUpdatedSlot();
void shortcutsUpdatedSlot();
void typeAddNode(void* parent, const TYPEDESCRIPTOR* type);
void typeClear();
void typeUpdateWidget();
private:
Ui::StructWidget* ui;
MenuBuilder* mMenuBuilder;
GotoDialog* mGotoDialog = nullptr;
void setupColumns();
void setupContextMenu();
private slots:
void on_treeWidget_customContextMenuRequested(const QPoint & pos);
void followDumpSlot();
void clearSlot();
void removeSlot();
void visitSlot();
void loadJsonSlot();
void parseFileSlot();
void changeAddrSlot();
void refreshSlot();
protected:
#include "ActionHelpers.h"
};
#endif // STRUCTWIDGET_H

View File

@ -10,9 +10,16 @@
<height>300</height>
</rect>
</property>
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="windowTitle">
<string>Struct</string>
</property>
<property name="windowIcon">
<iconset resource="../../resource.qrc">
<normaloff>:/icons/images/struct.png</normaloff>:/icons/images/struct.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
@ -31,10 +38,8 @@
</property>
<item>
<widget class="QTreeWidget" name="treeWidget">
<property name="font">
<font>
<family>Lucida Console</family>
</font>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
@ -69,6 +74,8 @@
</item>
</layout>
</widget>
<resources/>
<resources>
<include location="../../resource.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -187,6 +187,8 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
defaultColors.insert("MemoryMapCipBackgroundColor", QColor("#000000"));
defaultColors.insert("MemoryMapSectionTextColor", QColor("#8B671F"));
defaultColors.insert("SearchListViewHighlightColor", QColor("#FF0000"));
defaultColors.insert("StructBackgroundColor", QColor("#FFF8F0"));
defaultColors.insert("StructAlternateBackgroundColor", QColor("#DCD9CF"));
//bool settings
QMap<QString, bool> disassemblyBool;

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

BIN
src/gui/images/struct.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 759 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

View File

@ -270,5 +270,9 @@
<file>images/breakpoint_module_add.png</file>
<file>images/importsettings.png</file>
<file>images/initscript.png</file>
<file>images/struct.png</file>
<file>images/removestruct.png</file>
<file>images/visitstruct.png</file>
<file>images/structaddr.png</file>
</qresource>
</RCC>