diff --git a/tools/winedump/debug.c b/tools/winedump/debug.c index 07ae75c6df7..8d24a173e89 100644 --- a/tools/winedump/debug.c +++ b/tools/winedump/debug.c @@ -582,3 +582,116 @@ void dump_frame_pointer_omission(unsigned long base, unsigned long len) /* FPO is used to describe nonstandard stack frames */ printf("FIXME: FPO (frame pointer omission) debug symbol dumping not implemented yet.\n"); } + +struct stab_nlist +{ + union + { + char* n_name; + struct stab_nlist* n_next; + long n_strx; + } n_un; + unsigned char n_type; + char n_other; + short n_desc; + unsigned long n_value; +}; + +static const char* stabs_defs[] = { + NULL,NULL,NULL,NULL, /* 00 */ + NULL,NULL,NULL,NULL, /* 08 */ + NULL,NULL,NULL,NULL, /* 10 */ + NULL,NULL,NULL,NULL, /* 18 */ + "GSYM","FNAME","FUN","STSYM", /* 20 */ + "LCSYM","MAIN","ROSYM","PC", /* 28 */ + NULL,"NSYMS","NOMAP",NULL, /* 30 */ + "OBJ",NULL,"OPT",NULL, /* 38 */ + "RSYM","M2C","SLINE","DSLINE", /* 40 */ + "BSLINE","DEFD","FLINE",NULL, /* 48 */ + "EHDECL",NULL,"CATCH",NULL, /* 50 */ + NULL,NULL,NULL,NULL, /* 58 */ + "SSYM","ENDM","SO",NULL, /* 60 */ + NULL,NULL,NULL,NULL, /* 68 */ + NULL,NULL,NULL,NULL, /* 70 */ + NULL,NULL,NULL,NULL, /* 78 */ + "LSYM","BINCL","SOL",NULL, /* 80 */ + NULL,NULL,NULL,NULL, /* 88 */ + NULL,NULL,NULL,NULL, /* 90 */ + NULL,NULL,NULL,NULL, /* 98 */ + "PSYM","EINCL","ENTRY",NULL, /* a0 */ + NULL,NULL,NULL,NULL, /* a8 */ + NULL,NULL,NULL,NULL, /* b0 */ + NULL,NULL,NULL,NULL, /* b8 */ + "LBRAC","EXCL","SCOPE",NULL, /* c0 */ + NULL,NULL,NULL,NULL, /* c8 */ + NULL,NULL,NULL,NULL, /* d0 */ + NULL,NULL,NULL,NULL, /* d8 */ + "RBRAC","BCOMM","ECOMM",NULL, /* e0 */ + "ECOML","WITH",NULL,NULL, /* e8 */ + "NBTEXT","NBDATA","NBBSS","NBSTS", /* f0 */ + "NBLCS",NULL,NULL,NULL /* f8 */ +}; + +void dump_stabs(const void* pv_stabs, unsigned szstabs, const char* stabstr, unsigned szstr) +{ + int i; + int nstab; + const char* ptr; + char* stabbuff; + unsigned int stabbufflen; + const struct stab_nlist* stab_ptr = pv_stabs; + const char* strs_end; + char n_buffer[16]; + + nstab = szstabs / sizeof(struct stab_nlist); + strs_end = stabstr + szstr; + + /* + * Allocate a buffer into which we can build stab strings for cases + * where the stab is continued over multiple lines. + */ + stabbufflen = 65536; + stabbuff = malloc(stabbufflen); + + stabbuff[0] = '\0'; + + printf("#Sym n_type n_othr n_desc n_value n_strx String\n"); + + for (i = 0; i < nstab; i++, stab_ptr++) + { + ptr = stabstr + stab_ptr->n_un.n_strx; + if ((ptr > strs_end) || (ptr + strlen(ptr) > strs_end)) + { + ptr = "[[*** bad string ***]]"; + } + else if (ptr[strlen(ptr) - 1] == '\\') + { + /* + * Indicates continuation. Append this to the buffer, and go onto the + * next record. Repeat the process until we find a stab without the + * '/' character, as this indicates we have the whole thing. + */ + unsigned len = strlen(ptr); + if (strlen(stabbuff) + len > stabbufflen) + { + stabbufflen += 65536; + stabbuff = realloc(stabbuff, stabbufflen); + } + strncat(stabbuff, ptr, len - 1); + continue; + } + else if (stabbuff[0] != '\0') + { + strcat(stabbuff, ptr); + ptr = stabbuff; + } + if ((stab_ptr->n_type & 1) || !stabs_defs[stab_ptr->n_type / 2]) + sprintf(n_buffer, "<0x%02x>", stab_ptr->n_type); + else + sprintf(n_buffer, "%-6s", stabs_defs[stab_ptr->n_type / 2]); + printf("%4d %s %-8x % 6d %-8lx %-6lx %s\n", + i, n_buffer, stab_ptr->n_other, stab_ptr->n_desc, stab_ptr->n_value, + stab_ptr->n_un.n_strx, ptr); + } + free(stabbuff); +} diff --git a/tools/winedump/main.c b/tools/winedump/main.c index 8d90187cd3c..36a105be83e 100644 --- a/tools/winedump/main.c +++ b/tools/winedump/main.c @@ -192,6 +192,11 @@ static void do_dumpsect (const char* arg) globals.dumpsect = arg; } +static void do_rawdebug (void) +{ + globals.do_debug = 1; +} + static void do_dumpall(void) { globals.do_dumpheader = 1; @@ -228,6 +233,7 @@ static const struct my_option option_table[] = { {"dump", DUMP, 0, do_dump, "dump Dumps the content of the module (dll, exe...) named "}, {"-C", DUMP, 0, do_symdmngl, "-C Turns on symbol demangling"}, {"-f", DUMP, 0, do_dumphead, "-f Dumps file header information"}, + {"-G", DUMP, 0, do_rawdebug, "-G Dumps raw debug information"}, {"-j", DUMP, 1, do_dumpsect, "-j sect_name Dumps only the content of section sect_name (import, export, debug, resource, tls)"}, {"-x", DUMP, 0, do_dumpall, "-x Dumps everything"}, {"emf", EMF, 0, do_dumpemf, "emf Dumps an Enhanced Meta File"}, diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c index da55f639514..22b243ef2dd 100644 --- a/tools/winedump/pe.c +++ b/tools/winedump/pe.c @@ -1076,6 +1076,36 @@ static void dump_dir_resource(void) printf( "\n\n" ); } +static void dump_debug(void) +{ + const char* stabs = NULL; + unsigned szstabs = 0; + const char* stabstr = NULL; + unsigned szstr = 0; + unsigned i; + const IMAGE_SECTION_HEADER* sectHead; + + sectHead = (const IMAGE_SECTION_HEADER*) + ((const char*)PE_nt_headers + sizeof(DWORD) + + sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader); + + for (i = 0; i < PE_nt_headers->FileHeader.NumberOfSections; i++, sectHead++) + { + if (!strcmp((const char *)sectHead->Name, ".stab")) + { + stabs = RVA(sectHead->VirtualAddress, sectHead->Misc.VirtualSize); + szstabs = sectHead->Misc.VirtualSize; + } + if (!strncmp((const char *)sectHead->Name, ".stabstr", 8)) + { + stabstr = RVA(sectHead->VirtualAddress, sectHead->Misc.VirtualSize); + szstr = sectHead->Misc.VirtualSize; + } + } + if (stabs && stabstr) + dump_stabs(stabs, szstabs, stabstr, szstr); +} + void pe_dump(const void* pmt) { int all = (globals.dumpsect != NULL) && strcmp(globals.dumpsect, "ALL") == 0; @@ -1118,6 +1148,8 @@ void pe_dump(const void* pmt) dump_dir_reloc(); #endif } + if (globals.do_debug) + dump_debug(); } typedef struct _dll_symbol { diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index 93de9a8f634..f12b618f198 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -123,6 +123,7 @@ typedef struct __globals /* Options: dump mode */ int do_demangle; /* -d */ int do_dumpheader; /* -f */ + int do_debug; /* -G == 1, -g == 2 */ /* Option arguments: spec mode */ int start_ordinal; /* -s */ @@ -238,6 +239,8 @@ void ne_dump( const void *exe, size_t exe_size ); void le_dump( const void *exe, size_t exe_size ); void mdmp_dump( void ); +void dump_stabs(const void* pv_stabs, unsigned szstabs, const char* stabstr, unsigned szstr); + FILE *open_file (const char *name, const char *ext, const char *mode); #ifdef __GNUC__ diff --git a/tools/winedump/winedump.man.in b/tools/winedump/winedump.man.in index 19fd8de446b..f1b2e9e6e92 100644 --- a/tools/winedump/winedump.man.in +++ b/tools/winedump/winedump.man.in @@ -80,6 +80,9 @@ Dumps everything. This command prints all available information about the file. You may wish to pipe the output through more/less or into a file, since a lot of output will be produced. +.IP \fB-G\fR +Dumps contents of debug section if any (for now, only stabs +information is supported). .PP .B Spec mode: .IP \fI\fR