Breakpoint list at the bottom of the disassembly window

This commit is contained in:
Kingcom 2013-06-27 21:07:49 +02:00
parent b0f4849277
commit d4214af710
10 changed files with 365 additions and 33 deletions

View file

@ -172,6 +172,11 @@ int CBreakPoints::GetNumBreakpoints()
return (int)m_iBreakPoints.size(); return (int)m_iBreakPoints.size();
} }
BreakPoint CBreakPoints::GetBreakpoint(int i)
{
return m_iBreakPoints[i];
}
int CBreakPoints::GetBreakpointAddress(int i) int CBreakPoints::GetBreakpointAddress(int i)
{ {
return m_iBreakPoints[i].iAddress; return m_iBreakPoints[i].iAddress;

View file

@ -87,6 +87,7 @@ public:
static void InvalidateJit(); static void InvalidateJit();
static int GetNumBreakpoints(); static int GetNumBreakpoints();
static BreakPoint GetBreakpoint(int i);
static int GetBreakpointAddress(int i); static int GetBreakpointAddress(int i);
}; };

View file

@ -357,7 +357,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
if (debugger->isBreakpoint(address)) if (debugger->isBreakpoint(address))
{ {
textColor = 0x0000FF; textColor = 0x0000FF;
DrawIconEx(hdc,2,rowY1,breakPoint,32,32,0,0,DI_NORMAL); DrawIconEx(hdc,2,rowY1+1,breakPoint,32,32,0,0,DI_NORMAL);
} }
SetTextColor(hdc,textColor); SetTextColor(hdc,textColor);
@ -892,4 +892,13 @@ void CtrlDisAsmView::disassembleToFile()
fclose(output); fclose(output);
MessageBox(wnd,"Finished!","Done",MB_OK); MessageBox(wnd,"Finished!","Done",MB_OK);
}
void CtrlDisAsmView::getOpcodeText(u32 address, char* dest)
{
char addressText[64],opcode[64],arguments[256];
const char *dis = debugger->disasm(address, instructionSize);
parseDisasm(dis,opcode,arguments);
sprintf(dest,"%s %s",opcode,arguments);
} }

View file

@ -83,7 +83,8 @@ public:
void onMouseUp(WPARAM wParam, LPARAM lParam, int button); void onMouseUp(WPARAM wParam, LPARAM lParam, int button);
void onMouseMove(WPARAM wParam, LPARAM lParam, int button); void onMouseMove(WPARAM wParam, LPARAM lParam, int button);
void redraw(); void redraw();
void getOpcodeText(u32 address, char* dest);
int yToAddress(int y); int yToAddress(int y);
void setDontRedraw(bool b) { dontRedraw = b; }; void setDontRedraw(bool b) { dontRedraw = b; };

View file

