Compare commits
86 Commits
b7347f4506
...
a4be9f87f5
Author | SHA1 | Date |
---|---|---|
|
a4be9f87f5 | |
|
56ee888a0b | |
|
3e1b3d61bc | |
|
ffb6de5b56 | |
|
f6c3e4219a | |
|
c589bb57c8 | |
|
6e1a5000e8 | |
|
bba369d607 | |
|
437573276b | |
|
e3adaaac5d | |
|
5628094e17 | |
|
4ad555a509 | |
|
8820440f06 | |
|
51e697b726 | |
|
56c3249e75 | |
|
13bd1f3164 | |
|
335d94d2d9 | |
|
b74f6b5d5d | |
|
68112f51da | |
|
e2b658f0a3 | |
|
ce73e9cdf7 | |
|
ef925bcfa7 | |
|
df8bdfe1fb | |
|
7fcb626ba2 | |
|
517c82604f | |
|
c28653700a | |
|
0f5bc725f8 | |
|
c65c956f85 | |
|
3beec936ec | |
|
7f2566b6ed | |
|
7c00347a24 | |
|
fdc97fe6d1 | |
|
a349f9c05f | |
|
bdb38d6a97 | |
|
e2d1d79930 | |
|
7733012330 | |
|
663bfbbb06 | |
|
5797dae1c3 | |
|
812c91d361 | |
|
6fba4478fb | |
|
952c16aad7 | |
|
b22266b822 | |
|
3d56c4fd35 | |
|
7e9a89847e | |
|
6228bfe2bf | |
|
9fa8c8cea0 | |
|
11d96f1878 | |
|
dd91e4376a | |
|
2ce5a283f5 | |
|
02c762ff4a | |
|
cdee7fed64 | |
|
b6be841a48 | |
|
bc3d7574bc | |
|
7405acd42d | |
|
3616f2d33a | |
|
b28e317073 | |
|
323d318329 | |
|
d08773d3c7 | |
|
5659f7db2c | |
|
d68e1d44a8 | |
|
b3dc97c4a5 | |
|
48d81226ed | |
|
f557751365 | |
|
4a767ea507 | |
|
8c6f3089e9 | |
|
4e5c2bd9c4 | |
|
7d00017e69 | |
|
145053d8ae | |
|
e6b43cdc6c | |
|
4301af38a9 | |
|
78f37958eb | |
|
9f046b96e2 | |
|
414c9cb23e | |
|
a85f177567 | |
|
b477ffc490 | |
|
7bf53e72f1 | |
|
6b05405714 | |
|
f475f7d841 | |
|
479fdaf38d | |
|
b8c2aad3b3 | |
|
59b5d923cd | |
|
3151aa6280 | |
|
6a970e657d | |
|
791d6ba59c | |
|
d5901879a7 | |
|
6cd26dd3dd |
|
@ -1,13 +1,7 @@
|
|||
[submodule "src/gui/Translations"]
|
||||
path = src/gui/Translations
|
||||
url = ../Translations.git
|
||||
[submodule "src/dbg/btparser"]
|
||||
path = src/dbg/btparser
|
||||
url = ../btparser
|
||||
[submodule "deps"]
|
||||
path = deps
|
||||
url = ../deps
|
||||
shallow = true
|
||||
[submodule "src/zydis_wrapper/zydis"]
|
||||
path = src/zydis_wrapper/zydis
|
||||
url = ../zydis.git
|
||||
shallow = true
|
|
@ -21,7 +21,7 @@ An open-source binary debugger for Windows, aimed at malware analysis and revers
|
|||
|
||||
1. Download a snapshot from [GitHub](https://github.com/x64dbg/x64dbg/releases), [SourceForge](https://sourceforge.net/projects/x64dbg/files/snapshots) or [OSDN](https://osdn.net/projects/x64dbg) and extract it in a location your user has write access to.
|
||||
2. _Optionally_ use `x96dbg.exe` to register a shell extension and add shortcuts to your desktop.
|
||||
3. You can now run `x32\x32dbg.exe` if you want to debug a 32-bit executable or `x64\x64dbg.exe` to debug a 64-bit executable! If you are unsure you can always run `x96dbg.exe` and chose your architecture there.
|
||||
3. You can now run `x32\x32dbg.exe` if you want to debug a 32-bit executable or `x64\x64dbg.exe` to debug a 64-bit executable! If you are unsure you can always run `x96dbg.exe` and choose your architecture there.
|
||||
|
||||
You can also [compile](https://github.com/x64dbg/x64dbg/wiki/Compiling-the-whole-project) x64dbg yourself with a few easy steps!
|
||||
|
||||
|
@ -92,4 +92,4 @@ You can find an exhaustive list of GitHub contributors [here](https://github.com
|
|||
- [mrfearless](https://twitter.com/fearless0)
|
||||
- [JustMagic](https://github.com/JustasMasiulis)
|
||||
|
||||
Without the help of many people and other open-source projects, it would not have been possible to make x64dbg what is it today, thank you!
|
||||
Without the help of many people and other open-source projects, it would not have been possible to make x64dbg what it is today, thank you!
|
||||
|
|
|
@ -196,9 +196,9 @@ QMenuBar::item:disabled:selected {
|
|||
}
|
||||
|
||||
QMenu {
|
||||
border: 1px solid #212121;
|
||||
border: 1px solid #808080;
|
||||
color: #e0e0e0;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
QMenu::icon {
|
||||
|
@ -281,7 +281,7 @@ QMenu::right-arrow {
|
|||
}
|
||||
|
||||
QWidget:disabled {
|
||||
color: #454545;
|
||||
color: #646464;
|
||||
background-color: #212121;
|
||||
}
|
||||
|
||||
|
@ -313,6 +313,11 @@ QLineEdit {
|
|||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
/* e.g. "System breakpoint scripts" dialog */
|
||||
QLineEdit:disabled {
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
QAbstractItemView QLineEdit {
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -501,7 +506,7 @@ QMainWindow::separator:hover {
|
|||
|
||||
QMenu::separator {
|
||||
height: 1px;
|
||||
background-color: #2a2b2f;
|
||||
background-color: #808080;
|
||||
color: white;
|
||||
padding-left: 4px;
|
||||
margin-left: 10px;
|
||||
|
@ -550,7 +555,7 @@ QPushButton {
|
|||
color: #e0e0e0;
|
||||
background-color: #212121;
|
||||
border-width: 1px;
|
||||
border-color: #2a2b2f;
|
||||
border-color: #808080;
|
||||
border-style: solid;
|
||||
padding: 5px;
|
||||
border-radius: 2px;
|
||||
|
@ -567,7 +572,7 @@ QPushButton:disabled {
|
|||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 2px;
|
||||
color: #454545;
|
||||
color: #646464;
|
||||
}
|
||||
|
||||
QPushButton:focus {
|
||||
|
@ -581,11 +586,11 @@ QPushButton:pressed {
|
|||
padding-bottom: -17px;
|
||||
}
|
||||
|
||||
QComboBox {
|
||||
QComboBox, QFontComboBox {
|
||||
selection-background-color: #89a2f6;
|
||||
selection-color: #000000;
|
||||
border-style: solid;
|
||||
border: 1px solid #212121;
|
||||
border: 1px solid #424242;
|
||||
border-radius: 2px;
|
||||
padding: 5px;
|
||||
min-width: 75px;
|
||||
|
@ -596,15 +601,19 @@ QPushButton:checked {
|
|||
border-color: #2a2b2f;
|
||||
}
|
||||
|
||||
QPushButton:hover {
|
||||
border: 1px solid #e0e0e0;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
QComboBox:hover,
|
||||
QPushButton:hover,
|
||||
QAbstractSpinBox:hover,
|
||||
QLineEdit:hover,
|
||||
QTextEdit:hover,
|
||||
QPlainTextEdit:hover,
|
||||
QAbstractView:hover,
|
||||
QTreeView:hover {
|
||||
border: 1px solid #414141;
|
||||
border: 1px solid #646464;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
|
@ -619,6 +628,7 @@ QComboBox QAbstractItemView {
|
|||
border-radius: 2px;
|
||||
border: 1px solid #212121;
|
||||
selection-background-color: #414141;
|
||||
selection-color: #ffffff; /* e.g. calling convention ComboBox */
|
||||
}
|
||||
|
||||
QComboBox::drop-down {
|
||||
|
@ -1096,4 +1106,13 @@ QTabWidget::pane {
|
|||
QTabBar::tear {
|
||||
width: 0px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* e.g. "Exception filters" list, "Patch file" modules list, "Set page memory rights" table, "Select font" list, etc */
|
||||
QTableView, QListView {
|
||||
selection-color: #c8c8c8;
|
||||
}
|
||||
|
||||
DisassemblyPopup {
|
||||
border: 1px solid #c0c0c0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[Colors]
|
||||
AbstractTableViewBackgroundColor=#212121
|
||||
AbstractTableViewHeaderTextColor=#E0E0E0
|
||||
AbstractTableViewHeaderBackgroundColor=#414141
|
||||
AbstractTableViewSelectionColor=#414141
|
||||
AbstractTableViewSeparatorColor=#717171
|
||||
AbstractTableViewTextColor=#E0E0E0
|
||||
|
@ -51,7 +52,7 @@ DisassemblyCommentColor=#E0E0E0
|
|||
DisassemblyConditionalJumpLineFalseColor=#808080
|
||||
DisassemblyConditionalJumpLineTrueColor=#AA0000
|
||||
DisassemblyFunctionColor=#F88478
|
||||
DisassemblyHardwareBreakpointBackgroundColor=#XXXXXX
|
||||
DisassemblyHardwareBreakpointBackgroundColor=#000000
|
||||
DisassemblyHardwareBreakpointColor=#E6E976
|
||||
DisassemblyLabelBackgroundColor=#XXXXXX
|
||||
DisassemblyLabelColor=#B794F6
|
||||
|
@ -105,10 +106,10 @@ HexDumpUnknownCodePointerHighlightColor=#0000FF
|
|||
HexDumpUnknownDataPointerHighlightColor=#89A2F6
|
||||
HexDumpUserModuleCodePointerHighlightColor=#00FF00
|
||||
HexDumpUserModuleDataPointerHighlightColor=#008000
|
||||
HexEditBackgroundColor=#212121
|
||||
HexEditSelectionColor=#414141
|
||||
HexEditBackgroundColor=#313131
|
||||
HexEditSelectionColor=#515151
|
||||
HexEditTextColor=#E0E0E0
|
||||
HexEditWildcardColor=#C60000
|
||||
HexEditWildcardColor=#FF0000
|
||||
InstructionAddressBackgroundColor=#XXXXXX
|
||||
InstructionAddressColor=#F88478
|
||||
InstructionCallBackgroundColor=#XXXXXX
|
||||
|
|
|
@ -2015,11 +2015,6 @@ BRIDGE_IMPEXP DWORD GuiGetMainThreadId()
|
|||
return (DWORD)(duint)_gui_sendmessage(GUI_GET_MAIN_THREAD_ID, nullptr, nullptr);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP bool GuiIsDebuggerFocused()
|
||||
{
|
||||
return !!(duint)_gui_sendmessage(GUI_IS_DEBUGGER_FOCUSED, nullptr, nullptr);
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
hInst = hinstDLL;
|
||||
|
|
|
@ -176,7 +176,10 @@ extern "C"
|
|||
#define MAX_SECTION_SIZE 10
|
||||
#define MAX_COMMAND_LINE_SIZE 256
|
||||
#define MAX_MNEMONIC_SIZE 64
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 0x1000
|
||||
#endif // PAGE_SIZE
|
||||
|
||||
//Debugger enums
|
||||
typedef enum
|
||||
|
@ -1126,7 +1129,6 @@ 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);
|
||||
BRIDGE_IMPEXP bool GuiIsDebuggerFocused();
|
||||
|
||||
//Gui defines
|
||||
typedef enum
|
||||
|
@ -1275,7 +1277,7 @@ typedef enum
|
|||
GUI_GET_MAIN_THREAD_ID, // param1=unused, param2=unused
|
||||
GUI_ADD_MSG_TO_LOG_HTML, // param1=(const char*)msg, param2=unused
|
||||
GUI_IS_LOG_ENABLED, // param1=unused, param2=unused
|
||||
GUI_IS_DEBUGGER_FOCUSED, // param1=unused, param2=unused
|
||||
GUI_IS_DEBUGGER_FOCUSED_UNUSED, // This message is removed, could be used for future purposes
|
||||
GUI_SAVE_LOG, // param1=const char* file name,param2=unused
|
||||
GUI_REDIRECT_LOG, // param1=const char* file name,param2=unused
|
||||
GUI_STOP_REDIRECT_LOG, // param1=unused, param2=unused
|
||||
|
|
|
@ -73,7 +73,7 @@ bool TraceRecordManager::setTraceRecordType(duint pageAddress, TraceRecordType t
|
|||
newPage.moduleIndex = ~0;
|
||||
}
|
||||
|
||||
auto inserted = TraceRecord.insert(std::make_pair(ModHashFromAddr(pageAddress), newPage));
|
||||
auto inserted = TraceRecord.emplace(ModHashFromAddr(pageAddress), newPage);
|
||||
if(inserted.second == false) // we failed to insert new page into the map
|
||||
{
|
||||
efree(newPage.rawPtr);
|
||||
|
@ -205,14 +205,14 @@ void TraceRecordManager::TraceExecute(duint address, duint size)
|
|||
//See https://www.felixcloutier.com/x86/FXSAVE.html, max 512 bytes
|
||||
#define memoryContentSize 512
|
||||
|
||||
static void HandleZydisOperand(const Zydis & cp, int opindex, DISASM_ARGTYPE* argType, duint* value, unsigned char memoryContent[memoryContentSize], unsigned char* memorySize)
|
||||
static void HandleZydisOperand(const Zydis & zydis, int opindex, DISASM_ARGTYPE* argType, duint* value, unsigned char memoryContent[memoryContentSize], unsigned char* memorySize)
|
||||
{
|
||||
*value = cp.ResolveOpValue(opindex, [&cp](ZydisRegister reg)
|
||||
*value = (duint)zydis.ResolveOpValue(opindex, [&zydis](ZydisRegister reg) -> uint64_t
|
||||
{
|
||||
auto regName = cp.RegName(reg);
|
||||
auto regName = zydis.RegName(reg);
|
||||
return regName ? getregister(nullptr, regName) : 0; //TODO: temporary needs enums + caching
|
||||
});
|
||||
const auto & op = cp[opindex];
|
||||
const auto & op = zydis[opindex];
|
||||
switch(op.type)
|
||||
{
|
||||
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||
|
@ -269,7 +269,7 @@ void TraceRecordManager::TraceExecuteRecord(const Zydis & newInstruction)
|
|||
if(newInstruction.Success() && !newInstruction.IsNop() && newInstruction.GetId() != ZYDIS_MNEMONIC_LEA)
|
||||
{
|
||||
// This can happen when trace execute instruction is used, we need to fix that or something would go wrong with the GUI.
|
||||
newContext.registers.regcontext.cip = newInstruction.Address();
|
||||
newContext.registers.regcontext.cip = (duint)newInstruction.Address();
|
||||
DISASM_ARGTYPE argType;
|
||||
duint value;
|
||||
unsigned char memoryContent[memoryContentSize];
|
||||
|
@ -553,13 +553,13 @@ bool TraceRecordManager::enableTraceRecording(bool enabled, const char* fileName
|
|||
for(size_t i = 0; i < _countof(rtOldContextChanged); i++)
|
||||
rtOldContextChanged[i] = true;
|
||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Started trace recording to file: %s\r\n"), fileName);
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
unsigned char instr[MAX_DISASM_BUFFER];
|
||||
auto cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||
if(MemRead(cip, instr, MAX_DISASM_BUFFER))
|
||||
{
|
||||
cp.DisassembleSafe(cip, instr, MAX_DISASM_BUFFER);
|
||||
TraceExecuteRecord(cp);
|
||||
zydis.DisassembleSafe(cip, instr, MAX_DISASM_BUFFER);
|
||||
TraceExecuteRecord(zydis);
|
||||
}
|
||||
GuiOpenTraceFile(fileName);
|
||||
return true;
|
||||
|
@ -683,7 +683,7 @@ void TraceRecordManager::loadFromDb(JSON root)
|
|||
currentPage.moduleIndex = ~0;
|
||||
key = currentPage.rva;
|
||||
}
|
||||
TraceRecord.insert(std::make_pair(key, currentPage));
|
||||
TraceRecord.emplace(key, currentPage);
|
||||
}
|
||||
else
|
||||
efree(currentPage.rawPtr, "TraceRecordManager");
|
||||
|
|
|
@ -67,7 +67,10 @@ downslib_error downslib_download(const char* url,
|
|||
0);
|
||||
|
||||
if(!hInternet)
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
return downslib_error::inetopen;
|
||||
}
|
||||
|
||||
// Set a time-out value in milliseconds
|
||||
InternetSetOptionA(hInternet,
|
||||
|
|
|
@ -102,8 +102,8 @@ extern "C" DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr)
|
|||
unsigned char data[16];
|
||||
if(MemRead(addr, data, sizeof(data), nullptr, true))
|
||||
{
|
||||
Zydis cp;
|
||||
if(cp.Disassemble(addr, data))
|
||||
Zydis zydis;
|
||||
if(zydis.Disassemble(addr, data))
|
||||
{
|
||||
CONTEXT ctx;
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
|
@ -116,7 +116,7 @@ extern "C" DLL_EXPORT bool _dbg_isjumpgoingtoexecute(duint addr)
|
|||
auto cflags = ctx.EFlags;
|
||||
auto ccx = ctx.Ecx;
|
||||
#endif //_WIN64
|
||||
return cp.IsBranchGoingToExecute(cflags, ccx);
|
||||
return zydis.IsBranchGoingToExecute(cflags, ccx);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -329,11 +329,11 @@ static bool getAutoComment(duint addr, String & comment)
|
|||
BRIDGE_ADDRINFO newinfo;
|
||||
char string_text[MAX_STRING_SIZE] = "";
|
||||
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
auto getregs = !bOnlyCipAutoComments || addr == lastContext.cip;
|
||||
disasmget(cp, addr, &instr, getregs);
|
||||
disasmget(zydis, addr, &instr, getregs);
|
||||
// Some nop variants have 'operands' that should be ignored
|
||||
if(cp.Success() && !cp.IsNop())
|
||||
if(zydis.Success() && !zydis.IsNop())
|
||||
{
|
||||
//Ignore register values when not on CIP and OnlyCipAutoComments is enabled: https://github.com/x64dbg/x64dbg/issues/1383
|
||||
if(!getregs)
|
||||
|
@ -342,7 +342,7 @@ static bool getAutoComment(duint addr, String & comment)
|
|||
instr.arg[i].value = instr.arg[i].constant;
|
||||
}
|
||||
|
||||
if(addr == lastContext.cip && (cp.GetId() == ZYDIS_MNEMONIC_SYSCALL || (cp.GetId() == ZYDIS_MNEMONIC_INT && cp[0].imm.value.u == 0x2e)))
|
||||
if(addr == lastContext.cip && (zydis.GetId() == ZYDIS_MNEMONIC_SYSCALL || (zydis.GetId() == ZYDIS_MNEMONIC_INT && zydis[0].imm.value.u == 0x2e)))
|
||||
{
|
||||
auto syscallName = SyscallToName((unsigned int)lastContext.cax);
|
||||
if(!syscallName.empty())
|
||||
|
@ -367,9 +367,9 @@ static bool getAutoComment(duint addr, String & comment)
|
|||
if(instr.arg[i].constant == instr.arg[i].value) //avoid: call <module.label> ; addr:label
|
||||
{
|
||||
auto constant = instr.arg[i].constant;
|
||||
if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.IsCall())
|
||||
if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && zydis.IsCall())
|
||||
temp_string.assign("call $0");
|
||||
else if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.IsJump())
|
||||
else if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && zydis.IsJump())
|
||||
temp_string.assign("jmp $0");
|
||||
else if(instr.type == instr_branch)
|
||||
continue;
|
||||
|
@ -881,12 +881,12 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
|
|||
unsigned char data[MAX_DISASM_BUFFER];
|
||||
if(!MemIsValidReadPtr(addr, true) || !MemRead(addr, data, sizeof(data)))
|
||||
return 0;
|
||||
Zydis cp;
|
||||
if(!cp.Disassemble(addr, data))
|
||||
Zydis zydis;
|
||||
if(!zydis.Disassemble(addr, data))
|
||||
return 0;
|
||||
if(cp.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTLoop | Zydis::BTXbegin))
|
||||
if(zydis.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTLoop | Zydis::BTXbegin))
|
||||
{
|
||||
auto opValue = cp.ResolveOpValue(0, [](ZydisRegister reg) -> size_t
|
||||
auto opValue = (duint)zydis.ResolveOpValue(0, [](ZydisRegister reg) -> uint64_t
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
|
@ -949,10 +949,10 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
|
|||
return 0;
|
||||
}
|
||||
});
|
||||
if(cp.OpCount() && cp[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
if(zydis.OpCount() && zydis[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
{
|
||||
auto const tebseg = ArchValue(ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS);
|
||||
if(cp[0].mem.segment == tebseg)
|
||||
if(zydis[0].mem.segment == tebseg)
|
||||
opValue += duint(GetTEBLocation(hActiveThread));
|
||||
if(MemRead(opValue, &opValue, sizeof(opValue)))
|
||||
return opValue;
|
||||
|
@ -960,7 +960,7 @@ extern "C" DLL_EXPORT duint _dbg_getbranchdestination(duint addr)
|
|||
else
|
||||
return opValue;
|
||||
}
|
||||
if(cp.IsRet())
|
||||
if(zydis.IsRet())
|
||||
{
|
||||
auto csp = lastContext.csp;
|
||||
duint dest = 0;
|
||||
|
|
|
@ -31,9 +31,9 @@ bool CodeFollowPass::Analyse()
|
|||
return false;
|
||||
}
|
||||
|
||||
duint CodeFollowPass::GetReferenceOperand(const ZydisDecodedInstruction & Context)
|
||||
duint CodeFollowPass::GetReferenceOperand(const ZydisDisassembledInstruction & Context)
|
||||
{
|
||||
for(int i = 0; i < Context.operandCount; i++)
|
||||
for(int i = 0; i < Context.info.operand_count; i++)
|
||||
{
|
||||
auto operand = Context.operands[i];
|
||||
|
||||
|
@ -50,9 +50,9 @@ duint CodeFollowPass::GetReferenceOperand(const ZydisDecodedInstruction & Contex
|
|||
return 0;
|
||||
}
|
||||
|
||||
duint CodeFollowPass::GetMemoryOperand(Zydis & Disasm, const ZydisDecodedInstruction & Context, bool* Indirect)
|
||||
duint CodeFollowPass::GetMemoryOperand(Zydis & Disasm, const ZydisDisassembledInstruction & Context, bool* Indirect)
|
||||
{
|
||||
if(Context.operandCount <= 0)
|
||||
if(Context.info.operand_count <= 0)
|
||||
return 0;
|
||||
|
||||
// Only the first operand matters
|
||||
|
|
|
@ -14,6 +14,6 @@ public:
|
|||
virtual bool Analyse() override;
|
||||
|
||||
private:
|
||||
duint GetReferenceOperand(const ZydisDecodedInstruction & Context);
|
||||
duint GetMemoryOperand(Zydis & Disasm, const ZydisDecodedInstruction & Context, bool* Indirect);
|
||||
duint GetReferenceOperand(const ZydisDisassembledInstruction & Context);
|
||||
duint GetMemoryOperand(Zydis & Disasm, const ZydisDisassembledInstruction & Context, bool* Indirect);
|
||||
};
|
|
@ -79,6 +79,7 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
CFGraph graph(entryPoint);
|
||||
UintSet visited;
|
||||
std::queue<duint> queue;
|
||||
visited.reserve(queue.size());
|
||||
mEntryPoints.insert(entryPoint);
|
||||
queue.push(graph.entryPoint);
|
||||
while(!queue.empty())
|
||||
|
@ -93,7 +94,7 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
while(true)
|
||||
{
|
||||
node.icount++;
|
||||
if(!mCp.Disassemble(node.end, translateAddr(node.end)))
|
||||
if(!mZydis.Disassemble(node.end, translateAddr(node.end)))
|
||||
{
|
||||
if(writedata)
|
||||
mEncMap[node.end - mBase] = (byte)enc_byte;
|
||||
|
@ -108,7 +109,7 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
}
|
||||
// If the memory range doesn't fit the entire instruction
|
||||
// mark it as bytes and finish this node
|
||||
if(!inRange(node.end + mCp.Size() - 1))
|
||||
if(!inRange(node.end + mZydis.Size() - 1))
|
||||
{
|
||||
duint remainingSize = mBase + mSize - node.end;
|
||||
memset(&mEncMap[node.end - mBase], (byte)enc_byte, remainingSize);
|
||||
|
@ -118,15 +119,15 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
if(writedata)
|
||||
{
|
||||
mEncMap[node.end - mBase] = (byte)enc_code;
|
||||
for(int i = 1; i < mCp.Size(); i++)
|
||||
for(size_t i = 1; i < mZydis.Size(); i++)
|
||||
mEncMap[node.end - mBase + i] = (byte)enc_middle;
|
||||
}
|
||||
if(mCp.IsJump() || mCp.IsLoop()) //jump
|
||||
if(mZydis.IsJump() || mZydis.IsLoop()) //jump
|
||||
{
|
||||
//set the branch destinations
|
||||
node.brtrue = mCp.BranchDestination();
|
||||
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||
node.brfalse = node.end + mCp.Size();
|
||||
node.brtrue = (duint)mZydis.BranchDestination();
|
||||
if(mZydis.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||
node.brfalse = node.end + mZydis.Size();
|
||||
|
||||
//add node to the function graph
|
||||
graph.AddNode(node);
|
||||
|
@ -139,26 +140,26 @@ void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata)
|
|||
|
||||
break;
|
||||
}
|
||||
if(mCp.IsCall()) //call
|
||||
if(mZydis.IsCall()) //call
|
||||
{
|
||||
//TODO: handle no return
|
||||
duint target = mCp.BranchDestination();
|
||||
auto target = (duint)mZydis.BranchDestination();
|
||||
if(inRange(target) && mEntryPoints.find(target) == mEntryPoints.end())
|
||||
mCandidateEPs.insert(target);
|
||||
}
|
||||
if(mCp.IsRet()) //return
|
||||
if(mZydis.IsRet()) //return
|
||||
{
|
||||
node.terminal = true;
|
||||
graph.AddNode(node);
|
||||
break;
|
||||
}
|
||||
// If this instruction finishes the memory range, end the loop for this entry point
|
||||
if(!inRange(node.end + mCp.Size()))
|
||||
if(!inRange(node.end + mZydis.Size()))
|
||||
{
|
||||
graph.AddNode(node);
|
||||
break;
|
||||
}
|
||||
node.end += mCp.Size();
|
||||
node.end += mZydis.Size();
|
||||
}
|
||||
}
|
||||
mFunctions.push_back(graph);
|
||||
|
@ -172,20 +173,20 @@ void AdvancedAnalysis::linearXrefPass()
|
|||
|
||||
for(auto addr = mBase; addr < mBase + mSize;)
|
||||
{
|
||||
if(!mCp.Disassemble(addr, translateAddr(addr)))
|
||||
if(!mZydis.Disassemble(addr, translateAddr(addr)))
|
||||
{
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
addr += mCp.Size();
|
||||
addr += mZydis.Size();
|
||||
|
||||
XREF xref;
|
||||
xref.valid = true;
|
||||
xref.addr = 0;
|
||||
xref.from = mCp.Address();
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
xref.from = (duint)mZydis.Address();
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
duint dest = mCp.ResolveOpValue(i, [](ZydisRegister)->size_t
|
||||
auto dest = (duint)mZydis.ResolveOpValue(i, [](ZydisRegister) -> uint64_t
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
|
@ -197,9 +198,9 @@ void AdvancedAnalysis::linearXrefPass()
|
|||
}
|
||||
if(xref.addr)
|
||||
{
|
||||
if(mCp.IsCall())
|
||||
if(mZydis.IsCall())
|
||||
xref.type = XREF_CALL;
|
||||
else if(mCp.IsJump())
|
||||
else if(mZydis.IsJump())
|
||||
xref.type = XREF_JMP;
|
||||
else
|
||||
xref.type = XREF_DATA;
|
||||
|
@ -269,16 +270,16 @@ void AdvancedAnalysis::writeDataXrefs()
|
|||
{
|
||||
if(xref.type == XREF_DATA && xref.valid)
|
||||
{
|
||||
if(!mCp.Disassemble(xref.from, translateAddr(xref.from)))
|
||||
if(!mZydis.Disassemble(xref.from, translateAddr(xref.from)))
|
||||
{
|
||||
xref.valid = false;
|
||||
continue;
|
||||
}
|
||||
auto opcode = mCp.GetId();
|
||||
auto opcode = mZydis.GetId();
|
||||
bool isfloat = isFloatInstruction(opcode);
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
auto & op = mCp[i];
|
||||
auto & op = mZydis[i];
|
||||
ENCODETYPE type = enc_unknown;
|
||||
|
||||
//Todo: Analyze op type and set correct type
|
||||
|
@ -344,6 +345,7 @@ void AdvancedAnalysis::writeDataXrefs()
|
|||
|
||||
void AdvancedAnalysis::findFuzzyEntryPoints()
|
||||
{
|
||||
mCandidateEPs.reserve(mFuzzyEPs.size());
|
||||
for(const auto & entryPoint : mFuzzyEPs)
|
||||
{
|
||||
mCandidateEPs.insert(entryPoint);
|
||||
|
@ -392,6 +394,7 @@ void AdvancedAnalysis::analyzeCandidateFunctions(bool writedata)
|
|||
pendingEPs.clear();
|
||||
if(mCandidateEPs.size() == 0)
|
||||
return;
|
||||
pendingEPs.reserve(mCandidateEPs.size());
|
||||
for(const auto & entryPoint : mCandidateEPs)
|
||||
{
|
||||
pendingEPs.insert(entryPoint);
|
||||
|
|
|
@ -17,7 +17,7 @@ protected:
|
|||
duint mBase;
|
||||
duint mSize;
|
||||
unsigned char* mData;
|
||||
Zydis mCp;
|
||||
Zydis mZydis;
|
||||
|
||||
bool inRange(duint addr) const
|
||||
{
|
||||
|
|
|
@ -140,26 +140,26 @@ void ControlFlowAnalysis::BasicBlockStarts()
|
|||
for(duint i = 0; i < mSize;)
|
||||
{
|
||||
auto addr = mBase + i;
|
||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(bSkipFilling) //handle filling skip mode
|
||||
{
|
||||
if(!mCp.IsFilling()) //do nothing until the filling stopped
|
||||
if(!mZydis.IsFilling()) //do nothing until the filling stopped
|
||||
{
|
||||
bSkipFilling = false;
|
||||
mBlockStarts.insert(addr);
|
||||
}
|
||||
}
|
||||
else if(mCp.IsRet()) //RET breaks control flow
|
||||
else if(mZydis.IsRet()) //RET breaks control flow
|
||||
{
|
||||
bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
|
||||
}
|
||||
else if(mCp.IsJump() || mCp.IsLoop()) //branches
|
||||
else if(mZydis.IsJump() || mZydis.IsLoop()) //branches
|
||||
{
|
||||
auto dest1 = getReferenceOperand();
|
||||
duint dest2 = 0;
|
||||
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //conditional jump
|
||||
dest2 = addr + mCp.Size();
|
||||
if(mZydis.GetId() != ZYDIS_MNEMONIC_JMP) //conditional jump
|
||||
dest2 = addr + mZydis.Size();
|
||||
|
||||
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
|
||||
bSkipFilling = true;
|
||||
|
@ -168,7 +168,7 @@ void ControlFlowAnalysis::BasicBlockStarts()
|
|||
if(dest2)
|
||||
mBlockStarts.insert(dest2);
|
||||
}
|
||||
else if(mCp.IsCall())
|
||||
else if(mZydis.IsCall())
|
||||
{
|
||||
auto dest1 = getReferenceOperand();
|
||||
if(dest1)
|
||||
|
@ -183,7 +183,7 @@ void ControlFlowAnalysis::BasicBlockStarts()
|
|||
if(dest1)
|
||||
mBlockStarts.insert(dest1);
|
||||
}
|
||||
i += mCp.Size();
|
||||
i += mZydis.Size();
|
||||
}
|
||||
else
|
||||
i++;
|
||||
|
@ -204,23 +204,23 @@ void ControlFlowAnalysis::BasicBlocks()
|
|||
for(duint addr = start, prevaddr; addr < mBase + mSize;)
|
||||
{
|
||||
prevaddr = addr;
|
||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(mCp.IsRet())
|
||||
if(mZydis.IsRet())
|
||||
{
|
||||
insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
|
||||
break;
|
||||
}
|
||||
else if(mCp.IsJump() || mCp.IsLoop())
|
||||
else if(mZydis.IsJump() || mZydis.IsLoop())
|
||||
{
|
||||
auto dest1 = getReferenceOperand();
|
||||
auto dest2 = mCp.GetId() != ZYDIS_MNEMONIC_JMP ? addr + mCp.Size() : 0;
|
||||
auto dest2 = mZydis.GetId() != ZYDIS_MNEMONIC_JMP ? addr + mZydis.Size() : 0;
|
||||
insertBlock(BasicBlock(start, addr, dest1, dest2));
|
||||
insertParent(dest1, start);
|
||||
insertParent(dest2, start);
|
||||
break;
|
||||
}
|
||||
addr += mCp.Size();
|
||||
addr += mZydis.Size();
|
||||
}
|
||||
else
|
||||
addr++;
|
||||
|
@ -275,7 +275,7 @@ void ControlFlowAnalysis::Functions()
|
|||
{
|
||||
auto function = findFunctionStart(block, parents);
|
||||
if(!function) //this happens with loops / unreferenced blocks sometimes
|
||||
delayedBlocks.push_back(DelayedBlock(block, parents));
|
||||
delayedBlocks.emplace_back(block, parents);
|
||||
else
|
||||
block->function = function;
|
||||
}
|
||||
|
@ -413,9 +413,9 @@ String ControlFlowAnalysis::blockToString(const BasicBlock* block)
|
|||
|
||||
duint ControlFlowAnalysis::getReferenceOperand() const
|
||||
{
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
const auto & op = mCp[i];
|
||||
const auto & op = mZydis[i];
|
||||
if(op.type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
{
|
||||
auto dest = duint(op.imm.value.u);
|
||||
|
@ -426,7 +426,7 @@ duint ControlFlowAnalysis::getReferenceOperand() const
|
|||
{
|
||||
auto dest = duint(op.mem.disp.value);
|
||||
if(op.mem.base == ZYDIS_REGISTER_RIP) //rip-relative
|
||||
dest += mCp.Address() + mCp.Size();
|
||||
dest += (duint)mZydis.Address() + mZydis.Size();
|
||||
if(inRange(dest))
|
||||
return dest;
|
||||
}
|
||||
|
|
|
@ -45,12 +45,12 @@ void LinearAnalysis::populateReferences()
|
|||
for(duint i = 0; i < mSize;)
|
||||
{
|
||||
auto addr = mBase + i;
|
||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
auto ref = getReferenceOperand();
|
||||
if(ref)
|
||||
mFunctions.push_back({ ref, 0 });
|
||||
i += mCp.Size();
|
||||
i += mZydis.Size();
|
||||
}
|
||||
else
|
||||
i++;
|
||||
|
@ -72,8 +72,8 @@ void LinearAnalysis::analyseFunctions()
|
|||
auto end = findFunctionEnd(function.start, maxaddr);
|
||||
if(end)
|
||||
{
|
||||
if(mCp.Disassemble(end, translateAddr(end), MAX_DISASM_BUFFER))
|
||||
function.end = end + mCp.Size() - 1;
|
||||
if(mZydis.Disassemble(end, translateAddr(end), MAX_DISASM_BUFFER))
|
||||
function.end = end + mZydis.Size() - 1;
|
||||
else
|
||||
function.end = end;
|
||||
}
|
||||
|
@ -83,10 +83,10 @@ void LinearAnalysis::analyseFunctions()
|
|||
duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
||||
{
|
||||
//disassemble first instruction for some heuristics
|
||||
if(mCp.Disassemble(start, translateAddr(start), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(start, translateAddr(start), MAX_DISASM_BUFFER))
|
||||
{
|
||||
//JMP [123456] ; import
|
||||
if(mCp.IsJump() && mCp.OpCount() && mCp[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
if(mZydis.IsJump() && mZydis.OpCount() && mZydis[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -95,14 +95,14 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
|||
duint jumpback = 0;
|
||||
for(duint addr = start, fardest = 0; addr < maxaddr;)
|
||||
{
|
||||
if(mCp.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
if(mZydis.Disassemble(addr, translateAddr(addr), MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(addr + mCp.Size() > maxaddr) //we went past the maximum allowed address
|
||||
if(addr + mZydis.Size() > maxaddr) //we went past the maximum allowed address
|
||||
break;
|
||||
|
||||
if((mCp.IsJump() || mCp.IsLoop()) && mCp.OpCount() && mCp[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //jump
|
||||
if((mZydis.IsJump() || mZydis.IsLoop()) && mZydis.OpCount() && mZydis[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //jump
|
||||
{
|
||||
auto dest = duint(mCp[0].imm.value.u);
|
||||
auto dest = duint(mZydis[0].imm.value.u);
|
||||
|
||||
if(dest >= maxaddr) //jump across function boundaries
|
||||
{
|
||||
|
@ -112,19 +112,19 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
|||
{
|
||||
fardest = dest;
|
||||
}
|
||||
else if(end && dest < end && (mCp.GetId() == ZYDIS_MNEMONIC_JMP || mCp.GetId() == ZYDIS_MNEMONIC_LOOP)) //save the last JMP backwards
|
||||
else if(end && dest < end && (mZydis.GetId() == ZYDIS_MNEMONIC_JMP || mZydis.GetId() == ZYDIS_MNEMONIC_LOOP)) //save the last JMP backwards
|
||||
{
|
||||
jumpback = addr;
|
||||
}
|
||||
}
|
||||
else if(mCp.IsRet()) //possible function end?
|
||||
else if(mZydis.IsRet()) //possible function end?
|
||||
{
|
||||
end = addr;
|
||||
if(fardest < addr) //we stop if the farthest JXX destination forward is before this RET
|
||||
break;
|
||||
}
|
||||
|
||||
addr += mCp.Size();
|
||||
addr += mZydis.Size();
|
||||
}
|
||||
else
|
||||
addr++;
|
||||
|
@ -134,10 +134,10 @@ duint LinearAnalysis::findFunctionEnd(duint start, duint maxaddr)
|
|||
|
||||
duint LinearAnalysis::getReferenceOperand() const
|
||||
{
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
const auto & op = mCp[i];
|
||||
if(mCp.IsJump() || mCp.IsLoop()) //skip jumps/loops
|
||||
const auto & op = mZydis[i];
|
||||
if(mZydis.IsJump() || mZydis.IsLoop()) //skip jumps/loops
|
||||
continue;
|
||||
if(op.type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //we are looking for immediate references
|
||||
{
|
||||
|
|
|
@ -59,11 +59,11 @@ void RecursiveAnalysis::SetMarkers()
|
|||
duint rangeStart = 0, rangeEnd = 0, rangeInstructionCount = 0;
|
||||
for(auto rangeItr = blockRanges.begin(); rangeItr != blockRanges.end(); ++rangeItr)
|
||||
{
|
||||
auto disasmLen = [this](duint addr)
|
||||
auto disasmLen = [this](duint addr) -> size_t
|
||||
{
|
||||
if(!mCp.Disassemble(addr, translateAddr(addr)))
|
||||
if(!mZydis.Disassemble(addr, translateAddr(addr)))
|
||||
return 1;
|
||||
return mCp.Size();
|
||||
return mZydis.Size();
|
||||
};
|
||||
const auto & node = *rangeItr->second;
|
||||
if(!rangeStart)
|
||||
|
@ -149,6 +149,7 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
CFGraph graph(entryPoint);
|
||||
UintSet visited;
|
||||
std::queue<duint> queue;
|
||||
visited.reserve(queue.size());
|
||||
queue.push(graph.entryPoint);
|
||||
while(!queue.empty())
|
||||
{
|
||||
|
@ -170,14 +171,14 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
{
|
||||
if(!inRange(node.end))
|
||||
{
|
||||
node.end = mCp.Address();
|
||||
node.end = (duint)mZydis.Address();
|
||||
node.terminal = true;
|
||||
graph.AddNode(node);
|
||||
break;
|
||||
}
|
||||
|
||||
node.icount++;
|
||||
if(!mCp.Disassemble(node.end, translateAddr(node.end)))
|
||||
if(!mZydis.Disassemble(node.end, translateAddr(node.end)))
|
||||
{
|
||||
node.end++;
|
||||
continue;
|
||||
|
@ -186,10 +187,10 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
//do xref analysis on the instruction
|
||||
XREF xref;
|
||||
xref.addr = 0;
|
||||
xref.from = mCp.Address();
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
xref.from = (duint)mZydis.Address();
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
duint dest = mCp.ResolveOpValue(i, [](ZydisRegister)->size_t
|
||||
auto dest = (duint)mZydis.ResolveOpValue(i, [](ZydisRegister) -> uint64_t
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
|
@ -202,23 +203,23 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
if(xref.addr)
|
||||
mXrefs.push_back(xref);
|
||||
|
||||
if(!mCp.IsNop() && (mCp.IsJump() || mCp.IsLoop())) //non-nop jump
|
||||
if(!mZydis.IsNop() && (mZydis.IsJump() || mZydis.IsLoop())) //non-nop jump
|
||||
{
|
||||
//set the branch destinations
|
||||
node.brtrue = mCp.BranchDestination();
|
||||
if(mCp.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||
node.brfalse = node.end + mCp.Size();
|
||||
node.brtrue = (duint)mZydis.BranchDestination();
|
||||
if(mZydis.GetId() != ZYDIS_MNEMONIC_JMP) //unconditional jumps dont have a brfalse
|
||||
node.brfalse = node.end + mZydis.Size();
|
||||
|
||||
//consider register/memory branches as terminal nodes
|
||||
if(mCp.OpCount() && mCp[0].type != ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
if(mZydis.OpCount() && mZydis[0].type != ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||
{
|
||||
//jmp ptr [index * sizeof(duint) + switchTable]
|
||||
if(mCp[0].type == ZYDIS_OPERAND_TYPE_MEMORY && mCp[0].mem.base == ZYDIS_REGISTER_NONE && mCp[0].mem.index != ZYDIS_REGISTER_NONE
|
||||
&& mCp[0].mem.scale == sizeof(duint) && MemIsValidReadPtr(duint(mCp[0].mem.disp.value)))
|
||||
if(mZydis[0].type == ZYDIS_OPERAND_TYPE_MEMORY && mZydis[0].mem.base == ZYDIS_REGISTER_NONE && mZydis[0].mem.index != ZYDIS_REGISTER_NONE
|
||||
&& mZydis[0].mem.scale == sizeof(duint) && MemIsValidReadPtr(duint(mZydis[0].mem.disp.value)))
|
||||
{
|
||||
Memory<duint*> switchTable(512 * sizeof(duint));
|
||||
duint actualSize, index;
|
||||
MemRead(duint(mCp[0].mem.disp.value), switchTable(), 512 * sizeof(duint), &actualSize);
|
||||
MemRead(duint(mZydis[0].mem.disp.value), switchTable(), 512 * sizeof(duint), &actualSize);
|
||||
actualSize /= sizeof(duint);
|
||||
for(index = 0; index < actualSize; index++)
|
||||
if(MemIsCodePage(switchTable()[index], false) == false)
|
||||
|
@ -228,6 +229,8 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
{
|
||||
node.brtrue = 0;
|
||||
node.brfalse = 0;
|
||||
node.exits.reserve(actualSize);
|
||||
mXrefs.reserve(actualSize);
|
||||
for(index = 0; index < actualSize; index++)
|
||||
{
|
||||
node.exits.push_back(switchTable()[index]);
|
||||
|
@ -254,17 +257,17 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
|
||||
break;
|
||||
}
|
||||
if(mCp.IsCall())
|
||||
if(mZydis.IsCall())
|
||||
{
|
||||
//TODO: add this to a queue to be analyzed later
|
||||
}
|
||||
if(mCp.IsRet())
|
||||
if(mZydis.IsRet())
|
||||
{
|
||||
node.terminal = true;
|
||||
graph.AddNode(node);
|
||||
break;
|
||||
}
|
||||
node.end += mCp.Size();
|
||||
node.end += mZydis.Size();
|
||||
}
|
||||
}
|
||||
//second pass: split overlapping blocks introduced by backedges
|
||||
|
@ -276,7 +279,7 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
while(addr < node.end)
|
||||
{
|
||||
icount++;
|
||||
auto size = mCp.Disassemble(addr, translateAddr(addr)) ? mCp.Size() : 1;
|
||||
auto size = mZydis.Disassemble(addr, translateAddr(addr)) ? mZydis.Size() : 1;
|
||||
if(graph.nodes.count(addr + size))
|
||||
{
|
||||
node.end = addr;
|
||||
|
@ -309,10 +312,10 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint)
|
|||
auto addr = node.start;
|
||||
while(addr <= node.end) //disassemble all instructions
|
||||
{
|
||||
auto size = mCp.Disassemble(addr, translateAddr(addr)) ? mCp.Size() : 1;
|
||||
if(mCp.IsCall() && mCp.OpCount()) //call reg / call [reg+X]
|
||||
auto size = mZydis.Disassemble(addr, translateAddr(addr)) ? mZydis.Size() : 1;
|
||||
if(mZydis.IsCall() && mZydis.OpCount()) //call reg / call [reg+X]
|
||||
{
|
||||
auto & op = mCp[0];
|
||||
auto & op = mZydis[0];
|
||||
switch(op.type)
|
||||
{
|
||||
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||
|
|
|
@ -17,19 +17,19 @@ void XrefsAnalysis::Analyse()
|
|||
|
||||
for(auto addr = mBase; addr < mBase + mSize;)
|
||||
{
|
||||
if(!mCp.Disassemble(addr, translateAddr(addr)))
|
||||
if(!mZydis.Disassemble(addr, translateAddr(addr)))
|
||||
{
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
addr += mCp.Size();
|
||||
addr += mZydis.Size();
|
||||
|
||||
XREF xref;
|
||||
xref.addr = 0;
|
||||
xref.from = mCp.Address();
|
||||
for(auto i = 0; i < mCp.OpCount(); i++)
|
||||
xref.from = (duint)mZydis.Address();
|
||||
for(auto i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
duint dest = mCp.ResolveOpValue(i, [](ZydisRegister)->size_t
|
||||
auto dest = (duint)mZydis.ResolveOpValue(i, [](ZydisRegister) -> uint64_t
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
|
|
|
@ -131,11 +131,11 @@ bool BpNew(duint Address, bool Enable, bool Singleshot, short OldBytes, BP_TYPE
|
|||
|
||||
if(Type != BPDLL && Type != BPEXCEPTION)
|
||||
{
|
||||
return breakpoints.insert(std::make_pair(BreakpointKey(Type, ModHashFromAddr(Address)), bp)).second;
|
||||
return breakpoints.emplace(BreakpointKey(Type, ModHashFromAddr(Address)), bp).second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return breakpoints.insert(std::make_pair(BreakpointKey(Type, Address), bp)).second;
|
||||
return breakpoints.emplace(BreakpointKey(Type, Address), bp).second;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,7 +159,7 @@ bool BpNewDll(const char* module, bool Enable, bool Singleshot, DWORD TitanType,
|
|||
// Insert new entry to the global list
|
||||
EXCLUSIVE_ACQUIRE(LockBreakpoints);
|
||||
|
||||
return breakpoints.insert(std::make_pair(BreakpointKey(BPDLL, bp.addr), bp)).second;
|
||||
return breakpoints.emplace(BreakpointKey(BPDLL, bp.addr), bp).second;
|
||||
}
|
||||
|
||||
bool BpGet(duint Address, BP_TYPE Type, const char* Name, BREAKPOINT* Bp)
|
||||
|
@ -310,7 +310,7 @@ bool BpUpdateDllPath(const char* module1, BREAKPOINT** newBpInfo)
|
|||
_strlwr_s(temp.mod, strlen(temp.mod) + 1);
|
||||
temp.addr = ModHashFromName(module1);
|
||||
breakpoints.erase(i.first);
|
||||
auto newItem = breakpoints.insert(std::make_pair(BreakpointKey(BPDLL, temp.addr), temp));
|
||||
auto newItem = breakpoints.emplace(BreakpointKey(BPDLL, temp.addr), temp);
|
||||
*newBpInfo = &newItem.first->second;
|
||||
return true;
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ bool BpUpdateDllPath(const char* module1, BREAKPOINT** newBpInfo)
|
|||
_strlwr_s(temp.mod, strlen(temp.mod) + 1);
|
||||
temp.addr = ModHashFromName(dashPos1 + 1);
|
||||
breakpoints.erase(i.first);
|
||||
auto newItem = breakpoints.insert(std::make_pair(BreakpointKey(BPDLL, temp.addr), temp));
|
||||
auto newItem = breakpoints.emplace(BreakpointKey(BPDLL, temp.addr), temp);
|
||||
*newBpInfo = &newItem.first->second;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -78,9 +78,6 @@ Command::Command(const String & command)
|
|||
case '{':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
case '\\':
|
||||
dataAppend(ch);
|
||||
break;
|
||||
default:
|
||||
dataAppend('\\');
|
||||
dataAppend(ch);
|
||||
|
|
|
@ -504,7 +504,7 @@ static bool IsRepeated(const Zydis & zydis)
|
|||
case ZYDIS_MNEMONIC_SCASW:
|
||||
case ZYDIS_MNEMONIC_SCASD:
|
||||
case ZYDIS_MNEMONIC_SCASQ:
|
||||
return (zydis.GetInstr()->attributes & (ZYDIS_ATTRIB_HAS_REP | ZYDIS_ATTRIB_HAS_REPZ | ZYDIS_ATTRIB_HAS_REPNZ)) != 0;
|
||||
return (zydis.GetInstr()->info.attributes & (ZYDIS_ATTRIB_HAS_REP | ZYDIS_ATTRIB_HAS_REPZ | ZYDIS_ATTRIB_HAS_REPNZ)) != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,15 @@ bool cbDebugDump(int argc, char* argv[])
|
|||
GuiDumpAtN(addr, int(index));
|
||||
}
|
||||
else
|
||||
GuiDumpAt(addr);
|
||||
{
|
||||
ACTIVEVIEW activeView;
|
||||
GuiGetActiveView(&activeView);
|
||||
int dumpIndex;
|
||||
if(sscanf_s(activeView.title, "Dump %d", &dumpIndex) == 1)
|
||||
GuiDumpAtN(addr, dumpIndex);
|
||||
else
|
||||
GuiDumpAt(addr);
|
||||
}
|
||||
GuiShowCpu();
|
||||
GuiFocusView(GUI_DUMP);
|
||||
return true;
|
||||
|
|
|
@ -448,7 +448,7 @@ static bool cbRefFind(Zydis* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO*
|
|||
{
|
||||
GuiReferenceInitialize(refinfo->name);
|
||||
GuiReferenceAddColumn(sizeof(duint) * 2, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address")));
|
||||
GuiReferenceAddColumn(100, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceSetRowCount(0);
|
||||
GuiReferenceReloadData();
|
||||
return true;
|
||||
|
@ -550,9 +550,9 @@ static bool cbRefStr(Zydis* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO*
|
|||
{
|
||||
GuiReferenceInitialize(refinfo->name);
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address")));
|
||||
GuiReferenceAddColumn(100, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(50, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "String Address")));
|
||||
GuiReferenceAddColumn(500, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "String")));
|
||||
GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "String")));
|
||||
GuiReferenceAddCommand(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Follow in Disassembly and Dump")), "disasm $0;dump $2");
|
||||
GuiReferenceAddCommand(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Follow string in Dump")), "dump $2");
|
||||
GuiReferenceSetSearchStartCol(2); //only search the strings
|
||||
|
@ -600,9 +600,9 @@ static bool cbRefFuncPtr(Zydis* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFIN
|
|||
{
|
||||
GuiReferenceInitialize(refinfo->name);
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address")));
|
||||
GuiReferenceAddColumn(100, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(50, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Function pointer")));
|
||||
GuiReferenceAddColumn(500, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Label")));
|
||||
GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Label")));
|
||||
GuiReferenceSetSearchStartCol(2); //only search the function pointers
|
||||
GuiReferenceSetRowCount(0);
|
||||
GuiReferenceReloadData();
|
||||
|
@ -701,8 +701,8 @@ static bool cbModCallFind(Zydis* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFI
|
|||
{
|
||||
GuiReferenceInitialize(refinfo->name);
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address")));
|
||||
GuiReferenceAddColumn(100, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(MAX_LABEL_SIZE, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Destination")));
|
||||
GuiReferenceAddColumn(50, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Destination")));
|
||||
GuiReferenceSetRowCount(0);
|
||||
GuiReferenceReloadData();
|
||||
return true;
|
||||
|
@ -710,9 +710,9 @@ static bool cbModCallFind(Zydis* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFI
|
|||
duint foundaddr = 0;
|
||||
char label[MAX_LABEL_SIZE] = "";
|
||||
char module[MAX_MODULE_SIZE] = "";
|
||||
duint base = ModBaseFromAddr(disasm->Address()), size = 0;
|
||||
duint base = ModBaseFromAddr((duint)disasm->Address()), size = 0;
|
||||
if(!base)
|
||||
base = MemFindBaseAddr(disasm->Address(), &size);
|
||||
base = MemFindBaseAddr((duint)disasm->Address(), &size);
|
||||
else
|
||||
size = ModSizeFromAddr(base);
|
||||
if(!base || !size)
|
||||
|
@ -887,7 +887,7 @@ static bool cbGUIDFind(Zydis* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO
|
|||
{
|
||||
GuiReferenceInitialize(refinfo->name);
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address")));
|
||||
GuiReferenceAddColumn(100, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(50, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(40, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "GUID")));
|
||||
GuiReferenceAddColumn(20, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "ProgId")));
|
||||
GuiReferenceAddColumn(40, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Path")));
|
||||
|
@ -1021,7 +1021,7 @@ bool cbInstrGUIDFind(int argc, char* argv[])
|
|||
//very likely a GUID
|
||||
GUID temp;
|
||||
if(CLSIDFromString(subkeyName, &temp) == S_OK)
|
||||
allRegisteredGUIDs.insert(std::make_pair(temp, 0));
|
||||
allRegisteredGUIDs.emplace(temp, 0);
|
||||
}
|
||||
}
|
||||
subkeyNameLen = 40;
|
||||
|
|
|
@ -129,7 +129,7 @@ bool cbDebugRunToParty(int argc, char* argv[])
|
|||
if(!BpGet(j.addr, BPMEMORY, nullptr, &bp))
|
||||
{
|
||||
size_t size = DbgMemGetPageSize(j.addr);
|
||||
RunToUserCodeBreakpoints.push_back(std::make_pair(j.addr, size));
|
||||
RunToUserCodeBreakpoints.emplace_back(j.addr, size);
|
||||
SetMemoryBPXEx(j.addr, size, UE_MEMORY_EXECUTE, false, cbRunToUserCodeBreakpoint);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,23 +243,26 @@ bool cbInstrZydis(int argc, char* argv[])
|
|||
if(!valfromstring(argv[2], &addr, false))
|
||||
return false;
|
||||
|
||||
Zydis cp;
|
||||
if(!cp.Disassemble(addr, data))
|
||||
Zydis zydis;
|
||||
if(!zydis.Disassemble(addr, data))
|
||||
{
|
||||
dputs_untranslated("Failed to disassemble!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto instr = cp.GetInstr();
|
||||
int argcount = instr->operandCount;
|
||||
dputs_untranslated(cp.InstructionText(true).c_str());
|
||||
dprintf_untranslated("prefix size: %d\n", instr->raw.prefixes.count);
|
||||
if(instr->attributes & ZYDIS_ATTRIB_HAS_REX)
|
||||
dprintf_untranslated("rex.W: %d, rex.R: %d, rex.X: %d, rex.B: %d, rex.data: %02x\n", instr->raw.rex.W, instr->raw.rex.R, instr->raw.rex.X, instr->raw.rex.B, instr->raw.rex.data[0]);
|
||||
dprintf_untranslated("disp.offset: %d, disp.size: %d\n", instr->raw.disp.offset, instr->raw.disp.size);
|
||||
dprintf_untranslated("imm[0].offset: %d, imm[0].size: %d\n", instr->raw.imm[0].offset, instr->raw.imm[0].size);
|
||||
dprintf_untranslated("imm[1].offset: %d, imm[1].size: %d\n", instr->raw.imm[1].offset, instr->raw.imm[1].size);
|
||||
dprintf_untranslated("size: %d, id: %d, opcount: %d\n", cp.Size(), cp.GetId(), instr->operandCount);
|
||||
auto instr = zydis.GetInstr();
|
||||
int argcount = zydis.OpCount();
|
||||
dputs_untranslated(zydis.InstructionText(true).c_str());
|
||||
dprintf_untranslated("prefix size: %d\n", instr->info.raw.prefix_count);
|
||||
if(instr->info.attributes & ZYDIS_ATTRIB_HAS_REX)
|
||||
{
|
||||
auto rexdata = data[instr->info.raw.rex.offset];
|
||||
dprintf_untranslated("rex.W: %d, rex.R: %d, rex.X: %d, rex.B: %d, rex.data: %02x\n", instr->info.raw.rex.W, instr->info.raw.rex.R, instr->info.raw.rex.X, instr->info.raw.rex.B, rexdata);
|
||||
}
|
||||
dprintf_untranslated("disp.offset: %d, disp.size: %d\n", instr->info.raw.disp.offset, instr->info.raw.disp.size);
|
||||
dprintf_untranslated("imm[0].offset: %d, imm[0].size: %d\n", instr->info.raw.imm[0].offset, instr->info.raw.imm[0].size);
|
||||
dprintf_untranslated("imm[1].offset: %d, imm[1].size: %d\n", instr->info.raw.imm[1].offset, instr->info.raw.imm[1].size);
|
||||
dprintf_untranslated("size: %d, id: %d, opcount: %d\n", zydis.Size(), zydis.GetId(), instr->info.operand_count);
|
||||
auto rwstr = [](uint8_t action)
|
||||
{
|
||||
switch(action)
|
||||
|
@ -297,11 +300,11 @@ bool cbInstrZydis(int argc, char* argv[])
|
|||
for(int i = 0; i < argcount; i++)
|
||||
{
|
||||
const auto & op = instr->operands[i];
|
||||
dprintf("operand %d (size: %d, access: %s, visibility: %s) \"%s\", ", i + 1, op.size, rwstr(op.action), vis(op.visibility), cp.OperandText(i).c_str());
|
||||
dprintf("operand %d (size: %d, access: %s, visibility: %s) \"%s\", ", i + 1, op.size, rwstr(op.actions), vis(op.visibility), zydis.OperandText(i).c_str());
|
||||
switch(op.type)
|
||||
{
|
||||
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||
dprintf_untranslated("register: %s\n", cp.RegName(op.reg.value));
|
||||
dprintf_untranslated("register: %s\n", zydis.RegName(op.reg.value));
|
||||
break;
|
||||
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
||||
dprintf_untranslated("immediate: 0x%p\n", op.imm.value.u);
|
||||
|
@ -311,9 +314,9 @@ bool cbInstrZydis(int argc, char* argv[])
|
|||
//[base + index * scale +/- disp]
|
||||
const auto & mem = op.mem;
|
||||
dprintf_untranslated("memory segment: %s, base: %s, index: %s, scale: %d, displacement: 0x%p\n",
|
||||
cp.RegName(mem.segment),
|
||||
cp.RegName(mem.base),
|
||||
cp.RegName(mem.index),
|
||||
zydis.RegName(mem.segment),
|
||||
zydis.RegName(mem.base),
|
||||
zydis.RegName(mem.index),
|
||||
mem.scale,
|
||||
mem.disp.value);
|
||||
}
|
||||
|
@ -348,7 +351,7 @@ bool cbInstrVisualize(int argc, char* argv[])
|
|||
//DisassemblyBreakpointColor = #000000
|
||||
{
|
||||
//initialize
|
||||
Zydis _cp;
|
||||
Zydis zydis;
|
||||
duint _base = start;
|
||||
duint _size = maxaddr - start;
|
||||
Memory<unsigned char*> _data(_size);
|
||||
|
@ -376,14 +379,14 @@ bool cbInstrVisualize(int argc, char* argv[])
|
|||
|
||||
//continue algorithm
|
||||
const unsigned char* curData = (addr >= _base && addr < _base + _size) ? _data() + (addr - _base) : nullptr;
|
||||
if(_cp.Disassemble(addr, curData, MAX_DISASM_BUFFER))
|
||||
if(zydis.Disassemble(addr, curData, MAX_DISASM_BUFFER))
|
||||
{
|
||||
if(addr + _cp.Size() > maxaddr) //we went past the maximum allowed address
|
||||
if(addr + zydis.Size() > maxaddr) //we went past the maximum allowed address
|
||||
break;
|
||||
|
||||
if((_cp.IsJump() || _cp.IsLoop()) && _cp.OpCount() && _cp[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //jump
|
||||
if((zydis.IsJump() || zydis.IsLoop()) && zydis.OpCount() && zydis[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) //jump
|
||||
{
|
||||
duint dest = (duint)_cp[0].imm.value.u;
|
||||
duint dest = (duint)zydis[0].imm.value.u;
|
||||
|
||||
if(dest >= maxaddr) //jump across function boundaries
|
||||
{
|
||||
|
@ -393,19 +396,19 @@ bool cbInstrVisualize(int argc, char* argv[])
|
|||
{
|
||||
fardest = dest;
|
||||
}
|
||||
else if(end && dest < end && _cp.GetId() == ZYDIS_MNEMONIC_JMP) //save the last JMP backwards
|
||||
else if(end && dest < end && zydis.GetId() == ZYDIS_MNEMONIC_JMP) //save the last JMP backwards
|
||||
{
|
||||
jumpback = addr;
|
||||
}
|
||||
}
|
||||
else if(_cp.IsRet()) //possible function end?
|
||||
else if(zydis.IsRet()) //possible function end?
|
||||
{
|
||||
end = addr;
|
||||
if(fardest < addr) //we stop if the farthest JXX destination forward is before this RET
|
||||
break;
|
||||
}
|
||||
|
||||
addr += _cp.Size();
|
||||
addr += zydis.Size();
|
||||
}
|
||||
else
|
||||
addr++;
|
||||
|
@ -471,22 +474,22 @@ bool cbInstrBriefcheck(int argc, char* argv[])
|
|||
return false;
|
||||
Memory<unsigned char*> buffer(size + 16);
|
||||
DbgMemRead(base, buffer(), size);
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
std::unordered_set<String> reported;
|
||||
for(duint i = 0; i < size;)
|
||||
{
|
||||
if(!cp.Disassemble(base + i, buffer() + i, 16))
|
||||
if(!zydis.Disassemble(base + i, buffer() + i, 16))
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i += cp.Size();
|
||||
auto mnem = StringUtils::ToLower(cp.Mnemonic());
|
||||
i += zydis.Size();
|
||||
auto mnem = StringUtils::ToLower(zydis.Mnemonic());
|
||||
auto brief = MnemonicHelp::getBriefDescription(mnem.c_str());
|
||||
if(brief.length() || reported.count(mnem))
|
||||
continue;
|
||||
reported.insert(mnem);
|
||||
dprintf_untranslated("%p: %s\n", cp.Address(), mnem.c_str());
|
||||
dprintf_untranslated("%p: %s\n", zydis.Address(), mnem.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -79,8 +79,8 @@ bool cbInstrCommentList(int argc, char* argv[])
|
|||
//setup reference view
|
||||
GuiReferenceInitialize(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Comments")));
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address")));
|
||||
GuiReferenceAddColumn(64, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(10, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Comment")));
|
||||
GuiReferenceAddColumn(50, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Comment")));
|
||||
GuiReferenceSetRowCount(0);
|
||||
GuiReferenceReloadData();
|
||||
size_t cbsize;
|
||||
|
@ -159,7 +159,7 @@ bool cbInstrLabelList(int argc, char* argv[])
|
|||
//setup reference view
|
||||
GuiReferenceInitialize(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Labels")));
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address")));
|
||||
GuiReferenceAddColumn(100, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(50, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
|
||||
GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Label")));
|
||||
GuiReferenceSetRowCount(0);
|
||||
GuiReferenceReloadData();
|
||||
|
@ -275,7 +275,7 @@ bool cbInstrBookmarkList(int argc, char* argv[])
|
|||
|
||||
bool cbInstrBookmarkClear(int argc, char* argv[])
|
||||
{
|
||||
LabelClear();
|
||||
BookmarkClear();
|
||||
GuiUpdateAllViews();
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "All bookmarks deleted!"));
|
||||
return true;
|
||||
|
@ -416,8 +416,8 @@ bool cbInstrArgumentList(int argc, char* argv[])
|
|||
GuiReferenceInitialize(GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Arguments")));
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Start")));
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "End")));
|
||||
GuiReferenceAddColumn(100, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly (Start)")));
|
||||
GuiReferenceAddColumn(10, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Label/Comment")));
|
||||
GuiReferenceAddColumn(50, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly (Start)")));
|
||||
GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Label/Comment")));
|
||||
GuiReferenceSetRowCount(0);
|
||||
GuiReferenceReloadData();
|
||||
size_t cbsize;
|
||||
|
@ -512,7 +512,7 @@ bool cbInstrLoopList(int argc, char* argv[])
|
|||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "End")));
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Depth")));
|
||||
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Parent")));
|
||||
GuiReferenceAddColumn(100, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly (Start)")));
|
||||
GuiReferenceAddColumn(50, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly (Start)")));
|
||||
GuiReferenceAddColumn(0, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Label/Comment")));
|
||||
GuiReferenceSetRowCount(0);
|
||||
GuiReferenceReloadData();
|
||||
|
|
|
@ -1263,8 +1263,8 @@ void cbRtrStep()
|
|||
#endif //_WIN64
|
||||
)
|
||||
{
|
||||
Zydis cp;
|
||||
if(cp.Disassemble(cip, data) && cp.IsRet())
|
||||
Zydis zydis;
|
||||
if(zydis.Disassemble(cip, data) && zydis.IsRet())
|
||||
reachedReturn = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,17 +83,17 @@ bool disasmfast(const unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* b
|
|||
{
|
||||
if(!data || !basicinfo)
|
||||
return false;
|
||||
Zydis cp;
|
||||
cp.Disassemble(addr, data, MAX_DISASM_BUFFER);
|
||||
if(trydisasmfast(data, addr, basicinfo, cp.Success() ? cp.Size() : 1))
|
||||
Zydis zydis;
|
||||
zydis.Disassemble(addr, data, MAX_DISASM_BUFFER);
|
||||
if(trydisasmfast(data, addr, basicinfo, zydis.Success() ? zydis.Size() : 1))
|
||||
return true;
|
||||
if(!cp.Success())
|
||||
if(!zydis.Success())
|
||||
{
|
||||
strcpy_s(basicinfo->instruction, "???");
|
||||
basicinfo->size = 1;
|
||||
return false;
|
||||
}
|
||||
fillbasicinfo(&cp, basicinfo);
|
||||
fillbasicinfo(&zydis, basicinfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n)
|
|||
unsigned char* pdata;
|
||||
|
||||
// Reset Disasm Structure
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
|
||||
// Check if the pointer is not null
|
||||
if(data == NULL)
|
||||
|
@ -58,10 +58,10 @@ duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n)
|
|||
{
|
||||
abuf[i % 128] = addr;
|
||||
|
||||
if(!cp.Disassemble(0, pdata, (int)size))
|
||||
if(!zydis.Disassemble(0, pdata, (int)size))
|
||||
cmdsize = 1;
|
||||
else
|
||||
cmdsize = cp.Size();
|
||||
cmdsize = zydis.Size();
|
||||
|
||||
pdata += cmdsize;
|
||||
addr += cmdsize;
|
||||
|
@ -82,7 +82,7 @@ duint disasmnext(unsigned char* data, duint base, duint size, duint ip, int n)
|
|||
unsigned char* pdata;
|
||||
|
||||
// Reset Disasm Structure
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
|
||||
if(data == NULL)
|
||||
return 0;
|
||||
|
@ -98,10 +98,10 @@ duint disasmnext(unsigned char* data, duint base, duint size, duint ip, int n)
|
|||
|
||||
for(i = 0; i < n && size > 0; i++)
|
||||
{
|
||||
if(!cp.Disassemble(0, pdata, (int)size))
|
||||
if(!zydis.Disassemble(0, pdata, (int)size))
|
||||
cmdsize = 1;
|
||||
else
|
||||
cmdsize = cp.Size();
|
||||
cmdsize = zydis.Size();
|
||||
|
||||
pdata += cmdsize;
|
||||
ip += cmdsize;
|
||||
|
@ -111,16 +111,16 @@ duint disasmnext(unsigned char* data, duint base, duint size, duint ip, int n)
|
|||
return ip;
|
||||
}
|
||||
|
||||
static void HandleZydisOperand(Zydis & cp, int opindex, DISASM_ARG* arg, bool getregs)
|
||||
static void HandleZydisOperand(Zydis & zydis, int opindex, DISASM_ARG* arg, bool getregs)
|
||||
{
|
||||
auto value = cp.ResolveOpValue(opindex, [&cp, getregs](ZydisRegister reg)
|
||||
auto value = (duint)zydis.ResolveOpValue(opindex, [&zydis, getregs](ZydisRegister reg)
|
||||
{
|
||||
auto regName = getregs ? cp.RegName(reg) : nullptr;
|
||||
auto regName = getregs ? zydis.RegName(reg) : nullptr;
|
||||
return regName ? getregister(nullptr, regName) : 0; //TODO: temporary needs enums + caching
|
||||
});
|
||||
const auto & op = cp[opindex];
|
||||
const auto & op = zydis[opindex];
|
||||
arg->segment = SEG_DEFAULT;
|
||||
auto opText = cp.OperandText(opindex);
|
||||
auto opText = zydis.OperandText(opindex);
|
||||
StringUtils::ReplaceAll(opText, "0x", "");
|
||||
strcpy_s(arg->mnemonic, opText.c_str());
|
||||
switch(op.type)
|
||||
|
@ -144,7 +144,7 @@ static void HandleZydisOperand(Zydis & cp, int opindex, DISASM_ARG* arg, bool ge
|
|||
arg->type = arg_memory;
|
||||
const auto & mem = op.mem;
|
||||
if(mem.base == ZYDIS_REGISTER_RIP) //rip-relative
|
||||
arg->constant = cp.Address() + duint(mem.disp.value) + cp.Size();
|
||||
arg->constant = (duint)zydis.Address() + duint(mem.disp.value) + zydis.Size();
|
||||
else
|
||||
arg->constant = duint(mem.disp.value);
|
||||
if(mem.segment == ArchValue(ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS))
|
||||
|
@ -216,13 +216,13 @@ static void HandleZydisOperand(Zydis & cp, int opindex, DISASM_ARG* arg, bool ge
|
|||
}
|
||||
}
|
||||
|
||||
void disasmget(Zydis & cp, unsigned char* buffer, duint addr, DISASM_INSTR* instr, bool getregs)
|
||||
void disasmget(Zydis & zydis, unsigned char* buffer, duint addr, DISASM_INSTR* instr, bool getregs)
|
||||
{
|
||||
memset(instr, 0, sizeof(DISASM_INSTR));
|
||||
cp.Disassemble(addr, buffer, MAX_DISASM_BUFFER);
|
||||
if(trydisasm(buffer, addr, instr, cp.Success() ? cp.Size() : 1))
|
||||
zydis.Disassemble(addr, buffer, MAX_DISASM_BUFFER);
|
||||
if(trydisasm(buffer, addr, instr, zydis.Success() ? zydis.Size() : 1))
|
||||
return;
|
||||
if(!cp.Success())
|
||||
if(!zydis.Success())
|
||||
{
|
||||
strcpy_s(instr->instruction, "???");
|
||||
instr->instr_size = 1;
|
||||
|
@ -230,21 +230,21 @@ void disasmget(Zydis & cp, unsigned char* buffer, duint addr, DISASM_INSTR* inst
|
|||
instr->argcount = 0;
|
||||
return;
|
||||
}
|
||||
auto cpInstr = cp.GetInstr();
|
||||
strncpy_s(instr->instruction, cp.InstructionText().c_str(), _TRUNCATE);
|
||||
instr->instr_size = cpInstr->length;
|
||||
if(cp.IsBranchType(Zydis::BTJmp | Zydis::BTLoop | Zydis::BTRet | Zydis::BTCall))
|
||||
auto zyInstr = zydis.GetInstr();
|
||||
strncpy_s(instr->instruction, zydis.InstructionText().c_str(), _TRUNCATE);
|
||||
instr->instr_size = zyInstr->info.length;
|
||||
if(zydis.IsBranchType(Zydis::BTJmp | Zydis::BTLoop | Zydis::BTRet | Zydis::BTCall))
|
||||
instr->type = instr_branch;
|
||||
else if(strstr(instr->instruction, "sp") || strstr(instr->instruction, "bp"))
|
||||
instr->type = instr_stack;
|
||||
else
|
||||
instr->type = instr_normal;
|
||||
instr->argcount = cp.OpCount() <= 3 ? cp.OpCount() : 3;
|
||||
instr->argcount = zydis.OpCount() <= 3 ? zydis.OpCount() : 3;
|
||||
for(int i = 0; i < instr->argcount; i++)
|
||||
HandleZydisOperand(cp, i, &instr->arg[i], getregs);
|
||||
HandleZydisOperand(zydis, i, &instr->arg[i], getregs);
|
||||
}
|
||||
|
||||
void disasmget(Zydis & cp, duint addr, DISASM_INSTR* instr, bool getregs)
|
||||
void disasmget(Zydis & zydis, duint addr, DISASM_INSTR* instr, bool getregs)
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
{
|
||||
|
@ -254,15 +254,15 @@ void disasmget(Zydis & cp, duint addr, DISASM_INSTR* instr, bool getregs)
|
|||
}
|
||||
unsigned char buffer[MAX_DISASM_BUFFER] = "";
|
||||
if(MemRead(addr, buffer, sizeof(buffer)))
|
||||
disasmget(cp, buffer, addr, instr, getregs);
|
||||
disasmget(zydis, buffer, addr, instr, getregs);
|
||||
else
|
||||
memset(instr, 0, sizeof(DISASM_INSTR)); // Buffer overflow
|
||||
}
|
||||
|
||||
void disasmget(unsigned char* buffer, duint addr, DISASM_INSTR* instr, bool getregs)
|
||||
{
|
||||
Zydis cp;
|
||||
disasmget(cp, buffer, addr, instr, getregs);
|
||||
Zydis zydis;
|
||||
disasmget(zydis, buffer, addr, instr, getregs);
|
||||
}
|
||||
|
||||
void disasmget(duint addr, DISASM_INSTR* instr, bool getregs)
|
||||
|
@ -311,9 +311,16 @@ extern "C" __declspec(dllexport) bool isasciistring(const unsigned char* data, i
|
|||
if(bNewStringAlgorithm)
|
||||
{
|
||||
int len = 0;
|
||||
char* safebuffer = new char[maxlen];
|
||||
if(!safebuffer)
|
||||
char* safebuffer;
|
||||
try
|
||||
{
|
||||
safebuffer = new char[maxlen];
|
||||
}
|
||||
catch(const std::bad_alloc &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const char* p = (const char*)data; *p && len < maxlen - 1; len++, p++)
|
||||
{
|
||||
safebuffer[p - (const char*)data] = *p;
|
||||
|
@ -366,9 +373,16 @@ extern "C" __declspec(dllexport) bool isasciistring(const unsigned char* data, i
|
|||
extern "C" __declspec(dllexport) bool isunicodestring(const unsigned char* data, int maxlen)
|
||||
{
|
||||
int len = 0;
|
||||
wchar_t* safebuffer = new wchar_t[maxlen];
|
||||
if(!safebuffer)
|
||||
wchar_t* safebuffer;
|
||||
try
|
||||
{
|
||||
safebuffer = new wchar_t[maxlen];
|
||||
}
|
||||
catch(const std::bad_alloc &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const wchar_t* p = (const wchar_t*)data; *p && len < maxlen - 1; len += sizeof(wchar_t), p++)
|
||||
{
|
||||
safebuffer[p - (const wchar_t*)data] = *p;
|
||||
|
@ -518,10 +532,10 @@ bool disasmgetstringatwrapper(duint addr, char* dest, bool cache)
|
|||
|
||||
int disasmgetsize(duint addr, unsigned char* data)
|
||||
{
|
||||
Zydis cp;
|
||||
if(!cp.Disassemble(addr, data, MAX_DISASM_BUFFER))
|
||||
Zydis zydis;
|
||||
if(!zydis.Disassemble(addr, data, MAX_DISASM_BUFFER))
|
||||
return 1;
|
||||
return int(EncodeMapGetSize(addr, cp.Size()));
|
||||
return int(EncodeMapGetSize(addr, zydis.Size()));
|
||||
}
|
||||
|
||||
int disasmgetsize(duint addr)
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
//functions
|
||||
duint disasmback(unsigned char* data, duint base, duint size, duint ip, int n);
|
||||
duint disasmnext(unsigned char* data, duint base, duint size, duint ip, int n);
|
||||
void disasmget(Zydis & cp, unsigned char* buffer, duint addr, DISASM_INSTR* instr, bool getregs = true);
|
||||
void disasmget(Zydis & cp, duint addr, DISASM_INSTR* instr, bool getregs = true);
|
||||
void disasmget(Zydis & zydis, unsigned char* buffer, duint addr, DISASM_INSTR* instr, bool getregs = true);
|
||||
void disasmget(Zydis & zydis, duint addr, DISASM_INSTR* instr, bool getregs = true);
|
||||
void disasmget(unsigned char* buffer, duint addr, DISASM_INSTR* instr, bool getregs = true);
|
||||
void disasmget(duint addr, DISASM_INSTR* instr, bool getregs = true);
|
||||
bool disasmispossiblestring(duint addr, STRING_TYPE* type = nullptr);
|
||||
|
|
|
@ -287,7 +287,7 @@ bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type, bool* created)
|
|||
memset(map.data + offset, (byte)enc_middle, size);
|
||||
if(IsCodeType(type) && size > 1)
|
||||
{
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
Memory<unsigned char*> buffer(size);
|
||||
if(!MemRead(addr, buffer(), size))
|
||||
return false;
|
||||
|
@ -296,8 +296,8 @@ bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type, bool* created)
|
|||
for(auto i = offset; i < offset + size;)
|
||||
{
|
||||
map.data[i] = (byte)type;
|
||||
cp.Disassemble(base + i, buffer() + bufferoffset, int(buffersize - bufferoffset));
|
||||
cmdsize = cp.Success() ? cp.Size() : 1;
|
||||
zydis.Disassemble(base + i, buffer() + bufferoffset, int(buffersize - bufferoffset));
|
||||
cmdsize = zydis.Success() ? zydis.Size() : 1;
|
||||
i += cmdsize;
|
||||
bufferoffset += cmdsize;
|
||||
buffersize -= cmdsize;
|
||||
|
|
|
@ -57,6 +57,7 @@ bool ConstantCodeInit(const String & constantFile)
|
|||
std::unordered_map<unsigned int, String> names;
|
||||
if(!UniversalCodeInit(constantFile, names, 0))
|
||||
return false;
|
||||
Constants.reserve(names.size());
|
||||
for(const auto & it : names)
|
||||
Constants.insert({ it.second, it.first });
|
||||
return true;
|
||||
|
@ -244,6 +245,7 @@ bool SyscallInit()
|
|||
}
|
||||
else
|
||||
{
|
||||
SyscallIndices.reserve(sizeof(Win32kSyscalls) / sizeof(Win32kSyscalls[0]));
|
||||
for(auto & syscall : Win32kSyscalls)
|
||||
{
|
||||
auto index = syscall.GetSyscallIndex((USHORT)versionInfo.dwBuildNumber, ArchValue(true, false));
|
||||
|
|
|
@ -83,6 +83,7 @@ void ExpressionFunctions::Init()
|
|||
RegisterEasy("bswap", bswap);
|
||||
RegisterEasy("ternary,tern", ternary);
|
||||
RegisterEasy("GetTickCount,gettickcount", gettickcount);
|
||||
RegisterEasy("rdtsc", rdtsc);
|
||||
|
||||
//Memory
|
||||
RegisterEasy("mem.valid,mem.isvalid", memvalid);
|
||||
|
@ -154,10 +155,15 @@ void ExpressionFunctions::Init()
|
|||
|
||||
//Other
|
||||
RegisterEasy("isdebuggerfocused", isdebuggerfocused);
|
||||
RegisterEasy("isdebuggeefocused", isdebuggeefocused);
|
||||
|
||||
// Strings
|
||||
ExpressionFunctions::Register("ansi", ValueTypeString, { ValueTypeNumber }, Exprfunc::ansi, nullptr);
|
||||
ExpressionFunctions::Register("ansi.strict", ValueTypeString, { ValueTypeNumber }, Exprfunc::ansi_strict, nullptr);
|
||||
ExpressionFunctions::Register("utf8", ValueTypeString, { ValueTypeNumber }, Exprfunc::utf8, nullptr);
|
||||
ExpressionFunctions::Register("utf8.strict", ValueTypeString, { ValueTypeNumber }, Exprfunc::utf8_strict, nullptr);
|
||||
ExpressionFunctions::Register("utf16", ValueTypeString, { ValueTypeNumber }, Exprfunc::utf16, nullptr);
|
||||
ExpressionFunctions::Register("utf16.strict", ValueTypeString, { ValueTypeNumber }, Exprfunc::utf16_strict, nullptr);
|
||||
ExpressionFunctions::Register("strstr", ValueTypeNumber, { ValueTypeString, ValueTypeString }, Exprfunc::strstr, nullptr);
|
||||
ExpressionFunctions::Register("stristr", ValueTypeNumber, { ValueTypeString, ValueTypeString }, Exprfunc::stristr, nullptr);
|
||||
ExpressionFunctions::Register("streq", ValueTypeNumber, { ValueTypeString, ValueTypeString }, Exprfunc::streq, nullptr);
|
||||
|
|
|
@ -282,9 +282,9 @@ namespace Exprfunc
|
|||
unsigned char data[16];
|
||||
if(MemRead(addr, data, sizeof(data), nullptr, true))
|
||||
{
|
||||
Zydis cp;
|
||||
if(cp.Disassemble(addr, data))
|
||||
return cp.IsNop();
|
||||
Zydis zydis;
|
||||
if(zydis.Disassemble(addr, data))
|
||||
return zydis.IsNop();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -294,9 +294,9 @@ namespace Exprfunc
|
|||
unsigned char data[16];
|
||||
if(MemRead(addr, data, sizeof(data), nullptr, true))
|
||||
{
|
||||
Zydis cp;
|
||||
if(cp.Disassemble(addr, data))
|
||||
return cp.IsUnusual();
|
||||
Zydis zydis;
|
||||
if(zydis.Disassemble(addr, data))
|
||||
return zydis.IsUnusual();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -453,6 +453,11 @@ namespace Exprfunc
|
|||
return GetTickCount();
|
||||
}
|
||||
|
||||
duint rdtsc()
|
||||
{
|
||||
return (duint)__rdtsc();
|
||||
}
|
||||
|
||||
static duint readMem(duint addr, duint size)
|
||||
{
|
||||
duint value = 0;
|
||||
|
@ -600,9 +605,29 @@ namespace Exprfunc
|
|||
return getLastExceptionInfo().ExceptionRecord.ExceptionInformation[index];
|
||||
}
|
||||
|
||||
duint isprocessfocused(DWORD process)
|
||||
{
|
||||
HWND foreground = GetForegroundWindow();
|
||||
if(foreground)
|
||||
{
|
||||
DWORD pid;
|
||||
DWORD tid = GetWindowThreadProcessId(foreground, &pid);
|
||||
return pid == process;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
duint isdebuggerfocused()
|
||||
{
|
||||
return GuiIsDebuggerFocused();
|
||||
return isprocessfocused(GetCurrentProcessId());
|
||||
}
|
||||
|
||||
duint isdebuggeefocused()
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
return 0;
|
||||
return isprocessfocused(fdProcessInfo->dwProcessId);
|
||||
}
|
||||
|
||||
bool streq(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
|
@ -662,6 +687,45 @@ namespace Exprfunc
|
|||
return true;
|
||||
}
|
||||
|
||||
template<bool Strict>
|
||||
bool ansi(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
assert(argc == 1);
|
||||
assert(argv[0].type == ValueTypeNumber);
|
||||
|
||||
duint addr = argv[0].number;
|
||||
|
||||
std::vector<char> tempStr(MAX_STRING_SIZE + 1);
|
||||
duint NumberOfBytesRead = 0;
|
||||
if(!MemRead(addr, tempStr.data(), tempStr.size() - 1, &NumberOfBytesRead) && NumberOfBytesRead == 0 && Strict)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = ValueString(StringUtils::LocalCpToUtf8(tempStr.data()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool Strict>
|
||||
bool utf8(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
assert(argc == 1);
|
||||
assert(argv[0].type == ValueTypeNumber);
|
||||
|
||||
duint addr = argv[0].number;
|
||||
|
||||
std::vector<char> tempStr(MAX_STRING_SIZE + 1);
|
||||
duint NumberOfBytesRead = 0;
|
||||
if(!MemRead(addr, tempStr.data(), tempStr.size() - 1, &NumberOfBytesRead) && NumberOfBytesRead == 0 && Strict)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = ValueString(tempStr.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool Strict>
|
||||
bool utf16(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
assert(argc == 1);
|
||||
|
@ -671,7 +735,7 @@ namespace Exprfunc
|
|||
|
||||
std::vector<wchar_t> tempStr(MAX_STRING_SIZE + 1);
|
||||
duint NumberOfBytesRead = 0;
|
||||
if(!MemRead(addr, tempStr.data(), sizeof(wchar_t) * (tempStr.size() - 1), &NumberOfBytesRead) && NumberOfBytesRead == 0)
|
||||
if(!MemRead(addr, tempStr.data(), sizeof(wchar_t) * (tempStr.size() - 1), &NumberOfBytesRead) && NumberOfBytesRead == 0 && Strict)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -687,21 +751,33 @@ namespace Exprfunc
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ansi(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
return ansi<false>(result, argc, argv, userdata);
|
||||
}
|
||||
|
||||
bool ansi_strict(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
return ansi<true>(result, argc, argv, userdata);
|
||||
}
|
||||
|
||||
bool utf8(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
assert(argc == 1);
|
||||
assert(argv[0].type == ValueTypeNumber);
|
||||
return utf8<false>(result, argc, argv, userdata);
|
||||
}
|
||||
|
||||
duint addr = argv[0].number;
|
||||
bool utf8_strict(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
return utf8<true>(result, argc, argv, userdata);
|
||||
}
|
||||
|
||||
std::vector<char> tempStr(MAX_STRING_SIZE + 1);
|
||||
duint NumberOfBytesRead = 0;
|
||||
if(!MemRead(addr, tempStr.data(), tempStr.size() - 1, &NumberOfBytesRead) && NumberOfBytesRead == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool utf16(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
return utf16<false>(result, argc, argv, userdata);
|
||||
}
|
||||
|
||||
*result = ValueString(tempStr.data());
|
||||
return true;
|
||||
bool utf16_strict(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata)
|
||||
{
|
||||
return utf16<true>(result, argc, argv, userdata);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ namespace Exprfunc
|
|||
duint trhitcount(duint addr);
|
||||
duint trisrecording();
|
||||
duint gettickcount();
|
||||
duint rdtsc();
|
||||
|
||||
duint readbyte(duint addr);
|
||||
duint readword(duint addr);
|
||||
|
@ -87,12 +88,17 @@ namespace Exprfunc
|
|||
duint exinfo(duint index);
|
||||
|
||||
duint isdebuggerfocused();
|
||||
duint isdebuggeefocused();
|
||||
|
||||
bool streq(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool strieq(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool strstr(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool stristr(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool strlen(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool utf16(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool ansi(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool ansi_strict(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool utf8(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool utf8_strict(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool utf16(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
bool utf16_strict(ExpressionValue* result, int argc, const ExpressionValue* argv, void* userdata);
|
||||
}
|
|
@ -24,6 +24,7 @@ static void HandleTypesEnum()
|
|||
return;
|
||||
|
||||
auto TypeInfo = TypesInformation()->TypeInformation;
|
||||
HandleTypeNames.reserve(TypesInformation()->NumberOfTypes);
|
||||
for(ULONG i = 0; i < TypesInformation()->NumberOfTypes; i++)
|
||||
{
|
||||
auto wtypeName = WString(TypeInfo->TypeName.Buffer, TypeInfo->TypeName.Buffer + TypeInfo->TypeName.Length / 2);
|
||||
|
|
|
@ -24,6 +24,14 @@ std::map<Range, MEMPAGE, RangeCompare> memoryPages;
|
|||
bool bListAllPages = false;
|
||||
bool bQueryWorkingSet = false;
|
||||
|
||||
// Get system information once.
|
||||
static const SYSTEM_INFO systemInfo = []()
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
return si;
|
||||
}();
|
||||
|
||||
static std::vector<MEMPAGE> QueryMemPages()
|
||||
{
|
||||
// First gather all possible pages in the memory range
|
||||
|
@ -31,7 +39,7 @@ static std::vector<MEMPAGE> QueryMemPages()
|
|||
pages.reserve(200); //TODO: provide a better estimate
|
||||
|
||||
SIZE_T numBytes = 0;
|
||||
duint pageStart = 0;
|
||||
duint pageStart = (duint)systemInfo.lpMinimumApplicationAddress;
|
||||
duint allocationBase = 0;
|
||||
|
||||
do
|
||||
|
@ -106,7 +114,7 @@ static std::vector<MEMPAGE> QueryMemPages()
|
|||
return pages;
|
||||
}
|
||||
|
||||
static void ProcessFileSections(std::vector<MEMPAGE> & pageVector)
|
||||
static void ProcessFileSections(std::vector<MEMPAGE> & pageVector, std::vector<String> & errors)
|
||||
{
|
||||
if(pageVector.empty())
|
||||
return;
|
||||
|
@ -159,7 +167,7 @@ static void ProcessFileSections(std::vector<MEMPAGE> & pageVector)
|
|||
// Spam the user with errors to hopefully get more information
|
||||
std::string summary;
|
||||
summary = StringUtils::sprintf("The module at %p (%s%s) triggers a weird bug, please report an issue\n", modBase, modInfo->name, modInfo->extension);
|
||||
GuiAddLogMessage(summary.c_str());
|
||||
errors.push_back(std::move(summary));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,6 +201,27 @@ static void ProcessFileSections(std::vector<MEMPAGE> & pageVector)
|
|||
}
|
||||
}
|
||||
|
||||
auto listIncludedSections = [&]()
|
||||
{
|
||||
size_t infoOffset = 0;
|
||||
// Display module name in first region (useful if PE header and first section have same protection)
|
||||
if(pageBase == modBase)
|
||||
infoOffset = strlen(currentPage.info);
|
||||
for(size_t j = 0; j < sections.size() && infoOffset + 1 < _countof(currentPage.info); j++)
|
||||
{
|
||||
const auto & currentSection = sections.at(j);
|
||||
duint sectionStart = currentSection.addr;
|
||||
duint sectionEnd = sectionStart + currentSection.size;
|
||||
// Check if the section and page overlap
|
||||
if(pageBase < sectionEnd && pageBase + pageSize > sectionStart)
|
||||
{
|
||||
if(infoOffset)
|
||||
infoOffset += _snprintf_s(currentPage.info + infoOffset, sizeof(currentPage.info) - infoOffset, _TRUNCATE, ",");
|
||||
infoOffset += _snprintf_s(currentPage.info + infoOffset, sizeof(currentPage.info) - infoOffset, _TRUNCATE, " \"%s\"", currentSection.name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Section view
|
||||
if(!bListAllPages)
|
||||
{
|
||||
|
@ -247,30 +276,16 @@ static void ProcessFileSections(std::vector<MEMPAGE> & pageVector)
|
|||
for(const auto & page : newPages)
|
||||
summary += StringUtils::sprintf(" \"%s\": %p[%p]\n", page.info, page.mbi.BaseAddress, page.mbi.RegionSize);
|
||||
summary += "Please report an issue!\n";
|
||||
GuiAddLogMessage(summary.c_str());
|
||||
strncat_s(currentPage.info, " (error, see log)", _TRUNCATE);
|
||||
errors.push_back(std::move(summary));
|
||||
|
||||
// Fall back to the 'list all pages' algorithm
|
||||
listIncludedSections();
|
||||
}
|
||||
}
|
||||
// List all pages
|
||||
else
|
||||
{
|
||||
size_t infoOffset = 0;
|
||||
// Display module name in first region (useful if PE header and first section have same protection)
|
||||
if(pageBase == modBase)
|
||||
infoOffset = strlen(currentPage.info);
|
||||
for(size_t j = 0; j < sections.size() && infoOffset + 1 < _countof(currentPage.info); j++)
|
||||
{
|
||||
const auto & currentSection = sections.at(j);
|
||||
duint sectionStart = currentSection.addr;
|
||||
duint sectionEnd = sectionStart + currentSection.size;
|
||||
// Check if the section and page overlap
|
||||
if(pageBase < sectionEnd && pageBase + pageSize > sectionStart)
|
||||
{
|
||||
if(infoOffset)
|
||||
infoOffset += _snprintf_s(currentPage.info + infoOffset, sizeof(currentPage.info) - infoOffset, _TRUNCATE, ",");
|
||||
infoOffset += _snprintf_s(currentPage.info + infoOffset, sizeof(currentPage.info) - infoOffset, _TRUNCATE, " \"%s\"", currentSection.name);
|
||||
}
|
||||
}
|
||||
listIncludedSections();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,6 +320,7 @@ static void ProcessSystemPages(std::vector<MEMPAGE> & pageVector)
|
|||
auto HeapCount = min(_countof(ProcessHeaps), NumberOfHeaps);
|
||||
MemRead(ProcessHeapsPtr, ProcessHeaps, sizeof(duint) * HeapCount);
|
||||
std::unordered_map<duint, uint32_t> processHeapIds;
|
||||
processHeapIds.reserve(HeapCount);
|
||||
for(uint32_t i = 0; i < HeapCount; i++)
|
||||
processHeapIds.emplace(ProcessHeaps[i], i);
|
||||
|
||||
|
@ -396,7 +412,8 @@ void MemUpdateMap()
|
|||
std::vector<MEMPAGE> pageVector = QueryMemPages();
|
||||
|
||||
// Process file sections
|
||||
ProcessFileSections(pageVector);
|
||||
std::vector<String> errors;
|
||||
ProcessFileSections(pageVector, errors);
|
||||
|
||||
// Get a list of threads for information about Kernel/PEB/TEB/Stack ranges
|
||||
ProcessSystemPages(pageVector);
|
||||
|
@ -405,11 +422,22 @@ void MemUpdateMap()
|
|||
EXCLUSIVE_ACQUIRE(LockMemoryPages);
|
||||
memoryPages.clear();
|
||||
|
||||
// Print the annoying errors only once
|
||||
static std::unordered_set<String> shownErrors;
|
||||
for(auto & error : errors)
|
||||
{
|
||||
if(shownErrors.count(error) == 0)
|
||||
{
|
||||
GuiAddLogMessage(error.c_str());
|
||||
shownErrors.insert(std::move(error));
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto & page : pageVector)
|
||||
{
|
||||
duint start = (duint)page.mbi.BaseAddress;
|
||||
duint size = (duint)page.mbi.RegionSize;
|
||||
memoryPages.insert(std::make_pair(std::make_pair(start, start + size - 1), page));
|
||||
memoryPages.emplace(std::make_pair(start, start + size - 1), page);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -864,6 +864,10 @@ bool ModLoad(duint Base, duint Size, const char* FullPath, bool loadSymbols)
|
|||
// Load the physical module from disk
|
||||
if(StaticFileLoadW(wszFullPath.c_str(), UE_ACCESS_READ, false, &info.fileHandle, &info.loadedSize, &info.fileMap, &info.fileMapVA))
|
||||
{
|
||||
// Fix an anti-debug trick, which opens exclusive access to the file
|
||||
CloseHandle(info.fileHandle);
|
||||
info.fileHandle = (HANDLE)1; // Set to non-zero for TitanEngine compatibility
|
||||
|
||||
GetModuleInfo(info, info.fileMapVA);
|
||||
|
||||
Size = GetPE32DataFromMappedFile(info.fileMapVA, 0, UE_SIZEOFIMAGE);
|
||||
|
@ -902,7 +906,7 @@ bool ModLoad(duint Base, duint Size, const char* FullPath, bool loadSymbols)
|
|||
|
||||
// Add module to list
|
||||
EXCLUSIVE_ACQUIRE(LockModules);
|
||||
modinfo.insert(std::make_pair(Range(Base, Base + Size - 1), std::move(infoPtr)));
|
||||
modinfo.emplace(Range(Base, Base + Size - 1), std::move(infoPtr));
|
||||
EXCLUSIVE_RELEASE();
|
||||
|
||||
// Put labels for virtual module exports
|
||||
|
|
|
@ -56,7 +56,7 @@ bool PatchSet(duint Address, unsigned char OldByte, unsigned char NewByte)
|
|||
else
|
||||
{
|
||||
// The entry was never found, insert it
|
||||
patches.insert(std::make_pair(key, newPatch));
|
||||
patches.emplace(key, newPatch);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -41,10 +41,14 @@ public:
|
|||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
|
||||
*ppStream = new FileStream(hFile);
|
||||
|
||||
if(*ppStream == NULL)
|
||||
try
|
||||
{
|
||||
*ppStream = new FileStream(hFile);
|
||||
}
|
||||
catch(const std::bad_alloc &)
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,6 @@ struct PLUG_DATA
|
|||
{
|
||||
char plugpath[MAX_PATH];
|
||||
char plugname[MAX_PATH];
|
||||
bool isLoaded;
|
||||
HINSTANCE hPlugin;
|
||||
PLUGINIT pluginit;
|
||||
PLUGSTOP plugstop;
|
||||
|
@ -67,7 +66,7 @@ struct PLUG_FORMATFUNCTION
|
|||
};
|
||||
|
||||
//plugin management functions
|
||||
bool pluginload(const char* pluginname, bool loadall = false);
|
||||
bool pluginload(const char* pluginname);
|
||||
bool pluginunload(const char* pluginname, bool unloadall = false);
|
||||
void pluginloadall(const char* pluginDir);
|
||||
void pluginunloadall();
|
||||
|
|
|
@ -63,14 +63,14 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
sprintf_s(fullName, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "%s (Region %p)")), Name, scanStart);
|
||||
|
||||
// Initialize disassembler
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
|
||||
// Allow an "initialization" notice
|
||||
refInfo.refcount = 0;
|
||||
refInfo.userinfo = UserData;
|
||||
refInfo.name = fullName;
|
||||
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, cp, true, [](int percent)
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, zydis, true, [](int percent)
|
||||
{
|
||||
GuiReferenceSetCurrentTaskProgress(percent, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Region Search")));
|
||||
GuiReferenceSetProgress(percent);
|
||||
|
@ -104,14 +104,14 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
sprintf_s(fullName, "%s (%p)", Name, scanStart);
|
||||
|
||||
// Initialize disassembler
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
|
||||
// Allow an "initialization" notice
|
||||
refInfo.refcount = 0;
|
||||
refInfo.userinfo = UserData;
|
||||
refInfo.name = fullName;
|
||||
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, cp, true, [](int percent)
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, zydis, true, [](int percent)
|
||||
{
|
||||
GuiReferenceSetCurrentTaskProgress(percent, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Module Search")));
|
||||
GuiReferenceSetProgress(percent);
|
||||
|
@ -147,7 +147,7 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
}
|
||||
|
||||
// Initialize disassembler
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
|
||||
// Determine the full module
|
||||
sprintf_s(fullName, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "User Modules (%s)")), Name);
|
||||
|
@ -165,7 +165,7 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
scanStart = modList[i].base;
|
||||
scanSize = modList[i].size;
|
||||
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, cp, initCallBack, [&i, &modList](int percent)
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, zydis, initCallBack, [&i, &modList](int percent)
|
||||
{
|
||||
float fPercent = (float)percent / 100.f;
|
||||
float fTotalPercent = ((float)i + fPercent) / (float)modList.size();
|
||||
|
@ -209,7 +209,7 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
}
|
||||
|
||||
// Initialize disassembler
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
|
||||
// Determine the full module
|
||||
sprintf_s(fullName, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "System Modules (%s)")), Name);
|
||||
|
@ -228,7 +228,7 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
scanSize = modList[i].size;
|
||||
|
||||
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, cp, initCallBack, [&i, &modList](int percent)
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, zydis, initCallBack, [&i, &modList](int percent)
|
||||
{
|
||||
float fPercent = (float)percent / 100.f;
|
||||
float fTotalPercent = ((float)i + fPercent) / (float)modList.size();
|
||||
|
@ -271,7 +271,7 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
}
|
||||
|
||||
// Initialize disassembler
|
||||
Zydis cp;
|
||||
Zydis zydis;
|
||||
|
||||
// Determine the full module
|
||||
sprintf_s(fullName, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "All Modules (%s)")), Name);
|
||||
|
@ -289,7 +289,7 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
if(i != 0)
|
||||
initCallBack = false;
|
||||
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, cp, initCallBack, [&i, &modList](int percent)
|
||||
RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, zydis, initCallBack, [&i, &modList](int percent)
|
||||
{
|
||||
float fPercent = (float)percent / 100.f;
|
||||
float fTotalPercent = ((float)i + fPercent) / (float)modList.size();
|
||||
|
@ -309,7 +309,7 @@ int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Sile
|
|||
return refInfo.refcount;
|
||||
}
|
||||
|
||||
int RefFindInRange(duint scanStart, duint scanSize, CBREF Callback, void* UserData, bool Silent, REFINFO & refInfo, Zydis & cp, bool initCallBack, const CBPROGRESS & cbUpdateProgress, bool disasmText)
|
||||
int RefFindInRange(duint scanStart, duint scanSize, CBREF Callback, void* UserData, bool Silent, REFINFO & refInfo, Zydis & zydis, bool initCallBack, const CBPROGRESS & cbUpdateProgress, bool disasmText)
|
||||
{
|
||||
// Allocate and read a buffer from the remote process
|
||||
Memory<unsigned char*> data(scanSize, "reffind:data");
|
||||
|
@ -339,15 +339,15 @@ int RefFindInRange(duint scanStart, duint scanSize, CBREF Callback, void* UserDa
|
|||
int disasmMaxSize = min(MAX_DISASM_BUFFER, (int)(scanSize - i)); // Prevent going past the boundary
|
||||
int disasmLen = 1;
|
||||
|
||||
if(cp.Disassemble(scanStart, data() + i, disasmMaxSize))
|
||||
if(zydis.Disassemble(scanStart, data() + i, disasmMaxSize))
|
||||
{
|
||||
BASIC_INSTRUCTION_INFO basicinfo;
|
||||
fillbasicinfo(&cp, &basicinfo, disasmText);
|
||||
fillbasicinfo(&zydis, &basicinfo, disasmText);
|
||||
|
||||
if(Callback(&cp, &basicinfo, &refInfo))
|
||||
if(Callback(&zydis, &basicinfo, &refInfo))
|
||||
refInfo.refcount++;
|
||||
|
||||
disasmLen = cp.Size();
|
||||
disasmLen = zydis.Size();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -26,6 +26,6 @@ typedef bool (*CBREF)(Zydis* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO*
|
|||
typedef std::function<void(int)> CBPROGRESS;
|
||||
|
||||
int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Silent, const char* Name, REFFINDTYPE type, bool disasmText);
|
||||
int RefFindInRange(duint scanStart, duint scanSize, CBREF Callback, void* UserData, bool Silent, REFINFO & refInfo, Zydis & cp, bool initCallBack, const CBPROGRESS & cbUpdateProgress, bool disasmText);
|
||||
int RefFindInRange(duint scanStart, duint scanSize, CBREF Callback, void* UserData, bool Silent, REFINFO & refInfo, Zydis & zydis, bool initCallBack, const CBPROGRESS & cbUpdateProgress, bool disasmText);
|
||||
|
||||
#endif // _REFERENCE_H
|
||||
|
|
|
@ -30,6 +30,7 @@ void stackupdateseh()
|
|||
STACK_COMMENT comment;
|
||||
strcpy_s(comment.color, "!sehclr"); // Special token for SEH chain color.
|
||||
auto count = SEHList.size();
|
||||
newcache.reserve(count);
|
||||
for(duint i = 0; i < count; i++)
|
||||
{
|
||||
if(i + 1 != count)
|
||||
|
|
|
@ -502,6 +502,7 @@ static void loadTypes(const JSON troot, std::vector<Member> & types)
|
|||
size_t i;
|
||||
JSON vali;
|
||||
Member curType;
|
||||
types.reserve(json_array_size(troot));
|
||||
json_array_foreach(troot, i, vali)
|
||||
{
|
||||
auto type = json_string_value(json_object_get(vali, "type"));
|
||||
|
@ -556,6 +557,7 @@ static void loadFunctions(const JSON froot, std::vector<Function> & functions)
|
|||
size_t i;
|
||||
JSON vali;
|
||||
Function curFunction;
|
||||
functions.reserve(json_array_size(froot));
|
||||
json_array_foreach(froot, i, vali)
|
||||
{
|
||||
auto rettype = json_string_value(json_object_get(vali, "rettype"));
|
||||
|
@ -581,6 +583,7 @@ static void loadFunctions(const JSON froot, std::vector<Function> & functions)
|
|||
size_t j;
|
||||
JSON valj;
|
||||
Member curArg;
|
||||
curFunction.args.reserve(json_array_size(args));
|
||||
json_array_foreach(args, j, valj)
|
||||
{
|
||||
auto type = json_string_value(json_object_get(valj, "type"));
|
||||
|
|
|
@ -155,7 +155,7 @@ bool varnew(const char* Name, duint Value, VAR_TYPE Type)
|
|||
var.value.size = sizeof(duint);
|
||||
var.value.type = VAR_UINT;
|
||||
var.value.u.value = Value;
|
||||
variables.insert(std::make_pair(name_, var));
|
||||
variables.emplace(name_, var);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -699,8 +699,6 @@ extern "C" DLL_EXPORT const char* _dbg_dbginit()
|
|||
dputs(QT_TRANSLATE_NOOP("DBG", "Setting JSON memory management functions..."));
|
||||
json_set_alloc_funcs(json_malloc, json_free);
|
||||
//#endif //ENABLE_MEM_TRACE
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Initializing Zydis..."));
|
||||
Zydis::GlobalInitialize();
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Getting directory information..."));
|
||||
|
||||
strcpy_s(scriptDllDir, szUserDir);
|
||||
|
@ -833,7 +831,6 @@ extern "C" DLL_EXPORT void _dbg_dbgexitsignal()
|
|||
dputs(QT_TRANSLATE_NOOP("DBG", "Cleaning up allocated data..."));
|
||||
cmdfree();
|
||||
varfree();
|
||||
Zydis::GlobalFinalize();
|
||||
dputs(QT_TRANSLATE_NOOP("DBG", "Cleaning up wait objects..."));
|
||||
waitdeinitialize();
|
||||
SafeDbghelpDeinitialize();
|
||||
|
|
|
@ -34,6 +34,7 @@ struct XrefSerializer : AddrInfoSerializer<XREFSINFO>
|
|||
value.type = XREF_DATA;
|
||||
size_t i;
|
||||
JSON reference;
|
||||
value.references.reserve(json_array_size(references));
|
||||
json_array_foreach(references, i, reference)
|
||||
{
|
||||
XREF_RECORD record;
|
||||
|
|
|
@ -319,7 +319,7 @@ static VOID CALLBACK MyLdrDllNotification(
|
|||
|
||||
typedef BOOL(WINAPI* pfnSetDefaultDllDirectories)(DWORD DirectoryFlags);
|
||||
typedef BOOL(WINAPI* pfnSetDllDirectoryW)(LPCWSTR lpPathName);
|
||||
typedef BOOL(WINAPI* pfnAddDllDirectory)(LPCWSTR lpPathName);
|
||||
typedef PVOID(WINAPI* pfnAddDllDirectory)(LPCWSTR lpPathName);
|
||||
|
||||
static pfnSetDefaultDllDirectories pSetDefaultDllDirectories;
|
||||
static pfnSetDllDirectoryW pSetDllDirectoryW;
|
||||
|
|
|
@ -19,11 +19,11 @@ public:
|
|||
virtual void unlock() = 0;
|
||||
virtual AbstractStdTable* list() const = 0;
|
||||
virtual AbstractStdTable* searchList() const = 0;
|
||||
virtual void filter(const QString & filter, FilterType type, int startColumn) = 0;
|
||||
virtual void filter(const QString & filter, FilterType type, duint startColumn) = 0;
|
||||
|
||||
bool rowMatchesFilter(const QString & filter, FilterType type, int row, int startColumn) const
|
||||
bool rowMatchesFilter(const QString & filter, FilterType type, duint row, duint startColumn) const
|
||||
{
|
||||
int count = list()->getColumnCount();
|
||||
auto count = list()->getColumnCount();
|
||||
if(startColumn + 1 > count)
|
||||
return false;
|
||||
auto cs = Qt::CaseInsensitive;
|
||||
|
@ -32,21 +32,21 @@ public:
|
|||
case FilterStartsWithTextCaseSensitive:
|
||||
cs = Qt::CaseSensitive;
|
||||
case FilterStartsWithTextCaseInsensitive:
|
||||
for(int i = startColumn; i < count; i++)
|
||||
for(duint i = startColumn; i < count; i++)
|
||||
if(list()->getCellContent(row, i).startsWith(filter, cs))
|
||||
return true;
|
||||
break;
|
||||
case FilterContainsTextCaseSensitive:
|
||||
cs = Qt::CaseSensitive;
|
||||
case FilterContainsTextCaseInsensitive:
|
||||
for(int i = startColumn; i < count; i++)
|
||||
for(duint i = startColumn; i < count; i++)
|
||||
if(list()->getCellContent(row, i).contains(filter, cs))
|
||||
return true;
|
||||
break;
|
||||
case FilterRegexCaseSensitive:
|
||||
cs = Qt::CaseSensitive;
|
||||
case FilterRegexCaseInsensitive:
|
||||
for(int i = startColumn; i < count; i++)
|
||||
for(duint i = startColumn; i < count; i++)
|
||||
if(list()->getCellContent(row, i).contains(QRegExp(filter, cs)))
|
||||
return true;
|
||||
break;
|
||||
|
|
|
@ -8,7 +8,7 @@ AbstractStdTable::AbstractStdTable(QWidget* parent) : AbstractTableView(parent)
|
|||
|
||||
connect(Bridge::getBridge(), SIGNAL(repaintTableView()), this, SLOT(reloadData()));
|
||||
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequestedSlot(QPoint)));
|
||||
connect(this, SIGNAL(headerButtonPressed(int)), this, SLOT(headerButtonPressedSlot(int)));
|
||||
connect(this, SIGNAL(headerButtonPressed(duint)), this, SLOT(headerButtonPressedSlot(duint)));
|
||||
|
||||
Initialize();
|
||||
|
||||
|
@ -22,27 +22,27 @@ AbstractStdTable::AbstractStdTable(QWidget* parent) : AbstractTableView(parent)
|
|||
mExportTableCSV = makeShortcutAction(DIcon("database-export"), tr("&Export Table"), SLOT(exportTableSlot()), "ActionExport");
|
||||
}
|
||||
|
||||
QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
QString AbstractStdTable::paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h)
|
||||
{
|
||||
bool isaddr = DbgIsDebugging() && getRowCount() > 0 && col == mAddressColumn;
|
||||
bool wIsSelected = isSelected(rowBase, rowOffset);
|
||||
QString text = getCellContent(rowBase + rowOffset, col);
|
||||
bool rowSelected = isSelected(row);
|
||||
QString text = getCellContent(row, col);
|
||||
|
||||
duint wVA = isaddr ? duint(text.toULongLong(&isaddr, 16)) : 0;
|
||||
auto wIsTraced = isaddr && DbgFunctions()->GetTraceRecordHitCount(wVA) != 0;
|
||||
duint va = isaddr ? duint(text.toULongLong(&isaddr, 16)) : 0;
|
||||
auto rowTraced = isaddr && DbgFunctions()->GetTraceRecordHitCount(va) != 0;
|
||||
QColor lineBackgroundColor;
|
||||
bool isBackgroundColorSet;
|
||||
if(wIsSelected && wIsTraced)
|
||||
if(rowSelected && rowTraced)
|
||||
{
|
||||
lineBackgroundColor = mTracedSelectedAddressBackgroundColor;
|
||||
isBackgroundColorSet = true;
|
||||
}
|
||||
else if(wIsSelected)
|
||||
else if(rowSelected)
|
||||
{
|
||||
lineBackgroundColor = mSelectionColor;
|
||||
isBackgroundColorSet = true;
|
||||
}
|
||||
else if(wIsTraced)
|
||||
else if(rowTraced)
|
||||
{
|
||||
lineBackgroundColor = mTracedBackgroundColor;
|
||||
isBackgroundColorSet = true;
|
||||
|
@ -57,16 +57,16 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row
|
|||
if(col == mAddressColumn && isaddr)
|
||||
{
|
||||
char label[MAX_LABEL_SIZE] = "";
|
||||
if(bAddressLabel && DbgGetLabelAt(wVA, SEG_DEFAULT, label)) //has label
|
||||
if(bAddressLabel && DbgGetLabelAt(va, SEG_DEFAULT, label)) //has label
|
||||
{
|
||||
char module[MAX_MODULE_SIZE] = "";
|
||||
if(DbgGetModuleAt(wVA, module) && !QString(label).startsWith("JMP.&"))
|
||||
if(DbgGetModuleAt(va, module) && !QString(label).startsWith("JMP.&"))
|
||||
text += " <" + QString(module) + "." + QString(label) + ">";
|
||||
else
|
||||
text += " <" + QString(label) + ">";
|
||||
}
|
||||
BPXTYPE bpxtype = DbgGetBpxTypeAt(wVA);
|
||||
bool isbookmark = DbgGetBookmarkAt(wVA);
|
||||
BPXTYPE bpxtype = DbgGetBpxTypeAt(va);
|
||||
bool isbookmark = DbgGetBookmarkAt(va);
|
||||
|
||||
duint cip = Bridge::getBridge()->mLastCip;
|
||||
if(bCipBase)
|
||||
|
@ -76,7 +76,7 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row
|
|||
cip = base;
|
||||
}
|
||||
|
||||
if(DbgIsDebugging() && wVA == cip) //debugging + cip
|
||||
if(DbgIsDebugging() && va == cip) //debugging + cip
|
||||
{
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(mCipBackgroundColor));
|
||||
if(!isbookmark) //no bookmark
|
||||
|
@ -149,7 +149,7 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row
|
|||
if(bpxtype == bp_none) //no label, no breakpoint
|
||||
{
|
||||
QColor background;
|
||||
if(wIsSelected)
|
||||
if(rowSelected)
|
||||
{
|
||||
background = mSelectedAddressBackgroundColor;
|
||||
painter->setPen(mSelectedAddressColor); //black address (DisassemblySelectedAddressColor)
|
||||
|
@ -177,7 +177,7 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row
|
|||
else //other cases (memory breakpoint in disassembly) -> do as normal
|
||||
{
|
||||
QColor background;
|
||||
if(wIsSelected)
|
||||
if(rowSelected)
|
||||
{
|
||||
background = mSelectedAddressBackgroundColor;
|
||||
painter->setPen(mSelectedAddressColor); //black address (DisassemblySelectedAddressColor)
|
||||
|
@ -265,12 +265,12 @@ QString AbstractStdTable::paintContent(QPainter* painter, dsint rowBase, int row
|
|||
}
|
||||
}
|
||||
while(index != -1);
|
||||
QStringList split = text.split(QChar('\1'), QString::SkipEmptyParts, Qt::CaseInsensitive);
|
||||
QStringList split = text.split(QChar('\1'), Qt::SkipEmptyParts, Qt::CaseInsensitive);
|
||||
|
||||
//create rich text list
|
||||
RichTextPainter::CustomRichText_t curRichText;
|
||||
curRichText.flags = RichTextPainter::FlagColor;
|
||||
QColor textColor = getCellColor(rowBase + rowOffset, col);
|
||||
QColor textColor = getCellColor(row, col);
|
||||
QColor textBackgroundColor = Qt::transparent;
|
||||
QColor highlightColor = ConfigColor("SearchListViewHighlightColor");
|
||||
QColor highlightBackgroundColor = ConfigColor("SearchListViewHighlightBackgroundColor");
|
||||
|
@ -326,7 +326,7 @@ void AbstractStdTable::updateColors()
|
|||
|
||||
void AbstractStdTable::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
bool wAccept = true;
|
||||
bool accept = true;
|
||||
int y = transY(event->y());
|
||||
|
||||
if(mGuiState == AbstractStdTable::MultiRowsSelectionState)
|
||||
|
@ -335,18 +335,19 @@ void AbstractStdTable::mouseMoveEvent(QMouseEvent* event)
|
|||
|
||||
if(y >= 0 && y <= this->getTableHeight())
|
||||
{
|
||||
int wRowIndex = getTableOffset() + getIndexOffsetFromY(y);
|
||||
auto rowIndex = getTableOffset() + getIndexOffsetFromY(y);
|
||||
|
||||
if(wRowIndex < getRowCount())
|
||||
if(rowIndex < getRowCount())
|
||||
{
|
||||
if(mIsMultiSelectionAllowed)
|
||||
expandSelectionUpTo(wRowIndex);
|
||||
expandSelectionUpTo(rowIndex);
|
||||
else
|
||||
setSingleSelection(wRowIndex);
|
||||
setSingleSelection(rowIndex);
|
||||
|
||||
// TODO: only update if the selection actually changed
|
||||
updateViewport();
|
||||
|
||||
wAccept = false;
|
||||
accept = false;
|
||||
}
|
||||
}
|
||||
else if(y < 0)
|
||||
|
@ -359,13 +360,13 @@ void AbstractStdTable::mouseMoveEvent(QMouseEvent* event)
|
|||
}
|
||||
}
|
||||
|
||||
if(wAccept)
|
||||
if(accept)
|
||||
AbstractTableView::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void AbstractStdTable::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
bool wAccept = false;
|
||||
bool accept = false;
|
||||
|
||||
if(((event->buttons() & Qt::LeftButton) != 0) && ((event->buttons() & Qt::RightButton) == 0))
|
||||
{
|
||||
|
@ -373,26 +374,27 @@ void AbstractStdTable::mousePressEvent(QMouseEvent* event)
|
|||
{
|
||||
if(event->y() > getHeaderHeight())
|
||||
{
|
||||
int wRowIndex = getTableOffset() + getIndexOffsetFromY(transY(event->y()));
|
||||
auto rowIndex = getTableOffset() + getIndexOffsetFromY(transY(event->y()));
|
||||
|
||||
if(wRowIndex < getRowCount())
|
||||
if(rowIndex < getRowCount())
|
||||
{
|
||||
if(mIsMultiSelectionAllowed && (event->modifiers() & Qt::ShiftModifier))
|
||||
expandSelectionUpTo(wRowIndex);
|
||||
expandSelectionUpTo(rowIndex);
|
||||
else
|
||||
setSingleSelection(wRowIndex);
|
||||
setSingleSelection(rowIndex);
|
||||
|
||||
mGuiState = AbstractStdTable::MultiRowsSelectionState;
|
||||
|
||||
// TODO: only update if the selection actually changed
|
||||
updateViewport();
|
||||
|
||||
wAccept = true;
|
||||
accept = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!wAccept)
|
||||
if(!accept)
|
||||
AbstractTableView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
|
@ -405,7 +407,7 @@ void AbstractStdTable::mouseDoubleClickEvent(QMouseEvent* event)
|
|||
|
||||
void AbstractStdTable::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
bool wAccept = true;
|
||||
bool accept = true;
|
||||
|
||||
if((event->buttons() & Qt::LeftButton) == 0)
|
||||
{
|
||||
|
@ -413,13 +415,11 @@ void AbstractStdTable::mouseReleaseEvent(QMouseEvent* event)
|
|||
{
|
||||
mGuiState = AbstractStdTable::NoState;
|
||||
|
||||
updateViewport();
|
||||
|
||||
wAccept = false;
|
||||
accept = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(wAccept)
|
||||
if(accept)
|
||||
AbstractTableView::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
|
@ -433,10 +433,11 @@ void AbstractStdTable::keyPressEvent(QKeyEvent* event)
|
|||
key == Qt::Key_Down ||
|
||||
key == Qt::Key_Home ||
|
||||
key == Qt::Key_End ||
|
||||
key == Qt::Key_A)
|
||||
key == Qt::Key_A ||
|
||||
key == Qt::Key_C)
|
||||
{
|
||||
dsint wBotIndex = getTableOffset();
|
||||
dsint wTopIndex = wBotIndex + getNbrOfLineToPrint() - 1;
|
||||
auto botIndex = getTableOffset();
|
||||
auto topIndex = botIndex + getNbrOfLineToPrint() - 1;
|
||||
|
||||
switch(key)
|
||||
{
|
||||
|
@ -490,17 +491,25 @@ void AbstractStdTable::keyPressEvent(QKeyEvent* event)
|
|||
selectAll();
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_C:
|
||||
if(modifiers == Qt::ControlModifier) //Ctrl+C -> copy
|
||||
{
|
||||
copyLineSlot();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(getInitialSelection() < wBotIndex)
|
||||
if(getInitialSelection() < botIndex)
|
||||
{
|
||||
setTableOffset(getInitialSelection());
|
||||
}
|
||||
else if(getInitialSelection() >= wTopIndex)
|
||||
else if(getInitialSelection() >= topIndex)
|
||||
{
|
||||
setTableOffset(getInitialSelection() - getNbrOfLineToPrint() + 2);
|
||||
}
|
||||
|
||||
// TODO: only update if the selection actually changed
|
||||
updateViewport();
|
||||
}
|
||||
else
|
||||
|
@ -522,19 +531,19 @@ void AbstractStdTable::enableColumnSorting(bool enabled)
|
|||
/************************************************************************************
|
||||
Selection Management
|
||||
************************************************************************************/
|
||||
void AbstractStdTable::expandSelectionUpTo(int to)
|
||||
void AbstractStdTable::expandSelectionUpTo(duint to)
|
||||
{
|
||||
if(to < mSelection.firstSelectedIndex)
|
||||
{
|
||||
mSelection.fromIndex = to;
|
||||
mSelection.toIndex = mSelection.firstSelectedIndex;
|
||||
emit selectionChangedSignal(to);
|
||||
emit selectionChanged(to);
|
||||
}
|
||||
else if(to > mSelection.firstSelectedIndex)
|
||||
{
|
||||
mSelection.fromIndex = mSelection.firstSelectedIndex;
|
||||
mSelection.toIndex = to;
|
||||
emit selectionChangedSignal(to);
|
||||
emit selectionChanged(to);
|
||||
}
|
||||
else if(to == mSelection.firstSelectedIndex)
|
||||
{
|
||||
|
@ -544,46 +553,46 @@ void AbstractStdTable::expandSelectionUpTo(int to)
|
|||
|
||||
void AbstractStdTable::expandUp()
|
||||
{
|
||||
int wRowIndex = mSelection.firstSelectedIndex - 1;
|
||||
if(wRowIndex >= 0)
|
||||
auto rowIndex = mSelection.firstSelectedIndex - 1;
|
||||
if(rowIndex >= 0)
|
||||
{
|
||||
if(wRowIndex < mSelection.fromIndex)
|
||||
if(rowIndex < mSelection.fromIndex)
|
||||
{
|
||||
mSelection.fromIndex = wRowIndex;
|
||||
mSelection.firstSelectedIndex = wRowIndex;
|
||||
mSelection.fromIndex = rowIndex;
|
||||
mSelection.firstSelectedIndex = rowIndex;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelection.firstSelectedIndex = wRowIndex;
|
||||
mSelection.toIndex = wRowIndex;
|
||||
mSelection.firstSelectedIndex = rowIndex;
|
||||
mSelection.toIndex = rowIndex;
|
||||
}
|
||||
|
||||
emit selectionChangedSignal(wRowIndex);
|
||||
emit selectionChanged(rowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractStdTable::expandDown()
|
||||
{
|
||||
int wRowIndex = mSelection.firstSelectedIndex + 1;
|
||||
int endIndex = getRowCount() - 1;
|
||||
if(wRowIndex <= endIndex)
|
||||
auto rowIndex = mSelection.firstSelectedIndex + 1;
|
||||
auto endIndex = getRowCount() - 1;
|
||||
if(rowIndex <= endIndex)
|
||||
{
|
||||
|
||||
if(wRowIndex > mSelection.toIndex)
|
||||
if(rowIndex > mSelection.toIndex)
|
||||
{
|
||||
mSelection.firstSelectedIndex = wRowIndex;
|
||||
mSelection.toIndex = wRowIndex;
|
||||
mSelection.firstSelectedIndex = rowIndex;
|
||||
mSelection.toIndex = rowIndex;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelection.fromIndex = wRowIndex;
|
||||
mSelection.firstSelectedIndex = wRowIndex;
|
||||
mSelection.fromIndex = rowIndex;
|
||||
mSelection.firstSelectedIndex = rowIndex;
|
||||
}
|
||||
|
||||
|
||||
emit selectionChangedSignal(wRowIndex);
|
||||
emit selectionChanged(rowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,31 +606,31 @@ void AbstractStdTable::expandTop()
|
|||
|
||||
void AbstractStdTable::expandBottom()
|
||||
{
|
||||
int endIndex = getRowCount() - 1;
|
||||
if(endIndex >= 0)
|
||||
auto rowCount = getRowCount();
|
||||
if(rowCount > 0)
|
||||
{
|
||||
expandSelectionUpTo(endIndex);
|
||||
expandSelectionUpTo(rowCount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractStdTable::setSingleSelection(int index)
|
||||
void AbstractStdTable::setSingleSelection(duint index)
|
||||
{
|
||||
mSelection.firstSelectedIndex = index;
|
||||
mSelection.fromIndex = index;
|
||||
mSelection.toIndex = index;
|
||||
emit selectionChangedSignal(index);
|
||||
emit selectionChanged(index);
|
||||
}
|
||||
|
||||
int AbstractStdTable::getInitialSelection() const
|
||||
duint AbstractStdTable::getInitialSelection() const
|
||||
{
|
||||
return mSelection.firstSelectedIndex;
|
||||
}
|
||||
|
||||
QList<int> AbstractStdTable::getSelection() const
|
||||
QList<duint> AbstractStdTable::getSelection() const
|
||||
{
|
||||
QList<int> selection;
|
||||
QList<duint> selection;
|
||||
selection.reserve(mSelection.toIndex - mSelection.fromIndex);
|
||||
for(int i = mSelection.fromIndex; i <= mSelection.toIndex; i++)
|
||||
for(duint i = mSelection.fromIndex; i <= mSelection.toIndex; i++)
|
||||
{
|
||||
selection.append(i);
|
||||
}
|
||||
|
@ -638,7 +647,7 @@ void AbstractStdTable::selectStart()
|
|||
|
||||
void AbstractStdTable::selectEnd()
|
||||
{
|
||||
int endIndex = getRowCount() - 1;
|
||||
auto endIndex = getRowCount() - 1;
|
||||
if(endIndex >= 0)
|
||||
{
|
||||
setSingleSelection(endIndex);
|
||||
|
@ -647,60 +656,56 @@ void AbstractStdTable::selectEnd()
|
|||
|
||||
void AbstractStdTable::selectNext()
|
||||
{
|
||||
int wNext = getInitialSelection() + 1;
|
||||
// TODO: fix the signed/unsigned
|
||||
duint next = getInitialSelection() + 1;
|
||||
|
||||
// Bounding
|
||||
wNext = wNext > getRowCount() - 1 ? getRowCount() - 1 : wNext;
|
||||
wNext = wNext < 0 ? 0 : wNext;
|
||||
next = next > getRowCount() - 1 ? getRowCount() - 1 : next;
|
||||
next = next < 0 ? 0 : next;
|
||||
|
||||
setSingleSelection(wNext);
|
||||
setSingleSelection(next);
|
||||
}
|
||||
|
||||
void AbstractStdTable::selectPrevious()
|
||||
{
|
||||
int wNext = getInitialSelection() - 1;
|
||||
duint next = getInitialSelection() - 1;
|
||||
|
||||
// Bounding
|
||||
wNext = wNext > getRowCount() - 1 ? getRowCount() - 1 : wNext;
|
||||
wNext = wNext < 0 ? 0 : wNext;
|
||||
next = next > getRowCount() - 1 ? getRowCount() - 1 : next;
|
||||
next = next < 0 ? 0 : next;
|
||||
|
||||
setSingleSelection(wNext);
|
||||
setSingleSelection(next);
|
||||
}
|
||||
|
||||
void AbstractStdTable::selectAll()
|
||||
{
|
||||
int index = 0;
|
||||
int indexEnd = getRowCount() - 1;
|
||||
duint index = 0;
|
||||
duint indexEnd = getRowCount() - 1;
|
||||
|
||||
mSelection.firstSelectedIndex = index;
|
||||
mSelection.fromIndex = index;
|
||||
mSelection.toIndex = indexEnd;
|
||||
|
||||
emit selectionChangedSignal(index);
|
||||
emit selectionChanged(index);
|
||||
}
|
||||
|
||||
bool AbstractStdTable::isSelected(int base, int offset) const
|
||||
bool AbstractStdTable::isSelected(duint row) const
|
||||
{
|
||||
int wIndex = base + offset;
|
||||
|
||||
if(wIndex >= mSelection.fromIndex && wIndex <= mSelection.toIndex)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
return row >= mSelection.fromIndex && row <= mSelection.toIndex;
|
||||
}
|
||||
|
||||
bool AbstractStdTable::scrollSelect(int offset)
|
||||
bool AbstractStdTable::scrollSelect(duint row)
|
||||
{
|
||||
if(!isValidIndex(offset, 0))
|
||||
if(!isValidIndex(row, 0))
|
||||
return false;
|
||||
|
||||
int rangefrom = getTableOffset();
|
||||
int rangeto = rangefrom + getViewableRowsCount() - 1;
|
||||
if(offset < rangefrom) //offset lays before the current view
|
||||
setTableOffset(offset);
|
||||
else if(offset > (rangeto - 1)) //offset lays after the current view
|
||||
setTableOffset(offset - getViewableRowsCount() + 2);
|
||||
setSingleSelection(offset);
|
||||
auto rangefrom = getTableOffset();
|
||||
auto rangeto = rangefrom + getViewableRowsCount() - 1;
|
||||
if(row < rangefrom) //offset lays before the current view
|
||||
setTableOffset(row);
|
||||
else if(row > (rangeto - 1)) //offset lays after the current view
|
||||
setTableOffset(row - getViewableRowsCount() + 2);
|
||||
setSingleSelection(row);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -727,15 +732,15 @@ void AbstractStdTable::deleteAllColumns()
|
|||
|
||||
void AbstractStdTable::copyLineSlot()
|
||||
{
|
||||
int colCount = getColumnCount();
|
||||
auto colCount = getColumnCount();
|
||||
QString finalText = "";
|
||||
if(colCount == 1)
|
||||
finalText = getCellContent(getInitialSelection(), 0);
|
||||
else
|
||||
{
|
||||
for(int selected : getSelection())
|
||||
for(auto selected : getSelection())
|
||||
{
|
||||
for(int i = 0; i < colCount; i++)
|
||||
for(duint i = 0; i < colCount; i++)
|
||||
{
|
||||
QString cellContent = getCellContent(selected, i);
|
||||
if(!cellContent.length()) //skip empty cells
|
||||
|
@ -753,14 +758,14 @@ void AbstractStdTable::copyLineSlot()
|
|||
|
||||
void AbstractStdTable::copyLineToLogSlot()
|
||||
{
|
||||
int colCount = getColumnCount();
|
||||
int selected = getInitialSelection();
|
||||
auto colCount = getColumnCount();
|
||||
auto selected = getInitialSelection();
|
||||
QString finalText = "";
|
||||
if(colCount == 1)
|
||||
finalText = getCellContent(selected, 0);
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < colCount; i++)
|
||||
for(duint i = 0; i < colCount; i++)
|
||||
{
|
||||
QString cellContent = getCellContent(selected, i);
|
||||
if(!cellContent.length()) //skip empty cells
|
||||
|
@ -777,12 +782,12 @@ void AbstractStdTable::copyLineToLogSlot()
|
|||
|
||||
QString AbstractStdTable::copyTable(const std::vector<int> & colWidths)
|
||||
{
|
||||
int colCount = getColumnCount();
|
||||
int rowCount = getRowCount();
|
||||
auto colCount = getColumnCount();
|
||||
auto rowCount = getRowCount();
|
||||
QString finalText = "";
|
||||
if(colCount == 1)
|
||||
{
|
||||
for(int i = 0; i < rowCount; i++)
|
||||
for(duint i = 0; i < rowCount; i++)
|
||||
{
|
||||
QString cellContent = getCellContent(i, 0);
|
||||
if(!cellContent.length()) //skip empty cells
|
||||
|
@ -795,7 +800,7 @@ QString AbstractStdTable::copyTable(const std::vector<int> & colWidths)
|
|||
//std::vector<int> colWidths;
|
||||
//for(int i = 0; i < colCount; i++)
|
||||
// colWidths.push_back(getMaxColumnLength(i));
|
||||
for(int i = 0; i < colCount; i++)
|
||||
for(duint i = 0; i < colCount; i++)
|
||||
{
|
||||
if(i)
|
||||
finalText += " ";
|
||||
|
@ -806,10 +811,10 @@ QString AbstractStdTable::copyTable(const std::vector<int> & colWidths)
|
|||
finalText += getColTitle(i);
|
||||
}
|
||||
finalText += "\r\n";
|
||||
for(int i = 0; i < rowCount; i++)
|
||||
for(duint i = 0; i < rowCount; i++)
|
||||
{
|
||||
QString finalRowText = "";
|
||||
for(int j = 0; j < colCount; j++)
|
||||
for(duint j = 0; j < colCount; j++)
|
||||
{
|
||||
if(j)
|
||||
finalRowText += " ";
|
||||
|
@ -847,12 +852,12 @@ void AbstractStdTable::copyTableToLogSlot()
|
|||
void AbstractStdTable::copyTableResizeSlot()
|
||||
{
|
||||
std::vector<int> colWidths;
|
||||
int rowCount = getRowCount();
|
||||
int colCount = getColumnCount();
|
||||
for(int i = 0; i < colCount; i++)
|
||||
auto rowCount = getRowCount();
|
||||
auto colCount = getColumnCount();
|
||||
for(duint i = 0; i < colCount; i++)
|
||||
{
|
||||
int max = getCellContent(0, i).length();
|
||||
for(int j = 1; j < rowCount; j++)
|
||||
auto max = getCellContent(0, i).length();
|
||||
for(duint j = 1; j < rowCount; j++)
|
||||
max = std::max(getCellContent(j, i).length(), max);
|
||||
colWidths.push_back(max);
|
||||
}
|
||||
|
@ -866,7 +871,7 @@ void AbstractStdTable::copyTableResizeToLogSlot()
|
|||
int colCount = getColumnCount();
|
||||
for(int i = 0; i < colCount; i++)
|
||||
{
|
||||
int max = getCellContent(0, i).length();
|
||||
auto max = getCellContent(0, i).length();
|
||||
for(int j = 1; j < rowCount; j++)
|
||||
max = std::max(getCellContent(j, i).length(), max);
|
||||
colWidths.push_back(max);
|
||||
|
@ -889,7 +894,7 @@ void AbstractStdTable::exportTableSlot()
|
|||
{
|
||||
std::vector<QString> headers;
|
||||
headers.reserve(getColumnCount());
|
||||
for(int i = 0; i < getColumnCount(); i++)
|
||||
for(duint i = 0; i < getColumnCount(); i++)
|
||||
headers.push_back(getColTitle(i));
|
||||
ExportCSV(getRowCount(), getColumnCount(), headers, [this](duint row, duint column)
|
||||
{
|
||||
|
@ -926,7 +931,7 @@ void AbstractStdTable::setupCopyMenu(QMenu* copyMenu)
|
|||
|
||||
void AbstractStdTable::setupCopyColumnMenu(QMenu* copyMenu)
|
||||
{
|
||||
for(int i = 0; i < getColumnCount(); i++)
|
||||
for(duint i = 0; i < getColumnCount(); i++)
|
||||
{
|
||||
if(!getCellContent(getInitialSelection(), i).length()) //skip empty cells
|
||||
continue;
|
||||
|
@ -970,7 +975,7 @@ void AbstractStdTable::setupCopyColumnMenu(MenuBuilder* copyMenu)
|
|||
{
|
||||
copyMenu->addBuilder(new MenuBuilder(this, [this](QMenu * menu)
|
||||
{
|
||||
for(int i = 0; i < getColumnCount(); i++)
|
||||
for(duint i = 0; i < getColumnCount(); i++)
|
||||
{
|
||||
if(!getCellContent(getInitialSelection(), i).length()) //skip empty cells
|
||||
continue;
|
||||
|
@ -994,6 +999,8 @@ void AbstractStdTable::setCopyMenuOnly(bool bSet, bool bDebugOnly)
|
|||
|
||||
void AbstractStdTable::contextMenuRequestedSlot(const QPoint & pos)
|
||||
{
|
||||
if(pos.y() < getHeaderHeight())
|
||||
return;
|
||||
if(!mCopyMenuOnly)
|
||||
{
|
||||
emit contextMenuSignal(pos);
|
||||
|
@ -1001,18 +1008,18 @@ void AbstractStdTable::contextMenuRequestedSlot(const QPoint & pos)
|
|||
}
|
||||
if(mCopyMenuDebugOnly && !DbgIsDebugging())
|
||||
return;
|
||||
QMenu wMenu(this);
|
||||
QMenu wCopyMenu(tr("&Copy"), this);
|
||||
setupCopyMenu(&wCopyMenu);
|
||||
if(wCopyMenu.actions().length())
|
||||
auto menu = new QMenu(this);
|
||||
auto copyMenu = new QMenu(tr("&Copy"), this);
|
||||
setupCopyMenu(copyMenu);
|
||||
if(copyMenu->actions().length())
|
||||
{
|
||||
wMenu.addSeparator();
|
||||
wMenu.addMenu(&wCopyMenu);
|
||||
wMenu.exec(mapToGlobal(pos));
|
||||
menu->addSeparator();
|
||||
menu->addMenu(copyMenu);
|
||||
menu->popup(mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractStdTable::headerButtonPressedSlot(int col)
|
||||
void AbstractStdTable::headerButtonPressedSlot(duint col)
|
||||
{
|
||||
if(!mIsColumnSortingAllowed)
|
||||
return;
|
||||
|
@ -1036,22 +1043,16 @@ void AbstractStdTable::reloadData()
|
|||
AbstractTableView::reloadData();
|
||||
}
|
||||
|
||||
duint AbstractStdTable::getDisassemblyPopupAddress(int mousex, int mousey)
|
||||
duint AbstractStdTable::getAddressForPosition(int x, int y)
|
||||
{
|
||||
if(!bDisassemblyPopupEnabled) //No disassembly popup is meaningful for this table
|
||||
return 0;
|
||||
int c = getColumnIndexFromX(mousex);
|
||||
int r = getTableOffset() + getIndexOffsetFromY(transY(mousey));
|
||||
auto c = getColumnIndexFromX(x);
|
||||
auto r = getTableOffset() + getIndexOffsetFromY(transY(y));
|
||||
if(r < getRowCount())
|
||||
{
|
||||
QString cell = getCellContent(r, c);
|
||||
duint addr;
|
||||
bool ok = false;
|
||||
#ifdef _WIN64
|
||||
addr = cell.toULongLong(&ok, 16);
|
||||
#else //x86
|
||||
addr = cell.toULong(&ok, 16);
|
||||
#endif //_WIN64
|
||||
if(!ok)
|
||||
return 0;
|
||||
else
|
||||
|
|
|
@ -6,8 +6,8 @@ class AbstractStdTable : public AbstractTableView
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AbstractStdTable(QWidget* parent = 0);
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) override;
|
||||
explicit AbstractStdTable(QWidget* parent = nullptr);
|
||||
QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override;
|
||||
void updateColors() override;
|
||||
void reloadData() override;
|
||||
|
||||
|
@ -21,30 +21,29 @@ public:
|
|||
void enableColumnSorting(bool enabled);
|
||||
|
||||
// Selection Management
|
||||
void expandSelectionUpTo(int to);
|
||||
void expandSelectionUpTo(duint to);
|
||||
void expandUp();
|
||||
void expandDown();
|
||||
void expandTop();
|
||||
void expandBottom();
|
||||
void setSingleSelection(int index);
|
||||
int getInitialSelection() const;
|
||||
QList<int> getSelection() const;
|
||||
void setSingleSelection(duint index);
|
||||
duint getInitialSelection() const;
|
||||
QList<duint> getSelection() const;
|
||||
void selectStart();
|
||||
void selectEnd();
|
||||
void selectNext();
|
||||
void selectPrevious();
|
||||
void selectAll();
|
||||
bool isSelected(int base, int offset) const;
|
||||
bool scrollSelect(int offset);
|
||||
bool isSelected(duint row) const;
|
||||
bool scrollSelect(duint row);
|
||||
|
||||
// Data Management
|
||||
void addColumnAt(int width, QString title, bool isClickable, QString copyTitle = "");
|
||||
void deleteAllColumns() override;
|
||||
|
||||
virtual QString getCellContent(int r, int c) = 0;
|
||||
virtual bool isValidIndex(int r, int c) = 0;
|
||||
virtual void sortRows(int column, bool ascending) = 0;
|
||||
duint getDisassemblyPopupAddress(int mousex, int mousey) override;
|
||||
virtual QString getCellContent(duint row, duint column) = 0;
|
||||
virtual bool isValidIndex(duint row, duint column) = 0;
|
||||
virtual void sortRows(duint column, bool ascending) = 0;
|
||||
|
||||
//context menu helpers
|
||||
void setupCopyMenu(QMenu* copyMenu);
|
||||
|
@ -54,13 +53,13 @@ public:
|
|||
void setCopyMenuOnly(bool bSet, bool bDebugOnly = true);
|
||||
|
||||
//draw helpers
|
||||
void setHighlightText(QString highlightText, int minCol = 0)
|
||||
void setHighlightText(QString highlightText, duint minCol = 0)
|
||||
{
|
||||
mHighlightText = highlightText;
|
||||
mMinimumHighlightColumn = minCol;
|
||||
}
|
||||
|
||||
void setAddressColumn(int col, bool cipBase = false)
|
||||
void setAddressColumn(duint col, bool cipBase = false)
|
||||
{
|
||||
mAddressColumn = col;
|
||||
bCipBase = cipBase;
|
||||
|
@ -71,13 +70,8 @@ public:
|
|||
bAddressLabel = addressLabel;
|
||||
}
|
||||
|
||||
bool setDisassemblyPopupEnabled(bool enabled)
|
||||
{
|
||||
return bDisassemblyPopupEnabled = enabled;
|
||||
}
|
||||
|
||||
signals:
|
||||
void selectionChangedSignal(int index);
|
||||
void selectionChanged(duint index);
|
||||
void keyPressedSignal(QKeyEvent* event);
|
||||
void doubleClickedSignal();
|
||||
void contextMenuSignal(const QPoint & pos);
|
||||
|
@ -92,21 +86,22 @@ public slots:
|
|||
void copyEntrySlot();
|
||||
void exportTableSlot();
|
||||
void contextMenuRequestedSlot(const QPoint & pos);
|
||||
void headerButtonPressedSlot(int col);
|
||||
void headerButtonPressedSlot(duint col);
|
||||
|
||||
protected:
|
||||
QString copyTable(const std::vector<int> & colWidths);
|
||||
duint getAddressForPosition(int x, int y) override;
|
||||
|
||||
struct SelectionData
|
||||
{
|
||||
int firstSelectedIndex = 0;
|
||||
int fromIndex = 0;
|
||||
int toIndex = 0;
|
||||
duint firstSelectedIndex = 0;
|
||||
duint fromIndex = 0;
|
||||
duint toIndex = 0;
|
||||
};
|
||||
|
||||
SelectionData mSelection;
|
||||
|
||||
enum
|
||||
enum GuiState
|
||||
{
|
||||
NoState,
|
||||
MultiRowsSelectionState
|
||||
|
@ -121,7 +116,7 @@ protected:
|
|||
|
||||
struct SortData
|
||||
{
|
||||
int column = -1;
|
||||
duint column = -1;
|
||||
bool ascending = true;
|
||||
} mSort;
|
||||
|
||||
|
@ -146,7 +141,6 @@ protected:
|
|||
int mMinimumHighlightColumn = 0;
|
||||
int mAddressColumn = -1;
|
||||
bool bAddressLabel = true;
|
||||
bool bDisassemblyPopupEnabled = true;
|
||||
|
||||
QAction* mCopyLine;
|
||||
QAction* mCopyTable;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,7 @@
|
|||
#include "ActionHelpers.h"
|
||||
|
||||
class CachedFontMetrics;
|
||||
class DisassemblyPopup;
|
||||
class ColumnReorderDialog;
|
||||
|
||||
//Hacky class that fixes a really annoying cursor problem
|
||||
class AbstractTableScrollBar : public QScrollBar
|
||||
|
@ -22,8 +22,7 @@ class AbstractTableScrollBar : public QScrollBar
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit AbstractTableScrollBar(QScrollBar* scrollbar);
|
||||
void enterEvent(QEvent* event) override;
|
||||
void leaveEvent(QEvent* event) override;
|
||||
bool event(QEvent* event) override;
|
||||
};
|
||||
|
||||
class AbstractTableView;
|
||||
|
@ -32,17 +31,7 @@ class AbstractTableView : public QAbstractScrollArea, public ActionHelper<Abstra
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum GuiState
|
||||
{
|
||||
NoState,
|
||||
ReadyToResize,
|
||||
ResizeColumnState,
|
||||
HeaderButtonPressed,
|
||||
HeaderButtonReordering
|
||||
};
|
||||
|
||||
// Constructor
|
||||
explicit AbstractTableView(QWidget* parent = 0);
|
||||
explicit AbstractTableView(QWidget* parent = nullptr);
|
||||
virtual ~AbstractTableView() = default;
|
||||
|
||||
// Configuration
|
||||
|
@ -51,8 +40,8 @@ public:
|
|||
virtual void updateFonts();
|
||||
|
||||
// Pure Virtual Methods
|
||||
virtual QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) = 0;
|
||||
virtual QColor getCellColor(int r, int c);
|
||||
virtual QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) = 0;
|
||||
virtual QColor getCellColor(duint row, duint col);
|
||||
|
||||
// Painting Stuff
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
@ -65,53 +54,62 @@ public:
|
|||
void wheelEvent(QWheelEvent* event) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
void leaveEvent(QEvent* event) override;
|
||||
void hideEvent(QHideEvent* event) override;
|
||||
|
||||
// ScrollBar Management
|
||||
virtual dsint sliderMovedHook(int type, dsint value, dsint delta); // can be made protected
|
||||
int scaleFromUint64ToScrollBarRange(dsint value); // can be made private
|
||||
dsint scaleFromScrollBarRangeToUint64(int value); // can be made private
|
||||
virtual duint sliderMovedHook(QScrollBar::SliderAction action, duint prevTableOffset, dsint delta); // can be made protected
|
||||
int scaleFromUint64ToScrollBarRange(duint value); // can be made private
|
||||
duint scaleFromScrollBarRangeToUint64(int value); // can be made private
|
||||
|
||||
void updateScrollBarRange(dsint range); // setRowCount+resizeEvent needs this, can be made private
|
||||
void updateScrollBarRange(duint range); // setRowCount+resizeEvent needs this, can be made private
|
||||
|
||||
// Coordinates Utils
|
||||
int getIndexOffsetFromY(int y) const; // can be made protected
|
||||
int getColumnIndexFromX(int x) const; // can be made protected
|
||||
int getColumnPosition(int index) const; // can be made protected
|
||||
dsint getIndexOffsetFromY(int y) const; // can be made protected
|
||||
duint getColumnIndexFromX(int x) const; // can be made protected
|
||||
int getColumnPosition(duint column) const; // can be made protected
|
||||
int transY(int y) const; // can be made protected
|
||||
int getViewableRowsCount() const; // can be made protected
|
||||
virtual int getLineToPrintcount() const;
|
||||
|
||||
// TODO: this should probably be uint32_t?
|
||||
duint getViewableRowsCount() const; // can be made protected
|
||||
duint getMaxTableOffset() const;
|
||||
|
||||
// New Columns/New Size
|
||||
virtual void addColumnAt(int width, const QString & title, bool isClickable);
|
||||
virtual void setRowCount(dsint count);
|
||||
virtual void setRowCount(duint count);
|
||||
virtual void deleteAllColumns(); // can be made protected, although it makes sense as a public API
|
||||
void setColTitle(int index, const QString & title); // can be deleted, although it makes sense as a public API
|
||||
QString getColTitle(int index) const; // can be deleted, although it makes sense as a public API
|
||||
void setColTitle(duint col, const QString & title); // can be deleted, although it makes sense as a public API
|
||||
QString getColTitle(duint col) const; // can be deleted, although it makes sense as a public API
|
||||
|
||||
enum GuiState
|
||||
{
|
||||
NoState,
|
||||
ReadyToResize,
|
||||
ResizeColumnState,
|
||||
HeaderButtonPressed,
|
||||
HeaderButtonReordering
|
||||
};
|
||||
|
||||
// Getter & Setter
|
||||
dsint getRowCount() const;
|
||||
int getColumnCount() const;
|
||||
duint getRowCount() const;
|
||||
duint getColumnCount() const;
|
||||
int getRowHeight() const;
|
||||
int getColumnWidth(int index) const;
|
||||
void setColumnWidth(int index, int width);
|
||||
void setColumnOrder(int pos, int index);
|
||||
int getColumnOrder(int index) const;
|
||||
int getColumnWidth(duint col) const;
|
||||
void setColumnWidth(duint col, int width);
|
||||
void setColumnOrder(duint col, duint colNew);
|
||||
duint getColumnOrder(duint col) const;
|
||||
int getHeaderHeight() const; // can be made protected
|
||||
int getTableHeight() const; // can be made protected
|
||||
int getGuiState() const; // can be made protected
|
||||
int getNbrOfLineToPrint() const;
|
||||
void setNbrOfLineToPrint(int parNbrOfLineToPrint);
|
||||
GuiState getGuiState() const; // can be made protected
|
||||
duint getNbrOfLineToPrint() const; // TODO: should this be signed?
|
||||
void setNbrOfLineToPrint(duint parNbrOfLineToPrint);
|
||||
void setShowHeader(bool show);
|
||||
int getCharWidth() const;
|
||||
bool getColumnHidden(int col) const;
|
||||
void setColumnHidden(int col, bool hidden);
|
||||
int calculateColumnWidth(int characterCount) const;
|
||||
bool getColumnHidden(duint col) const;
|
||||
void setColumnHidden(duint col, bool hidden);
|
||||
bool getDrawDebugOnly() const;
|
||||
void setDrawDebugOnly(bool value);
|
||||
bool getAllowPainting() const;
|
||||
void setAllowPainting(bool allow);
|
||||
void setDisassemblyPopupEnabled(bool enable);
|
||||
|
||||
// UI customization
|
||||
void loadColumnFromConfig(const QString & viewName);
|
||||
|
@ -119,20 +117,20 @@ public:
|
|||
static void setupColumnConfigDefaultValue(QMap<QString, duint> & map, const QString & viewName, int columnCount);
|
||||
|
||||
// Table offset management
|
||||
dsint getTableOffset() const;
|
||||
void setTableOffset(dsint val);
|
||||
duint getTableOffset() const; // TODO: duint
|
||||
void setTableOffset(duint val); // TODO: duint
|
||||
|
||||
// Update/Reload/Refresh/Repaint
|
||||
virtual void prepareData();
|
||||
|
||||
virtual duint getDisassemblyPopupAddress(int mousex, int mousey);
|
||||
virtual duint getAddressForPosition(int x, int y);
|
||||
|
||||
signals:
|
||||
void enterPressedSignal();
|
||||
void headerButtonPressed(int col);
|
||||
void headerButtonReleased(int col);
|
||||
void tableOffsetChanged(dsint i);
|
||||
void viewableRowsChanged(int rows);
|
||||
void headerButtonPressed(duint col);
|
||||
void headerButtonReleased(duint col);
|
||||
void tableOffsetChanged(duint i);
|
||||
void viewableRowsChanged(duint rowCount);
|
||||
void repainted();
|
||||
|
||||
public slots:
|
||||
|
@ -145,96 +143,96 @@ public slots:
|
|||
|
||||
void editColumnDialog();
|
||||
|
||||
protected slots:
|
||||
void ShowDisassemblyPopup(duint addr, int x, int y); // this should probably be a slot, but doesn't need emit fixes (it's already used correctly)
|
||||
void timerEvent(QTimerEvent* event);
|
||||
|
||||
private slots:
|
||||
// Configuration
|
||||
void updateColorsSlot();
|
||||
void updateFontsSlot();
|
||||
void updateShortcutsSlot();
|
||||
void shutdownSlot();
|
||||
void closeSlot();
|
||||
|
||||
private:
|
||||
struct ColumnResizingData
|
||||
GuiState mGuiState = NoState;
|
||||
|
||||
struct ColumnResizeState
|
||||
{
|
||||
bool splitHandle;
|
||||
int index;
|
||||
int lastPosX;
|
||||
};
|
||||
bool splitHandle = false;
|
||||
int index = -1;
|
||||
int lastPosX = -1;
|
||||
} mColResizeData;
|
||||
|
||||
struct HeaderButton
|
||||
{
|
||||
bool isClickable;
|
||||
bool isPressed;
|
||||
bool isMouseOver;
|
||||
bool isClickable = false;
|
||||
bool isPressed = false;
|
||||
bool isMouseOver = false;
|
||||
};
|
||||
|
||||
struct Column
|
||||
{
|
||||
int width;
|
||||
bool hidden;
|
||||
int width = 0;
|
||||
int paintedWidth = -1;
|
||||
bool hidden = false;
|
||||
HeaderButton header;
|
||||
QString title;
|
||||
};
|
||||
|
||||
struct Header
|
||||
struct HeaderConfig
|
||||
{
|
||||
bool isVisible;
|
||||
int height;
|
||||
int activeButtonIndex;
|
||||
};
|
||||
|
||||
struct ScrollBar64
|
||||
{
|
||||
bool is64;
|
||||
int rightShiftCount;
|
||||
};
|
||||
|
||||
GuiState mGuiState;
|
||||
|
||||
Header mHeader;
|
||||
QPushButton mHeaderButtonSytle;
|
||||
bool isVisible = true;
|
||||
int height = 20;
|
||||
int activeButtonIndex = -1;
|
||||
} mHeader;
|
||||
|
||||
int mMinColumnWidth = 5;
|
||||
QList<Column> mColumnList;
|
||||
ColumnResizingData mColResizeData;
|
||||
QList<duint> mColumnOrder;
|
||||
int mReorderStartX = -1;
|
||||
duint mHoveredColumnDisplayIndex = 0;
|
||||
|
||||
QList<int> mColumnOrder;
|
||||
int mReorderStartX;
|
||||
int mHoveredColumnDisplayIndex;
|
||||
duint mRowCount = 0;
|
||||
duint mTableOffset = 0;
|
||||
duint mPrevTableOffset = -1;
|
||||
duint mNbrOfLineToPrint = 0;
|
||||
|
||||
dsint mRowCount;
|
||||
dsint mTableOffset;
|
||||
dsint mPrevTableOffset;
|
||||
int mNbrOfLineToPrint;
|
||||
bool mShouldReload = true;
|
||||
bool mDrawDebugOnly = false;
|
||||
|
||||
bool mShouldReload;
|
||||
bool mDrawDebugOnly;
|
||||
bool mPopupEnabled;
|
||||
int mPopupTimer;
|
||||
// State for accumulating scroll events
|
||||
enum ScrollDirection
|
||||
{
|
||||
ScrollUnknown,
|
||||
ScrollVertical,
|
||||
ScrollHorizontal,
|
||||
} mPixelScrollDirection = ScrollUnknown;
|
||||
QPoint mPixelScrollDelta;
|
||||
QPoint mAngleScrollDelta;
|
||||
|
||||
static int mMouseWheelScrollDelta;
|
||||
ScrollBar64 mScrollBarAttributes;
|
||||
struct ScrollBarAttributes
|
||||
{
|
||||
bool is64 = false;
|
||||
int rightShiftCount = 0;
|
||||
} mScrollBarAttributes;
|
||||
|
||||
int getColumnDisplayIndexFromX(int x);
|
||||
duint getColumnDisplayIndexFromX(int x);
|
||||
friend class ColumnReorderDialog;
|
||||
|
||||
protected:
|
||||
// Configuration
|
||||
QColor mBackgroundColor;
|
||||
QColor mTextColor;
|
||||
QColor mSeparatorColor;
|
||||
QColor mHeaderTextColor;
|
||||
QColor mSelectionColor;
|
||||
QString mViewName;
|
||||
void updateLastColumnWidth();
|
||||
|
||||
bool mAllowPainting;
|
||||
protected:
|
||||
bool mAllowPainting = true;
|
||||
|
||||
// Configuration
|
||||
QColor mTextColor;
|
||||
QColor mBackgroundColor;
|
||||
QColor mHeaderTextColor;
|
||||
QColor mHeaderBackgroundColor;
|
||||
QColor mSeparatorColor;
|
||||
QColor mSelectionColor;
|
||||
QString mViewName; // TODO: this is needed during construction
|
||||
|
||||
// Font metrics
|
||||
CachedFontMetrics* mFontMetrics;
|
||||
CachedFontMetrics* mFontMetrics = nullptr;
|
||||
void invalidateCachedFont();
|
||||
|
||||
// Disassembly Popup
|
||||
DisassemblyPopup* mDisassemblyPopup;
|
||||
ColumnReorderDialog* mReorderDialog = nullptr;
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,25 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "AbstractTableView.h"
|
||||
#include "QBeaEngine.h"
|
||||
#include "QZydis.h"
|
||||
#include <QTextLayout>
|
||||
#include "Architecture.h"
|
||||
|
||||
class CodeFoldingHelper;
|
||||
class MemoryPage;
|
||||
class DisassemblyPopup;
|
||||
|
||||
class Disassembly : public AbstractTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Disassembly(QWidget* parent, bool isMain);
|
||||
Disassembly(Architecture* architecture, bool isMain, QWidget* parent = nullptr);
|
||||
~Disassembly() override;
|
||||
Architecture* getArchitecture() const;
|
||||
|
||||
// Configuration
|
||||
void updateColors() override;
|
||||
void updateFonts() override;
|
||||
|
||||
// Reimplemented Functions
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) override;
|
||||
QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override;
|
||||
|
||||
// Mouse Management
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
|
@ -31,25 +34,25 @@ public:
|
|||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
// ScrollBar Management
|
||||
dsint sliderMovedHook(int type, dsint value, dsint delta) override;
|
||||
duint sliderMovedHook(QScrollBar::SliderAction action, duint value, dsint delta) override;
|
||||
|
||||
// Instructions Management
|
||||
dsint getPreviousInstructionRVA(dsint rva, duint count);
|
||||
dsint getNextInstructionRVA(dsint rva, duint count, bool isGlobal = false);
|
||||
dsint getInstructionRVA(dsint index, dsint count);
|
||||
Instruction_t DisassembleAt(dsint rva);
|
||||
Instruction_t DisassembleAt(dsint rva, dsint count);
|
||||
duint getPreviousInstructionRVA(duint rva, duint count);
|
||||
duint getNextInstructionRVA(duint rva, duint count, bool isGlobal = false);
|
||||
duint getInstructionRVA(duint index, dsint count);
|
||||
Instruction_t DisassembleAt(duint rva);
|
||||
Instruction_t DisassembleAt(duint rva, dsint count);
|
||||
|
||||
// Selection Management
|
||||
void expandSelectionUpTo(dsint to);
|
||||
void setSingleSelection(dsint index);
|
||||
dsint getInitialSelection() const;
|
||||
dsint getSelectionSize() const;
|
||||
dsint getSelectionStart() const;
|
||||
dsint getSelectionEnd() const;
|
||||
void expandSelectionUpTo(duint to);
|
||||
void setSingleSelection(duint index);
|
||||
duint getInitialSelection() const;
|
||||
duint getSelectionSize() const;
|
||||
duint getSelectionStart() const;
|
||||
duint getSelectionEnd() const;
|
||||
void selectNext(bool expand);
|
||||
void selectPrevious(bool expand);
|
||||
bool isSelected(dsint base, dsint offset);
|
||||
bool isSelected(duint base, dsint offset);
|
||||
bool isSelected(QList<Instruction_t>* buffer, int index) const;
|
||||
duint getSelectedVa() const;
|
||||
|
||||
|
@ -60,7 +63,7 @@ public:
|
|||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
// Public Methods
|
||||
duint rvaToVa(dsint rva) const;
|
||||
duint rvaToVa(duint rva) const;
|
||||
void disassembleClear();
|
||||
const duint getBase() const;
|
||||
duint getSize() const;
|
||||
|
@ -75,32 +78,31 @@ public:
|
|||
|
||||
//disassemble
|
||||
void gotoAddress(duint addr);
|
||||
void disassembleAt(dsint parVA, bool history, dsint newTableOffset);
|
||||
void disassembleAt(duint va, bool history, duint newTableOffset);
|
||||
|
||||
QList<Instruction_t>* instructionsBuffer(); // ugly
|
||||
const dsint baseAddress() const;
|
||||
const duint baseAddress() const;
|
||||
|
||||
QString getAddrText(dsint cur_addr, char label[MAX_LABEL_SIZE], bool getLabel = true);
|
||||
void prepareDataCount(const QList<dsint> & wRVAs, QList<Instruction_t>* instBuffer);
|
||||
void prepareDataRange(dsint startRva, dsint endRva, const std::function<bool(int, const Instruction_t &)> & disassembled);
|
||||
QString getAddrText(duint cur_addr, QString & label, bool getLabel = true);
|
||||
void prepareDataCount(const QList<duint> & rvas, QList<Instruction_t>* instBuffer);
|
||||
void prepareDataRange(duint startRva, duint endRva, const std::function<bool(int, const Instruction_t &)> & disassembled);
|
||||
RichTextPainter::List getRichBytes(const Instruction_t & instr, bool isSelected) const;
|
||||
|
||||
//misc
|
||||
void setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager);
|
||||
duint getDisassemblyPopupAddress(int mousex, int mousey) override;
|
||||
void unfold(dsint rva);
|
||||
void unfold(duint rva);
|
||||
bool hightlightToken(const ZydisTokenizer::SingleToken & token);
|
||||
bool isHighlightMode() const;
|
||||
|
||||
signals:
|
||||
void selectionChanged(dsint parVA);
|
||||
void selectionChanged(duint va);
|
||||
void selectionExpanded();
|
||||
void updateWindowTitle(QString title);
|
||||
|
||||
public slots:
|
||||
void disassembleAtSlot(dsint parVA, dsint parCIP);
|
||||
void disassembleAtSlot(duint va, duint cip);
|
||||
void debugStateChangedSlot(DBGSTATE state);
|
||||
void selectionChangedSlot(dsint parVA);
|
||||
void selectionChangedSlot(duint va);
|
||||
void tokenizerConfigUpdatedSlot();
|
||||
void updateConfigSlot();
|
||||
|
||||
|
@ -127,30 +129,31 @@ private:
|
|||
{
|
||||
GJD_Nothing,
|
||||
GJD_Up,
|
||||
GJD_Down
|
||||
GJD_Down,
|
||||
GJD_Out,
|
||||
};
|
||||
|
||||
struct SelectionData
|
||||
{
|
||||
dsint firstSelectedIndex;
|
||||
dsint fromIndex;
|
||||
dsint toIndex;
|
||||
};
|
||||
|
||||
SelectionData mSelection;
|
||||
duint firstSelectedIndex = 0;
|
||||
duint fromIndex = 0;
|
||||
duint toIndex = 0;
|
||||
} mSelection;
|
||||
|
||||
Architecture* mArchitecture = nullptr;
|
||||
bool mIsLastInstDisplayed;
|
||||
|
||||
GuiState mGuiState;
|
||||
|
||||
duint mCipVa = 0;
|
||||
|
||||
Instruction_t mSelectedInstruction;
|
||||
QList<Instruction_t> mInstBuffer;
|
||||
|
||||
struct HistoryData
|
||||
{
|
||||
dsint va;
|
||||
dsint tableOffset;
|
||||
duint va = 0;
|
||||
duint tableOffset = 0;
|
||||
};
|
||||
|
||||
QList<HistoryData> mVaHistory;
|
||||
|
@ -162,11 +165,14 @@ private:
|
|||
ColBytes,
|
||||
ColDisassembly,
|
||||
ColComment,
|
||||
ColMnemonicBrief,
|
||||
};
|
||||
|
||||
DisassemblyPopup* mDisassemblyPopup = nullptr;
|
||||
|
||||
protected:
|
||||
// Jumps Graphic
|
||||
int paintJumpsGraphic(QPainter* painter, int x, int y, dsint addr, bool isjmp);
|
||||
int paintJumpsGraphic(QPainter* painter, int x, int y, const Instruction_t & instruction);
|
||||
|
||||
// Function Graphic
|
||||
|
||||
|
@ -181,6 +187,9 @@ protected:
|
|||
};
|
||||
|
||||
int paintFunctionGraphic(QPainter* painter, int x, int y, Function_t funcType, bool loop);
|
||||
|
||||
duint getAddressForPosition(int mousex, int mousey) override;
|
||||
|
||||
// Configuration
|
||||
QColor mInstructionHighlightColor;
|
||||
QColor mDisassemblyRelocationUnderlineColor;
|
||||
|
@ -242,7 +251,7 @@ protected:
|
|||
dsint mRvaDisplayPageBase;
|
||||
bool mHighlightingMode;
|
||||
MemoryPage* mMemPage;
|
||||
QBeaEngine* mDisasm;
|
||||
QZydis* mDisasm;
|
||||
bool mShowMnemonicBrief;
|
||||
XREF_INFO mXrefInfo;
|
||||
CodeFoldingHelper* mCodeFoldingManager;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,6 @@
|
|||
#include "RichTextPainter.h"
|
||||
#include "MemoryPage.h"
|
||||
#include "VaHistory.h"
|
||||
#include <QTextCodec>
|
||||
|
||||
class HexDump : public AbstractTableView
|
||||
{
|
||||
|
@ -74,12 +73,12 @@ public:
|
|||
bool isData = true;
|
||||
int itemCount = 16;
|
||||
int separator = 0;
|
||||
QTextCodec* textCodec = nullptr; //name of the text codec (leave empty if you want to keep your sanity)
|
||||
QByteArray textEncoding; // name of the text codec (leave empty if you want to keep your sanity)
|
||||
DataDescriptor data;
|
||||
std::function<void()> columnSwitch;
|
||||
};
|
||||
|
||||
explicit HexDump(QWidget* parent = 0);
|
||||
HexDump(Architecture* architecture, QWidget* parent = nullptr);
|
||||
~HexDump() override;
|
||||
|
||||
// Configuration
|
||||
|
@ -87,41 +86,40 @@ public:
|
|||
void updateFonts() override;
|
||||
void updateShortcuts() override;
|
||||
|
||||
//QString getStringToPrint(int rowBase, int rowOffset, int col);
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) override;
|
||||
QString paintContent(QPainter* painter, duint row, duint column, int x, int y, int w, int h) override;
|
||||
void paintGraphicDump(QPainter* painter, int x, int y, int addr);
|
||||
void printSelected(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h);
|
||||
void printSelected(QPainter* painter, duint row, duint column, int x, int y, int w, int h);
|
||||
|
||||
// Selection Management
|
||||
void expandSelectionUpTo(dsint rva);
|
||||
void setSingleSelection(dsint rva);
|
||||
dsint getInitialSelection() const;
|
||||
dsint getSelectionStart() const;
|
||||
dsint getSelectionEnd() const;
|
||||
bool isSelected(dsint rva) const;
|
||||
void expandSelectionUpTo(duint rva);
|
||||
void setSingleSelection(duint rva);
|
||||
duint getInitialSelection() const;
|
||||
duint getSelectionStart() const;
|
||||
duint getSelectionEnd() const;
|
||||
bool isSelected(duint rva) const;
|
||||
|
||||
virtual void getColumnRichText(int col, dsint rva, RichTextPainter::List & richText);
|
||||
virtual void getColumnRichText(duint column, duint rva, RichTextPainter::List & richText);
|
||||
|
||||
static size_t getSizeOf(DataSize size);
|
||||
|
||||
void toString(DataDescriptor desc, duint rva, byte_t* data, RichTextPainter::CustomRichText_t & richText);
|
||||
void toString(DataDescriptor desc, duint rva, uint8_t* data, RichTextPainter::CustomRichText_t & richText);
|
||||
|
||||
void byteToString(duint rva, byte_t byte, ByteViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
void wordToString(duint rva, uint16 word, WordViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
static void dwordToString(duint rva, uint32 dword, DwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
static void qwordToString(duint rva, uint64 qword, QwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
void byteToString(duint rva, uint8_t byte, ByteViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
void wordToString(duint rva, uint16_t word, WordViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
static void dwordToString(duint rva, uint32_t dword, DwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
static void qwordToString(duint rva, uint64_t qword, QwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
static void twordToString(duint rva, void* tword, TwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
|
||||
|
||||
int getItemIndexFromX(int x) const;
|
||||
dsint getItemStartingAddress(int x, int y);
|
||||
duint getItemStartingAddress(int x, int y);
|
||||
|
||||
int getBytePerRowCount() const;
|
||||
size_t getBytePerRowCount() const;
|
||||
int getItemPixelWidth(ColumnDescriptor desc) const;
|
||||
|
||||
//descriptor management
|
||||
|
@ -129,8 +127,8 @@ public:
|
|||
void appendResetDescriptor(int width, QString title, bool clickable, ColumnDescriptor descriptor);
|
||||
void clearDescriptors();
|
||||
|
||||
void printDumpAt(dsint parVA, bool select, bool repaint = true, bool updateTableOffset = true);
|
||||
duint rvaToVa(dsint rva) const;
|
||||
void printDumpAt(duint parVA, bool select, bool repaint = true, bool updateTableOffset = true);
|
||||
duint rvaToVa(duint rva) const;
|
||||
|
||||
duint getTableOffsetRva() const;
|
||||
QString makeAddrText(duint va) const;
|
||||
|
@ -144,7 +142,7 @@ signals:
|
|||
void selectionUpdated();
|
||||
|
||||
public slots:
|
||||
void printDumpAt(dsint parVA);
|
||||
void printDumpAt(duint parVA);
|
||||
void debugStateChanged(DBGSTATE state);
|
||||
void updateDumpSlot();
|
||||
void copySelectionSlot();
|
||||
|
@ -162,9 +160,9 @@ private:
|
|||
|
||||
struct SelectionData
|
||||
{
|
||||
dsint firstSelectedIndex;
|
||||
dsint fromIndex;
|
||||
dsint toIndex;
|
||||
duint firstSelectedIndex = 0;
|
||||
duint fromIndex = 0;
|
||||
duint toIndex = 0;
|
||||
};
|
||||
|
||||
SelectionData mSelection;
|
||||
|
@ -209,13 +207,14 @@ private:
|
|||
std::vector<uint8_t> mUpdateCacheTemp;
|
||||
|
||||
protected:
|
||||
MemoryPage* mMemPage;
|
||||
int mByteOffset;
|
||||
Architecture* mArchitecture = nullptr;
|
||||
MemoryPage* mMemPage = nullptr;
|
||||
dsint mByteOffset = 0;
|
||||
QList<ColumnDescriptor> mDescriptor;
|
||||
int mForceColumn;
|
||||
bool mRvaDisplayEnabled;
|
||||
duint mRvaDisplayBase;
|
||||
dsint mRvaDisplayPageBase;
|
||||
duint mRvaDisplayPageBase;
|
||||
QString mSyncAddrExpression;
|
||||
QAction* mCopyAddress;
|
||||
QAction* mCopyRva;
|
||||
|
|
|
@ -67,7 +67,7 @@ QString HistoryLineEdit::addHistoryClear()
|
|||
|
||||
void HistoryLineEdit::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
int wKey = event->key();
|
||||
int key = event->key();
|
||||
|
||||
//This fixes a very annoying bug on some systems
|
||||
if(bSixPressed)
|
||||
|
@ -79,14 +79,14 @@ void HistoryLineEdit::keyPressEvent(QKeyEvent* event)
|
|||
return;
|
||||
}
|
||||
}
|
||||
if(wKey == Qt::Key_6)
|
||||
if(key == Qt::Key_6)
|
||||
bSixPressed = true;
|
||||
|
||||
if(wKey == Qt::Key_Up || wKey == Qt::Key_Down)
|
||||
if(key == Qt::Key_Up || key == Qt::Key_Down)
|
||||
{
|
||||
if(wKey == Qt::Key_Up)
|
||||
if(key == Qt::Key_Up)
|
||||
mCmdIndex++;
|
||||
else if(wKey == Qt::Key_Down)
|
||||
else if(key == Qt::Key_Down)
|
||||
mCmdIndex--;
|
||||
|
||||
mCmdIndex = mCmdIndex < -1 ? -1 : mCmdIndex;
|
||||
|
|
|
@ -7,7 +7,7 @@ class HistoryLineEdit : public QLineEdit
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HistoryLineEdit(QWidget* parent = 0);
|
||||
explicit HistoryLineEdit(QWidget* parent = nullptr);
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void addLineToHistory(QString parLine);
|
||||
QString getLineFromHistory();
|
||||
|
|
|
@ -278,7 +278,7 @@ void LabeledSplitter::loadFromConfig(const QString & configName)
|
|||
size_t sizeofState = strlen(state);
|
||||
if(sizeofState > 0)
|
||||
this->restoreState(QByteArray::fromBase64(QByteArray(state, int(sizeofState))));
|
||||
connect(Bridge::getBridge(), SIGNAL(shutdown()), this, SLOT(shutdownSlot()));
|
||||
connect(Bridge::getBridge(), SIGNAL(close()), this, SLOT(shutdownSlot()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class LabeledSplitterDetachedWindow : public QMainWindow
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LabeledSplitterDetachedWindow(QWidget* parent = 0, LabeledSplitter* splitterwidget = 0);
|
||||
LabeledSplitterDetachedWindow(QWidget* parent = nullptr, LabeledSplitter* splitterwidget = 0);
|
||||
~LabeledSplitterDetachedWindow();
|
||||
|
||||
int index;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Configuration.h"
|
||||
#include "Bridge.h"
|
||||
#include "MiscUtil.h"
|
||||
#include "DisassemblyPopup.h"
|
||||
|
||||
ReferenceView::ReferenceView(bool sourceView, QWidget* parent) : StdSearchListView(parent, true, false), mParent(dynamic_cast<QTabWidget*>(parent))
|
||||
{
|
||||
|
@ -53,6 +54,10 @@ ReferenceView::ReferenceView(bool sourceView, QWidget* parent) : StdSearchListVi
|
|||
connect(this, SIGNAL(enterPressedSignal()), this, SLOT(followGenericAddress()));
|
||||
|
||||
setupContextMenu();
|
||||
|
||||
// Add disassembly popups
|
||||
new DisassemblyPopup(stdList(), Bridge::getArchitecture());
|
||||
new DisassemblyPopup(stdSearchList(), Bridge::getArchitecture());
|
||||
}
|
||||
|
||||
void ReferenceView::setupContextMenu()
|
||||
|
@ -102,8 +107,8 @@ void ReferenceView::connectBridge()
|
|||
connect(Bridge::getBridge(), SIGNAL(referenceSetProgress(int)), this, SLOT(referenceSetProgressSlot(int)));
|
||||
connect(Bridge::getBridge(), SIGNAL(referenceSetCurrentTaskProgress(int, QString)), this, SLOT(referenceSetCurrentTaskProgressSlot(int, QString)));
|
||||
connect(Bridge::getBridge(), SIGNAL(referenceAddCommand(QString, QString)), this, SLOT(addCommand(QString, QString)));
|
||||
connect(stdSearchList(), SIGNAL(selectionChangedSignal(int)), this, SLOT(searchSelectionChanged(int)));
|
||||
connect(stdList(), SIGNAL(selectionChangedSignal(int)), this, SLOT(searchSelectionChanged(int)));
|
||||
connect(stdSearchList(), SIGNAL(selectionChanged(duint)), this, SLOT(searchSelectionChanged(int)));
|
||||
connect(stdList(), SIGNAL(selectionChanged(duint)), this, SLOT(searchSelectionChanged(int)));
|
||||
}
|
||||
|
||||
void ReferenceView::disconnectBridge()
|
||||
|
@ -113,8 +118,8 @@ void ReferenceView::disconnectBridge()
|
|||
disconnect(Bridge::getBridge(), SIGNAL(referenceSetProgress(int)), this, SLOT(referenceSetProgressSlot(int)));
|
||||
disconnect(Bridge::getBridge(), SIGNAL(referenceSetCurrentTaskProgress(int, QString)), this, SLOT(referenceSetCurrentTaskProgressSlot(int, QString)));
|
||||
disconnect(Bridge::getBridge(), SIGNAL(referenceAddCommand(QString, QString)), this, SLOT(addCommand(QString, QString)));
|
||||
disconnect(stdSearchList(), SIGNAL(selectionChangedSignal(int)), this, SLOT(searchSelectionChanged(int)));
|
||||
disconnect(stdList(), SIGNAL(selectionChangedSignal(int)), this, SLOT(searchSelectionChanged(int)));
|
||||
disconnect(stdSearchList(), SIGNAL(selectionChanged(int)), this, SLOT(searchSelectionChanged(int)));
|
||||
disconnect(stdList(), SIGNAL(selectionChanged(int)), this, SLOT(searchSelectionChanged(int)));
|
||||
}
|
||||
|
||||
int ReferenceView::progress() const
|
||||
|
@ -187,10 +192,14 @@ void ReferenceView::setRowCount(dsint count)
|
|||
|
||||
void ReferenceView::setSingleSelection(int index, bool scroll)
|
||||
{
|
||||
clearFilter();
|
||||
//clearFilter();
|
||||
stdList()->setSingleSelection(index);
|
||||
stdSearchList()->setSingleSelection(index);
|
||||
if(scroll) //TODO: better scrolling
|
||||
{
|
||||
stdList()->setTableOffset(index);
|
||||
stdSearchList()->setTableOffset(index);
|
||||
}
|
||||
}
|
||||
|
||||
void ReferenceView::addCommand(QString title, QString command)
|
||||
|
@ -199,7 +208,7 @@ void ReferenceView::addCommand(QString title, QString command)
|
|||
mCommands.append(command);
|
||||
}
|
||||
|
||||
void ReferenceView::referenceContextMenu(QMenu* wMenu)
|
||||
void ReferenceView::referenceContextMenu(QMenu* menu)
|
||||
{
|
||||
if(!mCurList->getRowCount())
|
||||
return;
|
||||
|
@ -209,39 +218,39 @@ void ReferenceView::referenceContextMenu(QMenu* wMenu)
|
|||
return;
|
||||
if(DbgMemIsValidReadPtr(addr))
|
||||
{
|
||||
wMenu->addAction(mFollowAddress);
|
||||
wMenu->addAction(mFollowDumpAddress);
|
||||
menu->addAction(mFollowAddress);
|
||||
menu->addAction(mFollowDumpAddress);
|
||||
dsint apiaddr = apiAddressFromString(mCurList->getCellContent(mCurList->getInitialSelection(), 1));
|
||||
if(apiaddr)
|
||||
wMenu->addAction(mFollowApiAddress);
|
||||
wMenu->addSeparator();
|
||||
wMenu->addAction(mToggleBreakpoint);
|
||||
wMenu->addAction(mSetBreakpointOnAllCommands);
|
||||
wMenu->addAction(mRemoveBreakpointOnAllCommands);
|
||||
menu->addAction(mFollowApiAddress);
|
||||
menu->addSeparator();
|
||||
menu->addAction(mToggleBreakpoint);
|
||||
menu->addAction(mSetBreakpointOnAllCommands);
|
||||
menu->addAction(mRemoveBreakpointOnAllCommands);
|
||||
if(apiaddr)
|
||||
{
|
||||
char label[MAX_LABEL_SIZE] = "";
|
||||
if(DbgGetLabelAt(apiaddr, SEG_DEFAULT, label))
|
||||
{
|
||||
wMenu->addSeparator();
|
||||
menu->addSeparator();
|
||||
mSetBreakpointOnAllApiCalls->setText(tr("Set breakpoint on all calls to %1").arg(label));
|
||||
wMenu->addAction(mSetBreakpointOnAllApiCalls);
|
||||
menu->addAction(mSetBreakpointOnAllApiCalls);
|
||||
mRemoveBreakpointOnAllApiCalls->setText(tr("Remove breakpoint on all calls to %1").arg(label));
|
||||
wMenu->addAction(mRemoveBreakpointOnAllApiCalls);
|
||||
menu->addAction(mRemoveBreakpointOnAllApiCalls);
|
||||
}
|
||||
}
|
||||
wMenu->addSeparator();
|
||||
wMenu->addAction(mToggleBookmark);
|
||||
menu->addSeparator();
|
||||
menu->addAction(mToggleBookmark);
|
||||
}
|
||||
if(this->mCommands.size() > 0)
|
||||
{
|
||||
wMenu->addSeparator();
|
||||
menu->addSeparator();
|
||||
for(auto i = 0; i < this->mCommandTitles.size(); i++)
|
||||
{
|
||||
QAction* newCommandAction = new QAction(this->mCommandTitles.at(i), wMenu);
|
||||
QAction* newCommandAction = new QAction(this->mCommandTitles.at(i), menu);
|
||||
newCommandAction->setData(QVariant(mCommands.at(i)));
|
||||
connect(newCommandAction, SIGNAL(triggered()), this, SLOT(referenceExecCommand()));
|
||||
wMenu->addAction(newCommandAction);
|
||||
menu->addAction(newCommandAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +289,7 @@ void ReferenceView::followGenericAddress()
|
|||
}
|
||||
}
|
||||
|
||||
void ReferenceView::setBreakpointAt(int row, BPSetAction action)
|
||||
void ReferenceView::setBreakpointAt(duint row, BPSetAction action)
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
|
@ -288,30 +297,30 @@ void ReferenceView::setBreakpointAt(int row, BPSetAction action)
|
|||
if(!mCurList->getRowCount())
|
||||
return;
|
||||
QString addrText = mCurList->getCellContent(row, 0).toUtf8().constData();
|
||||
duint wVA;
|
||||
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &wVA))
|
||||
duint va = 0;
|
||||
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &va))
|
||||
return;
|
||||
if(!DbgMemIsValidReadPtr(wVA))
|
||||
if(!DbgMemIsValidReadPtr(va))
|
||||
return;
|
||||
|
||||
BPXTYPE wBpType = DbgGetBpxTypeAt(wVA);
|
||||
QString wCmd;
|
||||
BPXTYPE bpType = DbgGetBpxTypeAt(va);
|
||||
QString cmd;
|
||||
|
||||
if((wBpType & bp_normal) == bp_normal)
|
||||
if((bpType & bp_normal) == bp_normal)
|
||||
{
|
||||
if(action == Toggle || action == Remove)
|
||||
wCmd = "bc " + ToPtrString(wVA);
|
||||
cmd = "bc " + ToPtrString(va);
|
||||
else if(action == Disable)
|
||||
wCmd = "bpd " + ToPtrString(wVA);
|
||||
cmd = "bpd " + ToPtrString(va);
|
||||
else if(action == Enable)
|
||||
wCmd = "bpe " + ToPtrString(wVA);
|
||||
cmd = "bpe " + ToPtrString(va);
|
||||
}
|
||||
else if(wBpType == bp_none && (action == Toggle || action == Enable))
|
||||
else if(bpType == bp_none && (action == Toggle || action == Enable))
|
||||
{
|
||||
wCmd = "bp " + ToPtrString(wVA);
|
||||
cmd = "bp " + ToPtrString(va);
|
||||
}
|
||||
|
||||
DbgCmdExecDirect(wCmd);
|
||||
DbgCmdExecDirect(cmd);
|
||||
}
|
||||
|
||||
void ReferenceView::toggleBreakpoint()
|
||||
|
@ -330,14 +339,14 @@ void ReferenceView::toggleBreakpoint()
|
|||
void ReferenceView::setBreakpointOnAllCommands()
|
||||
{
|
||||
GuiDisableUpdateScope s;
|
||||
for(int i = 0; i < mCurList->getRowCount(); i++)
|
||||
for(duint i = 0; i < mCurList->getRowCount(); i++)
|
||||
setBreakpointAt(i, Enable);
|
||||
}
|
||||
|
||||
void ReferenceView::removeBreakpointOnAllCommands()
|
||||
{
|
||||
GuiDisableUpdateScope s;
|
||||
for(int i = 0; i < mCurList->getRowCount(); i++)
|
||||
for(duint i = 0; i < mCurList->getRowCount(); i++)
|
||||
setBreakpointAt(i, Remove);
|
||||
}
|
||||
|
||||
|
@ -351,7 +360,7 @@ void ReferenceView::setBreakpointOnAllApiCalls()
|
|||
QString apiText = mCurList->getCellContent(mCurList->getInitialSelection(), 1);
|
||||
|
||||
GuiDisableUpdateScope s;
|
||||
for(int i = 0; i < mCurList->getRowCount(); i++)
|
||||
for(duint i = 0; i < mCurList->getRowCount(); i++)
|
||||
if(mCurList->getCellContent(i, 1) == apiText)
|
||||
setBreakpointAt(i, Enable);
|
||||
}
|
||||
|
@ -367,7 +376,7 @@ void ReferenceView::removeBreakpointOnAllApiCalls()
|
|||
QString apiText = mCurList->getCellContent(mCurList->getInitialSelection(), 1);
|
||||
|
||||
GuiDisableUpdateScope s;
|
||||
for(int i = 0; i < mCurList->getRowCount(); i++)
|
||||
for(duint i = 0; i < mCurList->getRowCount(); i++)
|
||||
if(mCurList->getCellContent(i, 1) == apiText)
|
||||
setBreakpointAt(i, Remove);
|
||||
}
|
||||
|
@ -380,17 +389,17 @@ void ReferenceView::toggleBookmark()
|
|||
if(!mCurList->getRowCount())
|
||||
return;
|
||||
QString addrText = mCurList->getCellContent(mCurList->getInitialSelection(), 0);
|
||||
duint wVA;
|
||||
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &wVA))
|
||||
duint va = 0;
|
||||
if(!DbgFunctions()->ValFromString(addrText.toUtf8().constData(), &va))
|
||||
return;
|
||||
if(!DbgMemIsValidReadPtr(wVA))
|
||||
if(!DbgMemIsValidReadPtr(va))
|
||||
return;
|
||||
|
||||
bool result;
|
||||
if(DbgGetBookmarkAt(wVA))
|
||||
result = DbgSetBookmarkAt(wVA, false);
|
||||
if(DbgGetBookmarkAt(va))
|
||||
result = DbgSetBookmarkAt(va, false);
|
||||
else
|
||||
result = DbgSetBookmarkAt(wVA, true);
|
||||
result = DbgSetBookmarkAt(va, true);
|
||||
if(!result)
|
||||
SimpleErrorBox(this, tr("Error!"), tr("DbgSetBookmarkAt failed!"));
|
||||
GuiUpdateAllViews();
|
||||
|
@ -419,7 +428,7 @@ void ReferenceView::referenceExecCommand()
|
|||
for(int selected : mCurList->getSelection()) //to do: enable multi-selection
|
||||
{
|
||||
QString specializedCommand = command;
|
||||
for(int i = 0; i < mCurList->getColumnCount(); i++)
|
||||
for(duint i = 0; i < mCurList->getColumnCount(); i++)
|
||||
{
|
||||
QString token = "$" + QString::number(i);
|
||||
if(specializedCommand.contains(token))
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <QProgressBar>
|
||||
#include <QLabel>
|
||||
#include "StdSearchListView.h"
|
||||
class DisassemblyPopup;
|
||||
|
||||
class QTabWidget;
|
||||
|
||||
|
@ -26,7 +25,7 @@ public slots:
|
|||
|
||||
void setSingleSelection(int index, bool scroll);
|
||||
void addCommand(QString title, QString command);
|
||||
void referenceContextMenu(QMenu* wMenu);
|
||||
void referenceContextMenu(QMenu* menu);
|
||||
void followAddress();
|
||||
void followDumpAddress();
|
||||
void followApiAddress();
|
||||
|
@ -75,7 +74,7 @@ private:
|
|||
Remove
|
||||
};
|
||||
|
||||
void setBreakpointAt(int row, BPSetAction action);
|
||||
void setBreakpointAt(duint row, BPSetAction action);
|
||||
dsint apiAddressFromString(const QString & s);
|
||||
|
||||
void mouseReleaseEvent(QMouseEvent* event);
|
||||
|
|
|
@ -93,7 +93,6 @@ SearchListView::SearchListView(QWidget* parent, AbstractSearchList* abstractSear
|
|||
|
||||
// Set global variables
|
||||
mCurList = abstractSearchList->list();
|
||||
mSearchStartCol = 0;
|
||||
|
||||
// Install input event filter
|
||||
mSearchBox->installEventFilter(this);
|
||||
|
@ -205,9 +204,9 @@ void SearchListView::filterEntries()
|
|||
bool hasSetSingleSelection = false;
|
||||
if(!mLastFirstColValue.isEmpty())
|
||||
{
|
||||
int rows = mCurList->getRowCount();
|
||||
auto rows = mCurList->getRowCount();
|
||||
mCurList->setTableOffset(0);
|
||||
for(int i = 0; i < rows; i++)
|
||||
for(duint i = 0; i < rows; i++)
|
||||
{
|
||||
if(mCurList->getCellContent(i, 0) == mLastFirstColValue)
|
||||
{
|
||||
|
@ -297,16 +296,16 @@ void SearchListView::clearFilter()
|
|||
|
||||
void SearchListView::listContextMenu(const QPoint & pos)
|
||||
{
|
||||
QMenu wMenu(this);
|
||||
emit listContextMenuSignal(&wMenu);
|
||||
wMenu.addSeparator();
|
||||
wMenu.addAction(mSearchAction);
|
||||
QMenu wCopyMenu(tr("&Copy"), this);
|
||||
wCopyMenu.setIcon(DIcon("copy"));
|
||||
mCurList->setupCopyMenu(&wCopyMenu);
|
||||
if(wCopyMenu.actions().length())
|
||||
wMenu.addMenu(&wCopyMenu);
|
||||
wMenu.exec(mCurList->mapToGlobal(pos));
|
||||
QMenu menu(this);
|
||||
emit listContextMenuSignal(&menu);
|
||||
menu.addSeparator();
|
||||
menu.addAction(mSearchAction);
|
||||
QMenu copyMenu(tr("&Copy"), this);
|
||||
copyMenu.setIcon(DIcon("copy"));
|
||||
mCurList->setupCopyMenu(©Menu);
|
||||
if(copyMenu.actions().length())
|
||||
menu.addMenu(©Menu);
|
||||
menu.exec(mCurList->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void SearchListView::doubleClickedSlot()
|
||||
|
@ -346,47 +345,57 @@ bool SearchListView::eventFilter(QObject* obj, QEvent* event)
|
|||
if(obj == mSearchBox && event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
|
||||
switch(keyEvent->key())
|
||||
int key = keyEvent->key();
|
||||
if(key == Qt::Key_Return || key == Qt::Key_Enter)
|
||||
{
|
||||
// The user pressed enter/return
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
// The user pressed enter/return
|
||||
if(mCurList->getCellContent(mCurList->getInitialSelection(), 0).length())
|
||||
emit enterPressedSignal();
|
||||
return true;
|
||||
|
||||
// Search box misc controls
|
||||
case Qt::Key_Escape:
|
||||
mSearchBox->clear();
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Right:
|
||||
case Qt::Key_Backspace:
|
||||
case Qt::Key_Delete:
|
||||
case Qt::Key_Home:
|
||||
case Qt::Key_End:
|
||||
case Qt::Key_Insert:
|
||||
return QWidget::eventFilter(obj, event);
|
||||
|
||||
}
|
||||
if(key == Qt::Key_Escape)
|
||||
{
|
||||
if(mFilterText.isEmpty())
|
||||
return QWidget::eventFilter(obj, event);
|
||||
else
|
||||
clearFilter();
|
||||
}
|
||||
if(!mSearchBox->text().isEmpty())
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
// Search box misc controls
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Right:
|
||||
case Qt::Key_Backspace:
|
||||
case Qt::Key_Delete:
|
||||
case Qt::Key_Home:
|
||||
case Qt::Key_End:
|
||||
case Qt::Key_Insert:
|
||||
return QWidget::eventFilter(obj, event);
|
||||
// Search box shortcuts reliant on mSearchBox not being empty
|
||||
case Qt::Key_X: //Ctrl+X
|
||||
case Qt::Key_A: //Ctrl+A
|
||||
if(keyEvent->modifiers() == Qt::ControlModifier)
|
||||
return QWidget::eventFilter(obj, event);
|
||||
}
|
||||
}
|
||||
switch(key)
|
||||
{
|
||||
// Search box shortcuts
|
||||
case Qt::Key_V: //Ctrl+V
|
||||
case Qt::Key_X: //Ctrl+X
|
||||
case Qt::Key_Z: //Ctrl+Z
|
||||
case Qt::Key_A: //Ctrl+A
|
||||
case Qt::Key_Y: //Ctrl+Y
|
||||
if(keyEvent->modifiers() == Qt::CTRL)
|
||||
if(keyEvent->modifiers() == Qt::ControlModifier)
|
||||
return QWidget::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
// Printable characters go to the search box
|
||||
QString keyText = keyEvent->text();
|
||||
if(!keyText.isEmpty() && QChar(keyText.toUtf8().at(0)).isPrint())
|
||||
return QWidget::eventFilter(obj, event);
|
||||
|
||||
// By default, all other keys are forwarded to the search view
|
||||
return QApplication::sendEvent(mCurList, event);
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ class SearchListView : public QWidget, public ActionHelper<SearchListView>
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SearchListView(QWidget* parent, AbstractSearchList* abstractSearchList, bool enableRegex, bool enableLock);
|
||||
SearchListView(QWidget* parent, AbstractSearchList* abstractSearchList, bool enableRegex, bool enableLock);
|
||||
|
||||
AbstractStdTable* mCurList;
|
||||
int mSearchStartCol;
|
||||
AbstractStdTable* mCurList = nullptr;
|
||||
duint mSearchStartCol = 0;
|
||||
|
||||
bool findTextInList(AbstractStdTable* list, QString text, int row, int startcol, bool startswith);
|
||||
void refreshSearchList();
|
||||
|
@ -32,7 +32,7 @@ private slots:
|
|||
|
||||
signals:
|
||||
void enterPressedSignal();
|
||||
void listContextMenuSignal(QMenu* wMenu);
|
||||
void listContextMenuSignal(QMenu* menu);
|
||||
void emptySearchResult();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -12,7 +12,7 @@ class ShortcutEdit : public QLineEdit
|
|||
bool mError;
|
||||
|
||||
public:
|
||||
explicit ShortcutEdit(QWidget* parent = 0);
|
||||
explicit ShortcutEdit(QWidget* parent = nullptr);
|
||||
const QKeySequence getKeysequence() const;
|
||||
bool error() const;
|
||||
|
||||
|
|
|
@ -24,20 +24,13 @@ int StdIconTable::getIconColumn() const
|
|||
return mIconColumn;
|
||||
}
|
||||
|
||||
void StdIconTable::setRowCount(dsint count)
|
||||
void StdIconTable::setRowCount(duint count)
|
||||
{
|
||||
int wRowToAddOrRemove = count - int(mIcon.size());
|
||||
for(int i = 0; i < qAbs(wRowToAddOrRemove); i++)
|
||||
{
|
||||
if(wRowToAddOrRemove > 0)
|
||||
mIcon.push_back(QIcon());
|
||||
else
|
||||
mIcon.pop_back();
|
||||
}
|
||||
mIcon.resize(count);
|
||||
StdTable::setRowCount(count);
|
||||
}
|
||||
|
||||
void StdIconTable::sortRows(int column, bool ascending)
|
||||
void StdIconTable::sortRows(duint column, bool ascending)
|
||||
{
|
||||
auto sortFn = mColumnSortFunctions.at(column);
|
||||
std::vector<size_t> index;
|
||||
|
@ -61,24 +54,24 @@ void StdIconTable::sortRows(int column, bool ascending)
|
|||
}
|
||||
}
|
||||
|
||||
QString StdIconTable::paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
QString StdIconTable::paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h)
|
||||
{
|
||||
if(col == mIconColumn)
|
||||
{
|
||||
// Draw the selection first, so that transparent icons are drawn properly
|
||||
if(isSelected(rowBase, rowOffset))
|
||||
if(isSelected(row))
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(mSelectionColor));
|
||||
|
||||
mIcon.at(rowBase + rowOffset).paint(painter, x, y, h, h);
|
||||
QString wStr = StdTable::paintContent(painter, rowBase, rowOffset, col, x + h, y, w - h, h);
|
||||
mIcon.at(row).paint(painter, x, y, h, h);
|
||||
QString str = StdTable::paintContent(painter, row, col, x + h, y, w - h, h);
|
||||
|
||||
if(wStr.length())
|
||||
if(str.length())
|
||||
{
|
||||
painter->setPen(getCellColor(rowBase + rowOffset, col));
|
||||
painter->drawText(QRect(x + 4 + h, y, w - 4 - h, h), Qt::AlignVCenter | Qt::AlignLeft, wStr);
|
||||
painter->setPen(getCellColor(row, col));
|
||||
painter->drawText(QRect(x + 4 + h, y, w - 4 - h, h), Qt::AlignVCenter | Qt::AlignLeft, str);
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
else
|
||||
return StdTable::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);
|
||||
return StdTable::paintContent(painter, row, col, x, y, w, h);
|
||||
}
|
||||
|
|
|
@ -7,17 +7,17 @@ class StdIconTable : public StdTable
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit StdIconTable(QWidget* parent = 0) : StdTable(parent), mIconColumn(0) {}
|
||||
explicit StdIconTable(QWidget* parent = nullptr) : StdTable(parent), mIconColumn(0) {}
|
||||
|
||||
// Data Management
|
||||
void setRowIcon(int r, const QIcon & icon); // set the icon for a row
|
||||
QIcon getRowIcon(int r) const;
|
||||
void setIconColumn(int c); // set in which column the icons appear
|
||||
int getIconColumn() const;
|
||||
void setRowCount(dsint count) override;
|
||||
void sortRows(int column, bool ascending) override;
|
||||
void setRowCount(duint count) override;
|
||||
void sortRows(duint column, bool ascending) override;
|
||||
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) override;
|
||||
QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override;
|
||||
|
||||
protected:
|
||||
std::vector<QIcon> mIcon; //listof(row) where row = (listof(col) where col = CellData)
|
||||
|
|
|
@ -79,18 +79,12 @@ void StdSearchListView::reloadData()
|
|||
});
|
||||
}
|
||||
|
||||
void StdSearchListView::setSearchStartCol(int col)
|
||||
void StdSearchListView::setSearchStartCol(duint col)
|
||||
{
|
||||
if(col < stdList()->getColumnCount())
|
||||
mSearchStartCol = col;
|
||||
}
|
||||
|
||||
bool StdSearchListView::setDisassemblyPopupEnabled(bool enabled)
|
||||
{
|
||||
stdList()->setDisassemblyPopupEnabled(enabled);
|
||||
return stdSearchList()->setDisassemblyPopupEnabled(enabled);
|
||||
}
|
||||
|
||||
StdTable* StdSearchListView::stdList()
|
||||
{
|
||||
return mSearchListData->mList;
|
||||
|
|
|
@ -18,13 +18,12 @@ public:
|
|||
void enableMultiSelection(bool enabled);
|
||||
void setAddressColumn(int col, bool cipBase = false);
|
||||
void loadColumnFromConfig(const QString & viewName);
|
||||
bool setDisassemblyPopupEnabled(bool enabled);
|
||||
|
||||
public slots:
|
||||
virtual void setRowCount(dsint count);
|
||||
void setCellContent(int r, int c, QString s);
|
||||
void reloadData();
|
||||
void setSearchStartCol(int col);
|
||||
void setSearchStartCol(duint col);
|
||||
|
||||
private:
|
||||
StdTableSearchList* mSearchListData;
|
||||
|
@ -32,6 +31,8 @@ private:
|
|||
protected:
|
||||
friend class SymbolView;
|
||||
friend class Bridge;
|
||||
friend class HandlesView;
|
||||
|
||||
StdTable* stdList();
|
||||
StdTable* stdSearchList();
|
||||
};
|
||||
|
|
|
@ -10,30 +10,17 @@ StdTable::StdTable(QWidget* parent) : AbstractStdTable(parent)
|
|||
************************************************************************************/
|
||||
bool StdTable::SortBy::AsText(const QString & a, const QString & b)
|
||||
{
|
||||
auto i = QString::compare(a, b);
|
||||
if(i < 0)
|
||||
return true;
|
||||
if(i > 0)
|
||||
return false;
|
||||
return duint(&a) < duint(&b);
|
||||
return QString::compare(a, b) < 0;
|
||||
}
|
||||
|
||||
bool StdTable::SortBy::AsInt(const QString & a, const QString & b)
|
||||
{
|
||||
if(a.toLongLong() < b.toLongLong())
|
||||
return true;
|
||||
if(a.toLongLong() > b.toLongLong())
|
||||
return false;
|
||||
return duint(&a) < duint(&b);
|
||||
return a.toLongLong() < b.toLongLong();
|
||||
}
|
||||
|
||||
bool StdTable::SortBy::AsHex(const QString & a, const QString & b)
|
||||
{
|
||||
if(a.toLongLong(0, 16) < b.toLongLong(0, 16))
|
||||
return true;
|
||||
if(a.toLongLong(0, 16) > b.toLongLong(0, 16))
|
||||
return false;
|
||||
return duint(&a) < duint(&b);
|
||||
return a.toLongLong(0, 16) < b.toLongLong(0, 16);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
|
@ -65,30 +52,36 @@ void StdTable::deleteAllColumns()
|
|||
mColumnSortFunctions.clear();
|
||||
}
|
||||
|
||||
void StdTable::setRowCount(dsint count)
|
||||
void StdTable::setRowCount(duint count)
|
||||
{
|
||||
int wRowToAddOrRemove = count - int(mData.size());
|
||||
for(int i = 0; i < qAbs(wRowToAddOrRemove); i++)
|
||||
auto oldSize = mData.size();
|
||||
mData.resize(count);
|
||||
if(oldSize < count)
|
||||
{
|
||||
if(wRowToAddOrRemove > 0)
|
||||
for(duint i = oldSize; i < count; i++)
|
||||
{
|
||||
mData.push_back(std::vector<CellData>());
|
||||
for(int j = 0; j < getColumnCount(); j++)
|
||||
mData[mData.size() - 1].push_back(CellData());
|
||||
mData[i].resize(getColumnCount());
|
||||
}
|
||||
else
|
||||
mData.pop_back();
|
||||
}
|
||||
AbstractTableView::setRowCount(count);
|
||||
}
|
||||
|
||||
void StdTable::setCellContent(int r, int c, QString s)
|
||||
void StdTable::setCellContent(duint r, duint c, QString s)
|
||||
{
|
||||
if(isValidIndex(r, c))
|
||||
mData[r][c].text = std::move(s);
|
||||
}
|
||||
|
||||
QString StdTable::getCellContent(int r, int c)
|
||||
void StdTable::setCellContent(duint r, duint c, QString s, duint userdata)
|
||||
{
|
||||
if(isValidIndex(r, c))
|
||||
{
|
||||
mData[r][c].text = std::move(s);
|
||||
mData[r][c].userdata = userdata;
|
||||
}
|
||||
}
|
||||
|
||||
QString StdTable::getCellContent(duint r, duint c)
|
||||
{
|
||||
if(isValidIndex(r, c))
|
||||
return mData[r][c].text;
|
||||
|
@ -96,25 +89,25 @@ QString StdTable::getCellContent(int r, int c)
|
|||
return QString("");
|
||||
}
|
||||
|
||||
void StdTable::setCellUserdata(int r, int c, duint userdata)
|
||||
void StdTable::setCellUserdata(duint r, duint c, duint userdata)
|
||||
{
|
||||
if(isValidIndex(r, c))
|
||||
mData[r][c].userdata = userdata;
|
||||
}
|
||||
|
||||
duint StdTable::getCellUserdata(int r, int c)
|
||||
duint StdTable::getCellUserdata(duint r, duint c)
|
||||
{
|
||||
return isValidIndex(r, c) ? mData[r][c].userdata : 0;
|
||||
}
|
||||
|
||||
bool StdTable::isValidIndex(int r, int c)
|
||||
bool StdTable::isValidIndex(duint r, duint c)
|
||||
{
|
||||
if(r < 0 || c < 0 || r >= int(mData.size()))
|
||||
return false;
|
||||
return c < int(mData.at(r).size());
|
||||
}
|
||||
|
||||
void StdTable::sortRows(int column, bool ascending)
|
||||
void StdTable::sortRows(duint column, bool ascending)
|
||||
{
|
||||
auto sortFn = mColumnSortFunctions.at(column);
|
||||
std::stable_sort(mData.begin(), mData.end(), [column, ascending, &sortFn](const std::vector<CellData> & a, const std::vector<CellData> & b)
|
||||
|
|
|
@ -6,7 +6,7 @@ class StdTable : public AbstractStdTable
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit StdTable(QWidget* parent = 0);
|
||||
explicit StdTable(QWidget* parent = nullptr);
|
||||
|
||||
// Sorting
|
||||
struct SortBy
|
||||
|
@ -20,13 +20,14 @@ public:
|
|||
// Data Management
|
||||
void addColumnAt(int width, QString title, bool isClickable, QString copyTitle = "", SortBy::t sortFn = SortBy::AsText);
|
||||
void deleteAllColumns() override;
|
||||
void setRowCount(dsint count) override;
|
||||
void setCellContent(int r, int c, QString s);
|
||||
QString getCellContent(int r, int c) override;
|
||||
void setCellUserdata(int r, int c, duint userdata);
|
||||
duint getCellUserdata(int r, int c);
|
||||
bool isValidIndex(int r, int c) override;
|
||||
void sortRows(int column, bool ascending) override;
|
||||
void setRowCount(duint count) override;
|
||||
void setCellContent(duint r, duint c, QString s);
|
||||
void setCellContent(duint r, duint c, QString s, duint userdata);
|
||||
QString getCellContent(duint r, duint c) override;
|
||||
void setCellUserdata(duint r, duint c, duint userdata);
|
||||
duint getCellUserdata(duint r, duint c);
|
||||
bool isValidIndex(duint r, duint c) override;
|
||||
void sortRows(duint column, bool ascending) override;
|
||||
|
||||
protected:
|
||||
struct CellData
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "StdTableSearchList.h"
|
||||
#include "StdIconTable.h"
|
||||
|
||||
void StdTableSearchList::filter(const QString & filter, FilterType type, int startColumn)
|
||||
void StdTableSearchList::filter(const QString & filter, FilterType type, duint startColumn)
|
||||
{
|
||||
StdIconTable* mSearchIconList = qobject_cast<StdIconTable*>(mSearchList);
|
||||
StdIconTable* mIconList = qobject_cast<StdIconTable*>(mList);
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
AbstractStdTable* list() const override { return mList; }
|
||||
AbstractStdTable* searchList() const override { return mSearchList; }
|
||||
|
||||
void filter(const QString & filter, FilterType type, int startColumn) override;
|
||||
void filter(const QString & filter, FilterType type, duint startColumn) override;
|
||||
|
||||
private:
|
||||
StdTable* mList;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "Bridge.h"
|
||||
#include <QClipboard>
|
||||
#include "QBeaEngine.h"
|
||||
#include "QZydis.h"
|
||||
#include "main.h"
|
||||
#include "Exports.h"
|
||||
|
||||
|
@ -12,6 +12,19 @@
|
|||
************************************************************************************/
|
||||
static Bridge* mBridge;
|
||||
|
||||
class BridgeArchitecture : public Architecture
|
||||
{
|
||||
bool disasm64() const override
|
||||
{
|
||||
return ArchValue(false, true);
|
||||
}
|
||||
|
||||
bool addr64() const override
|
||||
{
|
||||
return ArchValue(false, true);
|
||||
}
|
||||
} mArch;
|
||||
|
||||
/************************************************************************************
|
||||
Class Members
|
||||
************************************************************************************/
|
||||
|
@ -72,6 +85,11 @@ void Bridge::initBridge()
|
|||
mBridge = new Bridge();
|
||||
}
|
||||
|
||||
Architecture* Bridge::getArchitecture()
|
||||
{
|
||||
return &mArch;
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Helper Functions
|
||||
************************************************************************************/
|
||||
|
@ -100,7 +118,7 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
|||
{
|
||||
case GUI_DISASSEMBLE_AT:
|
||||
mLastCip = (duint)param2;
|
||||
emit disassembleAt((dsint)param1, (dsint)param2);
|
||||
emit disassembleAt((duint)param1, (duint)param2);
|
||||
break;
|
||||
|
||||
case GUI_SET_DEBUG_STATE:
|
||||
|
@ -317,7 +335,7 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
|||
|
||||
case GUI_REF_SETSEARCHSTARTCOL:
|
||||
if(referenceManager->currentReferenceView())
|
||||
referenceManager->currentReferenceView()->setSearchStartCol((int)param1);
|
||||
referenceManager->currentReferenceView()->setSearchStartCol((duint)param1);
|
||||
break;
|
||||
|
||||
case GUI_REF_INITIALIZE:
|
||||
|
@ -358,11 +376,11 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
|||
char* text = (char*)param2;
|
||||
if(!text || !parVA || !DbgIsDebugging())
|
||||
return 0;
|
||||
byte_t wBuffer[16];
|
||||
if(!DbgMemRead(parVA, wBuffer, 16))
|
||||
byte_t buffer[16];
|
||||
if(!DbgMemRead(parVA, buffer, 16))
|
||||
return 0;
|
||||
QBeaEngine disasm(int(ConfigUint("Disassembler", "MaxModuleSize")));
|
||||
Instruction_t instr = disasm.DisassembleAt(wBuffer, 16, 0, parVA);
|
||||
QZydis disasm(int(ConfigUint("Disassembler", "MaxModuleSize")), Bridge::getArchitecture());
|
||||
Instruction_t instr = disasm.DisassembleAt(buffer, 16, 0, parVA);
|
||||
QString finalInstruction;
|
||||
for(const auto & curToken : instr.tokens.tokens)
|
||||
finalInstruction += curToken.text;
|
||||
|
@ -558,6 +576,9 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
|||
case GUI_STACK:
|
||||
emit selectionStackSet(selection);
|
||||
break;
|
||||
case GUI_MEMMAP:
|
||||
emit selectionMemmapSet(selection);
|
||||
break;
|
||||
default:
|
||||
return (void*)false;
|
||||
}
|
||||
|
@ -920,9 +941,6 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
|
|||
|
||||
case GUI_GET_MAIN_THREAD_ID:
|
||||
return (void*)dwMainThreadId;
|
||||
|
||||
case GUI_IS_DEBUGGER_FOCUSED:
|
||||
return (void*)!!QApplication::activeWindow();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -7,6 +7,15 @@
|
|||
#include <QMenu>
|
||||
#include "Imports.h"
|
||||
#include "BridgeResult.h"
|
||||
#include "Architecture.h"
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
namespace Qt
|
||||
{
|
||||
static QString::SplitBehavior KeepEmptyParts = QString::KeepEmptyParts;
|
||||
static QString::SplitBehavior SkipEmptyParts = QString::SkipEmptyParts;
|
||||
}
|
||||
#endif // QT_VERSION
|
||||
|
||||
class ReferenceManager;
|
||||
class SymbolView;
|
||||
|
@ -18,11 +27,12 @@ class Bridge : public QObject
|
|||
friend class BridgeResult;
|
||||
|
||||
public:
|
||||
explicit Bridge(QObject* parent = 0);
|
||||
explicit Bridge(QObject* parent = nullptr);
|
||||
~Bridge();
|
||||
|
||||
static Bridge* getBridge();
|
||||
static void initBridge();
|
||||
static Architecture* getArchitecture();
|
||||
|
||||
// Message processing function
|
||||
void* processMessage(GUIMSG type, void* param1, void* param2);
|
||||
|
@ -47,7 +57,7 @@ public:
|
|||
bool loggingEnabled = true;
|
||||
|
||||
signals:
|
||||
void disassembleAt(dsint va, dsint eip);
|
||||
void disassembleAt(duint va, duint eip);
|
||||
void updateDisassembly();
|
||||
void dbgStateChanged(DBGSTATE state);
|
||||
void addMsgToLog(QByteArray msg);
|
||||
|
@ -57,11 +67,11 @@ signals:
|
|||
void saveLogToFile(QString file);
|
||||
void redirectLogStop();
|
||||
void redirectLogToFile(QString filename);
|
||||
void shutdown();
|
||||
void close();
|
||||
void updateRegisters();
|
||||
void updateBreakpoints();
|
||||
void updateWindowTitle(QString filename);
|
||||
void dumpAt(dsint va);
|
||||
void dumpAt(duint va);
|
||||
void scriptAdd(int count, const char** lines);
|
||||
void scriptClear();
|
||||
void scriptSetIp(int line);
|
||||
|
@ -76,7 +86,7 @@ signals:
|
|||
void clearSymbolLog();
|
||||
void setSymbolProgress(int progress);
|
||||
void referenceAddColumnAt(int width, QString title);
|
||||
void referenceSetRowCount(dsint count);
|
||||
void referenceSetRowCount(duint count);
|
||||
void referenceSetCellContent(int r, int c, QString s);
|
||||
void referenceAddCommand(QString title, QString command);
|
||||
void referenceReloadData();
|
||||
|
@ -113,6 +123,7 @@ signals:
|
|||
void selectionStackSet(const SELECTIONDATA* selection);
|
||||
void selectionGraphGet(SELECTIONDATA* selection);
|
||||
void selectionMemmapGet(SELECTIONDATA* selection);
|
||||
void selectionMemmapSet(const SELECTIONDATA* selection);
|
||||
void selectionSymmodGet(SELECTIONDATA* selection);
|
||||
void getStrWindow(const QString title, QString* text);
|
||||
void autoCompleteAddCmd(const QString cmd);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#include "Architecture.h"
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
This should probably take some inspiration from Zydis:
|
||||
- Address space min/max (64 vs 32 bit basically)
|
||||
- Disassembly architecture (likely should return a reference to a disassembler)
|
||||
|
||||
*/
|
||||
class Architecture
|
||||
{
|
||||
public:
|
||||
virtual ~Architecture() = default;
|
||||
|
||||
// TODO: replace this with something about address space
|
||||
virtual bool disasm64() const = 0;
|
||||
virtual bool addr64() const = 0;
|
||||
};
|
|
@ -1,75 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
#include "ZydisTokenizer.h"
|
||||
|
||||
class EncodeMap;
|
||||
class CodeFoldingHelper;
|
||||
|
||||
struct Instruction_t
|
||||
{
|
||||
enum BranchType
|
||||
{
|
||||
None,
|
||||
Conditional,
|
||||
Unconditional,
|
||||
Call
|
||||
};
|
||||
|
||||
Instruction_t()
|
||||
: rva(0),
|
||||
length(0),
|
||||
branchDestination(0),
|
||||
branchType(None)
|
||||
{
|
||||
}
|
||||
|
||||
QString instStr;
|
||||
QByteArray dump;
|
||||
uint8_t prefixSize, opcodeSize, group1Size, group2Size, group3Size;
|
||||
duint rva;
|
||||
int length;
|
||||
duint branchDestination;
|
||||
BranchType branchType;
|
||||
ZydisTokenizer::InstructionToken tokens;
|
||||
std::vector<std::pair<const char*, uint8_t>> regsReferenced;
|
||||
uint8_t vectorElementType[4];
|
||||
};
|
||||
|
||||
class QBeaEngine
|
||||
{
|
||||
public:
|
||||
explicit QBeaEngine(int maxModuleSize);
|
||||
~QBeaEngine();
|
||||
ulong DisassembleBack(const byte_t* data, duint base, duint size, duint ip, int n);
|
||||
ulong DisassembleNext(const byte_t* data, duint base, duint size, duint ip, int n);
|
||||
Instruction_t DisassembleAt(const byte_t* data, duint size, duint origBase, duint origInstRVA, bool datainstr = true);
|
||||
Instruction_t DecodeDataAt(const byte_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type);
|
||||
void setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager);
|
||||
void UpdateConfig();
|
||||
|
||||
EncodeMap* getEncodeMap()
|
||||
{
|
||||
return mEncodeMap;
|
||||
}
|
||||
|
||||
private:
|
||||
struct DataInstructionInfo
|
||||
{
|
||||
QString shortName;
|
||||
QString longName;
|
||||
QString cName;
|
||||
};
|
||||
|
||||
void UpdateDataInstructionMap();
|
||||
ZydisTokenizer _tokenizer;
|
||||
QHash<ENCODETYPE, DataInstructionInfo> dataInstMap;
|
||||
bool _bLongDataInst;
|
||||
EncodeMap* mEncodeMap;
|
||||
CodeFoldingHelper* mCodeFoldingManager;
|
||||
uint8_t reginfo[ZYDIS_REGISTER_MAX_VALUE + 1];
|
||||
uint8_t flaginfo[ZYDIS_CPUFLAG_MAX_VALUE + 1];
|
||||
};
|
||||
|
||||
void formatOpcodeString(const Instruction_t & inst, RichTextPainter::List & list, std::vector<std::pair<size_t, bool>> & realBytes);
|
|
@ -1,19 +1,24 @@
|
|||
#include "QBeaEngine.h"
|
||||
#include "QZydis.h"
|
||||
#include "StringUtil.h"
|
||||
#include "EncodeMap.h"
|
||||
#include "CodeFolding.h"
|
||||
#include "Bridge.h"
|
||||
|
||||
QBeaEngine::QBeaEngine(int maxModuleSize)
|
||||
: _tokenizer(maxModuleSize), mCodeFoldingManager(nullptr), _bLongDataInst(false)
|
||||
#ifndef _countof
|
||||
#define _countof(array) (sizeof(array) / sizeof(array[0]))
|
||||
#endif // _countof
|
||||
|
||||
QZydis::QZydis(int maxModuleSize, Architecture* architecture)
|
||||
: mTokenizer(maxModuleSize, architecture), mArchitecture(architecture)
|
||||
{
|
||||
ZydisTokenizer::UpdateColors();
|
||||
UpdateDataInstructionMap();
|
||||
this->mEncodeMap = new EncodeMap();
|
||||
mEncodeMap = new EncodeMap();
|
||||
}
|
||||
|
||||
QBeaEngine::~QBeaEngine()
|
||||
QZydis::~QZydis()
|
||||
{
|
||||
delete this->mEncodeMap;
|
||||
delete mEncodeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,14 +33,14 @@ QBeaEngine::~QBeaEngine()
|
|||
*
|
||||
* @return Return the RVA (Relative to the data pointer) of the nth instruction before the instruction pointed by ip
|
||||
*/
|
||||
ulong QBeaEngine::DisassembleBack(const byte_t* data, duint base, duint size, duint ip, int n)
|
||||
ulong QZydis::DisassembleBack(const uint8_t* data, duint base, duint size, duint ip, int n)
|
||||
{
|
||||
int i;
|
||||
uint abuf[128], addr, back, cmdsize;
|
||||
const unsigned char* pdata;
|
||||
|
||||
// Reset Disasm Structure
|
||||
Zydis cp;
|
||||
Zydis zydis(mArchitecture->disasm64());
|
||||
|
||||
// Check if the pointer is not null
|
||||
if(data == NULL)
|
||||
|
@ -89,10 +94,10 @@ ulong QBeaEngine::DisassembleBack(const byte_t* data, duint base, duint size, du
|
|||
}
|
||||
else
|
||||
{
|
||||
if(!cp.DisassembleSafe(addr + base, pdata, (int)size))
|
||||
if(!zydis.DisassembleSafe(addr + base, pdata, (int)size))
|
||||
cmdsize = 2; //heuristic for better output (FF FE or FE FF are usually part of an instruction)
|
||||
else
|
||||
cmdsize = cp.Size();
|
||||
cmdsize = zydis.Size();
|
||||
|
||||
cmdsize = mEncodeMap->getDataSize(base + addr, cmdsize);
|
||||
|
||||
|
@ -124,14 +129,14 @@ ulong QBeaEngine::DisassembleBack(const byte_t* data, duint base, duint size, du
|
|||
*
|
||||
* @return Return the RVA (Relative to the data pointer) of the nth instruction after the instruction pointed by ip
|
||||
*/
|
||||
ulong QBeaEngine::DisassembleNext(const byte_t* data, duint base, duint size, duint ip, int n)
|
||||
ulong QZydis::DisassembleNext(const uint8_t* data, duint base, duint size, duint ip, int n)
|
||||
{
|
||||
int i;
|
||||
uint cmdsize;
|
||||
const unsigned char* pdata;
|
||||
|
||||
// Reset Disasm Structure
|
||||
Zydis cp;
|
||||
Zydis zydis(mArchitecture->disasm64());
|
||||
|
||||
if(data == NULL)
|
||||
return 0;
|
||||
|
@ -154,10 +159,10 @@ ulong QBeaEngine::DisassembleNext(const byte_t* data, duint base, duint size, du
|
|||
}
|
||||
else
|
||||
{
|
||||
if(!cp.DisassembleSafe(ip + base, pdata, (int)size))
|
||||
if(!zydis.DisassembleSafe(ip + base, pdata, (int)size))
|
||||
cmdsize = 1;
|
||||
else
|
||||
cmdsize = cp.Size();
|
||||
cmdsize = zydis.Size();
|
||||
|
||||
cmdsize = mEncodeMap->getDataSize(base + ip, cmdsize);
|
||||
|
||||
|
@ -181,7 +186,7 @@ ulong QBeaEngine::DisassembleNext(const byte_t* data, duint base, duint size, du
|
|||
*
|
||||
* @return Return the disassembled instruction
|
||||
*/
|
||||
Instruction_t QBeaEngine::DisassembleAt(const byte_t* data, duint size, duint origBase, duint origInstRVA, bool datainstr)
|
||||
Instruction_t QZydis::DisassembleAt(const uint8_t* data, duint size, duint origBase, duint origInstRVA, bool datainstr)
|
||||
{
|
||||
if(datainstr)
|
||||
{
|
||||
|
@ -189,198 +194,196 @@ Instruction_t QBeaEngine::DisassembleAt(const byte_t* data, duint size, duint or
|
|||
if(!mEncodeMap->isCode(type))
|
||||
return DecodeDataAt(data, size, origBase, origInstRVA, type);
|
||||
}
|
||||
|
||||
//tokenize
|
||||
ZydisTokenizer::InstructionToken cap;
|
||||
_tokenizer.Tokenize(origBase + origInstRVA, data, size, cap);
|
||||
int len = _tokenizer.Size();
|
||||
|
||||
const auto & cp = _tokenizer.GetZydis();
|
||||
bool success = cp.Success();
|
||||
mTokenizer.Tokenize(origBase + origInstRVA, data, size, cap);
|
||||
int len = mTokenizer.Size();
|
||||
|
||||
const auto & zydis = mTokenizer.GetZydis();
|
||||
bool success = zydis.Success();
|
||||
|
||||
auto branchType = Instruction_t::None;
|
||||
Instruction_t wInst;
|
||||
if(success && cp.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTRet | Zydis::BTLoop | Zydis::BTXbegin))
|
||||
Instruction_t inst;
|
||||
if(success && zydis.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTRet | Zydis::BTLoop | Zydis::BTXbegin))
|
||||
{
|
||||
wInst.branchDestination = DbgGetBranchDestination(origBase + origInstRVA);
|
||||
if(cp.IsBranchType(Zydis::BTUncondJmp))
|
||||
inst.branchDestination = DbgGetBranchDestination(origBase + origInstRVA);
|
||||
if(zydis.IsBranchType(Zydis::BTUncondJmp))
|
||||
branchType = Instruction_t::Unconditional;
|
||||
else if(cp.IsBranchType(Zydis::BTCall))
|
||||
else if(zydis.IsBranchType(Zydis::BTCall))
|
||||
branchType = Instruction_t::Call;
|
||||
else if(cp.IsBranchType(Zydis::BTCondJmp) || cp.IsBranchType(Zydis::BTLoop))
|
||||
else if(zydis.IsBranchType(Zydis::BTCondJmp) || zydis.IsBranchType(Zydis::BTLoop))
|
||||
branchType = Instruction_t::Conditional;
|
||||
}
|
||||
else
|
||||
wInst.branchDestination = 0;
|
||||
inst.branchDestination = 0;
|
||||
|
||||
wInst.instStr = QString(cp.InstructionText().c_str());
|
||||
wInst.dump = QByteArray((const char*)data, len);
|
||||
wInst.rva = origInstRVA;
|
||||
inst.instStr = QString(zydis.InstructionText().c_str());
|
||||
inst.dump = QByteArray((const char*)data, len);
|
||||
inst.rva = origInstRVA;
|
||||
if(mCodeFoldingManager && mCodeFoldingManager->isFolded(origInstRVA))
|
||||
wInst.length = mCodeFoldingManager->getFoldEnd(origInstRVA + origBase) - (origInstRVA + origBase) + 1;
|
||||
inst.length = mCodeFoldingManager->getFoldEnd(origInstRVA + origBase) - (origInstRVA + origBase) + 1;
|
||||
else
|
||||
wInst.length = len;
|
||||
wInst.branchType = branchType;
|
||||
wInst.tokens = cap;
|
||||
cp.BytesGroup(&wInst.prefixSize, &wInst.opcodeSize, &wInst.group1Size, &wInst.group2Size, &wInst.group3Size);
|
||||
for(uint8_t i = 0; i < _countof(wInst.vectorElementType); ++i)
|
||||
wInst.vectorElementType[i] = cp.getVectorElementType(i);
|
||||
inst.length = len;
|
||||
inst.branchType = branchType;
|
||||
inst.tokens = cap;
|
||||
zydis.BytesGroup(&inst.prefixSize, &inst.opcodeSize, &inst.group1Size, &inst.group2Size, &inst.group3Size);
|
||||
for(uint8_t i = 0; i < _countof(inst.vectorElementType); ++i)
|
||||
inst.vectorElementType[i] = zydis.getVectorElementType(i);
|
||||
|
||||
if(!success)
|
||||
return wInst;
|
||||
return inst;
|
||||
|
||||
auto instr = cp.GetInstr();
|
||||
cp.RegInfo(reginfo);
|
||||
uint8_t regInfo[ZYDIS_REGISTER_MAX_VALUE + 1];
|
||||
uint8_t flagInfo[32];
|
||||
zydis.RegInfo(regInfo);
|
||||
zydis.FlagInfo(flagInfo);
|
||||
|
||||
for(size_t i = 0; i < _countof(instr->accessedFlags); ++i)
|
||||
regInfo[ZYDIS_REGISTER_RFLAGS] = Zydis::RAINone;
|
||||
regInfo[ZYDIS_REGISTER_EFLAGS] = Zydis::RAINone;
|
||||
regInfo[ZYDIS_REGISTER_FLAGS] = Zydis::RAINone;
|
||||
regInfo[mArchitecture->disasm64() ? ZYDIS_REGISTER_RIP : ZYDIS_REGISTER_EIP] = Zydis::RAINone;
|
||||
|
||||
inst.regsReferenced.reserve(ZYDIS_REGISTER_MAX_VALUE + 21);
|
||||
for(int i = ZYDIS_REGISTER_NONE; i <= ZYDIS_REGISTER_MAX_VALUE; ++i)
|
||||
{
|
||||
auto flagAction = instr->accessedFlags[i].action;
|
||||
if(flagAction == ZYDIS_CPUFLAG_ACTION_NONE)
|
||||
continue;
|
||||
|
||||
Zydis::RegAccessInfo rai;
|
||||
switch(flagAction)
|
||||
if(regInfo[i] != Zydis::RAINone)
|
||||
{
|
||||
case ZYDIS_CPUFLAG_ACTION_MODIFIED:
|
||||
case ZYDIS_CPUFLAG_ACTION_SET_0:
|
||||
case ZYDIS_CPUFLAG_ACTION_SET_1:
|
||||
rai = Zydis::RAIWrite;
|
||||
break;
|
||||
case ZYDIS_CPUFLAG_ACTION_TESTED:
|
||||
rai = Zydis::RAIRead;
|
||||
break;
|
||||
default:
|
||||
rai = Zydis::RAINone;
|
||||
break;
|
||||
inst.regsReferenced.emplace_back(zydis.RegName(ZydisRegister(i)), regInfo[i]);
|
||||
}
|
||||
}
|
||||
for(uint8_t i = 0; i < _countof(flagInfo); i++)
|
||||
{
|
||||
auto flag = 1u << i;
|
||||
auto name = zydis.FlagName(flag);
|
||||
auto rai = flagInfo[i];
|
||||
if(name != nullptr && rai != Zydis::RAINone)
|
||||
{
|
||||
inst.regsReferenced.emplace_back(name, rai);
|
||||
}
|
||||
|
||||
reginfo[ZYDIS_REGISTER_RFLAGS] = Zydis::RAINone;
|
||||
reginfo[ZYDIS_REGISTER_EFLAGS] = Zydis::RAINone;
|
||||
reginfo[ZYDIS_REGISTER_FLAGS] = Zydis::RAINone;
|
||||
|
||||
wInst.regsReferenced.emplace_back(cp.FlagName(ZydisCPUFlag(i)), rai);
|
||||
}
|
||||
|
||||
wInst.regsReferenced.reserve(ZYDIS_REGISTER_MAX_VALUE);
|
||||
reginfo[ArchValue(ZYDIS_REGISTER_EIP, ZYDIS_REGISTER_RIP)] = Zydis::RAINone;
|
||||
for(int i = ZYDIS_REGISTER_NONE; i <= ZYDIS_REGISTER_MAX_VALUE; ++i)
|
||||
if(reginfo[i])
|
||||
wInst.regsReferenced.emplace_back(cp.RegName(ZydisRegister(i)), reginfo[i]);
|
||||
|
||||
// Info about volatile and nonvolatile registers
|
||||
if(cp.IsBranchType(Zydis::BranchType::BTCall))
|
||||
if(zydis.IsBranchType(Zydis::BranchType::BTCall))
|
||||
{
|
||||
enum : uint8_t
|
||||
{
|
||||
Volatile = Zydis::RAIImplicit | Zydis::RAIWrite,
|
||||
Parameter = Volatile | Zydis::RAIRead,
|
||||
};
|
||||
#define info(reg, type) wInst.regsReferenced.emplace_back(#reg, type)
|
||||
#define info(reg, type) inst.regsReferenced.emplace_back(#reg, type)
|
||||
|
||||
#ifdef _WIN64
|
||||
// https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions
|
||||
info(rax, Volatile);
|
||||
info(rcx, Parameter);
|
||||
info(rdx, Parameter);
|
||||
info(r8, Parameter);
|
||||
info(r9, Parameter);
|
||||
info(r10, Volatile);
|
||||
info(r11, Volatile);
|
||||
info(xmm0, Parameter);
|
||||
info(ymm0, Parameter);
|
||||
info(xmm1, Parameter);
|
||||
info(ymm1, Parameter);
|
||||
info(xmm2, Parameter);
|
||||
info(ymm2, Parameter);
|
||||
info(xmm3, Parameter);
|
||||
info(ymm3, Parameter);
|
||||
info(xmm4, Parameter);
|
||||
info(ymm4, Parameter);
|
||||
info(xmm5, Parameter);
|
||||
info(ymm5, Parameter);
|
||||
|
||||
#else
|
||||
// https://en.wikipedia.org/wiki/X86_calling_conventions#Caller-saved_(volatile)_registers
|
||||
info(eax, Volatile);
|
||||
info(edx, Volatile);
|
||||
info(ecx, Volatile);
|
||||
#endif // _WIN64
|
||||
if(mArchitecture->disasm64())
|
||||
{
|
||||
// https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions
|
||||
info(rax, Volatile);
|
||||
info(rcx, Parameter);
|
||||
info(rdx, Parameter);
|
||||
info(r8, Parameter);
|
||||
info(r9, Parameter);
|
||||
info(r10, Volatile);
|
||||
info(r11, Volatile);
|
||||
info(xmm0, Parameter);
|
||||
info(ymm0, Parameter);
|
||||
info(xmm1, Parameter);
|
||||
info(ymm1, Parameter);
|
||||
info(xmm2, Parameter);
|
||||
info(ymm2, Parameter);
|
||||
info(xmm3, Parameter);
|
||||
info(ymm3, Parameter);
|
||||
info(xmm4, Parameter);
|
||||
info(ymm4, Parameter);
|
||||
info(xmm5, Parameter);
|
||||
info(ymm5, Parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// https://en.wikipedia.org/wiki/X86_calling_conventions#Caller-saved_(volatile)_registers
|
||||
info(eax, Volatile);
|
||||
info(edx, Volatile);
|
||||
info(ecx, Volatile);
|
||||
}
|
||||
|
||||
#undef info
|
||||
}
|
||||
|
||||
return wInst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
Instruction_t QBeaEngine::DecodeDataAt(const byte_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type)
|
||||
Instruction_t QZydis::DecodeDataAt(const uint8_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type)
|
||||
{
|
||||
//tokenize
|
||||
ZydisTokenizer::InstructionToken cap;
|
||||
|
||||
auto infoIter = dataInstMap.find(type);
|
||||
if(infoIter == dataInstMap.end())
|
||||
infoIter = dataInstMap.find(enc_byte);
|
||||
auto infoIter = mDataInstMap.find(type);
|
||||
if(infoIter == mDataInstMap.end())
|
||||
infoIter = mDataInstMap.find(enc_byte);
|
||||
|
||||
int len = mEncodeMap->getDataSize(origBase + origInstRVA, 1);
|
||||
|
||||
QString mnemonic = _bLongDataInst ? infoIter.value().longName : infoIter.value().shortName;
|
||||
QString mnemonic = mLongDataInst ? infoIter.value().longName : infoIter.value().shortName;
|
||||
|
||||
len = std::min(len, (int)size);
|
||||
|
||||
QString datastr = GetDataTypeString(data, len, type);
|
||||
|
||||
_tokenizer.TokenizeData(mnemonic, datastr, cap);
|
||||
mTokenizer.TokenizeData(mnemonic, datastr, cap);
|
||||
|
||||
Instruction_t wInst;
|
||||
wInst.instStr = mnemonic + " " + datastr;
|
||||
wInst.dump = QByteArray((const char*)data, len);
|
||||
wInst.rva = origInstRVA;
|
||||
wInst.length = len;
|
||||
wInst.branchType = Instruction_t::None;
|
||||
wInst.branchDestination = 0;
|
||||
wInst.tokens = cap;
|
||||
wInst.prefixSize = 0;
|
||||
wInst.opcodeSize = len;
|
||||
wInst.group1Size = 0;
|
||||
wInst.group2Size = 0;
|
||||
wInst.group3Size = 0;
|
||||
wInst.vectorElementType[0] = Zydis::VETDefault;
|
||||
wInst.vectorElementType[1] = Zydis::VETDefault;
|
||||
wInst.vectorElementType[2] = Zydis::VETDefault;
|
||||
wInst.vectorElementType[3] = Zydis::VETDefault;
|
||||
Instruction_t inst;
|
||||
inst.instStr = mnemonic + " " + datastr;
|
||||
inst.dump = QByteArray((const char*)data, len);
|
||||
inst.rva = origInstRVA;
|
||||
inst.length = len;
|
||||
inst.branchType = Instruction_t::None;
|
||||
inst.branchDestination = 0;
|
||||
inst.tokens = cap;
|
||||
inst.prefixSize = 0;
|
||||
inst.opcodeSize = len;
|
||||
inst.group1Size = 0;
|
||||
inst.group2Size = 0;
|
||||
inst.group3Size = 0;
|
||||
inst.vectorElementType[0] = Zydis::VETDefault;
|
||||
inst.vectorElementType[1] = Zydis::VETDefault;
|
||||
inst.vectorElementType[2] = Zydis::VETDefault;
|
||||
inst.vectorElementType[3] = Zydis::VETDefault;
|
||||
|
||||
return wInst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
void QBeaEngine::UpdateDataInstructionMap()
|
||||
void QZydis::UpdateDataInstructionMap()
|
||||
{
|
||||
dataInstMap.clear();
|
||||
dataInstMap.insert(enc_byte, {"db", "byte", "int8"});
|
||||
dataInstMap.insert(enc_word, {"dw", "word", "short"});
|
||||
dataInstMap.insert(enc_dword, {"dd", "dword", "int"});
|
||||
dataInstMap.insert(enc_fword, {"df", "fword", "fword"});
|
||||
dataInstMap.insert(enc_qword, {"dq", "qword", "long"});
|
||||
dataInstMap.insert(enc_tbyte, {"tbyte", "tbyte", "tbyte"});
|
||||
dataInstMap.insert(enc_oword, {"oword", "oword", "oword"});
|
||||
dataInstMap.insert(enc_mmword, {"mmword", "mmword", "long long"});
|
||||
dataInstMap.insert(enc_xmmword, {"xmmword", "xmmword", "_m128"});
|
||||
dataInstMap.insert(enc_ymmword, {"ymmword", "ymmword", "_m256"});
|
||||
dataInstMap.insert(enc_real4, {"real4", "real4", "float"});
|
||||
dataInstMap.insert(enc_real8, {"real8", "real8", "double"});
|
||||
dataInstMap.insert(enc_real10, {"real10", "real10", "long double"});
|
||||
dataInstMap.insert(enc_ascii, {"ascii", "ascii", "string"});
|
||||
dataInstMap.insert(enc_unicode, {"unicode", "unicode", "wstring"});
|
||||
mDataInstMap.clear();
|
||||
mDataInstMap.insert(enc_byte, {"db", "byte", "int8"});
|
||||
mDataInstMap.insert(enc_word, {"dw", "word", "short"});
|
||||
mDataInstMap.insert(enc_dword, {"dd", "dword", "int"});
|
||||
mDataInstMap.insert(enc_fword, {"df", "fword", "fword"});
|
||||
mDataInstMap.insert(enc_qword, {"dq", "qword", "long"});
|
||||
mDataInstMap.insert(enc_tbyte, {"tbyte", "tbyte", "tbyte"});
|
||||
mDataInstMap.insert(enc_oword, {"oword", "oword", "oword"});
|
||||
mDataInstMap.insert(enc_mmword, {"mmword", "mmword", "long long"});
|
||||
mDataInstMap.insert(enc_xmmword, {"xmmword", "xmmword", "_m128"});
|
||||
mDataInstMap.insert(enc_ymmword, {"ymmword", "ymmword", "_m256"});
|
||||
mDataInstMap.insert(enc_real4, {"real4", "real4", "float"});
|
||||
mDataInstMap.insert(enc_real8, {"real8", "real8", "double"});
|
||||
mDataInstMap.insert(enc_real10, {"real10", "real10", "long double"});
|
||||
mDataInstMap.insert(enc_ascii, {"ascii", "ascii", "string"});
|
||||
mDataInstMap.insert(enc_unicode, {"unicode", "unicode", "wstring"});
|
||||
}
|
||||
|
||||
void QBeaEngine::setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager)
|
||||
void QZydis::setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager)
|
||||
{
|
||||
mCodeFoldingManager = CodeFoldingManager;
|
||||
}
|
||||
|
||||
void QBeaEngine::UpdateConfig()
|
||||
void QZydis::UpdateConfig()
|
||||
{
|
||||
_bLongDataInst = ConfigBool("Disassembler", "LongDataInstruction");
|
||||
_tokenizer.UpdateConfig();
|
||||
mLongDataInst = ConfigBool("Disassembler", "LongDataInstruction");
|
||||
mTokenizer.UpdateConfig();
|
||||
}
|
||||
|
||||
void QZydis::UpdateArchitecture()
|
||||
{
|
||||
mTokenizer.UpdateArchitecture();
|
||||
}
|
||||
|
||||
void formatOpcodeString(const Instruction_t & inst, RichTextPainter::List & list, std::vector<std::pair<size_t, bool>> & realBytes)
|
|
@ -0,0 +1,80 @@
|
|||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
#include "ZydisTokenizer.h"
|
||||
|
||||
class EncodeMap;
|
||||
class CodeFoldingHelper;
|
||||
|
||||
struct Instruction_t
|
||||
{
|
||||
enum BranchType : uint8_t
|
||||
{
|
||||
None,
|
||||
Conditional,
|
||||
Unconditional,
|
||||
Call
|
||||
};
|
||||
|
||||
duint rva = 0;
|
||||
duint branchDestination = 0;
|
||||
int length = 0;
|
||||
uint8_t vectorElementType[4];
|
||||
uint8_t prefixSize = 0;
|
||||
uint8_t opcodeSize = 0;
|
||||
uint8_t group1Size = 0;
|
||||
uint8_t group2Size = 0;
|
||||
uint8_t group3Size = 0;
|
||||
BranchType branchType = None;
|
||||
|
||||
QString instStr;
|
||||
QByteArray dump;
|
||||
std::vector<std::pair<const char*, uint8_t>> regsReferenced;
|
||||
ZydisTokenizer::InstructionToken tokens;
|
||||
|
||||
Instruction_t()
|
||||
{
|
||||
memset(vectorElementType, 0, sizeof(vectorElementType));
|
||||
}
|
||||
};
|
||||
|
||||
class QZydis
|
||||
{
|
||||
public:
|
||||
QZydis(int maxModuleSize, Architecture* architecture);
|
||||
QZydis(const QZydis &) = delete;
|
||||
QZydis(QZydis &&) = delete;
|
||||
~QZydis();
|
||||
ulong DisassembleBack(const uint8_t* data, duint base, duint size, duint ip, int n);
|
||||
ulong DisassembleNext(const uint8_t* data, duint base, duint size, duint ip, int n);
|
||||
Instruction_t DisassembleAt(const uint8_t* data, duint size, duint origBase, duint origInstRVA, bool datainstr = true);
|
||||
Instruction_t DecodeDataAt(const uint8_t* data, duint size, duint origBase, duint origInstRVA, ENCODETYPE type);
|
||||
void setCodeFoldingManager(CodeFoldingHelper* CodeFoldingManager);
|
||||
void UpdateConfig();
|
||||
void UpdateArchitecture();
|
||||
|
||||
EncodeMap* getEncodeMap()
|
||||
{
|
||||
return mEncodeMap;
|
||||
}
|
||||
|
||||
private:
|
||||
struct DataInstructionInfo
|
||||
{
|
||||
QString shortName;
|
||||
QString longName;
|
||||
QString cName;
|
||||
};
|
||||
|
||||
void UpdateDataInstructionMap();
|
||||
|
||||
Architecture* mArchitecture = nullptr;
|
||||
ZydisTokenizer mTokenizer;
|
||||
QHash<ENCODETYPE, DataInstructionInfo> mDataInstMap;
|
||||
bool mLongDataInst = false;
|
||||
EncodeMap* mEncodeMap = nullptr;
|
||||
CodeFoldingHelper* mCodeFoldingManager = nullptr;
|
||||
};
|
||||
|
||||
void formatOpcodeString(const Instruction_t & inst, RichTextPainter::List & list, std::vector<std::pair<size_t, bool>> & realBytes);
|
|
@ -2,31 +2,35 @@
|
|||
#include "Configuration.h"
|
||||
#include "StringUtil.h"
|
||||
#include "CachedFontMetrics.h"
|
||||
#include "Bridge.h"
|
||||
|
||||
ZydisTokenizer::ZydisTokenizer(int maxModuleLength)
|
||||
: _maxModuleLength(maxModuleLength),
|
||||
_success(false),
|
||||
isNop(false),
|
||||
_mnemonicType(TokenType::Uncategorized)
|
||||
ZydisTokenizer::ZydisTokenizer(int maxModuleLength, Architecture* architecture)
|
||||
: mMaxModuleLength(maxModuleLength),
|
||||
mZydis(architecture->disasm64()),
|
||||
mArchitecture(architecture)
|
||||
{
|
||||
SetConfig(false, false, false, false, false, false, false, false, false);
|
||||
}
|
||||
|
||||
static ZydisTokenizer::TokenColor colorNamesMap[size_t(ZydisTokenizer::TokenType::Last)];
|
||||
QHash<QString, int> ZydisTokenizer::stringPoolMap;
|
||||
int ZydisTokenizer::poolId = 0;
|
||||
QHash<QString, int> ZydisTokenizer::gStringPool;
|
||||
int ZydisTokenizer::gPoolId = 0;
|
||||
|
||||
void ZydisTokenizer::addColorName(TokenType type, QString color, QString backgroundColor)
|
||||
{
|
||||
colorNamesMap[int(type)] = TokenColor(color, backgroundColor);
|
||||
}
|
||||
|
||||
ZydisTokenizer::TokenColor ZydisTokenizer::getTokenColor(TokenType type)
|
||||
{
|
||||
return colorNamesMap[(size_t)type];
|
||||
}
|
||||
|
||||
void ZydisTokenizer::addStringsToPool(const QString & strings)
|
||||
{
|
||||
QStringList stringList = strings.split(' ', QString::SkipEmptyParts);
|
||||
QStringList stringList = strings.split(' ', Qt::SkipEmptyParts);
|
||||
for(const QString & string : stringList)
|
||||
stringPoolMap.insert(string, poolId);
|
||||
poolId++;
|
||||
gStringPool.insert(string, gPoolId);
|
||||
gPoolId++;
|
||||
}
|
||||
|
||||
void ZydisTokenizer::UpdateColors()
|
||||
|
@ -72,8 +76,8 @@ void ZydisTokenizer::UpdateColors()
|
|||
|
||||
void ZydisTokenizer::UpdateStringPool()
|
||||
{
|
||||
poolId = 0;
|
||||
stringPoolMap.clear();
|
||||
gPoolId = 0;
|
||||
gStringPool.clear();
|
||||
// These registers must be in lower case.
|
||||
addStringsToPool("rax eax ax al ah");
|
||||
addStringsToPool("rbx ebx bx bl bh");
|
||||
|
@ -111,75 +115,75 @@ void ZydisTokenizer::UpdateStringPool()
|
|||
|
||||
bool ZydisTokenizer::Tokenize(duint addr, const unsigned char* data, int datasize, InstructionToken & instruction)
|
||||
{
|
||||
_inst = InstructionToken();
|
||||
mInst = InstructionToken();
|
||||
|
||||
_success = _cp.DisassembleSafe(addr, data, datasize);
|
||||
if(_success)
|
||||
mSuccess = mZydis.DisassembleSafe(addr, data, datasize);
|
||||
if(mSuccess)
|
||||
{
|
||||
if(!tokenizePrefix())
|
||||
return false;
|
||||
|
||||
isNop = _cp.IsNop();
|
||||
mIsNop = mZydis.IsNop();
|
||||
if(!tokenizeMnemonic())
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < _cp.OpCount(); i++)
|
||||
for(int i = 0; i < mZydis.OpCount(); i++)
|
||||
{
|
||||
if(i == 1 && _cp[0].size >= 128 && _cp[1].type == ZYDIS_OPERAND_TYPE_REGISTER
|
||||
&& ZydisRegisterGetClass(_cp[1].reg.value) == ZYDIS_REGCLASS_MASK)
|
||||
if(i == 1 && mZydis[0].size >= 128 && mZydis[1].type == ZYDIS_OPERAND_TYPE_REGISTER
|
||||
&& ZydisRegisterGetClass(mZydis[1].reg.value) == ZYDIS_REGCLASS_MASK)
|
||||
{
|
||||
if(_bArgumentSpaces)
|
||||
if(mArgumentSpaces)
|
||||
addToken(TokenType::ArgumentSpace, " ");
|
||||
addToken(TokenType::Comma, "{");
|
||||
if(!tokenizeOperand(_cp[i]))
|
||||
if(!tokenizeOperand(mZydis[i]))
|
||||
return false;
|
||||
addToken(TokenType::Comma, "}");
|
||||
}
|
||||
else if(i)
|
||||
{
|
||||
addToken(TokenType::Comma, ",");
|
||||
if(_bArgumentSpaces)
|
||||
if(mArgumentSpaces)
|
||||
addToken(TokenType::ArgumentSpace, " ");
|
||||
if(!tokenizeOperand(_cp[i]))
|
||||
if(!tokenizeOperand(mZydis[i]))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!tokenizeOperand(_cp[i]))
|
||||
if(!tokenizeOperand(mZydis[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isNop = false;
|
||||
mIsNop = false;
|
||||
addToken(TokenType::MnemonicUnusual, "???");
|
||||
}
|
||||
|
||||
if(_bNoHighlightOperands)
|
||||
if(mNoHighlightOperands)
|
||||
{
|
||||
while(_inst.tokens.size() && _inst.tokens[_inst.tokens.size() - 1].type == TokenType::Space)
|
||||
_inst.tokens.pop_back();
|
||||
for(SingleToken & token : _inst.tokens)
|
||||
token.type = _mnemonicType;
|
||||
while(mInst.tokens.size() && mInst.tokens[mInst.tokens.size() - 1].type == TokenType::Space)
|
||||
mInst.tokens.pop_back();
|
||||
for(SingleToken & token : mInst.tokens)
|
||||
token.type = mMnemonicType;
|
||||
}
|
||||
|
||||
instruction = _inst;
|
||||
instruction = mInst;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ZydisTokenizer::TokenizeData(const QString & datatype, const QString & data, InstructionToken & instruction)
|
||||
{
|
||||
_inst = InstructionToken();
|
||||
isNop = false;
|
||||
mInst = InstructionToken();
|
||||
mIsNop = false;
|
||||
|
||||
if(!tokenizeMnemonic(TokenType::MnemonicNormal, datatype))
|
||||
return false;
|
||||
|
||||
addToken(TokenType::Value, data);
|
||||
|
||||
instruction = _inst;
|
||||
instruction = mInst;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -213,40 +217,45 @@ void ZydisTokenizer::TokenizeTraceMemory(duint address, duint oldValue, duint ne
|
|||
|
||||
void ZydisTokenizer::UpdateConfig()
|
||||
{
|
||||
SetConfig(ConfigBool("Disassembler", "Uppercase"),
|
||||
ConfigBool("Disassembler", "TabbedMnemonic"),
|
||||
ConfigBool("Disassembler", "ArgumentSpaces"),
|
||||
ConfigBool("Disassembler", "HidePointerSizes"),
|
||||
ConfigBool("Disassembler", "HideNormalSegments"),
|
||||
ConfigBool("Disassembler", "MemorySpaces"),
|
||||
ConfigBool("Disassembler", "NoHighlightOperands"),
|
||||
ConfigBool("Disassembler", "NoCurrentModuleText"),
|
||||
ConfigBool("Disassembler", "0xPrefixValues"));
|
||||
_maxModuleLength = (int)ConfigUint("Disassembler", "MaxModuleSize");
|
||||
mUppercase = ConfigBool("Disassembler", "Uppercase");
|
||||
mTabbedMnemonic = ConfigBool("Disassembler", "TabbedMnemonic");
|
||||
mArgumentSpaces = ConfigBool("Disassembler", "ArgumentSpaces");
|
||||
mHidePointerSizes = ConfigBool("Disassembler", "HidePointerSizes");
|
||||
mHideNormalSegments = ConfigBool("Disassembler", "HideNormalSegments");
|
||||
mMemorySpaces = ConfigBool("Disassembler", "MemorySpaces");
|
||||
mNoHighlightOperands = ConfigBool("Disassembler", "NoHighlightOperands");
|
||||
mNoCurrentModuleText = ConfigBool("Disassembler", "NoCurrentModuleText");
|
||||
m0xPrefixValues = ConfigBool("Disassembler", "0xPrefixValues");
|
||||
mMaxModuleLength = (int)ConfigUint("Disassembler", "MaxModuleSize");
|
||||
UpdateStringPool();
|
||||
}
|
||||
|
||||
void ZydisTokenizer::UpdateArchitecture()
|
||||
{
|
||||
mZydis.Reset(mArchitecture->disasm64());
|
||||
}
|
||||
|
||||
void ZydisTokenizer::SetConfig(bool bUppercase, bool bTabbedMnemonic, bool bArgumentSpaces, bool bHidePointerSizes, bool bHideNormalSegments, bool bMemorySpaces, bool bNoHighlightOperands, bool bNoCurrentModuleText, bool b0xPrefixValues)
|
||||
{
|
||||
_bUppercase = bUppercase;
|
||||
_bTabbedMnemonic = bTabbedMnemonic;
|
||||
_bArgumentSpaces = bArgumentSpaces;
|
||||
_bHidePointerSizes = bHidePointerSizes;
|
||||
_bHideNormalSegments = bHideNormalSegments;
|
||||
_bMemorySpaces = bMemorySpaces;
|
||||
_bNoHighlightOperands = bNoHighlightOperands;
|
||||
_bNoCurrentModuleText = bNoCurrentModuleText;
|
||||
_b0xPrefixValues = b0xPrefixValues;
|
||||
mUppercase = bUppercase;
|
||||
mTabbedMnemonic = bTabbedMnemonic;
|
||||
mArgumentSpaces = bArgumentSpaces;
|
||||
mHidePointerSizes = bHidePointerSizes;
|
||||
mHideNormalSegments = bHideNormalSegments;
|
||||
mMemorySpaces = bMemorySpaces;
|
||||
mNoHighlightOperands = bNoHighlightOperands;
|
||||
mNoCurrentModuleText = bNoCurrentModuleText;
|
||||
m0xPrefixValues = b0xPrefixValues;
|
||||
}
|
||||
|
||||
int ZydisTokenizer::Size() const
|
||||
{
|
||||
return _success ? _cp.Size() : 1;
|
||||
return mSuccess ? mZydis.Size() : 1;
|
||||
}
|
||||
|
||||
const Zydis & ZydisTokenizer::GetZydis() const
|
||||
{
|
||||
return _cp;
|
||||
return mZydis;
|
||||
}
|
||||
|
||||
void ZydisTokenizer::TokenToRichText(const InstructionToken & instr, RichTextPainter::List & richTextList, const SingleToken* highlightToken)
|
||||
|
@ -312,17 +321,18 @@ bool ZydisTokenizer::IsHighlightableToken(const SingleToken & token)
|
|||
case TokenType::MemoryOperator:
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ZydisTokenizer::tokenTextPoolEquals(const QString & a, const QString & b)
|
||||
{
|
||||
if(a.compare(b, Qt::CaseInsensitive) == 0)
|
||||
return true;
|
||||
auto found1 = stringPoolMap.find(a.toLower());
|
||||
auto found2 = stringPoolMap.find(b.toLower());
|
||||
if(found1 == stringPoolMap.end() || found2 == stringPoolMap.end())
|
||||
auto found1 = gStringPool.find(a.toLower());
|
||||
auto found2 = gStringPool.find(b.toLower());
|
||||
if(found1 == gStringPool.end() || found2 == gStringPool.end())
|
||||
return false;
|
||||
return found1.value() == found2.value();
|
||||
}
|
||||
|
@ -353,9 +363,9 @@ void ZydisTokenizer::addToken(TokenType type, QString text, const TokenValue & v
|
|||
text = text.trimmed();
|
||||
break;
|
||||
}
|
||||
if(_bUppercase && !value.size)
|
||||
if(mUppercase && !value.size)
|
||||
text = text.toUpper();
|
||||
_inst.tokens.push_back(SingleToken(isNop ? TokenType::MnemonicNop : type, text, value));
|
||||
mInst.tokens.push_back(SingleToken(mIsNop ? TokenType::MnemonicNop : type, text, value));
|
||||
}
|
||||
|
||||
void ZydisTokenizer::addToken(TokenType type, const QString & text)
|
||||
|
@ -365,39 +375,39 @@ void ZydisTokenizer::addToken(TokenType type, const QString & text)
|
|||
|
||||
void ZydisTokenizer::addMemoryOperator(char operatorText)
|
||||
{
|
||||
if(_bMemorySpaces)
|
||||
if(mMemorySpaces)
|
||||
addToken(TokenType::MemoryOperatorSpace, " ");
|
||||
QString text;
|
||||
text += operatorText;
|
||||
addToken(TokenType::MemoryOperator, text);
|
||||
if(_bMemorySpaces)
|
||||
if(mMemorySpaces)
|
||||
addToken(TokenType::MemoryOperatorSpace, " ");
|
||||
}
|
||||
|
||||
QString ZydisTokenizer::printValue(const TokenValue & value, bool expandModule, int maxModuleLength) const
|
||||
QString ZydisTokenizer::printValue(const TokenValue & value, bool expandModule) const
|
||||
{
|
||||
QString labelText;
|
||||
char label_[MAX_LABEL_SIZE] = "";
|
||||
char module_[MAX_MODULE_SIZE] = "";
|
||||
char label[MAX_LABEL_SIZE] = "";
|
||||
char module[MAX_MODULE_SIZE] = "";
|
||||
QString moduleText;
|
||||
duint addr = value.value;
|
||||
bool bHasLabel = DbgGetLabelAt(addr, SEG_DEFAULT, label_);
|
||||
labelText = QString(label_);
|
||||
bool bHasLabel = DbgGetLabelAt(addr, SEG_DEFAULT, label);
|
||||
labelText = QString(label);
|
||||
bool bHasModule;
|
||||
if(_bNoCurrentModuleText)
|
||||
if(mNoCurrentModuleText)
|
||||
{
|
||||
duint size, base;
|
||||
base = DbgMemFindBaseAddr(this->GetZydis().Address(), &size);
|
||||
if(addr >= base && addr < base + size)
|
||||
bHasModule = false;
|
||||
else
|
||||
bHasModule = (expandModule && DbgGetModuleAt(addr, module_) && !QString(labelText).startsWith("JMP.&"));
|
||||
bHasModule = (expandModule && DbgGetModuleAt(addr, module) && !QString(labelText).startsWith("JMP.&"));
|
||||
}
|
||||
else
|
||||
bHasModule = (expandModule && DbgGetModuleAt(addr, module_) && !QString(labelText).startsWith("JMP.&"));
|
||||
moduleText = QString(module_);
|
||||
if(maxModuleLength != -1)
|
||||
moduleText.truncate(maxModuleLength);
|
||||
bHasModule = (expandModule && DbgGetModuleAt(addr, module) && !QString(labelText).startsWith("JMP.&"));
|
||||
moduleText = QString(module);
|
||||
if(mMaxModuleLength != -1)
|
||||
moduleText.truncate(mMaxModuleLength);
|
||||
if(moduleText.length())
|
||||
moduleText += ".";
|
||||
QString addrText = ToHexString(addr);
|
||||
|
@ -408,7 +418,7 @@ QString ZydisTokenizer::printValue(const TokenValue & value, bool expandModule,
|
|||
finalText = QString("%1%2").arg(moduleText).arg(addrText);
|
||||
else if(bHasLabel) //<label>
|
||||
finalText = QString("<%1>").arg(labelText);
|
||||
else if(_b0xPrefixValues)
|
||||
else if(m0xPrefixValues)
|
||||
finalText = QString("0x") + addrText;
|
||||
else
|
||||
finalText = addrText;
|
||||
|
@ -417,70 +427,69 @@ QString ZydisTokenizer::printValue(const TokenValue & value, bool expandModule,
|
|||
|
||||
bool ZydisTokenizer::tokenizePrefix()
|
||||
{
|
||||
//TODO: what happens with multiple prefixes?
|
||||
bool hasPrefix = true;
|
||||
QStringList prefixText;
|
||||
|
||||
auto attr = _cp.GetInstr()->attributes;
|
||||
|
||||
if(attr & ZYDIS_ATTRIB_HAS_LOCK)
|
||||
prefixText += "lock";
|
||||
else if(attr & ZYDIS_ATTRIB_HAS_REP)
|
||||
prefixText += "rep";
|
||||
else if(attr & ZYDIS_ATTRIB_HAS_REPE)
|
||||
prefixText += "repe";
|
||||
else if(attr & ZYDIS_ATTRIB_HAS_REPNE)
|
||||
prefixText += "repne";
|
||||
else if(attr & ZYDIS_ATTRIB_HAS_BOUND)
|
||||
prefixText += "bnd";
|
||||
else if(attr & ZYDIS_ATTRIB_HAS_XACQUIRE)
|
||||
prefixText += "xacquire";
|
||||
else if(attr & ZYDIS_ATTRIB_HAS_XRELEASE)
|
||||
prefixText += "xrelease";
|
||||
else
|
||||
hasPrefix = false;
|
||||
|
||||
if(hasPrefix)
|
||||
auto addPrefix = [this](const QString & prefix)
|
||||
{
|
||||
addToken(TokenType::Prefix, prefixText.join(' '));
|
||||
addToken(TokenType::Prefix, prefix);
|
||||
addToken(TokenType::Space, " ");
|
||||
}
|
||||
};
|
||||
|
||||
auto attr = mZydis.GetInstr()->info.attributes;
|
||||
if(attr & ZYDIS_ATTRIB_HAS_LOCK)
|
||||
addPrefix("lock");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_REP)
|
||||
addPrefix("rep");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_REPE)
|
||||
addPrefix("repe");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_REPNE)
|
||||
addPrefix("repne");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_BND)
|
||||
addPrefix("bnd");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_XACQUIRE)
|
||||
addPrefix("xacquire");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_XRELEASE)
|
||||
addPrefix("xrelease");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN)
|
||||
addPrefix("unlikely");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_BRANCH_TAKEN)
|
||||
addPrefix("likely");
|
||||
if(attr & ZYDIS_ATTRIB_HAS_NOTRACK)
|
||||
addPrefix("notrack");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ZydisTokenizer::tokenizeMnemonic()
|
||||
{
|
||||
QString mnemonic = QString(_cp.Mnemonic().c_str());
|
||||
_mnemonicType = TokenType::MnemonicNormal;
|
||||
QString mnemonic = QString(mZydis.Mnemonic().c_str());
|
||||
mMnemonicType = TokenType::MnemonicNormal;
|
||||
|
||||
if(_cp.IsBranchType(Zydis::BTFar))
|
||||
if(mZydis.IsBranchType(Zydis::BTFar))
|
||||
mnemonic += " far";
|
||||
|
||||
if(isNop)
|
||||
_mnemonicType = TokenType::MnemonicNop;
|
||||
else if(_cp.IsInt3())
|
||||
_mnemonicType = TokenType::MnemonicInt3;
|
||||
else if(_cp.IsUnusual())
|
||||
_mnemonicType = TokenType::MnemonicUnusual;
|
||||
else if(_cp.IsBranchType(Zydis::BTCallSem))
|
||||
_mnemonicType = TokenType::MnemonicCall;
|
||||
else if(_cp.IsBranchType(Zydis::BTCondJmpSem))
|
||||
_mnemonicType = TokenType::MnemonicCondJump;
|
||||
else if(_cp.IsBranchType(Zydis::BTUncondJmpSem))
|
||||
_mnemonicType = TokenType::MnemonicUncondJump;
|
||||
else if(_cp.IsBranchType(Zydis::BTRetSem))
|
||||
_mnemonicType = TokenType::MnemonicRet;
|
||||
else if(_cp.IsPushPop())
|
||||
_mnemonicType = TokenType::MnemonicPushPop;
|
||||
if(mIsNop)
|
||||
mMnemonicType = TokenType::MnemonicNop;
|
||||
else if(mZydis.IsInt3())
|
||||
mMnemonicType = TokenType::MnemonicInt3;
|
||||
else if(mZydis.IsUnusual())
|
||||
mMnemonicType = TokenType::MnemonicUnusual;
|
||||
else if(mZydis.IsBranchType(Zydis::BTCallSem))
|
||||
mMnemonicType = TokenType::MnemonicCall;
|
||||
else if(mZydis.IsBranchType(Zydis::BTCondJmpSem))
|
||||
mMnemonicType = TokenType::MnemonicCondJump;
|
||||
else if(mZydis.IsBranchType(Zydis::BTUncondJmpSem))
|
||||
mMnemonicType = TokenType::MnemonicUncondJump;
|
||||
else if(mZydis.IsBranchType(Zydis::BTRetSem))
|
||||
mMnemonicType = TokenType::MnemonicRet;
|
||||
else if(mZydis.IsPushPop())
|
||||
mMnemonicType = TokenType::MnemonicPushPop;
|
||||
|
||||
return tokenizeMnemonic(_mnemonicType, mnemonic);
|
||||
return tokenizeMnemonic(mMnemonicType, mnemonic);
|
||||
}
|
||||
|
||||
bool ZydisTokenizer::tokenizeMnemonic(TokenType type, const QString & mnemonic)
|
||||
{
|
||||
addToken(type, mnemonic);
|
||||
if(_bTabbedMnemonic)
|
||||
if(mTabbedMnemonic)
|
||||
{
|
||||
int spaceCount = 7 - mnemonic.length();
|
||||
if(spaceCount > 0)
|
||||
|
@ -534,12 +543,14 @@ bool ZydisTokenizer::tokenizeRegOperand(const ZydisDecodedOperand & op)
|
|||
case ZYDIS_REGCLASS_MASK:
|
||||
registerType = TokenType::ZmmRegister;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(reg.value == ArchValue(ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS))
|
||||
if(reg.value == (mArchitecture->disasm64() ? ZYDIS_REGISTER_GS : ZYDIS_REGISTER_FS))
|
||||
registerType = TokenType::MnemonicUnusual;
|
||||
|
||||
addToken(registerType, _cp.RegName(reg.value));
|
||||
addToken(registerType, mZydis.RegName(reg.value));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -547,20 +558,20 @@ bool ZydisTokenizer::tokenizeImmOperand(const ZydisDecodedOperand & op)
|
|||
{
|
||||
duint value;
|
||||
TokenType valueType;
|
||||
if(_cp.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTLoop | Zydis::BTXbegin))
|
||||
if(mZydis.IsBranchType(Zydis::BTJmp | Zydis::BTCall | Zydis::BTLoop | Zydis::BTXbegin))
|
||||
{
|
||||
valueType = TokenType::Address;
|
||||
value = op.imm.value.u;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto opsize = _cp.GetInstr()->operandWidth;
|
||||
auto opsize = mZydis.GetInstr()->info.operand_width;
|
||||
valueType = TokenType::Value;
|
||||
value = duint(op.imm.value.u) & (duint(-1) >> (sizeof(duint) * 8 - opsize));
|
||||
|
||||
}
|
||||
auto tokenValue = TokenValue(op.size / 8, value);
|
||||
addToken(valueType, printValue(tokenValue, true, _maxModuleLength), tokenValue);
|
||||
addToken(valueType, printValue(tokenValue, true), tokenValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -569,9 +580,9 @@ bool ZydisTokenizer::tokenizeMemOperand(const ZydisDecodedOperand & op)
|
|||
auto opsize = op.size / 8;
|
||||
|
||||
//memory size
|
||||
if(!_bHidePointerSizes)
|
||||
if(!mHidePointerSizes)
|
||||
{
|
||||
const char* sizeText = _cp.MemSizeName(opsize);
|
||||
const char* sizeText = mZydis.MemSizeName(opsize);
|
||||
if(sizeText)
|
||||
{
|
||||
addToken(TokenType::MemorySize, QString(sizeText) + " ptr");
|
||||
|
@ -583,11 +594,11 @@ bool ZydisTokenizer::tokenizeMemOperand(const ZydisDecodedOperand & op)
|
|||
|
||||
//memory segment
|
||||
bool bUnusualSegment = (mem.segment == ZYDIS_REGISTER_FS || mem.segment == ZYDIS_REGISTER_GS);
|
||||
if(!_bHideNormalSegments || bUnusualSegment)
|
||||
if(!mHideNormalSegments || bUnusualSegment)
|
||||
{
|
||||
auto segmentType = mem.segment == ArchValue(ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS)
|
||||
auto segmentType = mem.segment == (mArchitecture->disasm64() ? ZYDIS_REGISTER_GS : ZYDIS_REGISTER_FS)
|
||||
? TokenType::MnemonicUnusual : TokenType::MemorySegment;
|
||||
addToken(segmentType, _cp.RegName(mem.segment));
|
||||
addToken(segmentType, mZydis.RegName(mem.segment));
|
||||
addToken(TokenType::Uncategorized, ":");
|
||||
}
|
||||
|
||||
|
@ -608,28 +619,28 @@ bool ZydisTokenizer::tokenizeMemOperand(const ZydisDecodedOperand & op)
|
|||
//stuff inside the brackets
|
||||
if(mem.base == ZYDIS_REGISTER_RIP) //rip-relative (#replacement)
|
||||
{
|
||||
duint addr = _cp.Address() + duint(mem.disp.value) + _cp.Size();
|
||||
duint addr = mZydis.Address() + duint(mem.disp.value) + mZydis.Size();
|
||||
TokenValue value = TokenValue(opsize, addr);
|
||||
auto displacementType = DbgMemIsValidReadPtr(addr) ? TokenType::Address : TokenType::Value;
|
||||
addToken(displacementType, printValue(value, false, _maxModuleLength), value);
|
||||
addToken(displacementType, printValue(value, false), value);
|
||||
}
|
||||
else //#base + #index * #scale + #displacement
|
||||
{
|
||||
bool prependPlus = false;
|
||||
if(mem.base != ZYDIS_REGISTER_NONE) //base register
|
||||
{
|
||||
addToken(TokenType::MemoryBaseRegister, _cp.RegName(mem.base));
|
||||
addToken(TokenType::MemoryBaseRegister, mZydis.RegName(mem.base));
|
||||
prependPlus = true;
|
||||
}
|
||||
if(mem.index != ZYDIS_REGISTER_NONE) //index register
|
||||
{
|
||||
if(prependPlus)
|
||||
addMemoryOperator('+');
|
||||
addToken(TokenType::MemoryIndexRegister, _cp.RegName(mem.index));
|
||||
addToken(TokenType::MemoryIndexRegister, mZydis.RegName(mem.index));
|
||||
if(mem.scale > 1)
|
||||
{
|
||||
addMemoryOperator('*');
|
||||
addToken(TokenType::MemoryScale, QString().sprintf("%d", mem.scale));
|
||||
addToken(TokenType::MemoryScale, QString("%1").arg(mem.scale));
|
||||
}
|
||||
prependPlus = true;
|
||||
}
|
||||
|
@ -642,10 +653,10 @@ bool ZydisTokenizer::tokenizeMemOperand(const ZydisDecodedOperand & op)
|
|||
if(mem.disp.value < 0 && prependPlus)
|
||||
{
|
||||
operatorText = '-';
|
||||
valueText = printValue(TokenValue(opsize, duint(mem.disp.value * -1)), false, _maxModuleLength);
|
||||
valueText = printValue(TokenValue(opsize, duint(mem.disp.value * -1)), false);
|
||||
}
|
||||
else
|
||||
valueText = printValue(value, false, _maxModuleLength);
|
||||
valueText = printValue(value, false);
|
||||
if(prependPlus)
|
||||
addMemoryOperator(operatorText);
|
||||
addToken(displacementType, valueText, value);
|
||||
|
@ -662,12 +673,12 @@ bool ZydisTokenizer::tokenizeMemOperand(const ZydisDecodedOperand & op)
|
|||
bool ZydisTokenizer::tokenizePtrOperand(const ZydisDecodedOperand & op)
|
||||
{
|
||||
auto segValue = TokenValue(2, op.ptr.segment);
|
||||
addToken(TokenType::MemorySegment, printValue(segValue, true, _maxModuleLength), segValue);
|
||||
addToken(TokenType::MemorySegment, printValue(segValue, true), segValue);
|
||||
|
||||
addToken(TokenType::Uncategorized, ":");
|
||||
|
||||
auto offsetValue = TokenValue(_cp.GetInstr()->operandWidth / 8, op.ptr.offset);
|
||||
addToken(TokenType::Address, printValue(offsetValue, true, _maxModuleLength), offsetValue);
|
||||
auto offsetValue = TokenValue(mZydis.GetInstr()->info.operand_width / 8, op.ptr.offset);
|
||||
addToken(TokenType::Address, printValue(offsetValue, true), offsetValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <map>
|
||||
#include <QHash>
|
||||
#include <QtCore>
|
||||
#include "Architecture.h"
|
||||
|
||||
class ZydisTokenizer
|
||||
{
|
||||
|
@ -109,13 +110,7 @@ public:
|
|||
struct InstructionToken
|
||||
{
|
||||
std::vector<SingleToken> tokens; //list of tokens that form the instruction
|
||||
int x; //x of the first character
|
||||
|
||||
InstructionToken()
|
||||
{
|
||||
tokens.clear();
|
||||
x = 0;
|
||||
}
|
||||
int x = 0; //x of the first character
|
||||
};
|
||||
|
||||
struct TokenColor
|
||||
|
@ -152,10 +147,11 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
ZydisTokenizer(int maxModuleLength);
|
||||
ZydisTokenizer(int maxModuleLength, Architecture* architecture);
|
||||
bool Tokenize(duint addr, const unsigned char* data, int datasize, InstructionToken & instruction);
|
||||
bool TokenizeData(const QString & datatype, const QString & data, InstructionToken & instruction);
|
||||
void UpdateConfig();
|
||||
void UpdateArchitecture();
|
||||
void SetConfig(bool bUppercase, bool bTabbedMnemonic, bool bArgumentSpaces, bool bHidePointerSizes, bool bHideNormalSegments, bool bMemorySpaces, bool bNoHighlightOperands, bool bNoCurrentModuleText, bool b0xPrefixValues);
|
||||
int Size() const;
|
||||
const Zydis & GetZydis() const;
|
||||
|
@ -169,35 +165,37 @@ public:
|
|||
static void addColorName(TokenType type, QString color, QString backgroundColor);
|
||||
static void addStringsToPool(const QString & regs);
|
||||
static bool tokenTextPoolEquals(const QString & a, const QString & b);
|
||||
static TokenColor getTokenColor(TokenType type);
|
||||
|
||||
static void TokenizeTraceRegister(const char* reg, duint oldValue, duint newValue, std::vector<SingleToken> & tokens);
|
||||
static void TokenizeTraceMemory(duint address, duint oldValue, duint newValue, std::vector<SingleToken> & tokens);
|
||||
|
||||
|
||||
private:
|
||||
Zydis _cp;
|
||||
bool isNop;
|
||||
InstructionToken _inst;
|
||||
bool _success;
|
||||
int _maxModuleLength;
|
||||
bool _bUppercase;
|
||||
bool _bTabbedMnemonic;
|
||||
bool _bArgumentSpaces;
|
||||
bool _bHidePointerSizes;
|
||||
bool _bHideNormalSegments;
|
||||
bool _bMemorySpaces;
|
||||
bool _bNoHighlightOperands;
|
||||
bool _bNoCurrentModuleText;
|
||||
bool _b0xPrefixValues;
|
||||
TokenType _mnemonicType;
|
||||
Architecture* mArchitecture;
|
||||
Zydis mZydis;
|
||||
bool mSuccess = false;
|
||||
bool mIsNop = false;
|
||||
InstructionToken mInst;
|
||||
TokenType mMnemonicType = TokenType::Uncategorized;
|
||||
int mMaxModuleLength = -1;
|
||||
bool mUppercase = false;
|
||||
bool mTabbedMnemonic = false;
|
||||
bool mArgumentSpaces = false;
|
||||
bool mHidePointerSizes = false;
|
||||
bool mHideNormalSegments = false;
|
||||
bool mMemorySpaces = false;
|
||||
bool mNoHighlightOperands = false;
|
||||
bool mNoCurrentModuleText = false;
|
||||
bool m0xPrefixValues = false;
|
||||
|
||||
void addToken(TokenType type, QString text, const TokenValue & value);
|
||||
void addToken(TokenType type, const QString & text);
|
||||
void addMemoryOperator(char operatorText);
|
||||
QString printValue(const TokenValue & value, bool expandModule, int maxModuleLength) const;
|
||||
QString printValue(const TokenValue & value, bool expandModule) const;
|
||||
|
||||
static QHash<QString, int> stringPoolMap;
|
||||
static int poolId;
|
||||
static QHash<QString, int> gStringPool;
|
||||
static int gPoolId;
|
||||
|
||||
bool tokenizePrefix();
|
||||
bool tokenizeMnemonic();
|
||||
|
|
|
@ -14,7 +14,7 @@ class AboutDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AboutDialog(UpdateChecker* updateChecker, QWidget* parent = 0);
|
||||
explicit AboutDialog(UpdateChecker* updateChecker, QWidget* parent = nullptr);
|
||||
~AboutDialog();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -431,7 +431,7 @@ void AppearanceDialog::colorInfoListInit()
|
|||
colorInfoListCategory(tr("General Tables:"), "AbstractTableViewBackgroundColor", "AbstractTableView");
|
||||
colorInfoListAppend(tr("Background"), "AbstractTableViewBackgroundColor", "");
|
||||
colorInfoListAppend(tr("Selection"), "AbstractTableViewSelectionColor", "");
|
||||
colorInfoListAppend(tr("Header Text"), "AbstractTableViewHeaderTextColor", "");
|
||||
colorInfoListAppend(tr("Header"), "AbstractTableViewHeaderTextColor", "AbstractTableViewHeaderBackgroundColor");
|
||||
colorInfoListAppend(tr("Text"), "AbstractTableViewTextColor", "");
|
||||
colorInfoListAppend(tr("Separators"), "AbstractTableViewSeparatorColor", "");
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class AppearanceDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AppearanceDialog(QWidget* parent = 0);
|
||||
explicit AppearanceDialog(QWidget* parent = nullptr);
|
||||
~AppearanceDialog();
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -34,14 +34,14 @@ AssembleDialog::AssembleDialog(QWidget* parent) :
|
|||
ui->radioAsmjit->setChecked(true);
|
||||
}
|
||||
|
||||
Config()->setupWindowPos(this);
|
||||
Config()->loadWindowGeometry(this);
|
||||
}
|
||||
|
||||
AssembleDialog::~AssembleDialog()
|
||||
{
|
||||
mValidateThread->stop();
|
||||
mValidateThread->wait();
|
||||
Config()->saveWindowPos(this);
|
||||
Config()->saveWindowGeometry(this);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class AssembleDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AssembleDialog(QWidget* parent = 0);
|
||||
explicit AssembleDialog(QWidget* parent = nullptr);
|
||||
~AssembleDialog();
|
||||
QString editText;
|
||||
static bool bWarningShowedOnce;
|
||||
|
|
|
@ -47,7 +47,7 @@ AttachDialog::AttachDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Attach
|
|||
// Highlight the search box
|
||||
mSearchListView->mCurList->setFocus();
|
||||
|
||||
Config()->setupWindowPos(this);
|
||||
Config()->loadWindowGeometry(this);
|
||||
|
||||
// Populate the process list atleast once
|
||||
refresh();
|
||||
|
@ -55,7 +55,7 @@ AttachDialog::AttachDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Attach
|
|||
|
||||
AttachDialog::~AttachDialog()
|
||||
{
|
||||
Config()->saveWindowPos(this);
|
||||
Config()->saveWindowGeometry(this);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ retryFindWindow:
|
|||
refresh();
|
||||
QString pidText = QString().sprintf(ConfigBool("Gui", "PidTidInHex") ? "%.8X" : "%u", pid);
|
||||
bool found = false;
|
||||
for(int i = 0; i < mSearchListView->mCurList->getRowCount(); i++)
|
||||
for(duint i = 0; i < mSearchListView->mCurList->getRowCount(); i++)
|
||||
{
|
||||
if(mSearchListView->mCurList->getCellContent(i, ColPid) == pidText)
|
||||
{
|
||||
|
@ -138,12 +138,12 @@ retryFindWindow:
|
|||
}
|
||||
}
|
||||
|
||||
void AttachDialog::processListContextMenu(QMenu* wMenu)
|
||||
void AttachDialog::processListContextMenu(QMenu* menu)
|
||||
{
|
||||
// Don't show menu options if nothing is listed
|
||||
if(!mSearchListView->mCurList->getRowCount())
|
||||
return;
|
||||
|
||||
wMenu->addAction(mAttachAction);
|
||||
wMenu->addAction(mRefreshAction);
|
||||
menu->addAction(mAttachAction);
|
||||
menu->addAction(mRefreshAction);
|
||||
}
|
||||
|
|
|
@ -16,14 +16,14 @@ class AttachDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AttachDialog(QWidget* parent = 0);
|
||||
explicit AttachDialog(QWidget* parent = nullptr);
|
||||
~AttachDialog();
|
||||
|
||||
private slots:
|
||||
void on_btnAttach_clicked();
|
||||
void on_btnFindWindow_clicked();
|
||||
void refresh();
|
||||
void processListContextMenu(QMenu* wMenu);
|
||||
void processListContextMenu(QMenu* menu);
|
||||
|
||||
private:
|
||||
Ui::AttachDialog* ui;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Bridge.h"
|
||||
#include "MenuBuilder.h"
|
||||
#include "Breakpoints.h"
|
||||
#include "DisassemblyPopup.h"
|
||||
|
||||
BreakpointsView::BreakpointsView(QWidget* parent)
|
||||
: StdTable(parent), mExceptionMaxLength(0)
|
||||
|
@ -22,14 +23,14 @@ BreakpointsView::BreakpointsView(QWidget* parent)
|
|||
addColumnAt(0, tr("Summary"), true);
|
||||
loadColumnFromConfig("BreakpointsView");
|
||||
|
||||
mDisasm = new QBeaEngine(ConfigUint("Disassembler", "MaxModuleSize"));
|
||||
mDisasm = new QZydis(ConfigUint("Disassembler", "MaxModuleSize"), Bridge::getArchitecture());
|
||||
mDisasm->UpdateConfig();
|
||||
enableMultiSelection(true);
|
||||
|
||||
setupContextMenu();
|
||||
|
||||
connect(Bridge::getBridge(), SIGNAL(updateBreakpoints()), this, SLOT(updateBreakpointsSlot()));
|
||||
connect(Bridge::getBridge(), SIGNAL(disassembleAt(dsint, dsint)), this, SLOT(disassembleAtSlot(dsint, dsint)));
|
||||
connect(Bridge::getBridge(), SIGNAL(disassembleAt(duint, duint)), this, SLOT(disassembleAtSlot(duint, duint)));
|
||||
connect(Config(), SIGNAL(tokenizerConfigUpdated()), this, SLOT(tokenizerConfigUpdatedSlot()));
|
||||
|
||||
connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint)));
|
||||
|
@ -37,6 +38,8 @@ BreakpointsView::BreakpointsView(QWidget* parent)
|
|||
connect(this, SIGNAL(enterPressedSignal()), this, SLOT(followBreakpointSlot()));
|
||||
|
||||
Initialize();
|
||||
|
||||
new DisassemblyPopup(this, Bridge::getArchitecture());
|
||||
}
|
||||
|
||||
void BreakpointsView::setupContextMenu()
|
||||
|
@ -139,7 +142,7 @@ void BreakpointsView::updateColors()
|
|||
updateBreakpointsSlot();
|
||||
}
|
||||
|
||||
void BreakpointsView::sortRows(int column, bool ascending)
|
||||
void BreakpointsView::sortRows(duint column, bool ascending)
|
||||
{
|
||||
std::stable_sort(mData.begin(), mData.end(), [this, column, ascending](const std::vector<CellData> & a, const std::vector<CellData> & b)
|
||||
{
|
||||
|
@ -161,15 +164,15 @@ void BreakpointsView::sortRows(int column, bool ascending)
|
|||
});
|
||||
}
|
||||
|
||||
QString BreakpointsView::paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
QString BreakpointsView::paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h)
|
||||
{
|
||||
if(isSelected(rowBase, rowOffset))
|
||||
if(isSelected(row))
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(col == ColDisasm ? mDisasmSelectionColor : mSelectionColor));
|
||||
else if(col == ColDisasm)
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(mDisasmBackgroundColor));
|
||||
auto index = bpIndex(rowBase + rowOffset);
|
||||
auto index = bpIndex(row);
|
||||
auto & bp = mBps.at(index);
|
||||
auto cellContent = getCellContent(rowBase + rowOffset, col);
|
||||
auto cellContent = getCellContent(row, col);
|
||||
if(col > ColType && !bp.addr && !bp.active)
|
||||
{
|
||||
auto mid = h / 2.0;
|
||||
|
@ -556,7 +559,7 @@ void BreakpointsView::updateBreakpointsSlot()
|
|||
reloadData();
|
||||
}
|
||||
|
||||
void BreakpointsView::disassembleAtSlot(dsint addr, dsint cip)
|
||||
void BreakpointsView::disassembleAtSlot(duint addr, duint cip)
|
||||
{
|
||||
Q_UNUSED(addr);
|
||||
mCip = cip;
|
||||
|
@ -570,10 +573,10 @@ void BreakpointsView::tokenizerConfigUpdatedSlot()
|
|||
|
||||
void BreakpointsView::contextMenuSlot(const QPoint & pos)
|
||||
{
|
||||
QMenu wMenu(this);
|
||||
mMenuBuilder->build(&wMenu);
|
||||
if(!wMenu.actions().isEmpty())
|
||||
wMenu.exec(mapToGlobal(pos));
|
||||
QMenu menu(this);
|
||||
mMenuBuilder->build(&menu);
|
||||
if(!menu.actions().isEmpty())
|
||||
menu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void BreakpointsView::followBreakpointSlot()
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <QWidget>
|
||||
#include "Bridge.h"
|
||||
#include "StdTable.h"
|
||||
#include "QBeaEngine.h"
|
||||
#include "QZydis.h"
|
||||
|
||||
class MenuBuilder;
|
||||
|
||||
|
@ -11,17 +11,17 @@ class BreakpointsView : public StdTable
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BreakpointsView(QWidget* parent = 0);
|
||||
explicit BreakpointsView(QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
void setupContextMenu();
|
||||
void updateColors() override;
|
||||
void sortRows(int column, bool ascending) override;
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h) override;
|
||||
void sortRows(duint column, bool ascending) override;
|
||||
QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override;
|
||||
|
||||
private slots:
|
||||
void updateBreakpointsSlot();
|
||||
void disassembleAtSlot(dsint addr, dsint cip);
|
||||
void disassembleAtSlot(duint addr, duint cip);
|
||||
void tokenizerConfigUpdatedSlot();
|
||||
void contextMenuSlot(const QPoint & pos);
|
||||
void followBreakpointSlot();
|
||||
|
@ -64,7 +64,7 @@ private:
|
|||
duint mCip = 0;
|
||||
MenuBuilder* mMenuBuilder;
|
||||
QAction* mEnableDisableAction;
|
||||
QBeaEngine* mDisasm;
|
||||
QZydis* mDisasm;
|
||||
|
||||
const int bpIndex(int i) const
|
||||
{
|
||||
|
|
|
@ -28,12 +28,12 @@ BrowseDialog::BrowseDialog(QWidget* parent, const QString & title, const QString
|
|||
QCompleter* completer = new QCompleter(ui->lineEdit);
|
||||
completer->setModel(new QDirModel(completer));
|
||||
ui->lineEdit->setCompleter(completer);
|
||||
Config()->setupWindowPos(this);
|
||||
Config()->loadWindowGeometry(this);
|
||||
}
|
||||
|
||||
BrowseDialog::~BrowseDialog()
|
||||
{
|
||||
Config()->saveWindowPos(this);
|
||||
Config()->saveWindowGeometry(this);
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,10 @@
|
|||
#include "Configuration.h"
|
||||
#include "Bridge.h"
|
||||
|
||||
CPUArgumentWidget::CPUArgumentWidget(QWidget* parent) :
|
||||
CPUArgumentWidget::CPUArgumentWidget(Architecture* architecture, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::CPUArgumentWidget),
|
||||
mTable(nullptr),
|
||||
mCurrentCallingConvention(-1),
|
||||
mStackOffset(0),
|
||||
mAllowUpdate(true)
|
||||
mArchitecture(architecture)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
mTable = ui->table;
|
||||
|
@ -32,7 +29,7 @@ CPUArgumentWidget::CPUArgumentWidget(QWidget* parent) :
|
|||
connect(mFollowAddrStack, SIGNAL(triggered()), this, SLOT(followStackSlot()));
|
||||
|
||||
connect(Bridge::getBridge(), SIGNAL(repaintTableView()), this, SLOT(refreshData()));
|
||||
connect(Bridge::getBridge(), SIGNAL(disassembleAt(dsint, dsint)), this, SLOT(disassembleAtSlot(dsint, dsint)));
|
||||
connect(Bridge::getBridge(), SIGNAL(disassembleAt(duint, duint)), this, SLOT(disassembleAtSlot(duint, duint)));
|
||||
}
|
||||
|
||||
CPUArgumentWidget::~CPUArgumentWidget()
|
||||
|
@ -46,7 +43,7 @@ void CPUArgumentWidget::updateStackOffset(bool iscall)
|
|||
mStackOffset = cur.getStackOffset() + (iscall ? 0 : cur.getCallOffset());
|
||||
}
|
||||
|
||||
void CPUArgumentWidget::disassembleAtSlot(dsint addr, dsint cip)
|
||||
void CPUArgumentWidget::disassembleAtSlot(duint addr, duint cip)
|
||||
{
|
||||
Q_UNUSED(addr);
|
||||
if(mCurrentCallingConvention == -1) //no calling conventions
|
||||
|
@ -120,12 +117,12 @@ void CPUArgumentWidget::refreshData()
|
|||
mTable->reloadData();
|
||||
}
|
||||
|
||||
static void configAction(QMenu & wMenu, const QIcon & icon, QAction* action, const QString & value, const QString & name)
|
||||
static void configAction(QMenu & menu, const QIcon & icon, QAction* action, const QString & value, const QString & name)
|
||||
{
|
||||
action->setText(QApplication::translate("CPUArgumentWidget", "Follow %1 in %2").arg(value).arg(name));
|
||||
action->setIcon(icon);
|
||||
action->setObjectName(value);
|
||||
wMenu.addAction(action);
|
||||
menu.addAction(action);
|
||||
}
|
||||
|
||||
void CPUArgumentWidget::contextMenuSlot(QPoint pos)
|
||||
|
@ -136,7 +133,7 @@ void CPUArgumentWidget::contextMenuSlot(QPoint pos)
|
|||
if(int(mArgumentValues.size()) <= selection)
|
||||
return;
|
||||
auto value = mArgumentValues[selection];
|
||||
QMenu wMenu(this);
|
||||
QMenu menu(this);
|
||||
if(DbgMemIsValidReadPtr(value))
|
||||
{
|
||||
duint valueAddr;
|
||||
|
@ -152,27 +149,27 @@ void CPUArgumentWidget::contextMenuSlot(QPoint pos)
|
|||
return addr >= base && addr < base + size;
|
||||
};
|
||||
|
||||
configAction(wMenu, DIcon(ArchValue("processor32", "processor64")), mFollowDisasm, valueText, tr("Disassembler"));
|
||||
configAction(wMenu, DIcon("dump"), mFollowDump, valueText, tr("Dump"));
|
||||
configAction(menu, DIcon(ArchValue("processor32", "processor64")), mFollowDisasm, valueText, tr("Disassembler"));
|
||||
configAction(menu, DIcon("dump"), mFollowDump, valueText, tr("Dump"));
|
||||
if(inStackRange(value))
|
||||
configAction(wMenu, DIcon("stack"), mFollowStack, valueText, tr("Stack"));
|
||||
configAction(menu, DIcon("stack"), mFollowStack, valueText, tr("Stack"));
|
||||
if(DbgMemIsValidReadPtr(valueAddr))
|
||||
{
|
||||
configAction(wMenu, DIcon(ArchValue("processor32", "processor64")), mFollowAddrDisasm, valueAddrText, tr("Disassembler"));
|
||||
configAction(wMenu, DIcon("dump"), mFollowDump, valueAddrText, tr("Dump"));
|
||||
configAction(menu, DIcon(ArchValue("processor32", "processor64")), mFollowAddrDisasm, valueAddrText, tr("Disassembler"));
|
||||
configAction(menu, DIcon("dump"), mFollowDump, valueAddrText, tr("Dump"));
|
||||
if(inStackRange(valueAddr))
|
||||
configAction(wMenu, DIcon("stack"), mFollowAddrStack, valueAddrText, tr("Stack"));
|
||||
configAction(menu, DIcon("stack"), mFollowAddrStack, valueAddrText, tr("Stack"));
|
||||
}
|
||||
}
|
||||
QMenu wCopyMenu(tr("&Copy"));
|
||||
wCopyMenu.setIcon(DIcon("copy"));
|
||||
mTable->setupCopyMenu(&wCopyMenu);
|
||||
if(wCopyMenu.actions().length())
|
||||
QMenu copyMenu(tr("&Copy"));
|
||||
copyMenu.setIcon(DIcon("copy"));
|
||||
mTable->setupCopyMenu(©Menu);
|
||||
if(copyMenu.actions().length())
|
||||
{
|
||||
wMenu.addSeparator();
|
||||
wMenu.addMenu(&wCopyMenu);
|
||||
menu.addSeparator();
|
||||
menu.addMenu(©Menu);
|
||||
}
|
||||
wMenu.exec(mTable->mapToGlobal(pos));
|
||||
menu.exec(mTable->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void CPUArgumentWidget::followDisasmSlot()
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <vector>
|
||||
#include "StdTable.h"
|
||||
#include "StringUtil.h"
|
||||
#include "Architecture.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ class CPUArgumentWidget : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CPUArgumentWidget(QWidget* parent = 0);
|
||||
explicit CPUArgumentWidget(Architecture* architecture, QWidget* parent = nullptr);
|
||||
~CPUArgumentWidget();
|
||||
|
||||
static QString defaultArgFormat(const QString & format, const QString & expression)
|
||||
|
@ -40,7 +41,7 @@ public:
|
|||
}
|
||||
|
||||
public slots:
|
||||
void disassembleAtSlot(dsint addr, dsint cip);
|
||||
void disassembleAtSlot(duint addr, duint cip);
|
||||
void refreshData();
|
||||
|
||||
private slots:
|
||||
|
@ -133,11 +134,12 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
Ui::CPUArgumentWidget* ui;
|
||||
StdTable* mTable;
|
||||
int mCurrentCallingConvention;
|
||||
duint mStackOffset;
|
||||
bool mAllowUpdate;
|
||||
Architecture* mArchitecture = nullptr;
|
||||
Ui::CPUArgumentWidget* ui = nullptr;
|
||||
StdTable* mTable = nullptr;
|
||||
int mCurrentCallingConvention = -1;
|
||||
duint mStackOffset = 0;
|
||||
bool mAllowUpdate = true;
|
||||
std::vector<CallingConvention> mCallingConventions;
|
||||
std::vector<duint> mArgumentValues;
|
||||
QAction* mFollowDisasm;
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#include "BrowseDialog.h"
|
||||
#include "Tracer/TraceBrowser.h"
|
||||
|
||||
CPUDisassembly::CPUDisassembly(QWidget* parent, bool isMain) : Disassembly(parent, isMain)
|
||||
CPUDisassembly::CPUDisassembly(Architecture* architecture, bool isMain, QWidget* parent)
|
||||
: Disassembly(architecture, isMain, parent)
|
||||
{
|
||||
setWindowTitle("Disassembly");
|
||||
|
||||
|
@ -34,7 +35,7 @@ CPUDisassembly::CPUDisassembly(QWidget* parent, bool isMain) : Disassembly(paren
|
|||
setupRightClickContextMenu();
|
||||
|
||||
// Connect bridge<->disasm calls
|
||||
connect(Bridge::getBridge(), SIGNAL(disassembleAt(dsint, dsint)), this, SLOT(disassembleAtSlot(dsint, dsint)));
|
||||
connect(Bridge::getBridge(), SIGNAL(disassembleAt(duint, duint)), this, SLOT(disassembleAtSlot(duint, duint)));
|
||||
if(mIsMain)
|
||||
{
|
||||
connect(Bridge::getBridge(), SIGNAL(selectionDisasmGet(SELECTIONDATA*)), this, SLOT(selectionGetSlot(SELECTIONDATA*)));
|
||||
|
@ -45,6 +46,9 @@ CPUDisassembly::CPUDisassembly(QWidget* parent, bool isMain) : Disassembly(paren
|
|||
// Connect some internal signals
|
||||
connect(this, SIGNAL(selectionExpanded()), this, SLOT(selectionUpdatedSlot()));
|
||||
|
||||
// Load configuration
|
||||
mShowMnemonicBrief = ConfigBool("Disassembler", "ShowMnemonicBrief");
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
|
@ -130,7 +134,7 @@ void CPUDisassembly::mouseDoubleClickEvent(QMouseEvent* event)
|
|||
}
|
||||
}
|
||||
|
||||
void CPUDisassembly::addFollowReferenceMenuItem(QString name, dsint value, QMenu* menu, bool isReferences, bool isFollowInCPU)
|
||||
void CPUDisassembly::addFollowReferenceMenuItem(QString name, duint value, QMenu* menu, bool isReferences, bool isFollowInCPU)
|
||||
{
|
||||
foreach(QAction* action, menu->actions()) //check for duplicate action
|
||||
if(action->text() == name)
|
||||
|
@ -146,7 +150,7 @@ void CPUDisassembly::addFollowReferenceMenuItem(QString name, dsint value, QMenu
|
|||
connect(newAction, SIGNAL(triggered()), this, SLOT(followActionSlot()));
|
||||
}
|
||||
|
||||
void CPUDisassembly::setupFollowReferenceMenu(dsint wVA, QMenu* menu, bool isReferences, bool isFollowInCPU)
|
||||
void CPUDisassembly::setupFollowReferenceMenu(duint va, QMenu* menu, bool isReferences, bool isFollowInCPU)
|
||||
{
|
||||
//remove previous actions
|
||||
QList<QAction*> list = menu->actions();
|
||||
|
@ -159,12 +163,12 @@ void CPUDisassembly::setupFollowReferenceMenu(dsint wVA, QMenu* menu, bool isRef
|
|||
if(isReferences)
|
||||
menu->addAction(mReferenceSelectedAddressAction);
|
||||
else
|
||||
addFollowReferenceMenuItem(tr("&Selected Address"), wVA, menu, isReferences, isFollowInCPU);
|
||||
addFollowReferenceMenuItem(tr("&Selected Address"), va, menu, isReferences, isFollowInCPU);
|
||||
}
|
||||
|
||||
//add follow actions
|
||||
DISASM_INSTR instr;
|
||||
DbgDisasmAt(wVA, &instr);
|
||||
DbgDisasmAt(va, &instr);
|
||||
|
||||
if(!isReferences) //follow in dump
|
||||
{
|
||||
|
@ -253,13 +257,13 @@ void CPUDisassembly::setupFollowReferenceMenu(dsint wVA, QMenu* menu, bool isRef
|
|||
*/
|
||||
void CPUDisassembly::contextMenuEvent(QContextMenuEvent* event)
|
||||
{
|
||||
QMenu wMenu(this);
|
||||
QMenu menu(this);
|
||||
if(!mHighlightContextMenu)
|
||||
mMenuBuilder->build(&wMenu);
|
||||
mMenuBuilder->build(&menu);
|
||||
else if(mHighlightToken.text.length())
|
||||
mHighlightMenuBuilder->build(&wMenu);
|
||||
if(wMenu.actions().length())
|
||||
wMenu.exec(event->globalPos());
|
||||
mHighlightMenuBuilder->build(&menu);
|
||||
if(menu.actions().length())
|
||||
menu.exec(event->globalPos());
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
|
@ -732,19 +736,19 @@ void CPUDisassembly::setLabelSlot()
|
|||
{
|
||||
if(!DbgIsDebugging())
|
||||
return;
|
||||
duint wVA = rvaToVa(getInitialSelection());
|
||||
duint va = rvaToVa(getInitialSelection());
|
||||
LineEditDialog mLineEdit(this);
|
||||
mLineEdit.setTextMaxLength(MAX_LABEL_SIZE - 2);
|
||||
QString addr_text = ToPtrString(wVA);
|
||||
QString addr_text = ToPtrString(va);
|
||||
char label_text[MAX_COMMENT_SIZE] = "";
|
||||
if(DbgGetLabelAt((duint)wVA, SEG_DEFAULT, label_text))
|
||||
if(DbgGetLabelAt((duint)va, SEG_DEFAULT, label_text))
|
||||
mLineEdit.setText(QString(label_text));
|
||||
mLineEdit.setWindowTitle(tr("Add label at ") + addr_text);
|
||||
restart:
|
||||
if(mLineEdit.exec() != QDialog::Accepted)
|
||||
return;
|
||||
QByteArray utf8data = mLineEdit.editText.toUtf8();
|
||||
if(!utf8data.isEmpty() && DbgIsValidExpression(utf8data.constData()) && DbgValFromString(utf8data.constData()) != wVA)
|
||||
if(!utf8data.isEmpty() && DbgIsValidExpression(utf8data.constData()) && DbgValFromString(utf8data.constData()) != va)
|
||||
{
|
||||
QMessageBox msg(QMessageBox::Warning, tr("The label may be in use"),
|
||||
tr("The label \"%1\" may be an existing label or a valid expression. Using such label might have undesired effects. Do you still want to continue?").arg(mLineEdit.editText),
|
||||
|
@ -755,7 +759,7 @@ restart:
|
|||
if(msg.exec() == QMessageBox::No)
|
||||
goto restart;
|
||||
}
|
||||
if(!DbgSetLabelAt(wVA, utf8data.constData()))
|
||||
if(!DbgSetLabelAt(va, utf8data.constData()))
|
||||
SimpleErrorBox(this, tr("Error!"), tr("DbgSetLabelAt failed!"));
|
||||
|
||||
GuiUpdateAllViews();
|
||||
|
@ -895,12 +899,12 @@ void CPUDisassembly::assembleSlot()
|
|||
|
||||
do
|
||||
{
|
||||
dsint wRVA = getInitialSelection();
|
||||
duint wVA = rvaToVa(wRVA);
|
||||
unfold(wRVA);
|
||||
QString addr_text = ToPtrString(wVA);
|
||||
dsint rva = getInitialSelection();
|
||||
duint va = rvaToVa(rva);
|
||||
unfold(rva);
|
||||
QString addr_text = ToPtrString(va);
|
||||
|
||||
Instruction_t instr = this->DisassembleAt(wRVA);
|
||||
Instruction_t instr = this->DisassembleAt(rva);
|
||||
|
||||
QString actual_inst = instr.instStr;
|
||||
|
||||
|
@ -911,7 +915,7 @@ void CPUDisassembly::assembleSlot()
|
|||
|
||||
assembly_error = false;
|
||||
|
||||
assembleDialog.setSelectedInstrVa(wVA);
|
||||
assembleDialog.setSelectedInstrVa(va);
|
||||
if(ConfigBool("Disassembler", "Uppercase"))
|
||||
actual_inst = actual_inst.toUpper().replace(QRegularExpression("0X([0-9A-F]+)"), "0x\\1");
|
||||
assembleDialog.setTextEditValue(actual_inst);
|
||||
|
@ -934,7 +938,7 @@ void CPUDisassembly::assembleSlot()
|
|||
if(expression == QString("???") || expression.toLower() == instr.instStr.toLower() || expression == QString(""))
|
||||
break;
|
||||
|
||||
if(!DbgFunctions()->AssembleAtEx(wVA, expression.toUtf8().constData(), error, assembleDialog.bFillWithNopsChecked))
|
||||
if(!DbgFunctions()->AssembleAtEx(va, expression.toUtf8().constData(), error, assembleDialog.bFillWithNopsChecked))
|
||||
{
|
||||
QMessageBox msg(QMessageBox::Critical, tr("Error!"), tr("Failed to assemble instruction \" %1 \" (%2)").arg(expression).arg(error));
|
||||
msg.setWindowIcon(DIcon("compile-error"));
|
||||
|
@ -948,20 +952,20 @@ void CPUDisassembly::assembleSlot()
|
|||
while(assembly_error);
|
||||
|
||||
//select next instruction after assembling
|
||||
setSingleSelection(wRVA);
|
||||
setSingleSelection(rva);
|
||||
|
||||
dsint botRVA = getTableOffset();
|
||||
dsint topRVA = getInstructionRVA(getTableOffset(), getNbrOfLineToPrint() - 1);
|
||||
auto botRVA = getTableOffset();
|
||||
auto topRVA = getInstructionRVA(getTableOffset(), getNbrOfLineToPrint() - 1);
|
||||
|
||||
dsint wInstrSize = getInstructionRVA(wRVA, 1) - wRVA - 1;
|
||||
|
||||
expandSelectionUpTo(wRVA + wInstrSize);
|
||||
// TODO: this seems dumb
|
||||
auto instrSize = getInstructionRVA(rva, 1) - rva - 1;
|
||||
expandSelectionUpTo(rva + instrSize);
|
||||
selectNext(false);
|
||||
|
||||
if(getSelectionStart() < botRVA)
|
||||
setTableOffset(getSelectionStart());
|
||||
else if(getSelectionEnd() >= topRVA)
|
||||
setTableOffset(getInstructionRVA(getSelectionEnd(), -getNbrOfLineToPrint() + 2));
|
||||
setTableOffset(getInstructionRVA(getSelectionEnd(), -(dsint)getNbrOfLineToPrint() + 2));
|
||||
|
||||
//refresh view
|
||||
GuiUpdateAllViews();
|
||||
|
@ -1354,6 +1358,7 @@ void CPUDisassembly::enableHighlightingModeSlot()
|
|||
void CPUDisassembly::binaryEditSlot()
|
||||
{
|
||||
HexEditDialog hexEdit(this);
|
||||
hexEdit.showKeepSize(true);
|
||||
dsint selStart = getSelectionStart();
|
||||
dsint selSize = getSelectionEnd() - selStart + 1;
|
||||
byte_t* data = new byte_t[selSize];
|
||||
|
@ -1375,7 +1380,6 @@ void CPUDisassembly::binaryEditSlot()
|
|||
void CPUDisassembly::binaryFillSlot()
|
||||
{
|
||||
HexEditDialog hexEdit(this);
|
||||
hexEdit.showKeepSize(false);
|
||||
hexEdit.mHexEdit->setOverwriteMode(false);
|
||||
dsint selStart = getSelectionStart();
|
||||
hexEdit.setWindowTitle(tr("Fill code at %1").arg(ToPtrString(rvaToVa(selStart))));
|
||||
|
@ -1530,7 +1534,8 @@ void CPUDisassembly::pushSelectionInto(bool copyBytes, QTextStream & stream, QTe
|
|||
if(i)
|
||||
stream << "\r\n";
|
||||
duint cur_addr = rvaToVa(inst.rva);
|
||||
QString address = getAddrText(cur_addr, 0, addressLen > sizeof(duint) * 2 + 1);
|
||||
QString label;
|
||||
QString address = getAddrText(cur_addr, label, addressLen > sizeof(duint) * 2 + 1);
|
||||
QString bytes;
|
||||
QString bytesHtml;
|
||||
if(copyBytes)
|
||||
|
@ -1956,6 +1961,7 @@ void CPUDisassembly::traceCoverageDisableSlot()
|
|||
void CPUDisassembly::mnemonicBriefSlot()
|
||||
{
|
||||
mShowMnemonicBrief = !mShowMnemonicBrief;
|
||||
Config()->setBool("Disassembler", "ShowMnemonicBrief", mShowMnemonicBrief);
|
||||
reloadData();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ class CPUDisassembly : public Disassembly
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CPUDisassembly(QWidget* parent, bool isMain);
|
||||
CPUDisassembly(Architecture* architecture, bool isMain, QWidget* parent = nullptr);
|
||||
|
||||
// Mouse management
|
||||
void contextMenuEvent(QContextMenuEvent* event);
|
||||
|
@ -22,8 +22,8 @@ public:
|
|||
|
||||
// Context menu management
|
||||
void setupRightClickContextMenu();
|
||||
void addFollowReferenceMenuItem(QString name, dsint value, QMenu* menu, bool isReferences, bool isFollowInCPU);
|
||||
void setupFollowReferenceMenu(dsint wVA, QMenu* menu, bool isReferences, bool isFollowInCPU);
|
||||
void addFollowReferenceMenuItem(QString name, duint value, QMenu* menu, bool isReferences, bool isFollowInCPU);
|
||||
void setupFollowReferenceMenu(duint va, QMenu* menu, bool isReferences, bool isFollowInCPU);
|
||||
void copySelectionSlot(bool copyBytes);
|
||||
void copySelectionToFileSlot(bool copyBytes);
|
||||
void setSideBar(CPUSideBar* sideBar);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,14 +12,14 @@ class CPUDump : public HexDump
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CPUDump(CPUDisassembly* disas, CPUMultiDump* multiDump, QWidget* parent = 0);
|
||||
void getColumnRichText(int col, dsint rva, RichTextPainter::List & richText) override;
|
||||
QString paintContent(QPainter* painter, dsint rowBase, int rowOffset, int col, int x, int y, int w, int h);
|
||||
explicit CPUDump(CPUMultiDump* multiDump, CPUDisassembly* disasassembly, QWidget* parent = nullptr);
|
||||
void getColumnRichText(duint col, duint rva, RichTextPainter::List & richText) override;
|
||||
QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override;
|
||||
void setupContextMenu();
|
||||
void getAttention();
|
||||
void contextMenuEvent(QContextMenuEvent* event);
|
||||
void mouseDoubleClickEvent(QMouseEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
void contextMenuEvent(QContextMenuEvent* event) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* event) override;
|
||||
|
||||
signals:
|
||||
void displayReferencesWidget();
|
||||
|
@ -82,7 +82,7 @@ public slots:
|
|||
void syncWithExpressionSlot();
|
||||
void allocMemorySlot();
|
||||
|
||||
void headerButtonReleasedSlot(int colIndex);
|
||||
void headerButtonReleasedSlot(duint colIndex);
|
||||
|
||||
private:
|
||||
MenuBuilder* mMenuBuilder;
|
||||
|
@ -94,8 +94,8 @@ private:
|
|||
|
||||
GotoDialog* mGoto = nullptr;
|
||||
GotoDialog* mGotoOffset = nullptr;
|
||||
CPUDisassembly* mDisas;
|
||||
CPUMultiDump* mMultiDump;
|
||||
CPUDisassembly* mDisassembly = nullptr;
|
||||
CPUMultiDump* mMultiDump = nullptr;
|
||||
int mAsciiSeparator = 0;
|
||||
|
||||
enum ViewEnum_t
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue