- Implement dumping of COFF debug symbol table.

- Fix winedump syntax description.
- Spelling fixes.
This commit is contained in:
Andreas Mohr 2002-09-11 00:49:48 +00:00 committed by Alexandre Julliard
parent 025b52d950
commit 52097fd703
4 changed files with 150 additions and 41 deletions

View File

@ -59,7 +59,7 @@ Winedump can be used for different usages:
- demangling MSVC C++ symbol names
- dumping the 'PE' files contents
Usage: winedump [-h sym <sym> spec <dll> dump <dll>] [mode options]
Usage: winedump [-h | sym <sym> | spec <dll> | dump <dll>] [mode options]
When used in -h mode
-h Display this help message
When used in sym mode
@ -472,7 +472,7 @@ struct foobar { int _FIXME; };
The output should be piped through 'sort' and 'uniq' to remove multiple
declarations, e.g:
winedump -d foo -c -I "inc/*.h" -v | grep FIXME | sort | uniq > fixup.h
winedump foo -c -I "inc/*.h" -v | grep FIXME | sort | uniq > fixup.h
By adding '#include "fixup.h"' to foobar_dll.h your compile errors will be
greatly reduced.
@ -582,10 +582,13 @@ Which is enough information to begin implementing the function.
Dumping
-------
Another tool might be helpful digging into a 32bit DLL (and any PE image file):
Another tool might be helpful for digging into a 32bit DLL (and any PE image file):
pedump.
Usage:
winedump [-h | sym <sym> | spec <dll> | dump <dll> ] [switches]
winedump switches:
-h Display this help message
-d <dll> Use dll for input file and generate implementation code
-C Turns on symbol demangling
@ -593,13 +596,13 @@ Usage:
-j dir_name Dumps only the content of directory dir_name (import, export, debug)
-x Dumps everything
The basic usage, to look everything in a file is:
winedump dump -d mydll.dll -x
The basic usage, to look at everything in a file is:
winedump dump mydll.dll -x
It'll print any available information on the file. This information can be splitted
into sub-categories:
- file hedaers (request by -f or -x) are made of the standard PE header structures,
- file headers (request by -f or -x) are made of the standard PE header structures,
plus the COFF sections
- directories: you can print them one after the other using the -j switch. Currently,
only the import, export and debug directories are implemented.
- directories: you can print them one after the other using the -j switch.
Currently, only the import, export and debug directories are implemented.
- -x displays the file headers and any available directory.

View File

@ -97,6 +97,10 @@
* (OMFDirHeader.cDir)
*/
extern void *PE_base;
extern IMAGE_NT_HEADERS* PE_nt_headers;
static void* cv_base /* = 0 */;
static int dump_cv_sst_module(OMFDirEntry* omfde)
@ -482,7 +486,106 @@ static void dump_codeview_headers(unsigned long base, unsigned long len)
dump_codeview_all_modules(dirHeader);
}
static const char* get_coff_name( PIMAGE_SYMBOL coff_sym, const char* coff_strtab )
{
static char namebuff[9];
const char* nampnt;
if( coff_sym->N.Name.Short )
{
memcpy(namebuff, coff_sym->N.ShortName, 8);
namebuff[8] = '\0';
nampnt = &namebuff[0];
}
else
{
nampnt = coff_strtab + coff_sym->N.Name.Long;
}
if( nampnt[0] == '_' )
nampnt++;
return nampnt;
}
void dump_coff(unsigned long coffbase, unsigned long len)
{
PIMAGE_COFF_SYMBOLS_HEADER coff;
PIMAGE_SYMBOL coff_sym;
PIMAGE_SYMBOL coff_symbols;
PIMAGE_LINENUMBER coff_linetab;
char * coff_strtab;
IMAGE_SECTION_HEADER *sectHead = (IMAGE_SECTION_HEADER*)((char*)PE_nt_headers + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader);
unsigned int i;
const char * nampnt;
int naux;
coff = (PIMAGE_COFF_SYMBOLS_HEADER)PRD(coffbase, len);
coff_symbols = (PIMAGE_SYMBOL) ((unsigned int) coff + coff->LvaToFirstSymbol);
coff_linetab = (PIMAGE_LINENUMBER) ((unsigned int) coff + coff->LvaToFirstLinenumber);
coff_strtab = (char *) (coff_symbols + coff->NumberOfSymbols);
printf("\nDebug table: COFF format. modbase %p, coffbase %p\n", PE_base, coff);
printf(" ID | seg:offs [ abs ] | symbol/function name\n");
for(i=0; i < coff->NumberOfSymbols; i++ )
{
coff_sym = coff_symbols + i;
naux = coff_sym->NumberOfAuxSymbols;
if( coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE )
{
printf("file %s\n", (char *) (coff_sym + 1));
i += naux;
continue;
}
if( (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
&& (naux == 0)
&& (coff_sym->SectionNumber == 1) )
{
DWORD base = sectHead[coff_sym->SectionNumber - 1].VirtualAddress;
/*
* This is a normal static function when naux == 0.
* Just register it. The current file is the correct
* one in this instance.
*/
nampnt = get_coff_name( coff_sym, coff_strtab );
printf("%05d | %02d:%08lx [%08lx] | %s\n", i, coff_sym->SectionNumber - 1, coff_sym->Value - base, coff_sym->Value, nampnt);
i += naux;
continue;
}
if( (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
&& ISFCN(coff_sym->Type)
&& (coff_sym->SectionNumber > 0) )
{
DWORD base = sectHead[coff_sym->SectionNumber - 1].VirtualAddress;
nampnt = get_coff_name( coff_sym, coff_strtab );
/* FIXME: add code to find out the file this symbol belongs to,
* see winedbg */
printf("%05d | %02d:%08lx [%08lx] | %s\n", i, coff_sym->SectionNumber - 1, coff_sym->Value - base, coff_sym->Value, nampnt);
i += naux;
continue;
}
/*
* For now, skip past the aux entries.
*/
i += naux;
}
}
void dump_codeview(unsigned long base, unsigned long len)
{
dump_codeview_headers(base, len);
}
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");
}

View File

@ -46,9 +46,9 @@
# define O_BINARY 0
#endif
static void* base;
static unsigned long total_len;
static IMAGE_NT_HEADERS* nt_headers;
void* PE_base;
unsigned long PE_total_len;
IMAGE_NT_HEADERS* PE_nt_headers;
enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG};
@ -85,14 +85,14 @@ static const char* get_machine_str(DWORD mach)
void* PRD(unsigned long prd, unsigned long len)
{
return (prd + len > total_len) ? NULL : (char*)base + prd;
return (prd + len > PE_total_len) ? NULL : (char*)PE_base + prd;
}
unsigned long Offset(void* ptr)
{
if (ptr < base) {printf("<<<<<ptr below\n");return 0;}
if ((char *)ptr >= (char*)base + total_len) {printf("<<<<<ptr above\n");return 0;}
return (char*)ptr - (char*)base;
if (ptr < PE_base) {printf("<<<<<ptr below\n");return 0;}
if ((char *)ptr >= (char*)PE_base + PE_total_len) {printf("<<<<<ptr above\n");return 0;}
return (char*)ptr - (char*)PE_base;
}
void* RVA(unsigned long rva, unsigned long len)
@ -100,13 +100,13 @@ void* RVA(unsigned long rva, unsigned long len)
IMAGE_SECTION_HEADER* sectHead;
int i;
sectHead = (IMAGE_SECTION_HEADER*)((char*)nt_headers + sizeof(DWORD) +
sectHead = (IMAGE_SECTION_HEADER*)((char*)PE_nt_headers + sizeof(DWORD) +
sizeof(IMAGE_FILE_HEADER) +
nt_headers->FileHeader.SizeOfOptionalHeader);
PE_nt_headers->FileHeader.SizeOfOptionalHeader);
if (rva == 0) return NULL;
for (i = nt_headers->FileHeader.NumberOfSections - 1; i >= 0; i--)
for (i = PE_nt_headers->FileHeader.NumberOfSections - 1; i >= 0; i--)
{
if (sectHead[i].VirtualAddress <= rva &&
rva + len <= (DWORD)sectHead[i].VirtualAddress + sectHead[i].SizeOfRawData)
@ -125,10 +125,10 @@ void* RVA(unsigned long rva, unsigned long len)
static void* get_dir(unsigned idx)
{
if (idx >= nt_headers->OptionalHeader.NumberOfRvaAndSizes)
if (idx >= PE_nt_headers->OptionalHeader.NumberOfRvaAndSizes)
return NULL;
return RVA(nt_headers->OptionalHeader.DataDirectory[idx].VirtualAddress,
nt_headers->OptionalHeader.DataDirectory[idx].Size);
return RVA(PE_nt_headers->OptionalHeader.DataDirectory[idx].VirtualAddress,
PE_nt_headers->OptionalHeader.DataDirectory[idx].Size);
}
static const char* DirectoryNames[16] = {
@ -146,7 +146,7 @@ static void dump_pe_header(void)
unsigned i;
printf("File Header\n");
fileHeader = &nt_headers->FileHeader;
fileHeader = &PE_nt_headers->FileHeader;
printf(" Machine: %04X (%s)\n",
fileHeader->Machine, get_machine_str(fileHeader->Machine));
@ -175,7 +175,7 @@ static void dump_pe_header(void)
/* hope we have the right size */
printf("Optional Header\n");
optionalHeader = &nt_headers->OptionalHeader;
optionalHeader = &PE_nt_headers->OptionalHeader;
printf(" Magic 0x%-4X %u\n",
optionalHeader->Magic, optionalHeader->Magic);
printf(" linker version %u.%02u\n",
@ -401,12 +401,12 @@ static void dump_dir_imported_functions(void)
unsigned nb_imp, i;
if (!importDesc) return;
nb_imp = nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size /
nb_imp = PE_nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size /
sizeof(*importDesc);
if (!nb_imp) return;
printf("Import Table size: %lu\n",
nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size);/* FIXME */
PE_nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size);/* FIXME */
for (i = 0; i < nb_imp - 1; i++) /* the last descr is set as 0 as a sentinel */
{
@ -495,11 +495,13 @@ static void dump_dir_debug_dir(IMAGE_DEBUG_DIRECTORY* idd, int idx)
case IMAGE_DEBUG_TYPE_UNKNOWN:
break;
case IMAGE_DEBUG_TYPE_COFF:
dump_coff(idd->PointerToRawData, idd->SizeOfData);
break;
case IMAGE_DEBUG_TYPE_CODEVIEW:
dump_codeview(idd->PointerToRawData, idd->SizeOfData);
break;
case IMAGE_DEBUG_TYPE_FPO:
dump_frame_pointer_omission(idd->PointerToRawData, idd->SizeOfData);
break;
case IMAGE_DEBUG_TYPE_MISC:
{
@ -535,7 +537,7 @@ static void dump_dir_debug(void)
unsigned nb_dbg, i;
if (!debugDir) return;
nb_dbg = nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_DEBUG_DIRECTORY].Size /
nb_dbg = PE_nt_headers->OptionalHeader.DataDirectory[IMAGE_FILE_DEBUG_DIRECTORY].Size /
sizeof(*debugDir);
if (!nb_dbg) return;
@ -740,10 +742,10 @@ static void do_dump(void)
if (globals.do_dumpheader)
{
dump_pe_header();
/* FIX%E: should check ptr */
dump_sections((char*)nt_headers + sizeof(DWORD) +
sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader,
nt_headers->FileHeader.NumberOfSections);
/* FIXME: should check ptr */
dump_sections((char*)PE_nt_headers + sizeof(DWORD) +
sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader,
PE_nt_headers->FileHeader.NumberOfSections);
}
else if (!globals.dumpsect)
{
@ -792,7 +794,7 @@ static enum FileSig check_headers(void)
{
if (*pdw == IMAGE_NT_SIGNATURE)
{
nt_headers = PRD(dh->e_lfanew, sizeof(DWORD));
PE_nt_headers = PRD(dh->e_lfanew, sizeof(DWORD));
sig = SIG_PE;
}
else
@ -830,14 +832,14 @@ int pe_analysis(const char* name, void (*fn)(void), enum FileSig wanted_sig)
if (fd == -1) fatal("Can't open file");
if (fstat(fd, &s) < 0) fatal("Can't get size");
total_len = s.st_size;
PE_total_len = s.st_size;
#ifdef HAVE_MMAP
if ((base = mmap(NULL, total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
if ((PE_base = mmap(NULL, PE_total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
#endif
{
if (!(base = malloc( total_len ))) fatal( "Out of memory" );
if (read( fd, base, total_len ) != total_len) fatal( "Cannot read file" );
if (!(PE_base = malloc( PE_total_len ))) fatal( "Out of memory" );
if (read( fd, PE_base, PE_total_len ) != PE_total_len) fatal( "Cannot read file" );
}
effective_sig = check_headers();
@ -854,7 +856,7 @@ int pe_analysis(const char* name, void (*fn)(void), enum FileSig wanted_sig)
case SIG_UNKNOWN: /* shouldn't happen... */
ret = 0; break;
case SIG_PE:
printf("Contents of \"%s\": %ld bytes\n\n", name, total_len);
printf("Contents of \"%s\": %ld bytes\n\n", name, PE_total_len);
(*fn)();
break;
case SIG_DBG:
@ -872,10 +874,10 @@ int pe_analysis(const char* name, void (*fn)(void), enum FileSig wanted_sig)
if (ret) printf("Done dumping %s\n", name);
#ifdef HAVE_MMAP
if (munmap(base, total_len) == -1)
if (munmap(PE_base, PE_total_len) == -1)
#endif
{
free( base );
free( PE_base );
}
close(fd);

View File

@ -19,7 +19,8 @@
*/
extern void dump_codeview(unsigned long ptr, unsigned long len);
extern void dump_coff(unsigned long coffbase, unsigned long len);
extern void dump_frame_pointer_omission(unsigned long base, unsigned long len);
extern void* PRD(unsigned long prd, unsigned long len);
extern unsigned long Offset(void* ptr);
extern char* get_time_str(DWORD _t);