winedump: Added -G option to dump raw stabs information from PE files.
diff --git a/tools/winedump/debug.c b/tools/winedump/debug.c
index 07ae75c..8d24a17 100644
--- a/tools/winedump/debug.c
+++ b/tools/winedump/debug.c
@@ -582,3 +582,116 @@
/* 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 8d90187..36a105b 100644
--- a/tools/winedump/main.c
+++ b/tools/winedump/main.c
@@ -192,6 +192,11 @@
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 @@
{"dump", DUMP, 0, do_dump, "dump <mod> Dumps the content of the module (dll, exe...) named <mod>"},
{"-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 da55f63..22b243e 100644
--- a/tools/winedump/pe.c
+++ b/tools/winedump/pe.c
@@ -1076,6 +1076,36 @@
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 @@
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 93de9a8..f12b618 100644
--- a/tools/winedump/winedump.h
+++ b/tools/winedump/winedump.h
@@ -123,6 +123,7 @@
/* 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 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 19fd8de..f1b2e9e 100644
--- a/tools/winedump/winedump.man.in
+++ b/tools/winedump/winedump.man.in
@@ -80,6 +80,9 @@
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<dll>\fR