@ -29,6 +29,45 @@
#include <windowsx.h> #include <windowsx.h>
#include <commctrl.h> #include <commctrl.h>
char* breakpointColumns[] = {
"Type", "Offset", "Size/Label", "Opcode", "Hits", "Enabled"
};
float breakpointColumnSizes[] = {
0.12f, 0.2f, 0.2f, 0.3f, 0.1f, 0.08f
};
enum { BPL_TYPE, BPL_OFFSET, BPL_SIZELABEL, BPL_OPCODE, BPL_HITS, BPL_ENABLED, BPL_COLUMNCOUNT };
static FAR WNDPROC DefBreakpointListProc;
static LRESULT CALLBACK BreakpointListProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_KEYDOWN:
if(wParam == VK_RETURN)
{
int index = ListView_GetSelectionMark(hDlg);
SendMessage(GetParent(hDlg),WM_USER+4,index,0);
return 0;
} else if (wParam == VK_DELETE)
{
int index = ListView_GetSelectionMark(hDlg);
SendMessage(GetParent(hDlg),WM_USER+5,index,0);
return 0;
}
default:
return (LRESULT)CallWindowProc((WNDPROC)DefBreakpointListProc,hDlg,message,wParam,lParam);
};
return 0;
}
CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Dialog((LPCSTR)IDD_DISASM, _hInstance, _hParent) CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Dialog((LPCSTR)IDD_DISASM, _hInstance, _hParent)
{ {
cpu = _cpu; cpu = _cpu;
@ -62,6 +101,15 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di
GetWindowRect(GetDlgItem(m_hDlg, IDC_REGLIST),&regRect); GetWindowRect(GetDlgItem(m_hDlg, IDC_REGLIST),&regRect);
GetWindowRect(GetDlgItem(m_hDlg, IDC_DISASMVIEW),&disRect); GetWindowRect(GetDlgItem(m_hDlg, IDC_DISASMVIEW),&disRect);
GetWindowRect(GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST),&breakpointRect);
int minWidth = max((regRect.right-regRect.left)+(disRect.right-disRect.left)+24,
(breakpointRect.right-breakpointRect.left)+16);
if (w < minWidth) w = minWidth;
int minHeight = max((disRect.bottom-disRect.top)+(breakpointRect.bottom-breakpointRect.top)+37,
(regRect.bottom-regRect.top)+(breakpointRect.bottom-breakpointRect.top)+150);
if (h < minHeight) h = minHeight;
HWND tabs = GetDlgItem(m_hDlg, IDC_LEFTTABS); HWND tabs = GetDlgItem(m_hDlg, IDC_LEFTTABS);
@ -79,23 +127,35 @@ CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Di
ShowWindow(GetDlgItem(m_hDlg, IDC_REGLIST), SW_NORMAL); ShowWindow(GetDlgItem(m_hDlg, IDC_REGLIST), SW_NORMAL);
ShowWindow(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), SW_HIDE); ShowWindow(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), SW_HIDE);
SetTimer(m_hDlg,1,1000,0); SetTimer(m_hDlg,1,1000,0);
/*
DWORD intAddress[14] =
{0x100, 0x200,0x300,0x400,0x500,0x600,0x700,0x800,0x900,0xc00,0xd00,0xf00,0x1300,0x1700};
char *intName[14] =
{"100 Reset","200 Mcheck", "300 DSI","400 ISI","500 External",
"600 Align","700 Program","800 FPU N/A","900 DEC","C00 SC",
"D00 Trace","F00 Perf","1300 Breakpt","1700 Thermal"};*/
//
// --- activate debug mode --- // subclass the breakpoint list
// HWND breakpointHwnd = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST);
DefBreakpointListProc = (WNDPROC)GetWindowLongPtr(breakpointHwnd,GWLP_WNDPROC);
SetWindowLongPtr(breakpointHwnd,GWLP_WNDPROC,(LONG_PTR)BreakpointListProc);
// create columns for the breakpoint list
SendMessage(breakpointHwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.iSubItem = 0;
lvc.fmt = LVCFMT_LEFT;
int totalListSize = (breakpointRect.right-breakpointRect.left-20);
for (int i = 0; i < BPL_COLUMNCOUNT; i++)
{
lvc.cx = breakpointColumnSizes[i] * totalListSize;
lvc.pszText = breakpointColumns[i];
ListView_InsertColumn(breakpointHwnd, i, &lvc);
}
// Actually resize the window to the proper size (after the above setup.) // Actually resize the window to the proper size (after the above setup.)
if (w != -1 && h != -1) if (w != -1 && h != -1)
{ {
// this will also call UpdateSize
SetWindowPos(m_hDlg, 0, x, y, w, h, 0); SetWindowPos(m_hDlg, 0, x, y, w, h, 0);
UpdateSize(w, h);
} }
SetDebugMode(true); SetDebugMode(true);
@ -105,6 +165,225 @@ CDisasm::~CDisasm()
{ {
} }
int getTotalBreakpointCount()
{
int count = CBreakPoints::MemChecks.size();
for (int i = 0; i < CBreakPoints::GetNumBreakpoints(); i++)
{
if (!CBreakPoints::GetBreakpoint(i).bTemporary) count++;
}
return count;
}
void CDisasm::updateBreakpointList()
{
HWND breakpointHwnd = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST);
int breakpointCount = getTotalBreakpointCount();
int items = ListView_GetItemCount(breakpointHwnd);
while (items < breakpointCount)
{
LVITEM lvI;
lvI.pszText = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message.
lvI.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE;
lvI.stateMask = 0;
lvI.iSubItem = 0;
lvI.state = 0;
lvI.iItem = items;
lvI.iImage = items;
ListView_InsertItem(breakpointHwnd, &lvI);
items++;
}
while (items > breakpointCount)
{
ListView_DeleteItem(breakpointHwnd,--items);
}
InvalidateRect(breakpointHwnd,NULL,true);
UpdateWindow(breakpointHwnd);
}
int getBreakpointIndex(int itemIndex, bool& isMemory)
{
// memory breakpoints first
if (itemIndex < CBreakPoints::MemChecks.size())
{
isMemory = true;
return itemIndex;
}
itemIndex -= CBreakPoints::MemChecks.size();
int i = 0;
while (i < CBreakPoints::GetNumBreakpoints())
{
if (CBreakPoints::GetBreakpoint(i).bTemporary)
{
i++;
continue;
}
// the index is 0 when there are no more breakpoints to skip
if (itemIndex == 0)
{
isMemory = false;
return i;
}
i++;
itemIndex--;
}
return -1;
}
void CDisasm::removeBreakpoint(int itemIndex)
{
bool isMemory;
int index = getBreakpointIndex(itemIndex,isMemory);
if (index == -1) return;
if (isMemory)
{
CBreakPoints::MemChecks.erase(CBreakPoints::MemChecks.begin()+index);
CBreakPoints::InvalidateJit();
updateBreakpointList();
} else {
u32 address = CBreakPoints::GetBreakpointAddress(index);
CBreakPoints::RemoveBreakPoint(address);
}
}
void CDisasm::gotoBreakpointAddress(int itemIndex)
{
bool isMemory;
int index = getBreakpointIndex(itemIndex,isMemory);
if (index == -1) return;
if (isMemory)
{
u32 address = CBreakPoints::MemChecks[index].iStartAddress;
for (int i=0; i<numCPUs; i++)
if (memoryWindow[i])
memoryWindow[i]->Goto(address);
} else {
u32 address = CBreakPoints::GetBreakpointAddress(index);
Goto(address);
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
}
}
static char breakpointText[256];
void CDisasm::handleBreakpointNotify(LPARAM lParam)
{
if (((LPNMHDR)lParam)->code == NM_DBLCLK)
{
LPNMITEMACTIVATE item = (LPNMITEMACTIVATE) lParam;
gotoBreakpointAddress(item->iItem);
return;
}
if (((LPNMHDR)lParam)->code == LVN_GETDISPINFO)
{
NMLVDISPINFO* dispInfo = (NMLVDISPINFO*)lParam;
std::vector<MemCheck>& mem = CBreakPoints::MemChecks;
bool isMemory;
int index = getBreakpointIndex(dispInfo->item.iItem,isMemory);
if (index == -1) return;
breakpointText[0] = 0;
switch (dispInfo->item.iSubItem)
{
case BPL_TYPE:
{
if (isMemory)
{
if (mem[index].bOnRead)
{
strcpy(breakpointText,"Read");
if (mem[index].bOnWrite) strcat(breakpointText,"/");
}
if (mem[index].bOnWrite) strcat(breakpointText,"Write");
} else {
strcpy(breakpointText,"Execute");
}
}
break;
case BPL_OFFSET:
{
if (isMemory)
{
sprintf(breakpointText,"0x%08X",mem[index].iStartAddress);
} else {
sprintf(breakpointText,"0x%08X",CBreakPoints::GetBreakpointAddress(index));
}
}
break;
case BPL_SIZELABEL:
{
if (isMemory)
{
if (mem[index].bRange == false) sprintf(breakpointText,"0x%08X",1);
else sprintf(breakpointText,"0x%08X",mem[index].iEndAddress-mem[index].iStartAddress);
} else {
const char* sym = cpu->findSymbolForAddress(CBreakPoints::GetBreakpointAddress(index));
if (sym != NULL)
{
if (memcmp(sym,"z_",2) == 0) sym += 2;
if (memcmp(sym,"zz_",3) == 0) sym += 3;
strcpy(breakpointText,sym);
} else {
strcpy(breakpointText,"-");
}
}
}
break;
case BPL_OPCODE:
{
if (isMemory)
{
strcpy(breakpointText,"-");
} else {
CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW));
ptr->getOpcodeText(CBreakPoints::GetBreakpointAddress(index),breakpointText);
}
}
break;
case BPL_HITS:
{
if (isMemory)
{
sprintf(breakpointText,"0x%08X",mem[index].numHits);
} else {
strcpy(breakpointText,"-");
}
}
break;
case BPL_ENABLED:
{
if (isMemory)
{
strcpy(breakpointText,mem[index].bBreak == true ? "True" : "False");
} else {
strcpy(breakpointText,CBreakPoints::GetBreakpoint(index).bOn ? "True" : "False");
}
}
break;
default:
return;
}
if (breakpointText[0] == 0) strcat(breakpointText,"Invalid");
dispInfo->item.pszText = breakpointText;
}
}
BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
{ {
//if (!m_hDlg) return FALSE; //if (!m_hDlg) return FALSE;
@ -125,19 +404,26 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
break; break;
case WM_NOTIFY: case WM_NOTIFY:
switch (wParam)
{ {
HWND tabs = GetDlgItem(m_hDlg, IDC_LEFTTABS); case IDC_LEFTTABS:
NMHDR* pNotifyMessage = NULL;
pNotifyMessage = (LPNMHDR)lParam;
if (pNotifyMessage->hwndFrom == tabs)
{ {
int iPage = TabCtrl_GetCurSel (tabs); HWND tabs = GetDlgItem(m_hDlg, IDC_LEFTTABS);
ShowWindow(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), iPage?SW_NORMAL:SW_HIDE); NMHDR* pNotifyMessage = NULL;
ShowWindow(GetDlgItem(m_hDlg, IDC_REGLIST), iPage?SW_HIDE:SW_NORMAL); pNotifyMessage = (LPNMHDR)lParam;
if (pNotifyMessage->hwndFrom == tabs)
{
int iPage = TabCtrl_GetCurSel (tabs);
ShowWindow(GetDlgItem(m_hDlg, IDC_FUNCTIONLIST), iPage?SW_NORMAL:SW_HIDE);
ShowWindow(GetDlgItem(m_hDlg, IDC_REGLIST), iPage?SW_HIDE:SW_NORMAL);
}
} }
break; break;
case IDC_BREAKPOINTLIST:
handleBreakpointNotify(lParam);
break;
} }
break;
case WM_COMMAND: case WM_COMMAND:
{ {
CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW)); CtrlDisAsmView *ptr = CtrlDisAsmView::getFrom(GetDlgItem(m_hDlg,IDC_DISASMVIEW));
@ -299,6 +585,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
check.bRange = false; check.bRange = false;
CBreakPoints::MemChecks.push_back(check); CBreakPoints::MemChecks.push_back(check);
CBreakPoints::InvalidateJit(); CBreakPoints::InvalidateJit();
updateBreakpointList();
} }
if (isRunning) if (isRunning)
@ -353,13 +640,15 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
case IDC_GOTOPC: case IDC_GOTOPC:
{ {
ptr->gotoPC(); ptr->gotoPC();
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
UpdateDialog(); UpdateDialog();
} }
break; break;
case IDC_GOTOLR: case IDC_GOTOLR:
{ {
ptr->gotoAddr(cpu->GetLR()); ptr->gotoAddr(cpu->GetLR());
SetFocus(GetDlgItem(m_hDlg, IDC_DISASMVIEW));
} }
break; break;
@ -396,6 +685,12 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
Core_EnableStepping(false); Core_EnableStepping(false);
break; break;
} }
case WM_USER+4:
gotoBreakpointAddress(wParam);
break;
case WM_USER+5:
removeBreakpoint(wParam);
break;
case WM_SIZE: case WM_SIZE:
{ {
UpdateSize(LOWORD(lParam), HIWORD(lParam)); UpdateSize(LOWORD(lParam), HIWORD(lParam));
@ -427,13 +722,20 @@ void CDisasm::UpdateSize(WORD width, WORD height)
HWND disasm = GetDlgItem(m_hDlg, IDC_DISASMVIEW); HWND disasm = GetDlgItem(m_hDlg, IDC_DISASMVIEW);
HWND funclist = GetDlgItem(m_hDlg, IDC_FUNCTIONLIST); HWND funclist = GetDlgItem(m_hDlg, IDC_FUNCTIONLIST);
HWND regList = GetDlgItem(m_hDlg, IDC_REGLIST); HWND regList = GetDlgItem(m_hDlg, IDC_REGLIST);
int wf = regRect.right - regRect.left; HWND breakpointList = GetDlgItem(m_hDlg, IDC_BREAKPOINTLIST);
int top = 138;
MoveWindow(regList, 8, top, wf, height - top - 8, TRUE); int breakpointHeight = breakpointRect.bottom-breakpointRect.top;
MoveWindow(funclist, 8, top, wf, height - top - 8, TRUE); int breakpointTop = height-breakpointHeight-8;
int w = width - wf; int regWidth = regRect.right - regRect.left;
top = 25; int regTop = 138;
MoveWindow(disasm, wf + 15,top, w - 20, height - top - 8, TRUE); int disasmWidth = width-regWidth;
int disasmTop = 25;
MoveWindow(regList, 8, regTop, regWidth, height-regTop-breakpointHeight-12, TRUE);
MoveWindow(funclist, 8, regTop, regWidth, height-regTop-breakpointHeight-12, TRUE);
MoveWindow(disasm,regWidth+15,disasmTop,disasmWidth-20,height-disasmTop-breakpointHeight-12,TRUE);
MoveWindow(breakpointList,8,breakpointTop,width-16,breakpointHeight,TRUE);
} }
void CDisasm::SavePosition() void CDisasm::SavePosition()
@ -456,6 +758,7 @@ void CDisasm::SetDebugMode(bool _bDebug)
if (_bDebug) if (_bDebug)
{ {
CBreakPoints::ClearTemporaryBreakPoints(); CBreakPoints::ClearTemporaryBreakPoints();
updateBreakpointList();
EnableWindow( GetDlgItem(hDlg, IDC_GO), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_GO), TRUE);
EnableWindow( GetDlgItem(hDlg, IDC_STEP), TRUE); EnableWindow( GetDlgItem(hDlg, IDC_STEP), TRUE);

View file

@ -18,13 +18,17 @@ private:
RECT minRect; RECT minRect;
RECT regRect; RECT regRect;
RECT disRect; RECT disRect;
RECT breakpointRect;
DebugInterface *cpu; DebugInterface *cpu;
BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam); BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam);
void UpdateSize(WORD width, WORD height); void UpdateSize(WORD width, WORD height);
void SavePosition(); void SavePosition();
void updateBreakpointList();
void handleBreakpointNotify(LPARAM lParam);
void gotoBreakpointAddress(int itemIndex);
void removeBreakpoint(int itemIndex);
public: public:
int index; //helper int index; //helper
@ -33,8 +37,12 @@ public:
// //
// --- tools --- // --- tools ---
// //
// Update Dialog
virtual void Update() { UpdateDialog(true); }; virtual void Update()
{
UpdateDialog(true);
updateBreakpointList();
};
void UpdateDialog(bool _bComplete = false); void UpdateDialog(bool _bComplete = false);
// SetDebugMode // SetDebugMode
void SetDebugMode(bool _bDebug); void SetDebugMode(bool _bDebug);

