📄 stackwnd.c
字号:
/*
Copyright 2001-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
You may contact the author at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
**********************************************************************
STACKWND.C unrolls the stack, and shows functions called at a level
higher than the breakpoint (this thread only)
**********************************************************************
*/
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <richedit.h>
#include <stdio.h>
#include "header.h"
#include "operands.h"
#include "opcodes.h"
#include <ctype.h>
#include "cvinfo.h"
extern HWND hwndSourceTab;
extern HINSTANCE hInstance;
extern HWND hwndClient, hwndStatus, hwndFrame;
extern PROCESS DebugProcess;
extern enum DebugState uState;
extern THREAD *StoppedThread;
typedef struct _stacklist
{
struct _stacklist *next;
int address;
char name[256];
} STACKLIST;
HWND hwndStack;
static char szStackClassName[] = "xccStackClass";
static char szStackBlankClassName[] = "xccStackClass2";
static HWND hwndCtrl, hwndBlank;
static LOGFONT fontdata =
{
16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH |
FF_DONTCARE, "Courier New"
};
static HFONT StackFont;
static int StackAddress, StackLines;
static STACKLIST *StackList;
static int curpos;
static char *szStackTitle = "Stack Window";
void StackDoPaint(HWND hwnd)
{
int i;
STACKLIST *list = StackList;
int Address = StackAddress;
char buf[256], *p;
HBRUSH wbrush = GetStockObject(WHITE_BRUSH);
PAINTSTRUCT ps;
CONTEXT context;
HDC dc;
HFONT oldFont;
RECT rect;
int lines;
GetClientRect(hwnd, &rect);
lines = (rect.bottom - rect.top) / 16;
dc = BeginPaint(hwnd, &ps);
FillRect(dc, &rect, wbrush);
SelectObject(dc, StackFont);
while (list && Address)
{
list = list->next;
Address -= 1;
}
for (i = 0; i < lines && list; i++)
{
sprintf(buf, "%08X: %s", list->address, list->name);
if (i == curpos)
{
int oldtext = GetTextColor(dc);
int oldbk = GetBkColor(dc);
SetTextColor(dc, oldbk);
SetBkColor(dc, oldtext);
TextOut(dc, 0, i *16+rect.top, buf, strlen(buf));
SetTextColor(dc, oldtext);
SetBkColor(dc, oldbk);
}
else
TextOut(dc, 0, i *16+rect.top, buf, strlen(buf));
list = list->next;
}
SelectObject(dc, oldFont);
EndPaint(hwnd, &ps);
}
//-------------------------------------------------------------------------
void ClearStackArea(HWND hwnd)
{
while (StackList)
{
STACKLIST *s = StackList->next;
free(StackList);
StackList = s;
}
StackLines = 0;
StackAddress = 0;
curpos = 0;
SetScrollRange(hwnd, SB_VERT, StackAddress, StackLines, FALSE);
SetScrollPos(hwnd, SB_VERT, 0, TRUE);
}
//-------------------------------------------------------------------------
int eipReal(int eip)
{
int len, i;
unsigned char buf[16];
ReadProcessMemory(DebugProcess.hProcess, (LPVOID)(eip - 16), (LPVOID) &buf,
16, &len);
if (buf[11] == 0xe8)
return eip - 5;
for (i = 14; i >= 0; i--)
if (buf[i] == 0xff && ((buf[i] &0x38) == 0x10))
return eip - (16-i);
return eip;
}
//-------------------------------------------------------------------------
int readStackedData(int inebp, int *outebp)
{
DWORD eip = 0;
int len = 0;
ReadProcessMemory(DebugProcess.hProcess, (LPVOID)(inebp + 4), (LPVOID) &eip,
4, &len);
ReadProcessMemory(DebugProcess.hProcess, (LPVOID)inebp, (LPVOID)outebp, 4,
&len);
return eip;
}
//-------------------------------------------------------------------------
int findStackedFunction(int eipCursor, int *outebp, int *level, THREAD **thread)
{
PROCSYM32 *cursym = FindFunctionSymbol(eipCursor);
THREAD *l = DebugProcess.threads;
while (l)
{
int eip;
eip = l->regs.Eip;
*outebp = l->regs.Ebp;
*level = 0;
*thread = l;
while (eip)
{
PROCSYM32 *tempsym = FindFunctionSymbol(eip);
if (tempsym == cursym)
return eip;
eip = readStackedData(*outebp, outebp);
(*level)++;
}
l = l->next;
}
return 0;
}
//-------------------------------------------------------------------------
void SetStackArea(HWND hwnd)
{
int ebp = StoppedThread->regs.Ebp;
int eip = StoppedThread->regs.Eip;
int len;
STACKLIST *stackbase = 0, *stackptr, *newstack;
char *symtab;
int offset;
char buf[256];
int lines = 0;
StackLines = 0;
if (uState != atBreakpoint && uState != atException)
return ;
while (1)
{
eip = eipReal(eip);
FindFunctionName(buf, eip);
newstack = malloc(sizeof(STACKLIST));
if (!newstack)
return ;
newstack->next = 0;
strcpy(newstack->name, buf);
newstack->address = eip;
if (stackbase)
stackptr = stackptr->next = newstack;
else
stackbase = stackptr = newstack;
eip = 0;
lines++;
eip = readStackedData(ebp, &ebp);
if (!eip)
break;
}
StackList = stackbase;
StackLines = lines;
SetScrollRange(hwnd, SB_VERT, 0, lines - 1, TRUE);
}
//-------------------------------------------------------------------------
LRESULT CALLBACK _export StackBlankProc(HWND hwnd, UINT iMessage, WPARAM wParam,
LPARAM lParam)
{
RECT r;
char module[256];
STACKLIST *sl;
int i, lines;
switch (iMessage)
{
case WM_PAINT:
StackDoPaint(hwnd);
return 0;
case WM_SETFOCUS:
// SendMessage(hwndFrame,WM_REDRAWTOOLBAR,0,0) ;
break;
case WM_KILLFOCUS:
break;
case WM_LBUTTONDOWN:
lines = HIWORD(lParam);
if (lines / 16+StackAddress < StackLines)
{
curpos = lines / 16;
InvalidateRect(hwnd, 0, TRUE);
}
// fall through
case WM_RBUTTONDOWN:
SetFocus(hwnd);
break;
case WM_LBUTTONDBLCLK:
PostMessage(hwnd, WM_KEYDOWN, VK_RETURN, 0);
break;
case WM_KEYDOWN:
switch (wParam)
{
case VK_RETURN:
sl = StackList;
lines = StackAddress + curpos;
while (sl && lines)
{
sl = sl->next;
lines--;
}
if (sl)
{
if (GetBreakpointLine(sl->address, module, &lines))
{
char *p;
char nmodule[256];
static DWINFO x;
FindModuleName(nmodule, module);
strcpy(x.dwName, nmodule);
p = strrchr(nmodule, '\\');
if (p)
strcpy(x.dwTitle, p + 1);
else
strcpy(x.dwTitle, nmodule);
x.dwLineNo = lines;
x.logMRU = FALSE;
CreateDrawWindow(&x);
}
}
break;
case VK_UP:
if (curpos)
curpos--;
else if (StackAddress)
{
StackAddress--;
SetScrollPos(hwnd, SB_VERT, StackAddress, TRUE);
}
InvalidateRect(hwnd, 0, 0);
break;
case VK_DOWN:
GetClientRect(hwnd, &r);
lines = r.bottom / 16;
if (curpos < StackLines - 1)
{
if (curpos < lines - 1)
curpos++;
else if (StackAddress < StackLines - 1)
{
StackAddress++;
SetScrollPos(hwnd, SB_VERT, StackAddress, TRUE);
}
InvalidateRect(hwnd, 0, TRUE);
}
break;
}
break;
case WM_VSCROLL:
GetClientRect(hwnd, &r);
lines = r.bottom / 16;
switch (LOWORD(wParam))
{
case SB_BOTTOM:
StackAddress = StackLines - (lines *1);
break;
case SB_TOP:
StackAddress = 0;
break;
case SB_ENDSCROLL:
return 0;
case SB_LINEDOWN:
StackAddress += 1;
break;
case SB_LINEUP:
StackAddress -= 1;
break;
case SB_PAGEDOWN:
StackAddress += 1 *(lines - 1);
break;
case SB_PAGEUP:
StackAddress -= 1 *(lines - 1);
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
StackAddress = HIWORD(wParam);
break;
}
if (StackAddress < 0)
StackAddress = 0;
if (StackAddress >= StackLines)
StackAddress = StackLines - 1;
InvalidateRect(hwnd, 0, 0);
SetScrollPos(hwnd, SB_VERT, StackAddress, TRUE);
return 0;
}
return DefWindowProc(hwnd, iMessage, wParam, lParam);
}
//-------------------------------------------------------------------------
LRESULT CALLBACK _export StackProc(HWND hwnd, UINT iMessage, WPARAM wParam,
LPARAM lParam)
{
int i, lines;
HDC dc;
PAINTSTRUCT ps;
TEXTMETRIC metric;
DEBUG_EVENT *xc;
HFONT oldFont;
LOGBRUSH brushstr;
RECT r;
switch (iMessage)
{
case WM_MDIACTIVATE:
SendMessage(hwndCtrl, LCF_SETACTIVE, 0, lParam == (LPARAM)hwnd);
if (lParam == (LPARAM)hwnd)
{
SendMessage(hwndSourceTab, WM_SETACTIVETAB, 0, (LPARAM)hwnd);
SetFocus(hwndBlank);
}
return TRUE;
case WM_SETFOCUS:
// SetFocus(hwndBlank) ;
break;
case WM_SYSCOMMAND:
if (wParam == SC_CLOSE)
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
case WM_COMMAND:
break;
case WM_CREATE:
hwndStack = hwnd;
GetClientRect(hwnd, &r);
hwndCtrl = CreateControlWindow(DID_STACKWND, hwnd, &r, (int)(
(LPMDICREATESTRUCT)(*(int*)lParam))->lParam, szStackTitle);
SendMessage(hwndCtrl, LCF_ADJUSTRECT, 0, (LPARAM) &r);
hwndBlank = CreateWindow(szStackBlankClassName, 0, WS_VSCROLL +
WS_CHILD + WS_CLIPSIBLINGS + WS_BORDER + WS_VISIBLE, r.left,
r.top, r.right - r.left, r.bottom - r.top, hwndCtrl, 0,
hInstance, 0);
StackFont = CreateFontIndirect(&fontdata);
wParam = 1;
// fall through
case WM_RESTACK:
ClearStackArea(hwndBlank);
if (uState != notDebugging && wParam)
SetStackArea(hwndBlank);
InvalidateRect(hwndBlank, 0, 0);
break;
case WM_PAINT:
dc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
return 0;
case WM_CLOSE:
dmgrHideWindow(DID_STACKWND, TRUE);
return 0;
case WM_DESTROY:
dmgrRemoveClient((CCW_params*)GetWindowLong(hwndCtrl, 0));
DestroyWindow(hwndBlank);
ClearStackArea(hwnd);
hwndStack = 0;
DeleteObject(StackFont);
break;
case WM_SIZE:
r.left = r.top = 0;
r.right = LOWORD(lParam);
r.bottom = HIWORD(lParam);
MoveWindow(hwndCtrl, 0, 0, r.right, r.bottom, TRUE);
SendMessage(hwndCtrl, LCF_ADJUSTRECT, 0, (LPARAM) &r);
MoveWindow(hwndBlank, r.left, r.top, r.right - r.left, r.bottom -
r.top, TRUE);
break;
case WM_INITMENUPOPUP:
return 0;
default:
break;
}
return DefMDIChildProc(hwnd, iMessage, wParam, lParam);
}
//-------------------------------------------------------------------------
void RegisterStackWindow(void)
{
WNDCLASS wc;
memset(&wc, 0, sizeof(wc));
wc.style = CS_HREDRAW + CS_VREDRAW + CS_DBLCLKS;
wc.lpfnWndProc = &StackProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szStackClassName;
RegisterClass(&wc);
wc.lpfnWndProc = &StackBlankProc;
wc.lpszClassName = szStackBlankClassName;
RegisterClass(&wc);
}
//-------------------------------------------------------------------------
HWND CreateStackWindow(void)
{
CCW_params p;
MDICREATESTRUCT mc;
HWND rv;
RECT r;
if (hwndStack)
{
SendMessage(hwndStack, WM_SETFOCUS, 0, 0);
return hwndStack;
}
GetClientRect(hwndClient, &r);
mc.szClass = szStackClassName;
mc.szTitle = szStackTitle;
mc.hOwner = hInstance;
mc.x = CW_USEDEFAULT;
mc.y = CW_USEDEFAULT;
mc.cx = 30 * 8;
mc.cy = 19 * 8;
mc.style = WS_CHILD | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_CLIPCHILDREN,
mc.lParam = (LPARAM)0;
rv = (HWND)SendMessage(hwndClient, WM_MDICREATE, 0, (LPARAM) &mc);
return rv;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -