winedump: Added -G option to dump raw stabs information from PE files.

This commit is contained in:
Eric Pouech 2006-08-27 08:50:46 +02:00 committed by Alexandre Julliard
parent 9766dd1a5f
commit c2f1240a53
5 changed files with 157 additions and 0 deletions

View File

@ -582,3 +582,116 @@ void dump_frame_pointer_omission(unsigned long base, unsigned long len)
/* FPO is used to describe nonstandard stack frames */ /* FPO is used to describe nonstandard stack frames */
printf("FIXME: FPO (frame pointer omission) debug symbol dumping not implemented yet.\n"); 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);
}

View File

@ -192,6 +192,11 @@ static void do_dumpsect (const char* arg)
globals.dumpsect = arg; globals.dumpsect = arg;
} }
static void do_rawdebug (void)
{
globals.do_debug = 1;
}
static void do_dumpall(void) static void do_dumpall(void)
{ {
globals.do_dumpheader = 1; globals.do_dumpheader = 1;
@ -228,6 +233,7 @@ static const struct my_option option_table[] = {
{"dump", DUMP, 0, do_dump, "dump <mod> Dumps the content of the module (dll, exe...) named <mod>"}, {"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"}, {"-C", DUMP, 0, do_symdmngl, "-C Turns on symbol demangling"},
{"-f", DUMP, 0, do_dumphead, "-f Dumps file header information"}, {"-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)"}, {"-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"}, {"-x", DUMP, 0, do_dumpall, "-x Dumps everything"},
{"emf", EMF, 0, do_dumpemf, "emf Dumps an Enhanced Meta File"}, {"emf", EMF, 0, do_dumpemf, "emf Dumps an Enhanced Meta File"},

View File

@ -1076,6 +1076,36 @@ static void dump_dir_resource(void)
printf( "\n\n" ); 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) void pe_dump(const void* pmt)
{ {
int all = (globals.dumpsect != NULL) && strcmp(globals.dumpsect, "ALL") == 0; int all = (globals.dumpsect != NULL) && strcmp(globals.dumpsect, "ALL") == 0;
@ -1118,6 +1148,8 @@ void pe_dump(const void* pmt)
dump_dir_reloc(); dump_dir_reloc();
#endif #endif
} }
if (globals.do_debug)
dump_debug();
} }
typedef struct _dll_symbol { typedef struct _dll_symbol {

View File

@ -123,6 +123,7 @@ typedef struct __globals
/* Options: dump mode */ /* Options: dump mode */
int do_demangle; /* -d */ int do_demangle; /* -d */
int do_dumpheader; /* -f */ int do_dumpheader; /* -f */
int do_debug; /* -G == 1, -g == 2 */
/* Option arguments: spec mode */ /* Option arguments: spec mode */
int start_ordinal; /* -s */ 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 le_dump( const void *exe, size_t exe_size );
void mdmp_dump( void ); 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); FILE *open_file (const char *name, const char *ext, const char *mode);
#ifdef __GNUC__ #ifdef __GNUC__

View File

@ -80,6 +80,9 @@ Dumps everything.
This command prints all available information about the This command prints all available information about the
file. You may wish to pipe the output through more/less or file. You may wish to pipe the output through more/less or
into a file, since a lot of output will be produced. 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 .PP
.B Spec mode: .B Spec mode:
.IP \fI<dll>\fR .IP \fI<dll>\fR