View file

@ -181,6 +181,7 @@ void CMemoryDlg::Goto(u32 addr)
Show(true); Show(true);
CtrlMemView *mv = CtrlMemView::getFrom(GetDlgItem(CMemoryDlg::m_hDlg,IDC_MEMVIEW)); CtrlMemView *mv = CtrlMemView::getFrom(GetDlgItem(CMemoryDlg::m_hDlg,IDC_MEMVIEW));
mv->gotoAddr(addr); mv->gotoAddr(addr);
SetFocus(GetDlgItem(CMemoryDlg::m_hDlg,IDC_MEMVIEW));
} }

View file

@ -17,6 +17,10 @@ Key bindings:
-Ctrl+C will continue the previous search -Ctrl+C will continue the previous search
-Ctrl+X will disassemble to a file you specify. First you enter the size (in bytes, hexadecimal) of the code to be disassembled, then you select a file name. It will start at the cursor -Ctrl+X will disassemble to a file you specify. First you enter the size (in bytes, hexadecimal) of the code to be disassembled, then you select a file name. It will start at the cursor
All breakpoints are listed in the table at the bottom of the disassembly view. Doube clicking an execute breakpoint will move the disassembly view to that position, double clicking a memory breakpoint will open the memory viewer and move it to the start of the breakpoint range. Pressing delete will remove the selected breakpoint.
If there is a symbol defined for the position of an execute breakpoint, that will also be displayed.
########### ###########
Memory View Memory View
########### ###########

Binary file not shown.

Binary file not shown.