Merge pull request #4552 from Kingcom/Debugger

Debugger changes
This commit is contained in:
Henrik Rydgård 2013-11-16 04:36:39 -08:00
commit 997f5090d7
4 changed files with 171 additions and 97 deletions

View File

@ -248,7 +248,7 @@ namespace MIPSAnalyst {
u32 addr;
for (addr = startAddr; addr <= endAddr; addr+=4) {
SymbolInfo syminfo;
if (symbolMap.GetSymbolInfo(&syminfo, addr, ST_FUNCTION)) {
if (symbolMap.GetSymbolInfo(&syminfo, addr, ST_FUNCTION) && syminfo.size >= 4) {
addr = syminfo.address + syminfo.size;
continue;
}

View File

@ -121,7 +121,8 @@ public:
switch (cat)
{
case 0:
cpu->r[index] = value;
if (index != 0)
cpu->r[index] = value;
break;
case 1:

View File

@ -31,22 +31,22 @@ extern HMENU g_hPopupMenus;
void CtrlDisAsmView::init()
{
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.lpszClassName = szClassName;
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = CtrlDisAsmView::wndProc;
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hIcon = 0;
wc.lpszMenuName = 0;
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof( CtrlDisAsmView * );
wc.hIconSm = 0;
WNDCLASSEX wc;
RegisterClassEx(&wc);
wc.cbSize = sizeof(wc);
wc.lpszClassName = szClassName;
wc.hInstance = GetModuleHandle(0);
wc.lpfnWndProc = CtrlDisAsmView::wndProc;
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hIcon = 0;
wc.lpszMenuName = 0;
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof( CtrlDisAsmView * );
wc.hIconSm = 0;
RegisterClassEx(&wc);
}
void CtrlDisAsmView::deinit()
@ -220,19 +220,19 @@ LRESULT CALLBACK CtrlDisAsmView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPA
{
CtrlDisAsmView *ccp = CtrlDisAsmView::getFrom(hwnd);
static bool lmbDown=false,rmbDown=false;
switch(msg)
{
case WM_NCCREATE:
// Allocate a new CustCtrl structure for this window.
ccp = new CtrlDisAsmView(hwnd);
switch(msg)
{
case WM_NCCREATE:
// Allocate a new CustCtrl structure for this window.
ccp = new CtrlDisAsmView(hwnd);
// Continue with window creation.
return ccp != NULL;
// Continue with window creation.
return ccp != NULL;
// Clean up when the window is destroyed.
case WM_NCDESTROY:
delete ccp;
break;
case WM_NCDESTROY:
delete ccp;
break;
case WM_SETFONT:
break;
case WM_SIZE:
@ -293,17 +293,17 @@ LRESULT CALLBACK CtrlDisAsmView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPA
}
}
return DLGC_WANTCHARS|DLGC_WANTARROWS;
default:
break;
}
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
return DefWindowProc(hwnd, msg, wParam, lParam);
}
CtrlDisAsmView *CtrlDisAsmView::getFrom(HWND hwnd)
{
return (CtrlDisAsmView *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
return (CtrlDisAsmView *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
@ -452,6 +452,24 @@ void CtrlDisAsmView::parseDisasm(const char* disasm, char* opcode, char* argumen
*arguments = 0;
}
std::string trimString(std::string input)
{
int pos = input.find_first_not_of(" \t");
if (pos != 0 && pos != std::string::npos)
{
input = input.erase(0,pos);
}
pos = input.find_last_not_of(" \t");
if (pos != std::string::npos)
{
int size = input.length()-pos-1;
input = input.erase(pos+1,size);
}
return input;
}
void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText)
{
u32 encoded;
@ -465,6 +483,33 @@ void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText)
if (!result)
return;
// check if it changes registers first
auto seperator = op.find('=');
if (seperator != std::string::npos)
{
std::string registerName = trimString(op.substr(0,seperator));
std::string expression = trimString(op.substr(seperator+1));
u32 value;
if (parseExpression(expression.c_str(),debugger,value) == true)
{
for (int cat = 0; cat < debugger->GetNumCategories(); cat++)
{
for (int reg = 0; reg < debugger->GetNumRegsInCategory(cat); reg++)
{
if (strcasecmp(debugger->GetRegName(cat,reg),registerName.c_str()) == 0)
{
debugger->SetRegValue(cat,reg,value);
SendMessage(GetParent(wnd),WM_DEB_UPDATE,0,0);
return;
}
}
}
}
// try to assemble the input if it failed
}
result = MIPSAsm::MipsAssembleOpcode(op.c_str(),debugger,address,encoded);
if (result == true)
{
@ -740,6 +785,8 @@ void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam)
default:
return;
}
scanFunctions();
redraw();
}
@ -837,6 +884,20 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
case 'd': // toogle breakpoint enabled
toggleBreakpoint(true);
break;
case VK_UP:
windowStart -= instructionSize;
scanFunctions();
break;
case VK_DOWN:
windowStart += instructionSize;
scanFunctions();
break;
case VK_NEXT:
setCurAddress(windowEnd-instructionSize,KeyDownAsync(VK_SHIFT));
break;
case VK_PRIOR:
setCurAddress(windowStart,KeyDownAsync(VK_SHIFT));
break;
}
} else {
switch (wParam & 0xFFFF)
@ -990,29 +1051,27 @@ void CtrlDisAsmView::copyInstructions(u32 startAddr, u32 endAddr, bool withDisas
{
int count = (endAddr - startAddr) / instructionSize;
char opcode[64], arguments[256];
int space = count * (withDisasm ? 256 : 32);
char *temp = new char[space];
char *p = temp, *end = temp + space;
for (u32 pos = startAddr; pos < endAddr; pos += instructionSize)
if (withDisasm == false)
{
if (withDisasm)
int space = count * 32;
char *temp = new char[space];
char *p = temp, *end = temp + space;
for (u32 pos = startAddr; pos < endAddr; pos += instructionSize)
{
const char *dizz = debugger->disasm(pos, instructionSize);
parseDisasm(dizz, opcode, arguments);
p += snprintf(p, end - p, "%s\t%s", opcode, arguments);
}
else
p += snprintf(p, end - p, "%08X", debugger->readMemory(pos));
// Don't leave a trailing newline.
if (pos + instructionSize < endAddr)
p += snprintf(p, end - p, "\r\n");
// Don't leave a trailing newline.
if (pos + instructionSize < endAddr)
p += snprintf(p, end - p, "\r\n");
}
W32Util::CopyTextToClipboard(wnd, temp);
delete [] temp;
} else
{
std::string disassembly = disassembleRange(startAddr,endAddr-startAddr);
W32Util::CopyTextToClipboard(wnd, disassembly.c_str());
}
W32Util::CopyTextToClipboard(wnd, temp);
delete [] temp;
}
void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
@ -1312,6 +1371,63 @@ void CtrlDisAsmView::search(bool continueSearch)
searching = false;
}
std::string CtrlDisAsmView::disassembleRange(u32 start, u32 size)
{
std::string result;
// gather all branch targets without labels
std::set<u32> branchAddresses;
for (u32 i = 0; i < size; i += instructionSize)
{
char opcode[64],arguments[256];
const char *dis = debugger->disasm(start+i, instructionSize);
parseDisasm(dis,opcode,arguments);
if (branchTarget != -1 && debugger->findSymbolForAddress(branchTarget) == NULL)
{
if (branchAddresses.find(branchTarget) == branchAddresses.end())
{
branchAddresses.insert(branchTarget);
}
}
}
bool previousLabel = true;
for (u32 i = 0; i < size; i += instructionSize)
{
u32 disAddress = start+i;
char addressText[64],opcode[64],arguments[256],buffer[512];
const char *dis = debugger->disasm(disAddress, instructionSize);
parseDisasm(dis,opcode,arguments);
bool isLabel = getDisasmAddressText(disAddress,addressText,false);
if (isLabel)
{
if (!previousLabel) result += "\r\n";
sprintf(buffer,"%s\r\n\r\n",addressText);
result += buffer;
} else if (branchAddresses.find(disAddress) != branchAddresses.end())
{
if (!previousLabel) result += "\r\n";
sprintf(buffer,"pos_%08X:\r\n\r\n",disAddress);
result += buffer;
}
if (branchTarget != -1 && debugger->findSymbolForAddress(branchTarget) == NULL)
{
char* str = strstr(arguments,"0x");
sprintf(str,"pos_%08X",branchTarget);
}
sprintf(buffer,"\t%s\t%s\r\n",opcode,arguments);
result += buffer;
previousLabel = isLabel;
}
return result;
}
void CtrlDisAsmView::disassembleToFile()
{
wchar_t fileName[MAX_PATH];
@ -1342,58 +1458,14 @@ void CtrlDisAsmView::disassembleToFile()
if (GetSaveFileName(&ofn) == false) return;
FILE* output = _wfopen(fileName, L"w");
FILE* output = _wfopen(fileName, L"wb");
if (output == NULL) {
MessageBox(wnd,L"Could not open file!",L"Error",MB_OK);
return;
}
// gather all branch targets without labels
std::set<u32> branchAddresses;
for (u32 i = 0; i < size; i += instructionSize)
{
char opcode[64],arguments[256];
const char *dis = debugger->disasm(curAddress+i, instructionSize);
parseDisasm(dis,opcode,arguments);
if (branchTarget != -1 && debugger->findSymbolForAddress(branchTarget) == NULL)
{
if (branchAddresses.find(branchTarget) == branchAddresses.end())
{
branchAddresses.insert(branchTarget);
}
}
}
bool previousLabel = true;
for (u32 i = 0; i < size; i += instructionSize)
{
u32 disAddress = curAddress+i;
char addressText[64],opcode[64],arguments[256];
const char *dis = debugger->disasm(disAddress, instructionSize);
parseDisasm(dis,opcode,arguments);
bool isLabel = getDisasmAddressText(disAddress,addressText,false);
if (isLabel)
{
if (!previousLabel) fprintf(output,"\n");
fprintf(output,"%s\n\n",addressText);
} else if (branchAddresses.find(disAddress) != branchAddresses.end())
{
if (!previousLabel) fprintf(output,"\n");
fprintf(output,"pos_%08X:\n\n",disAddress);
}
if (branchTarget != -1 && debugger->findSymbolForAddress(branchTarget) == NULL)
{
char* str = strstr(arguments,"0x");
sprintf(str,"pos_%08X",branchTarget);
}
fprintf(output,"\t%s\t%s\n",opcode,arguments);
previousLabel = isLabel;
}
std::string disassembly = disassembleRange(curAddress,size);
fprintf(output,"%s",disassembly.c_str());
fclose(output);
MessageBox(wnd,L"Finished!",L"Done",MB_OK);

View File

@ -90,6 +90,7 @@ class CtrlDisAsmView
bool keyTaken;
void assembleOpcode(u32 address, std::string defaultText);
std::string disassembleRange(u32 start, u32 size);
void disassembleToFile();
void search(bool continueSearch);
void followBranch();