📄 dbgmain.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
**********************************************************************
DBGMAIN.C is the primary debugger interface. It interacts with win32
to do the things necessary to debug a WIN32 program; however it does
not deal directly with the debug info symbol file. That is done in
symtab.c
**********************************************************************
*/
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <richedit.h>
#define TF_BIT 0x100
#include "header.h"
extern HWND hwndSourceTab;
extern HWND hwndFrame, hwndASM, hwndRegister, hwndWatch, hwndThread;
extern HWND hwndToolDebug, hwndStack, hwndError, hwndDump;
extern HANDLE children[MAX_CHILDREN];
extern int numberofdrawwindows;
extern PROJLIST *selectedProject;
enum DebugState uState = notDebugging;
PROCESS DebugProcess;
HANDLE StartupSem, BreakpointSem;
THREAD *StoppedThread;
int stopWinMain;
static PROJLIST *debugProject;
static DWORD debugThreadID;
static int Semaphores;
static int SingleStepping;
static int LastSkipAddr;
void StartDebug(char *cmd);
int initiateDebug(PROJLIST *plist)
{
static char cmd[512];
if (uState == notDebugging)
{
int val = IsPEFile(plist->name);
debugProject = plist;
stopWinMain = plist->buildFlags &BF_BREAKWINMAIN ? 1 : 0;
if (val <= 0)
{
if (val == 0)
ExtendedMessageBox("File not found", MB_SYSTEMMODAL |
MB_SETFOREGROUND, "File %s was not found", cmd);
else
ExtendedMessageBox("Not PE file", MB_SYSTEMMODAL |
MB_SETFOREGROUND,
"File %s must be a win32 executable to debug.", cmd);
return uState;
} Semaphores = TRUE;
StartupSem = CreateSemaphore(0, 0, 1, 0);
BreakpointSem = CreateSemaphore(0, 0, 1, 0);
sprintf(cmd, "\"%s\" %s", plist->name, plist->cmdline);
CloseHandle(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)StartDebug,
(LPVOID)cmd, 0, &debugThreadID));
WaitForSingleObject(StartupSem, INFINITE);
PostMessage(hwndFrame, WM_REDRAWTOOLBAR, 0, 0);
}
return uState;
}
//-------------------------------------------------------------------------
HANDLE GetThreadHandle(DWORD procid, DWORD threadid)
{
THREAD *thread = DebugProcess.threads;
while (thread)
{
if (thread->idThread == threadid)
return thread->hThread;
thread = thread->next;
}
return DebugProcess.threads->hThread;
}
//-------------------------------------------------------------------------
BOOL CALLBACK topenumfunc(HWND wnd, LPARAM value)
{
DWORD id;
GetWindowThreadProcessId(wnd, &id);
if (id == value)
{
SetForegroundWindow(wnd);
if (IsIconic(wnd))
ShowWindow(wnd, SW_RESTORE);
return FALSE;
}
return TRUE;
}
/* if we don't do this, the debugger locks up sometimes */
void ProcessToTop(DWORD processid)
{
HWND top;
// return ;
top = GetTopWindow(0);
EnumWindows((WNDENUMPROC)topenumfunc, processid);
// while (GetTopWindow(0) != top)
// Sleep(1);
}
//-------------------------------------------------------------------------
static int HandleBreakpoint(DEBUG_EVENT *info)
{
if (uState != Aborting)
uState = atBreakpoint;
PostMessage(hwndFrame, WM_REDRAWTOOLBAR, 0, 0);
PostMessage(hwndFrame, WM_BREAKPOINT, 0, (LPARAM)info);
if (hwndRegister)
PostMessage(hwndRegister, WM_COMMAND, ID_SETADDRESS, (LPARAM)
GetThreadHandle(info->dwProcessId, info->dwThreadId));
PostMessage(hwndWatch, WM_COMMAND, ID_SETADDRESS, 0);
if (hwndStack)
PostMessage(hwndStack, WM_RESTACK, (WPARAM)1, 0);
if (hwndThread)
PostMessage(hwndThread, WM_RESTACK, (WPARAM)1, 0);
if (hwndDump)
PostMessage(hwndDump, WM_RESTACK, 0, 0);
if (uState != Aborting && uState != notDebugging)
{
WaitForSingleObject(BreakpointSem, INFINITE);
}
// PostMessage(hwndRegister,WM_COMMAND,ID_SETCONTEXT,0) ;
if (hwndStack)
PostMessage(hwndStack, WM_RESTACK, (WPARAM)0, 0);
if (hwndThread)
PostMessage(hwndThread, WM_RESTACK, (WPARAM)0, 0);
ApplyBreakAddress(0, 0); // get rid of the break line
if (uState == notDebugging || uState == Aborting)
{
PostMessage(hwndFrame, WM_REDRAWTOOLBAR, 0, 0);
return DBG_TERMINATE_PROCESS;
}
else
{
if (uState != SteppingOut && uState != SteppingOver && uState !=
SteppingIn && uState != StepInOut)
uState = Running;
PostMessage(hwndFrame, WM_REDRAWTOOLBAR, 0, 0);
return DBG_CONTINUE;
}
}
//-------------------------------------------------------------------------
static int HandleException(DEBUG_EVENT *info)
{
if (uState == notDebugging || uState == Aborting)
return DBG_EXCEPTION_NOT_HANDLED;
if (!(selectedProject->buildFlags &BF_DEBUGEXCEPTION))
if (info->u.Exception.dwFirstChance)
return DBG_EXCEPTION_NOT_HANDLED;
uState = atException;
PostMessage(hwndFrame, WM_REDRAWTOOLBAR, 0, 0);
PostMessage(hwndFrame, WM_EXCEPTION, 0, (LPARAM)info);
PostMessage(hwndWatch, WM_COMMAND, ID_SETADDRESS, 0);
if (hwndStack)
PostMessage(hwndStack, WM_RESTACK, (WPARAM)1, 0);
if (hwndThread)
PostMessage(hwndThread, WM_RESTACK, (WPARAM)1, 0);
if (hwndRegister)
PostMessage(hwndRegister, WM_COMMAND, ID_SETADDRESS, (LPARAM)
GetThreadHandle(info->dwProcessId, info->dwThreadId));
if (hwndDump)
PostMessage(hwndDump, WM_RESTACK, 0, 0);
WaitForSingleObject(BreakpointSem, INFINITE);
// PostMessage(hwndRegister,WM_COMMAND,ID_SETCONTEXT,0) ;
if (hwndStack)
PostMessage(hwndStack, WM_RESTACK, (WPARAM)0, 0);
if (hwndThread)
PostMessage(hwndThread, WM_RESTACK, (WPARAM)0, 0);
if (uState == notDebugging || uState == Aborting)
{
PostMessage(hwndFrame, WM_REDRAWTOOLBAR, 0, 0);
return DBG_TERMINATE_PROCESS;
}
if (uState != SteppingOut && uState != SteppingOver && uState != SteppingIn
&& uState != StepInOut)
uState = Running;
PostMessage(hwndFrame, WM_REDRAWTOOLBAR, 0, 0);
return DBG_CONTINUE;
}
//-------------------------------------------------------------------------
void SingleStep(DWORD procID, DWORD threadID)
{
StoppedThread->regs.EFlags |= TF_BIT;
SingleStepping = TRUE;
}
//-------------------------------------------------------------------------
void ClearTraceFlag(DWORD procID, DWORD threadID)
{
SingleStepping = FALSE;
}
//-------------------------------------------------------------------------
void BlastExitProcFunc(HANDLE hProcess, DWORD procID, DWORD threadID, DWORD
address)
{
int buf = 0; // exit code
StoppedThread->regs.Eip = address;
StoppedThread->regs.Esp -= 4;
WriteProcessMemory(hProcess, (LPVOID)StoppedThread->regs.Esp, (LPVOID) &buf,
4, 0);
StoppedThread->regs.Esp -= 4;
}
//-------------------------------------------------------------------------
void GetRegs(DWORD procID, DWORD threadID)
{
THREAD *thread = DebugProcess.threads;
StoppedThread = thread;
while (thread)
{
if (thread->idThread == threadID)
StoppedThread = thread;
thread->regs.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT |
CONTEXT_DEBUG_REGISTERS;
GetThreadContext(thread->hThread, &thread->regs);
thread = thread->next;
}
}
//-------------------------------------------------------------------------
void SetRegs(DWORD procID, DWORD threadID)
{
THREAD *thread = DebugProcess.threads;
while (thread)
{
SetThreadContext(thread->hThread, &thread->regs);
thread = thread->next;
}
}
//-------------------------------------------------------------------------
void SetTempBreakPoint(int procid, int threadid, int address)
{
DebugProcess.breakpoints.address = address;
DebugProcess.idTempBpThread = threadid;
}
//-------------------------------------------------------------------------
void ClearTempBreakPoint(int procid)
{
DebugProcess.breakpoints.address = 0;
}
//-------------------------------------------------------------------------
int SittingOnBreakPoint(DEBUG_EVENT *dbe)
{
return isBreakPoint((int)dbe->u.Exception.ExceptionRecord.ExceptionAddress);
}
//-------------------------------------------------------------------------
void WriteBreakPoint(HANDLE hProcess, int address, int value)
{
int bf = value;
MEMORY_BASIC_INFORMATION mbi;
DWORD dwOldProtect;
// if (!IsNT() && address >= 0x80000000)
// return ;
if (!VirtualQueryEx(hProcess, (LPVOID)address, &mbi, sizeof(mbi)))
ExtendedMessageBox("Error", MB_SYSTEMMODAL, "Could not query pages %d",
GetLastError());
if (!VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize,
PAGE_EXECUTE_WRITECOPY, &mbi.Protect))
ExtendedMessageBox("Error", MB_SYSTEMMODAL,
"Could not protect pages %d", GetLastError());
if (!WriteProcessMemory(hProcess, (LPVOID)address, (LPVOID) &bf, 1, 0))
ExtendedMessageBox("hi", MB_SYSTEMMODAL,
"Could not write breakpoint address %x %d", address, GetLastError())
;
VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, mbi.Protect,
&dwOldProtect);
FlushInstructionCache(hProcess, (LPVOID)address, 1);
}
//-------------------------------------------------------------------------
void allocBreakPoint(HANDLE hProcess, BREAKPOINT *pt)
{
unsigned char bf;
if (!pt->active && pt->address)
{
DWORD len;
if (ReadProcessMemory(hProcess, (LPVOID)pt->address, (LPVOID) &bf, 1,
&len))
{
if (!len)
return ;
if (bf == 0xcc)
return ;
WriteBreakPoint(hProcess, pt->address, 0xcc);
pt->active = TRUE;
pt->tempVal = bf;
}
}
}
//-------------------------------------------------------------------------
void freeBreakPoint(HANDLE hProcess, BREAKPOINT *pt)
{
if (pt->active)
{
WriteBreakPoint(hProcess, pt->address, pt->tempVal);
pt->active = FALSE;
}
}
//-------------------------------------------------------------------------
void SetBreakPoints(int procid, int running)
{
BREAKPOINT *p = &DebugProcess.breakpoints;
#ifdef HBREAK
if (running)
hbpSetBP();
#endif
while (p)
{
if (p->address)
allocBreakPoint(DebugProcess.hProcess, p);
p = p->next;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -