1
0
Fork 0
x64dbg/x64_dbg_gui/Project/Src/Gui/MemoryMapView.cpp

357 lines
13 KiB
C++

#include "MemoryMapView.h"
#include "Configuration.h"
MemoryMapView::MemoryMapView(StdTable *parent) : StdTable(parent)
{
enableMultiSelection(false);
int charwidth=getCharWidth();
addColumnAt(8+charwidth*2*sizeof(uint_t), "ADDR", false, "Address"); //addr
addColumnAt(8+charwidth*2*sizeof(uint_t), "SIZE", false, "Size"); //size
addColumnAt(8+charwidth*32, "INFO", false, "Page Information"); //page information
addColumnAt(8+charwidth*3, "TYP", false, "Allocation Type"); //allocation type
addColumnAt(8+charwidth*5, "CPROT", false, "Current Protection"); //current protection
addColumnAt(8+charwidth*5, "APROT", false, "Allocation Protection"); //allocation protection
addColumnAt(100, "", false);
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(stateChangedSlot(DBGSTATE)));
connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint)));
setupContextMenu();
}
void MemoryMapView::setupContextMenu()
{
//Follow in Dump
mFollowDump = new QAction("&Follow in Dump", this);
connect(mFollowDump, SIGNAL(triggered()), this, SLOT(followDumpSlot()));
//Follow in Disassembler
mFollowDisassembly = new QAction("Follow in &Disassembler", this);
mFollowDisassembly->setShortcutContext(Qt::WidgetShortcut);
mFollowDisassembly->setShortcut(QKeySequence("enter"));
connect(mFollowDisassembly, SIGNAL(triggered()), this, SLOT(followDisassemblerSlot()));
connect(this, SIGNAL(enterPressedSignal()), this, SLOT(followDisassemblerSlot()));
//Breakpoint menu
mBreakpointMenu = new QMenu("Memory &Breakpoint", this);
//Breakpoint->Memory Access
mMemoryAccessMenu = new QMenu("Access", this);
mMemoryAccessSingleshoot = new QAction("&Singleshoot", this);
connect(mMemoryAccessSingleshoot, SIGNAL(triggered()), this, SLOT(memoryAccessSingleshootSlot()));
mMemoryAccessMenu->addAction(mMemoryAccessSingleshoot);
mMemoryAccessRestore = new QAction("&Restore", this);
connect(mMemoryAccessRestore, SIGNAL(triggered()), this, SLOT(memoryAccessRestoreSlot()));
mMemoryAccessMenu->addAction(mMemoryAccessRestore);
mBreakpointMenu->addMenu(mMemoryAccessMenu);
//Breakpoint->Memory Write
mMemoryWriteMenu = new QMenu("Write", this);
mMemoryWriteSingleshoot = new QAction("&Singleshoot", this);
connect(mMemoryWriteSingleshoot, SIGNAL(triggered()), this, SLOT(memoryWriteSingleshootSlot()));
mMemoryWriteMenu->addAction(mMemoryWriteSingleshoot);
mMemoryWriteRestore = new QAction("&Restore", this);
connect(mMemoryWriteRestore, SIGNAL(triggered()), this, SLOT(memoryWriteRestoreSlot()));
mMemoryWriteMenu->addAction(mMemoryWriteRestore);
mBreakpointMenu->addMenu(mMemoryWriteMenu);
//Breakpoint->Memory Execute
mMemoryExecuteMenu = new QMenu("Execute", this);
mMemoryExecuteSingleshoot = new QAction("&Singleshoot", this);
mMemoryExecuteSingleshoot->setShortcutContext(Qt::WidgetShortcut);
connect(mMemoryExecuteSingleshoot, SIGNAL(triggered()), this, SLOT(memoryExecuteSingleshootSlot()));
mMemoryExecuteMenu->addAction(mMemoryExecuteSingleshoot);
mMemoryExecuteRestore = new QAction("&Restore", this);
connect(mMemoryExecuteRestore, SIGNAL(triggered()), this, SLOT(memoryExecuteRestoreSlot()));
mMemoryExecuteMenu->addAction(mMemoryExecuteRestore);
mBreakpointMenu->addMenu(mMemoryExecuteMenu);
//Breakpoint->Remove
mMemoryRemove = new QAction("&Remove", this);
mMemoryRemove->setShortcutContext(Qt::WidgetShortcut);
connect(mMemoryRemove, SIGNAL(triggered()), this, SLOT(memoryRemoveSlot()));
mBreakpointMenu->addAction(mMemoryRemove);
//Action shortcut action that does something
mMemoryExecuteSingleshootToggle = new QAction(this);
mMemoryExecuteSingleshootToggle->setShortcutContext(Qt::WidgetShortcut);
this->addAction(mMemoryExecuteSingleshootToggle);
connect(mMemoryExecuteSingleshootToggle, SIGNAL(triggered()), this, SLOT(memoryExecuteSingleshootToggleSlot()));
refreshShortcutsSlot();
connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcutsSlot()));
}
void MemoryMapView::refreshShortcutsSlot()
{
mMemoryExecuteSingleshoot->setShortcut(ConfigShortcut("ActionToggleBreakpoint"));
mMemoryRemove->setShortcut(ConfigShortcut("ActionToggleBreakpoint"));
mMemoryExecuteSingleshootToggle->setShortcut(ConfigShortcut("ActionToggleBreakpoint"));
}
void MemoryMapView::contextMenuSlot(const QPoint &pos)
{
if(!DbgIsDebugging())
return;
QMenu* wMenu = new QMenu(this); //create context menu
wMenu->addAction(mFollowDisassembly);
wMenu->addAction(mFollowDump);
wMenu->addSeparator();
wMenu->addMenu(mBreakpointMenu);
QMenu wCopyMenu("&Copy", this);
setupCopyMenu(&wCopyMenu);
if(wCopyMenu.actions().length())
{
wMenu->addSeparator();
wMenu->addMenu(&wCopyMenu);
}
QString wStr = getCellContent(getInitialSelection(), 0);
#ifdef _WIN64
uint_t selectedAddr=wStr.toULongLong(0, 16);
#else //x86
uint_t selectedAddr=wStr.toULong(0, 16);
#endif //_WIN64
if((DbgGetBpxTypeAt(selectedAddr)&bp_memory)==bp_memory) //memory breakpoint set
{
mMemoryAccessMenu->menuAction()->setVisible(false);
mMemoryWriteMenu->menuAction()->setVisible(false);
mMemoryExecuteMenu->menuAction()->setVisible(false);
mMemoryRemove->setVisible(true);
}
else //memory breakpoint not set
{
mMemoryAccessMenu->menuAction()->setVisible(true);
mMemoryWriteMenu->menuAction()->setVisible(true);
mMemoryExecuteMenu->menuAction()->setVisible(true);
mMemoryRemove->setVisible(false);
}
wMenu->exec(mapToGlobal(pos)); //execute context menu
}
QString MemoryMapView::getProtectionString(DWORD Protect)
{
QString wS;
switch(Protect & 0xFF)
{
case PAGE_EXECUTE:
wS = QString("E---");
break;
case PAGE_EXECUTE_READ:
wS = QString("ER--");
break;
case PAGE_EXECUTE_READWRITE:
wS = QString("ERW-");
break;
case PAGE_EXECUTE_WRITECOPY:
wS = QString("ERWC");
break;
case PAGE_NOACCESS:
wS = QString("----");
break;
case PAGE_READONLY:
wS = QString("-R--");
break;
case PAGE_READWRITE:
wS = QString("-RW-");
break;
case PAGE_WRITECOPY:
wS = QString("-RWC");
break;
}
if(Protect&PAGE_GUARD)
wS+=QString("G");
else
wS+=QString("-");
return wS;
}
QString MemoryMapView::paintContent(QPainter *painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h)
{
if(col==0) //address
{
QString wStr = getCellContent(rowBase + rowOffset, col);
#ifdef _WIN64
uint_t addr=wStr.toULongLong(0, 16);
#else //x86
uint_t addr=wStr.toULong(0, 16);
#endif //_WIN64
if((DbgGetBpxTypeAt(addr)&bp_memory)==bp_memory)
{
QString wStr = getCellContent(rowBase + rowOffset, col);
QColor bpBackgroundColor=ConfigColor("MemoryMapBreakpointBackgroundColor");
if(bpBackgroundColor.alpha())
painter->fillRect(QRect(x, y, w - 1, h), QBrush(bpBackgroundColor));
painter->setPen(ConfigColor("MemoryMapBreakpointColor"));
painter->drawText(QRect(x + 4, y, getColumnWidth(col) - 4, getRowHeight()), Qt::AlignVCenter | Qt::AlignLeft, wStr);
return "";
}
else if(isSelected(rowBase, rowOffset) == true)
painter->fillRect(QRect(x, y, w, h), QBrush(selectionColor));
}
else if(col == 2) //info
{
QString wStr = StdTable::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);;
if(wStr.startsWith(" \""))
{
painter->setPen(ConfigColor("MemoryMapSectionTextColor"));
painter->drawText(QRect(x + 4, y, getColumnWidth(col) - 4, getRowHeight()), Qt::AlignVCenter | Qt::AlignLeft, wStr);
return "";
}
}
return StdTable::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);
}
void MemoryMapView::stateChangedSlot(DBGSTATE state)
{
if(state == paused)
{
MEMMAP wMemMapStruct;
int wI;
memset(&wMemMapStruct, 0, sizeof(MEMMAP));
DbgMemMap(&wMemMapStruct);
setRowCount(wMemMapStruct.count);
for(wI = 0; wI < wMemMapStruct.count; wI++)
{
QString wS;
MEMORY_BASIC_INFORMATION wMbi = (wMemMapStruct.page)[wI].mbi;
// Base address
wS = QString("%1").arg((uint_t)wMbi.BaseAddress, sizeof(uint_t)*2, 16, QChar('0')).toUpper();
setCellContent(wI, 0, wS);
// Size
wS = QString("%1").arg((uint_t)wMbi.RegionSize, sizeof(uint_t)*2, 16, QChar('0')).toUpper();
setCellContent(wI, 1, wS);
// Information
wS = QString((wMemMapStruct.page)[wI].info);
setCellContent(wI, 2, wS);
// State
switch(wMbi.State)
{
case MEM_FREE:
wS = QString("FREE");
break;
case MEM_COMMIT:
wS = QString("COMM");
break;
case MEM_RESERVE:
wS = QString("RESV");
break;
default:
wS = QString("????");
}
setCellContent(wI, 3, wS);
// Type
switch(wMbi.Type)
{
case MEM_IMAGE:
wS = QString("IMG");
break;
case MEM_MAPPED:
wS = QString("MAP");
break;
case MEM_PRIVATE:
wS = QString("PRV");
break;
default:
wS = QString("N/A");
break;
}
setCellContent(wI, 3, wS);
// current access protection
wS=getProtectionString(wMbi.Protect);
setCellContent(wI, 4, wS);
// allocation protection
wS=getProtectionString(wMbi.AllocationProtect);
setCellContent(wI, 5, wS);
}
if(wMemMapStruct.page != 0)
BridgeFree(wMemMapStruct.page);
reloadData(); //refresh memory map
}
}
void MemoryMapView::followDumpSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExecDirect(QString("dump "+addr_text).toUtf8().constData());
emit showCpu();
}
void MemoryMapView::followDisassemblerSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExecDirect(QString("disasm "+addr_text).toUtf8().constData());
emit showCpu();
}
void MemoryMapView::memoryAccessSingleshootSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExec(QString("bpm "+addr_text+", 0, r").toUtf8().constData());
}
void MemoryMapView::memoryAccessRestoreSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExec(QString("bpm "+addr_text+", 1, r").toUtf8().constData());
}
void MemoryMapView::memoryWriteSingleshootSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExec(QString("bpm "+addr_text+", 0, w").toUtf8().constData());
}
void MemoryMapView::memoryWriteRestoreSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExec(QString("bpm "+addr_text+", 1, w").toUtf8().constData());
}
void MemoryMapView::memoryExecuteSingleshootSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExec(QString("bpm "+addr_text+", 0, x").toUtf8().constData());
}
void MemoryMapView::memoryExecuteRestoreSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExec(QString("bpm "+addr_text+", 1, x").toUtf8().constData());
}
void MemoryMapView::memoryRemoveSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
DbgCmdExec(QString("bpmc "+addr_text).toUtf8().constData());
}
void MemoryMapView::memoryExecuteSingleshootToggleSlot()
{
QString addr_text = getCellContent(getInitialSelection(), 0);
#ifdef _WIN64
uint_t selectedAddr=addr_text.toULongLong(0, 16);
#else //x86
uint_t selectedAddr=addr_text.toULong(0, 16);
#endif //_WIN64
if((DbgGetBpxTypeAt(selectedAddr)&bp_memory)==bp_memory) //memory breakpoint set
memoryRemoveSlot();
else
memoryExecuteSingleshootSlot();
}