34#define DBGHELP(name,ret,par) typedef ret (WINAPI *name##Type) par;
38#define DBGHELP(name,ret,par) name##Type _##name;
49#define DBGHELP(name,ret,par) #name,
50static char const *DebughelpFunctionNames[] =
58static HMODULE g_dbghelp;
61static bool g_oldDbghelp;
63static void InitDbghelp(
void)
70 char dbgHelpPath[256];
71 if (GetModuleFileName(
NULL,dbgHelpPath,
sizeof(dbgHelpPath)))
73 char *slash=strrchr(dbgHelpPath,
'\\');
76 strcpy(slash+1,
"DBGHELP.DLL");
77 g_dbghelp=::LoadLibrary(dbgHelpPath);
82 g_dbghelp=::LoadLibrary(
"DBGHELP.DLL");
88 unsigned *funcptr=gDbg.funcPtr;
89 for (
unsigned k=0;DebughelpFunctionNames[k];++k,++funcptr)
91 *funcptr=(unsigned)GetProcAddress(g_dbghelp,DebughelpFunctionNames[k]);
95 if (DebughelpFunctionNames[k])
98 while (funcptr!=gDbg.funcPtr)
104 gDbg._SymSetOptions(gDbg._SymGetOptions()|SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
107 gDbg._SymInitialize((HANDLE)GetCurrentProcessId(),
NULL,
TRUE);
111 if (!GetProcAddress(g_dbghelp,
"SymEnumSymbolsForAddr"))
127 m_numAddr=src.m_numAddr;
128 memcpy(m_addr,src.m_addr,m_numAddr*
sizeof(*m_addr));
135 DFAIL_IF_MSG(n<0||n>=MAX_ADDR,n <<
"/" << MAX_ADDR)
return 0;
142 DFAIL_IF(bufSize<64||bufSize>=0x80000000)
return;
146 char *bufEnd=buf+bufSize;
148 buf+=wsprintf(buf,
"%08x",addr);
151 unsigned modBase=gDbg._SymGetModuleBase((HANDLE)GetCurrentProcessId(),addr);
154 strcpy(buf,
" (unknown module)");
159 if (IsBadReadPtr((
void *)addr,4)||IsBadCodePtr((FARPROC)addr))
161 strcpy(buf,
" (invalid code addr)");
165 char symbolBuffer[512];
166 GetModuleFileName((HMODULE)modBase,symbolBuffer,
sizeof(symbolBuffer));
168 char *p=strrchr(symbolBuffer,
'\\');
169 p=p?p+1:symbolBuffer;
175 buf+=wsprintf(buf,
"+0x%x",addr-modBase);
178 PIMAGEHLP_SYMBOL symPtr=(PIMAGEHLP_SYMBOL)symbolBuffer;
179 memset(symPtr,0,
sizeof(symbolBuffer));
180 symPtr->SizeOfStruct=
sizeof(IMAGEHLP_SYMBOL);
181 symPtr->MaxNameLength=
sizeof(symbolBuffer)-
sizeof(IMAGEHLP_SYMBOL);
183 if (!gDbg._SymGetSymFromAddr((HANDLE)GetCurrentProcessId(),addr,&displacement,symPtr))
185 if ((
unsigned int)(bufEnd-buf)<strlen(symPtr->Name)+16)
187 buf+=wsprintf(buf,
", %s+0x%x",symPtr->Name,displacement);
191 memset(&line,0,
sizeof(line));
192 line.SizeOfStruct=
sizeof(line);
193 if (!gDbg._SymGetLineFromAddr((HANDLE)GetCurrentProcessId(),addr,&displacement,&line))
196 p=strrchr(line.FileName,
'\\');
197 p=p?p+1:line.FileName;
199 if ((
unsigned int)(bufEnd-buf)<strlen(p)+16)
201 buf+=wsprintf(buf,
", %s:%i+0x%x",p,line.LineNumber,displacement);
205 char *bufMod,
unsigned sizeMod,
unsigned *relMod,
206 char *bufSym,
unsigned sizeSym,
unsigned *relSym,
207 char *bufFile,
unsigned sizeFile,
unsigned *linePtr,
unsigned *relLine)
211 if (bufMod) *bufMod=0;
212 if (relMod) *relMod=0;
213 if (bufSym) *bufSym=0;
214 if (relSym) *relSym=0;
216 if (bufFile) *bufFile=0;
217 if (linePtr) *linePtr=0;
218 if (relLine) *relLine=0;
220 DFAIL_IF(bufMod&&sizeMod<16)
return;
221 DFAIL_IF(bufSym&&sizeSym<16)
return;
222 DFAIL_IF(bufFile&&sizeFile<16)
return;
225 unsigned modBase=gDbg._SymGetModuleBase((HANDLE)GetCurrentProcessId(),addr);
229 strcpy(bufMod,
"(unknown mod)");
231 strcpy(bufSym,
"(unknown)");
236 if (IsBadReadPtr((
void *)addr,4)||IsBadCodePtr((FARPROC)addr))
239 strcpy(bufMod,
"(inv code addr)");
241 strcpy(bufSym,
"(unknown)");
245 char symbolBuffer[512];
248 GetModuleFileName((HMODULE)modBase,symbolBuffer,
sizeof(symbolBuffer));
250 char *p=strrchr(symbolBuffer,
'\\');
251 p=p?p+1:symbolBuffer;
252 strncpy(bufMod,p,sizeMod);
256 *relMod=addr-modBase;
261 PIMAGEHLP_SYMBOL symPtr=(PIMAGEHLP_SYMBOL)symbolBuffer;
262 memset(symPtr,0,
sizeof(symbolBuffer));
263 symPtr->SizeOfStruct=
sizeof(IMAGEHLP_SYMBOL);
264 symPtr->MaxNameLength=
sizeof(symbolBuffer)-
sizeof(IMAGEHLP_SYMBOL);
266 if (gDbg._SymGetSymFromAddr((HANDLE)GetCurrentProcessId(),addr,&displacement,symPtr))
268 strncpy(bufSym,symPtr->Name,sizeSym);
271 *relSym=displacement;
274 strcpy(bufSym,
"(unknown)");
281 memset(&line,0,
sizeof(line));
282 line.SizeOfStruct=
sizeof(line);
284 if (!gDbg._SymGetLineFromAddr((HANDLE)GetCurrentProcessId(),addr,&displacement,&line))
285 strcpy(bufFile,
"(unknown)");
288 char *p=strrchr(line.FileName,
'\\');
289 p=p?p+1:line.FileName;
290 strncpy(bufFile,p,sizeFile);
291 bufFile[sizeFile-1]=0;
293 *linePtr=line.LineNumber;
295 *relLine=displacement;
302 dbg << sig.Size() <<
" addresses:\n";
304 for (
unsigned k=0;k<sig.Size();k++)
307 sig.GetSymbol(sig.GetAddress(k),buf,
sizeof(buf));
316DebugStackwalk::DebugStackwalk(
void)
322DebugStackwalk::~DebugStackwalk()
343 if (!gDbg._StackWalk)
347 STACKFRAME stackFrame;
348 memset(&stackFrame,0,
sizeof(stackFrame));
350 stackFrame.AddrPC.Mode = AddrModeFlat;
351 stackFrame.AddrStack.Mode = AddrModeFlat;
352 stackFrame.AddrFrame.Mode = AddrModeFlat;
357 stackFrame.AddrPC.Offset = ctx->Eip;
358 stackFrame.AddrStack.Offset = ctx->Esp;
359 stackFrame.AddrFrame.Offset = ctx->Ebp;
364 unsigned long reg_eip, reg_ebp, reg_esp;
373 stackFrame.AddrPC.Offset = reg_eip;
374 stackFrame.AddrStack.Offset = reg_esp;
375 stackFrame.AddrFrame.Offset = reg_ebp;
380 while (sig.m_numAddr<Signature::MAX_ADDR&&
381 gDbg._StackWalk(IMAGE_FILE_MACHINE_I386,GetCurrentProcess(),GetCurrentThread(),
382 &stackFrame,
NULL,
NULL,gDbg._SymFunctionTableAccess,gDbg._SymGetModuleBase,
NULL))
387 sig.m_addr[sig.m_numAddr++]=stackFrame.AddrPC.Offset;
390 return sig.m_numAddr;
Debug module main class (singleton).
static void GetSymbol(unsigned addr, char *buf, unsigned bufSize)
Determines symbol for given address.
Signature & operator=(const Signature &src)
unsigned GetAddress(int n) const
Get a single address from the signature.
static int StackWalk(Signature &sig, struct _CONTEXT *ctx=0)
Walks the stack from the given address.
static void * GetDbghelpHandle(void)
static bool IsOldDbghelp(void)
#define DFAIL_IF_MSG(cond, msg)
Debug & operator<<(Debug &dbg, const DebugStackwalk::Signature &sig)
Dumps a complete signature with symbols.