976 lines
20 KiB
C
976 lines
20 KiB
C
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <assert.h>
|
|
#include <imagehlp.h>
|
|
#include <dbhpriv.h>
|
|
|
|
#define MAX_STR 256
|
|
#define WILD_UNDERSCORE 1
|
|
#define SYM_BUFFER_SIZE (sizeof(IMAGEHLP_SYMBOL64) + MAX_SYM_NAME)
|
|
|
|
|
|
typedef struct {
|
|
char mask[MAX_STR];
|
|
DWORD64 base;
|
|
} ENUMSYMDATA, *PENUMSYMDATA;
|
|
|
|
|
|
typedef enum
|
|
{
|
|
cmdQuit = 0,
|
|
cmdHelp,
|
|
cmdVerbose,
|
|
cmdLoad,
|
|
cmdUnload,
|
|
cmdEnum,
|
|
cmdName,
|
|
cmdAddr,
|
|
cmdBase,
|
|
cmdNext,
|
|
cmdPrev,
|
|
cmdLine,
|
|
cmdSymInfo,
|
|
cmdDiaVer,
|
|
cmdUndec,
|
|
cmdFindFile,
|
|
cmdEnumSrcFiles,
|
|
cmdMax
|
|
};
|
|
|
|
typedef BOOL (*CMDPROC)(char *params);
|
|
|
|
typedef struct _CMD
|
|
{
|
|
char token[MAX_STR + 1];
|
|
char shorttoken[4];
|
|
CMDPROC fn;
|
|
} CMD, *PCMD;
|
|
|
|
|
|
BOOL fnQuit(char *);
|
|
BOOL fnHelp(char *);
|
|
BOOL fnVerbose(char *);
|
|
BOOL fnLoad(char *);
|
|
BOOL fnUnload(char *);
|
|
BOOL fnEnum(char *);
|
|
BOOL fnName(char *);
|
|
BOOL fnAddr(char *);
|
|
BOOL fnBase(char *);
|
|
BOOL fnNext(char *);
|
|
BOOL fnPrev(char *);
|
|
BOOL fnLine(char *);
|
|
BOOL fnSymInfo(char *);
|
|
BOOL fnDiaVer(char *);
|
|
BOOL fnUndec(char *);
|
|
BOOL fnFindFile(char *);
|
|
BOOL fnEnumSrcFiles(char *);
|
|
|
|
|
|
CMD gCmd[cmdMax] =
|
|
{
|
|
{"quit", "q", fnQuit},
|
|
{"help", "h", fnHelp},
|
|
{"verbose", "v", fnVerbose},
|
|
{"load", "l", fnLoad},
|
|
{"unload", "u", fnUnload},
|
|
{"enum", "x", fnEnum},
|
|
{"name", "n", fnName},
|
|
{"addr", "a", fnAddr},
|
|
{"base", "b", fnBase},
|
|
{"next", "t", fnNext},
|
|
{"prev", "v", fnPrev},
|
|
{"line", "i", fnLine},
|
|
{"sym" , "s", fnSymInfo},
|
|
{"dia", "d", fnDiaVer},
|
|
{"undec", "n", fnUndec},
|
|
{"ff", "f", fnFindFile},
|
|
{"src", "r", fnEnumSrcFiles}
|
|
};
|
|
|
|
char gModName[MAX_STR];
|
|
char gImageName[MAX_STR];
|
|
char gSymbolSearchPath[MAX_STR];
|
|
DWORD64 gBase;
|
|
DWORD64 gDefaultBase;
|
|
DWORD64 gDefaultBaseForPDB;
|
|
DWORD gOptions;
|
|
HANDLE gHP;
|
|
|
|
|
|
int
|
|
WINAPIV
|
|
dprintf(
|
|
LPSTR Format,
|
|
...
|
|
)
|
|
{
|
|
static char buf[1000] = "DBGHELP: ";
|
|
va_list args;
|
|
|
|
if ((gOptions & SYMOPT_DEBUG) == 0)
|
|
return 1;
|
|
|
|
va_start(args, Format);
|
|
_vsnprintf(buf, sizeof(buf)-9, Format, args);
|
|
va_end(args);
|
|
printf(buf);
|
|
return 1;
|
|
}
|
|
|
|
|
|
__inline int ucase(int c)
|
|
{
|
|
return (gOptions & SYMOPT_CASE_INSENSITIVE) ? toupper(c) : c;
|
|
}
|
|
|
|
|
|
void dumpsym(
|
|
PIMAGEHLP_SYMBOL64 sym
|
|
)
|
|
{
|
|
printf(" name : %s\n", sym->Name);
|
|
printf(" addr : 0x%I64x\n", sym->Address);
|
|
printf(" size : 0x%x\n", sym->Size);
|
|
printf("flags : 0x%x\n", sym->Flags);
|
|
}
|
|
|
|
|
|
BOOL
|
|
MatchPattern(
|
|
char *sz,
|
|
char *pattern
|
|
)
|
|
{
|
|
char c, p, l;
|
|
|
|
if (!*pattern)
|
|
return TRUE;
|
|
|
|
for (; ;) {
|
|
p = *pattern++;
|
|
p = (char)ucase(p);
|
|
switch (p) {
|
|
case 0: // end of pattern
|
|
return *sz ? FALSE : TRUE; // if end of string TRUE
|
|
|
|
case '*':
|
|
while (*sz) { // match zero or more char
|
|
if (MatchPattern (sz++, pattern)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return MatchPattern (sz, pattern);
|
|
|
|
case '?':
|
|
if (*sz++ == 0) { // match any one char
|
|
return FALSE; // not end of string
|
|
}
|
|
break;
|
|
|
|
case WILD_UNDERSCORE:
|
|
while (*sz == '_') {
|
|
sz++;
|
|
}
|
|
break;
|
|
|
|
case '[':
|
|
if ( (c = *sz++) == 0) { // match char set
|
|
return FALSE; // syntax
|
|
}
|
|
|
|
c = (CHAR)ucase(c);
|
|
l = 0;
|
|
while (p = *pattern++) {
|
|
if (p == ']') { // if end of char set, then
|
|
return FALSE; // no match found
|
|
}
|
|
|
|
if (p == '-') { // check a range of chars?
|
|
p = *pattern; // get high limit of range
|
|
if (p == 0 || p == ']') {
|
|
return FALSE; // syntax
|
|
}
|
|
|
|
if (c >= l && c <= p) {
|
|
break; // if in range, move on
|
|
}
|
|
}
|
|
|
|
l = p;
|
|
if (c == p) { // if char matches this element
|
|
break; // move on
|
|
}
|
|
}
|
|
|
|
while (p && p != ']') { // got a match in char set
|
|
p = *pattern++; // skip to end of set
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
c = *sz++;
|
|
if (ucase(c) != p) { // check for exact char
|
|
return FALSE; // not a match
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
cbEnumSymbols(
|
|
PSYMBOL_INFO si,
|
|
ULONG size,
|
|
PVOID context
|
|
)
|
|
{
|
|
PENUMSYMDATA esd = (PENUMSYMDATA)context;
|
|
|
|
printf("0x%I64x : ", si->Address, si->Name);
|
|
if (si->Flags & SYMF_FORWARDER)
|
|
printf("%c ", 'F');
|
|
else if (si->Flags & SYMF_EXPORT)
|
|
printf("%c ", 'E');
|
|
else
|
|
printf(" ");
|
|
printf("%s\n", si->Name);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
cbEnumSym(
|
|
PTSTR name,
|
|
DWORD64 address,
|
|
ULONG size,
|
|
PVOID context
|
|
)
|
|
{
|
|
PENUMSYMDATA esd = (PENUMSYMDATA)context;
|
|
|
|
if (MatchPattern(name, esd->mask))
|
|
printf("0x%I64x : %s\n", address, name);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
cbSrcFiles(
|
|
PSOURCEFILE pSourceFile,
|
|
PVOID UserContext
|
|
)
|
|
{
|
|
if (!pSourceFile)
|
|
return FALSE;
|
|
|
|
printf("%s\n", pSourceFile->FileName);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
cbSymbol(
|
|
HANDLE hProcess,
|
|
ULONG ActionCode,
|
|
ULONG64 CallbackData,
|
|
ULONG64 UserContext
|
|
)
|
|
{
|
|
PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl;
|
|
PIMAGEHLP_CBA_READ_MEMORY prm;
|
|
IMAGEHLP_MODULE64 mi;
|
|
PUCHAR p;
|
|
ULONG i;
|
|
|
|
idsl = (PIMAGEHLP_DEFERRED_SYMBOL_LOAD64) CallbackData;
|
|
|
|
switch ( ActionCode ) {
|
|
case CBA_DEBUG_INFO:
|
|
dprintf("%s", (LPSTR)CallbackData);
|
|
break;
|
|
|
|
#if 0
|
|
case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
|
|
if (fControlC)
|
|
{
|
|
fControlC = 0;
|
|
return TRUE;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case CBA_DEFERRED_SYMBOL_LOAD_START:
|
|
dprintf("loading symbols for %s\n", gModName);
|
|
break;
|
|
|
|
case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
|
|
if (idsl->FileName && *idsl->FileName)
|
|
dprintf( "*** Error: could not load symbols for %s\n", idsl->FileName );
|
|
else
|
|
dprintf( "*** Error: could not load symbols [MODNAME UNKNOWN]\n");
|
|
break;
|
|
|
|
case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
|
|
dprintf("loaded symbols for %s\n", gModName);
|
|
break;
|
|
|
|
case CBA_SYMBOLS_UNLOADED:
|
|
dprintf("unloaded symbols for %s\n", gModName);
|
|
break;
|
|
|
|
#if 0
|
|
case CBA_READ_MEMORY:
|
|
prm = (PIMAGEHLP_CBA_READ_MEMORY)CallbackData;
|
|
return g_Target->ReadVirtual(prm->addr,
|
|
prm->buf,
|
|
prm->bytes,
|
|
prm->bytesread) == S_OK;
|
|
#endif
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
PIMAGEHLP_SYMBOL64 SymbolFromName(char *param)
|
|
{
|
|
BOOL rc;
|
|
PIMAGEHLP_SYMBOL64 sym;
|
|
char name[MAX_STR];
|
|
|
|
assert(name & *name);
|
|
|
|
sym = malloc(SYM_BUFFER_SIZE);
|
|
if (!sym)
|
|
return FALSE;
|
|
ZeroMemory(sym, SYM_BUFFER_SIZE);
|
|
sym->MaxNameLength = MAX_SYM_NAME;
|
|
|
|
sprintf(name, "%s!%s", gModName, param);
|
|
rc = SymGetSymFromName64(gHP, name, sym);
|
|
if (!rc) {
|
|
free(sym);
|
|
return NULL;
|
|
}
|
|
|
|
return sym;
|
|
}
|
|
|
|
|
|
BOOL fnQuit(char *param)
|
|
{
|
|
printf("goodbye\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL fnHelp(char *param)
|
|
{
|
|
printf(" dbh commands :\n");
|
|
printf(" help : prints this message\n");
|
|
printf(" quit : quits this program\n");
|
|
printf("verbose <on/off> : controls debug spew\n");
|
|
printf(" load <modname> : loads the requested module\n");
|
|
printf(" unload : unloads the current module\n");
|
|
printf(" enum <mask> : enumerates all matching symbols\n");
|
|
printf(" name <symname> : finds a symbol by it's name\n");
|
|
printf(" addr <address> : finds a symbol by it's hex address\n");
|
|
printf(" base <address> : sets the new default base address\n");
|
|
printf(" next <add/nam> : finds the symbol after the passed sym\n");
|
|
printf(" prev <add/nam> : finds the symbol before the passed sym\n");
|
|
printf(" line <file:#> : finds the matching line number\n");
|
|
printf(" sym : displays type and location of symbols\n");
|
|
printf(" dia : displays the DIA version\n");
|
|
printf("ff <path> <file> : finds file in path\n");
|
|
printf(" src <mask> : lists source files\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnVerbose(char *param)
|
|
{
|
|
int opts = gOptions;
|
|
|
|
if (!param || !*param)
|
|
printf("");
|
|
else if (!_strcmpi(param, "on"))
|
|
opts |= SYMOPT_DEBUG;
|
|
else if (!_strcmpi(param, "off"))
|
|
opts = gOptions & ~SYMOPT_DEBUG;
|
|
else
|
|
printf("verbose <on//off>\n");
|
|
|
|
gOptions = SymSetOptions(opts);
|
|
|
|
printf("verbose mode %s.\n", gOptions & SYMOPT_DEBUG ? "on" : "off");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnLoad(char *param)
|
|
{
|
|
DWORD64 addr;
|
|
char ext[MAX_STR];
|
|
char mod[MAX_STR];
|
|
|
|
if (!param || !*param || !strchr(param, '.'))
|
|
{
|
|
printf("load <modname> must specify a file to load symbols for.\n");
|
|
return TRUE;
|
|
}
|
|
|
|
_splitpath(param, NULL, NULL, mod, ext);
|
|
|
|
addr = 0;
|
|
if (gDefaultBase)
|
|
addr = gDefaultBase;
|
|
else if (!_strcmpi(ext, ".pdb"))
|
|
addr = gDefaultBaseForPDB;
|
|
|
|
fnUnload(NULL);
|
|
|
|
addr = SymLoadModule64(gHP,
|
|
NULL, // hFile,
|
|
param, // ImageName,
|
|
mod, // ModuleName,
|
|
addr, // BaseOfDll,
|
|
0x1000000); // SizeOfDll
|
|
|
|
if (!addr)
|
|
{
|
|
printf("error 0x%x loading %s\n", GetLastError(), param);
|
|
return TRUE;
|
|
}
|
|
|
|
if (gBase && !SymUnloadModule64(gHP, gBase))
|
|
printf("error unloading %s at 0x%x\n", gModName, gBase);
|
|
|
|
strcpy(gModName, mod);
|
|
strcpy(gImageName, param);
|
|
gBase = addr;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnUnload(char *param)
|
|
{
|
|
if (!gBase)
|
|
return TRUE;
|
|
|
|
if (!SymUnloadModule64(gHP, gBase))
|
|
printf("error unloading %s at 0x%x\n", gModName, gBase);
|
|
|
|
gBase = 0;
|
|
*gModName = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnEnum(char *param)
|
|
{
|
|
BOOL rc;
|
|
ENUMSYMDATA esd;
|
|
|
|
esd.base = gBase;
|
|
strcpy(esd.mask, param ? param : "");
|
|
|
|
rc = SymEnumSymbols(gHP, gBase, param, cbEnumSymbols, &esd);
|
|
if (!rc)
|
|
printf("error 0x%0 calling SymEnumerateSymbols()\n", GetLastError());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnEnumSrcFiles(char *param)
|
|
{
|
|
BOOL rc;
|
|
|
|
rc = SymEnumSourceFiles(gHP, gBase, param, cbSrcFiles, NULL);
|
|
if (!rc)
|
|
printf("error 0x%0 calling SymEnumSourceFiles()\n", GetLastError());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnName(char *param)
|
|
{
|
|
BOOL rc;
|
|
PIMAGEHLP_SYMBOL64 sym;
|
|
|
|
if (!param || !*param)
|
|
{
|
|
printf("name <symbolname> - finds a symbol by it's name\n");
|
|
return TRUE;
|
|
}
|
|
|
|
sym = SymbolFromName(param);
|
|
if (!sym)
|
|
return TRUE;
|
|
|
|
dumpsym(sym);
|
|
free(sym);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnAddr(char *param)
|
|
{
|
|
BOOL rc;
|
|
PIMAGEHLP_SYMBOL64 sym;
|
|
DWORD64 addr;
|
|
DWORD64 disp;
|
|
char *p;
|
|
|
|
addr = 0;
|
|
if (param && *param)
|
|
{
|
|
p = param;
|
|
if (*(p + 1) == 'x' || *(p + 1) == 'X')
|
|
p += 2;
|
|
sscanf(p, "%I64x", &addr);
|
|
}
|
|
|
|
if (!addr)
|
|
{
|
|
printf("addr <address> : finds a symbol by it's hex address\n");
|
|
return TRUE;
|
|
}
|
|
|
|
sym = malloc(SYM_BUFFER_SIZE);
|
|
if (!sym)
|
|
return FALSE;
|
|
ZeroMemory(sym, SYM_BUFFER_SIZE);
|
|
sym->MaxNameLength = MAX_SYM_NAME;
|
|
|
|
rc = SymGetSymFromAddr64(gHP, addr, &disp, sym);
|
|
if (rc)
|
|
{
|
|
printf("%s", sym->Name);
|
|
if (disp)
|
|
printf("+0x%I64x", disp);
|
|
printf("\n");
|
|
dumpsym(sym);
|
|
}
|
|
|
|
free(sym);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnNextPrev(int direction, char *param)
|
|
{
|
|
BOOL rc;
|
|
PIMAGEHLP_SYMBOL64 sym;
|
|
DWORD64 addr;
|
|
char name[MAX_STR];
|
|
char *p;
|
|
|
|
addr = 0;
|
|
if (param && *param)
|
|
{
|
|
p = param;
|
|
if (*(p + 1) == 'x' || *(p + 1) == 'X')
|
|
p += 2;
|
|
sscanf(p, "%I64x", &addr);
|
|
}
|
|
|
|
if (!addr)
|
|
{
|
|
sym = SymbolFromName(param);
|
|
if (!sym)
|
|
return TRUE;
|
|
addr = sym->Address;
|
|
if (!addr) {
|
|
free(sym);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sym = malloc(SYM_BUFFER_SIZE);
|
|
if (!sym)
|
|
return FALSE;
|
|
}
|
|
|
|
if (direction > 0)
|
|
rc = SymGetSymNext64(gHP, sym);
|
|
else
|
|
rc = SymGetSymPrev64(gHP, sym);
|
|
|
|
if (rc)
|
|
dumpsym(sym);
|
|
|
|
free(sym);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnNext(char *param)
|
|
{
|
|
return fnNextPrev(1, param);
|
|
}
|
|
|
|
|
|
BOOL fnPrev(char *param)
|
|
{
|
|
return fnNextPrev(-1, param);
|
|
}
|
|
|
|
|
|
BOOL fnBase(char *param)
|
|
{
|
|
BOOL rc;
|
|
PIMAGEHLP_SYMBOL64 sym;
|
|
DWORD64 addr;
|
|
DWORD64 disp;
|
|
char *p;
|
|
|
|
addr = 0;
|
|
if (param && *param)
|
|
{
|
|
p = param;
|
|
if (*(p + 1) == 'x' || *(p + 1) == 'X')
|
|
p += 2;
|
|
sscanf(p, "%I64x", &addr);
|
|
}
|
|
|
|
if (!addr)
|
|
{
|
|
printf("base <address> : sets the base address for module loads\n");
|
|
return TRUE;
|
|
}
|
|
|
|
gDefaultBase = addr;
|
|
if (gBase)
|
|
fnLoad(gImageName);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnLine(char *param)
|
|
{
|
|
char *file;
|
|
DWORD linenum;
|
|
BOOL rc;
|
|
IMAGEHLP_LINE64 line;
|
|
LONG disp;
|
|
|
|
if (!param || !*param)
|
|
return TRUE;
|
|
|
|
file = param;
|
|
|
|
while (*param != ':') {
|
|
if (!*param)
|
|
return TRUE;
|
|
param++;
|
|
}
|
|
*param++ = 0;
|
|
linenum = atoi(param);
|
|
if (!linenum)
|
|
return TRUE;
|
|
|
|
memset(&line, 0, sizeof(line));
|
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
|
rc = SymGetLineFromName64(gHP,
|
|
gModName,
|
|
file,
|
|
linenum,
|
|
&disp,
|
|
&line);
|
|
|
|
if (!rc) {
|
|
printf("line: error 0x%x looking for %s#%d\n",
|
|
GetLastError(),
|
|
file,
|
|
linenum);
|
|
return TRUE;
|
|
}
|
|
|
|
printf("file : %s\n", line.FileName);
|
|
printf("line : %d\n", linenum);
|
|
printf("addr : 0x%I64x\n", line.Address);
|
|
printf("disp : 0x%x\n", disp);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnSymInfo(char *param)
|
|
{
|
|
DBH_MODSYMINFO msi;
|
|
|
|
if (!gBase)
|
|
return TRUE;
|
|
|
|
msi.function = dbhModSymInfo;
|
|
msi.sizeofstruct = sizeof(msi);
|
|
msi.addr = gBase;
|
|
|
|
if (!dbghelp(gHP, (PVOID)&msi))
|
|
printf("error grabbing symbol info\n");
|
|
|
|
printf("%s: symtype=0x%x, src=%s\n", gModName, msi.type, msi.file);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL fnDiaVer(char *param)
|
|
{
|
|
DBH_DIAVERSION dv;
|
|
|
|
dv.function = dbhDiaVersion;
|
|
dv.sizeofstruct = sizeof(dv);
|
|
|
|
if (!dbghelp(0, (PVOID)&dv))
|
|
printf("error grabbing dia version info\n");
|
|
|
|
printf("DIA version 0x%x\n", dv.ver);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL fnUndec(char *param)
|
|
{
|
|
DWORD rc;
|
|
char uname[MAX_SYM_NAME + 1];
|
|
|
|
if (!param || !*param)
|
|
{
|
|
printf("undec <symbolname> - undecorates a C++ mangled symbol name\n");
|
|
return TRUE;
|
|
}
|
|
|
|
rc = UnDecorateSymbolName(param, uname, MAX_SYM_NAME, UNDNAME_COMPLETE);
|
|
if (!rc) {
|
|
printf("error 0x%u undecorating %s\n", GetLastError(), param);
|
|
} else {
|
|
printf("%s = %s\n", param, uname);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL fnFindFile(char *param)
|
|
{
|
|
DWORD rc;
|
|
char root[MAX_PATH + 1];
|
|
char file[MAX_PATH + 1];
|
|
char found[MAX_PATH + 1];
|
|
|
|
if (!param)
|
|
{
|
|
printf("ff <root path> <file name> - finds file in path\n");
|
|
return TRUE;
|
|
}
|
|
|
|
sscanf(param, "%s %s", root, file);
|
|
|
|
if (!*root || !*file)
|
|
{
|
|
printf("ff <root path> <file name> - finds file in path\n");
|
|
return TRUE;
|
|
}
|
|
|
|
*found = 0;
|
|
|
|
rc = SearchTreeForFile(root, file, found);
|
|
|
|
if (!rc) {
|
|
printf("error 0x%u looking for %s\n", GetLastError(), file);
|
|
} else {
|
|
printf("found %s\n", found);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
char *GetParameters(char *cmd)
|
|
{
|
|
char *p = cmd;
|
|
char *param = NULL;
|
|
|
|
while (*p++)
|
|
{
|
|
if (isspace(*p))
|
|
{
|
|
*p++ = 0;
|
|
return *p ? p : NULL;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void prompt()
|
|
{
|
|
if (!*gModName)
|
|
printf("dbh: ");
|
|
else
|
|
printf("%s [0x%I64x]: ", gModName, gBase);
|
|
}
|
|
|
|
|
|
int InputLoop()
|
|
{
|
|
char cmd[MAX_STR + 1];
|
|
char *params;
|
|
int i;
|
|
BOOL rc;
|
|
|
|
printf("\n");
|
|
|
|
do
|
|
{
|
|
|
|
prompt();
|
|
gets(cmd);
|
|
params = GetParameters(cmd);
|
|
// printf("cmd[%s] params[%s]\n", cmd, params);
|
|
|
|
for (i = 0; i < cmdMax; i++)
|
|
{
|
|
if (!_strcmpi(cmd, gCmd[i].token) ||
|
|
!_strcmpi(cmd, gCmd[i].shorttoken))
|
|
break;
|
|
}
|
|
|
|
if (i == cmdMax)
|
|
{
|
|
printf("[%s] is an unrecognized command.\n", cmd);
|
|
rc = TRUE;
|
|
continue;
|
|
}
|
|
else
|
|
rc = gCmd[i].fn(params);
|
|
|
|
} while (rc);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL init()
|
|
{
|
|
int i;
|
|
BOOL rc;
|
|
|
|
*gModName = 0;
|
|
gBase = 0;;
|
|
gDefaultBaseForPDB = 0x1000000;
|
|
|
|
printf("dbh: initializing...\n");
|
|
i = GetEnvironmentVariable("_NT_SYMBOL_PATH", gSymbolSearchPath, MAX_STR);
|
|
if (i < 1)
|
|
*gSymbolSearchPath = 0;
|
|
printf("Symbol Path = [%s]\n", gSymbolSearchPath);
|
|
|
|
gHP = GetCurrentProcess();
|
|
rc = SymInitialize(gHP, gSymbolSearchPath, FALSE);
|
|
if (!rc)
|
|
{
|
|
printf("error 0x%x from SymInitialize()\n", GetLastError());
|
|
return rc;
|
|
}
|
|
|
|
gOptions = SymSetOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_NO_CPP | SYMOPT_LOAD_LINES);
|
|
printf("SymOpts = 0x%x\n", gOptions);
|
|
|
|
rc = SymRegisterCallback64(gHP, cbSymbol, 0);
|
|
if (!rc)
|
|
{
|
|
printf("error 0x%x from SymRegisterCallback64()\n", GetLastError());
|
|
return rc;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
void cleanup()
|
|
{
|
|
fnUnload(NULL);
|
|
SymCleanup(gHP);
|
|
}
|
|
|
|
|
|
BOOL cmdline(int argc, char *argv[])
|
|
{
|
|
int i;
|
|
char *p;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
p = argv[i];
|
|
switch (*p)
|
|
{
|
|
case '/':
|
|
case '-':
|
|
p++;
|
|
switch (tolower(*p))
|
|
{
|
|
case 'v':
|
|
fnVerbose("on");
|
|
break;
|
|
default:
|
|
printf("%s is an unknown switch\n", argv[i]);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
fnLoad(argv[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#include <crtdbg.h>
|
|
|
|
__cdecl
|
|
main(
|
|
int argc,
|
|
char *argv[],
|
|
char *envp[]
|
|
)
|
|
{
|
|
DWORD rc;
|
|
_CrtSetDbgFlag( ( _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF ) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG ) );
|
|
|
|
if (!init())
|
|
return 1;
|
|
cmdline(argc, argv);
|
|
rc = InputLoop();
|
|
cleanup();
|
|
|
|
_CrtDumpMemoryLeaks();
|
|
|
|
return rc;
|
|
}
|
|
|