Add autocomment for breakpoint
This commit is contained in:
parent
025fcf5125
commit
3817686d95
|
@ -287,6 +287,225 @@ static bool getLabel(duint addr, char* label, bool noFuncOffset)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static bool getAutoComment(duint addr, String & comment)
|
||||
{
|
||||
bool retval;
|
||||
duint disp;
|
||||
char fileName[MAX_STRING_SIZE] = {};
|
||||
int lineNumber = 0;
|
||||
if(!bNoSourceLineAutoComments && SymGetSourceLine(addr, fileName, &lineNumber, &disp) && !disp)
|
||||
{
|
||||
|
||||
char* actualName = fileName;
|
||||
char* l = strrchr(fileName, '\\');
|
||||
if(l)
|
||||
actualName = l + 1;
|
||||
|
||||
comment = StringUtils::sprintf("%s:%u", actualName, lineNumber);
|
||||
retval = true;
|
||||
}
|
||||
|
||||
DISASM_INSTR instr;
|
||||
String temp_string;
|
||||
BRIDGE_ADDRINFO newinfo;
|
||||
char string_text[MAX_STRING_SIZE] = "";
|
||||
|
||||
Zydis cp;
|
||||
auto getregs = !bOnlyCipAutoComments || addr == lastContext.cip;
|
||||
disasmget(cp, addr, &instr, getregs);
|
||||
// Some nop variants have 'operands' that should be ignored
|
||||
if(cp.Success() && !cp.IsNop())
|
||||
{
|
||||
//Ignore register values when not on CIP and OnlyCipAutoComments is enabled: https://github.com/x64dbg/x64dbg/issues/1383
|
||||
if(!getregs)
|
||||
{
|
||||
for(int i = 0; i < instr.argcount; i++)
|
||||
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)))
|
||||
{
|
||||
auto syscallName = SyscallToName((unsigned int)lastContext.cax);
|
||||
if(!syscallName.empty())
|
||||
{
|
||||
if(!comment.empty())
|
||||
{
|
||||
comment.push_back(',');
|
||||
comment.push_back(' ');
|
||||
}
|
||||
comment.append(syscallName);
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < instr.argcount; i++)
|
||||
{
|
||||
memset(&newinfo, 0, sizeof(BRIDGE_ADDRINFO));
|
||||
newinfo.flags = flaglabel;
|
||||
|
||||
STRING_TYPE strtype = str_none;
|
||||
|
||||
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())
|
||||
temp_string.assign("call $0");
|
||||
else if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.IsJump())
|
||||
temp_string.assign("jmp $0");
|
||||
else if(instr.type == instr_branch)
|
||||
continue;
|
||||
else if(instr.arg[i].type == arg_normal && constant < 256 && (isprint(int(constant)) || isspace(int(constant))) && (strstr(instr.instruction, "cmp") || strstr(instr.instruction, "mov")))
|
||||
{
|
||||
temp_string.assign(instr.arg[i].mnemonic);
|
||||
temp_string.push_back(':');
|
||||
temp_string.push_back('\'');
|
||||
temp_string.append(StringUtils::Escape((unsigned char)constant));
|
||||
temp_string.push_back('\'');
|
||||
}
|
||||
else if(DbgGetStringAt(instr.arg[i].constant, string_text))
|
||||
{
|
||||
temp_string.assign(instr.arg[i].mnemonic);
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(string_text);
|
||||
}
|
||||
}
|
||||
else if(instr.arg[i].memvalue && (DbgGetStringAt(instr.arg[i].memvalue, string_text) || _dbg_addrinfoget(instr.arg[i].memvalue, instr.arg[i].segment, &newinfo)))
|
||||
{
|
||||
if(*string_text)
|
||||
{
|
||||
temp_string.assign("[");
|
||||
temp_string.append(instr.arg[i].mnemonic);
|
||||
temp_string.push_back(']');
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(string_text);
|
||||
}
|
||||
else if(*newinfo.label)
|
||||
{
|
||||
temp_string.assign("[");
|
||||
temp_string.append(instr.arg[i].mnemonic);
|
||||
temp_string.push_back(']');
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(newinfo.label);
|
||||
}
|
||||
}
|
||||
else if(instr.arg[i].value && (DbgGetStringAt(instr.arg[i].value, string_text) || _dbg_addrinfoget(instr.arg[i].value, instr.arg[i].segment, &newinfo)))
|
||||
{
|
||||
if(instr.type != instr_normal) //stack/jumps (eg add esp, 4 or jmp 401110) cannot directly point to strings
|
||||
{
|
||||
if(*newinfo.label)
|
||||
{
|
||||
temp_string = instr.arg[i].mnemonic;
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(newinfo.label);
|
||||
}
|
||||
}
|
||||
else if(*string_text)
|
||||
{
|
||||
temp_string = instr.arg[i].mnemonic;
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(string_text);
|
||||
}
|
||||
else if(*newinfo.label)
|
||||
{
|
||||
temp_string = instr.arg[i].mnemonic;
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(newinfo.label);
|
||||
}
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
if(!strstr(comment.c_str(), temp_string.c_str())) //avoid duplicate comments
|
||||
{
|
||||
if(!comment.empty())
|
||||
{
|
||||
comment.push_back(',');
|
||||
comment.push_back(' ');
|
||||
}
|
||||
comment.append(temp_string);
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
BREAKPOINT bp;
|
||||
// Add autocomment for breakpoints with BreakpointsView format because there's usually something useful
|
||||
if(BpGet(addr, BPNORMAL, nullptr, &bp) || BpGet(addr, BPHARDWARE, nullptr, &bp))
|
||||
{
|
||||
auto next = [&temp_string]()
|
||||
{
|
||||
if(!temp_string.empty())
|
||||
temp_string += ", ";
|
||||
};
|
||||
if(*bp.breakCondition)
|
||||
{
|
||||
next();
|
||||
temp_string += GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "breakif"));
|
||||
temp_string += "(";
|
||||
temp_string += bp.breakCondition;
|
||||
temp_string += ")";
|
||||
}
|
||||
|
||||
if(bp.fastResume)
|
||||
{
|
||||
next();
|
||||
temp_string += GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "fastresume()"));
|
||||
}
|
||||
else //fast resume skips all other steps
|
||||
{
|
||||
if(*bp.logText)
|
||||
{
|
||||
next();
|
||||
if(*bp.logCondition)
|
||||
{
|
||||
temp_string += GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "logif"));
|
||||
temp_string += "(";
|
||||
temp_string += bp.logCondition;
|
||||
temp_string += ", ";
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_string += GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "log"));
|
||||
temp_string += "(";
|
||||
}
|
||||
temp_string += bp.logText;
|
||||
temp_string += ")";
|
||||
}
|
||||
|
||||
if(*bp.commandText)
|
||||
{
|
||||
next();
|
||||
if(*bp.commandCondition)
|
||||
{
|
||||
temp_string += GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "cmdif"));
|
||||
temp_string += "(";
|
||||
temp_string += bp.commandCondition;
|
||||
temp_string += ", ";
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_string += GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "cmd"));
|
||||
temp_string += "(";
|
||||
}
|
||||
temp_string += bp.commandText;
|
||||
temp_string += ")";
|
||||
}
|
||||
}
|
||||
if(!temp_string.empty())
|
||||
{
|
||||
if(!comment.empty())
|
||||
{
|
||||
comment.push_back(',');
|
||||
comment.push_back(' ');
|
||||
}
|
||||
comment.append(temp_string);
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
StringUtils::ReplaceAll(comment, "{", "{{");
|
||||
StringUtils::ReplaceAll(comment, "}", "}}");
|
||||
return retval;
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, BRIDGE_ADDRINFO* addrinfo)
|
||||
{
|
||||
if(!DbgIsDebugging())
|
||||
|
@ -331,145 +550,7 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, BRID
|
|||
else
|
||||
{
|
||||
String comment;
|
||||
duint disp;
|
||||
char fileName[MAX_STRING_SIZE] = {};
|
||||
int lineNumber = 0;
|
||||
if(!bNoSourceLineAutoComments && SymGetSourceLine(addr, fileName, &lineNumber, &disp) && !disp)
|
||||
{
|
||||
|
||||
char* actualName = fileName;
|
||||
char* l = strrchr(fileName, '\\');
|
||||
if(l)
|
||||
actualName = l + 1;
|
||||
|
||||
comment = StringUtils::sprintf("%s:%u", actualName, lineNumber);
|
||||
retval = true;
|
||||
}
|
||||
|
||||
DISASM_INSTR instr;
|
||||
String temp_string;
|
||||
BRIDGE_ADDRINFO newinfo;
|
||||
char string_text[MAX_STRING_SIZE] = "";
|
||||
|
||||
Zydis cp;
|
||||
auto getregs = !bOnlyCipAutoComments || addr == lastContext.cip;
|
||||
disasmget(cp, addr, &instr, getregs);
|
||||
// Some nop variants have 'operands' that should be ignored
|
||||
if(cp.Success() && !cp.IsNop())
|
||||
{
|
||||
//Ignore register values when not on CIP and OnlyCipAutoComments is enabled: https://github.com/x64dbg/x64dbg/issues/1383
|
||||
if(!getregs)
|
||||
{
|
||||
for(int i = 0; i < instr.argcount; i++)
|
||||
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)))
|
||||
{
|
||||
auto syscallName = SyscallToName((unsigned int)lastContext.cax);
|
||||
if(!syscallName.empty())
|
||||
{
|
||||
if(!comment.empty())
|
||||
{
|
||||
comment.push_back(',');
|
||||
comment.push_back(' ');
|
||||
}
|
||||
comment.append(syscallName);
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < instr.argcount; i++)
|
||||
{
|
||||
memset(&newinfo, 0, sizeof(BRIDGE_ADDRINFO));
|
||||
newinfo.flags = flaglabel;
|
||||
|
||||
STRING_TYPE strtype = str_none;
|
||||
|
||||
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())
|
||||
temp_string.assign("call $0");
|
||||
else if(instr.arg[i].type == arg_normal && instr.arg[i].value == addr + instr.instr_size && cp.IsJump())
|
||||
temp_string.assign("jmp $0");
|
||||
else if(instr.type == instr_branch)
|
||||
continue;
|
||||
else if(instr.arg[i].type == arg_normal && constant < 256 && (isprint(int(constant)) || isspace(int(constant))) && (strstr(instr.instruction, "cmp") || strstr(instr.instruction, "mov")))
|
||||
{
|
||||
temp_string.assign(instr.arg[i].mnemonic);
|
||||
temp_string.push_back(':');
|
||||
temp_string.push_back('\'');
|
||||
temp_string.append(StringUtils::Escape((unsigned char)constant));
|
||||
temp_string.push_back('\'');
|
||||
}
|
||||
else if(DbgGetStringAt(instr.arg[i].constant, string_text))
|
||||
{
|
||||
temp_string.assign(instr.arg[i].mnemonic);
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(string_text);
|
||||
}
|
||||
}
|
||||
else if(instr.arg[i].memvalue && (DbgGetStringAt(instr.arg[i].memvalue, string_text) || _dbg_addrinfoget(instr.arg[i].memvalue, instr.arg[i].segment, &newinfo)))
|
||||
{
|
||||
if(*string_text)
|
||||
{
|
||||
temp_string.assign("[");
|
||||
temp_string.append(instr.arg[i].mnemonic);
|
||||
temp_string.push_back(']');
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(string_text);
|
||||
}
|
||||
else if(*newinfo.label)
|
||||
{
|
||||
temp_string.assign("[");
|
||||
temp_string.append(instr.arg[i].mnemonic);
|
||||
temp_string.push_back(']');
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(newinfo.label);
|
||||
}
|
||||
}
|
||||
else if(instr.arg[i].value && (DbgGetStringAt(instr.arg[i].value, string_text) || _dbg_addrinfoget(instr.arg[i].value, instr.arg[i].segment, &newinfo)))
|
||||
{
|
||||
if(instr.type != instr_normal) //stack/jumps (eg add esp, 4 or jmp 401110) cannot directly point to strings
|
||||
{
|
||||
if(*newinfo.label)
|
||||
{
|
||||
temp_string = instr.arg[i].mnemonic;
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(newinfo.label);
|
||||
}
|
||||
}
|
||||
else if(*string_text)
|
||||
{
|
||||
temp_string = instr.arg[i].mnemonic;
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(string_text);
|
||||
}
|
||||
else if(*newinfo.label)
|
||||
{
|
||||
temp_string = instr.arg[i].mnemonic;
|
||||
temp_string.push_back(':');
|
||||
temp_string.append(newinfo.label);
|
||||
}
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
if(!strstr(comment.c_str(), temp_string.c_str())) //avoid duplicate comments
|
||||
{
|
||||
if(!comment.empty())
|
||||
{
|
||||
comment.push_back(',');
|
||||
comment.push_back(' ');
|
||||
}
|
||||
comment.append(temp_string);
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
StringUtils::ReplaceAll(comment, "{", "{{");
|
||||
StringUtils::ReplaceAll(comment, "}", "}}");
|
||||
retval = getAutoComment(addr, comment);
|
||||
strcpy_s(addrinfo->comment, "\1");
|
||||
strncat_s(addrinfo->comment, comment.c_str(), _TRUNCATE);
|
||||
}
|
||||
|
|
|
@ -458,7 +458,7 @@ void BreakpointsView::updateBreakpointsSlot()
|
|||
if(*bp.breakCondition)
|
||||
{
|
||||
next();
|
||||
colored("breakif", mSummaryKeywordColor);
|
||||
colored(tr("breakif"), mSummaryKeywordColor);
|
||||
colored("(", mSummaryParenColor);
|
||||
text(bp.breakCondition);
|
||||
colored(")", mSummaryParenColor);
|
||||
|
@ -475,17 +475,19 @@ void BreakpointsView::updateBreakpointsSlot()
|
|||
if(*bp.logText)
|
||||
{
|
||||
next();
|
||||
colored(tr("log"), mSummaryKeywordColor);
|
||||
if(*bp.logCondition)
|
||||
{
|
||||
colored("if", mSummaryKeywordColor);
|
||||
colored(tr("logif"), mSummaryKeywordColor);
|
||||
colored("(", mSummaryParenColor);
|
||||
text(bp.logCondition);
|
||||
colored(",", mSummaryParenColor);
|
||||
text(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
colored(tr("log"), mSummaryKeywordColor);
|
||||
colored("(", mSummaryParenColor);
|
||||
}
|
||||
colored(QString("\"%1\"").arg(bp.logText), mSummaryStringColor);
|
||||
colored(")", mSummaryParenColor);
|
||||
}
|
||||
|
@ -493,17 +495,19 @@ void BreakpointsView::updateBreakpointsSlot()
|
|||
if(*bp.commandText)
|
||||
{
|
||||
next();
|
||||
colored(tr("cmd"), mSummaryKeywordColor);
|
||||
if(*bp.commandCondition)
|
||||
{
|
||||
colored("if", mSummaryKeywordColor);
|
||||
colored(tr("cmdif"), mSummaryKeywordColor);
|
||||
colored("(", mSummaryParenColor);
|
||||
text(bp.commandCondition);
|
||||
colored(",", mSummaryParenColor);
|
||||
text(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
colored(tr("cmd"), mSummaryKeywordColor);
|
||||
colored("(", mSummaryParenColor);
|
||||
}
|
||||
colored(QString("\"%1\"").arg(bp.commandText), mSummaryStringColor);
|
||||
colored(")", mSummaryParenColor);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue