diff --git a/reactos/tools/dumpstab.c b/reactos/tools/dumpstab.c new file mode 100644 index 00000000000..66733e51117 --- /dev/null +++ b/reactos/tools/dumpstab.c @@ -0,0 +1,210 @@ +/* + * Usage: dumpstab input-file + * + * There are two sources of information: the .stab/.stabstr + * sections of the executable and the COFF symbol table. Most + * of the information is in the .stab/.stabstr sections. + * However, most of our asm files don't contain .stab directives, + * so routines implemented in assembler won't show up in the + * .stab section. They are present in the COFF symbol table. + * So, we mostly use the .stab/.stabstr sections, but we augment + * the info there with info from the COFF symbol table when + * possible. + * + * This is a tool and is compiled using the host compiler, + * i.e. on Linux gcc and not mingw-gcc (cross-compiler). + * Therefore we can't include SDK headers and we have to + * duplicate some definitions here. + * Also note that the internal functions are "old C-style", + * returning an int, where a return of 0 means success and + * non-zero is failure. + */ + +#include +#include +#include +#include + +#include "rsym.h" + +const char* +stab_type_name ( int stab_type ) +{ + static char buf[32]; + switch ( stab_type ) + { +#define X(n) case n: return #n; + X(N_GYSM) + X(N_FNAME) + X(N_FUN) + X(N_STSYM) + X(N_LCSYM) + X(N_MAIN) + X(N_PC) + X(N_NSYMS) + X(N_NOMAP) + X(N_RSYM) + X(N_M2C) + X(N_SLINE) + X(N_DSLINE) + X(N_BSLINE) + //X(N_BROWS) + X(N_DEFD) + X(N_EHDECL) + //X(N_MOD2) + X(N_CATCH) + X(N_SSYM) + X(N_SO) + X(N_LSYM) + X(N_BINCL) + X(N_SOL) + X(N_PSYM) + X(N_EINCL) + X(N_ENTRY) + X(N_LBRAC) + X(N_EXCL) + X(N_SCOPE) + X(N_RBRAC) + X(N_BCOMM) + X(N_ECOMM) + X(N_ECOML) + X(N_LENG) + } + sprintf ( buf, "%lu", stab_type ); + return buf; +} + +static int +GetStabInfo(void *FileData, PIMAGE_FILE_HEADER PEFileHeader, + PIMAGE_SECTION_HEADER PESectionHeaders, + ULONG *StabSymbolsLength, void **StabSymbolsBase, + ULONG *StabStringsLength, void **StabStringsBase) +{ + ULONG Idx; + + /* Load .stab and .stabstr sections if available */ + *StabSymbolsBase = NULL; + *StabSymbolsLength = 0; + *StabStringsBase = NULL; + *StabStringsLength = 0; + + for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) + { + /* printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); */ + if ((strncmp((char*)PESectionHeaders[Idx].Name, ".stab", 5) == 0) + && (PESectionHeaders[Idx].Name[5] == 0)) + { + /* printf(".stab section found. Size %d\n", + PESectionHeaders[Idx].SizeOfRawData); */ + + *StabSymbolsLength = PESectionHeaders[Idx].SizeOfRawData; + *StabSymbolsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData); + } + + if (strncmp((char*)PESectionHeaders[Idx].Name, ".stabstr", 8) == 0) + { + /* printf(".stabstr section found. Size %d\n", + PESectionHeaders[Idx].SizeOfRawData); */ + + *StabStringsLength = PESectionHeaders[Idx].SizeOfRawData; + *StabStringsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData); + } + } + + return 0; +} + +static void +IterateStabs(ULONG StabSymbolsLength, void *StabSymbolsBase, + ULONG StabStringsLength, void *StabStringsBase, + ULONG_PTR ImageBase, PIMAGE_FILE_HEADER PEFileHeader, + PIMAGE_SECTION_HEADER PESectionHeaders) +{ + PSTAB_ENTRY e; + ULONG Count, i; + + e = StabSymbolsBase; + Count = StabSymbolsLength / sizeof(STAB_ENTRY); + if (Count == 0) /* No symbol info */ + return; + + printf ( "type,other,desc,value,str\n" ); + for (i = 0; i < Count; i++) + { + printf ( "%s,%lu(0x%x),%lu(0x%x),%lu(0x%x),%s\n", + stab_type_name(e[i].n_type), + e[i].n_other, + e[i].n_other, + e[i].n_desc, + e[i].n_desc, + e[i].n_value, + e[i].n_value, + (char *) StabStringsBase + e[i].n_strx ); + } +} + +int main(int argc, char* argv[]) +{ + PIMAGE_DOS_HEADER PEDosHeader; + PIMAGE_FILE_HEADER PEFileHeader; + PIMAGE_OPTIONAL_HEADER PEOptHeader; + PIMAGE_SECTION_HEADER PESectionHeaders; + ULONG ImageBase; + void *StabBase; + ULONG StabsLength; + void *StabStringBase; + ULONG StabStringsLength; + char* path1; + size_t FileSize; + void *FileData; + + if (2 != argc) + { + fprintf(stderr, "Usage: dumpstabs \n"); + exit(1); + } + + path1 = convert_path(argv[1]); + + FileData = load_file ( path1, &FileSize ); + if ( !FileData ) + { + fprintf ( stderr, "An error occured loading '%s'\n", path1 ); + exit(1); + } + + /* Check if MZ header exists */ + PEDosHeader = (PIMAGE_DOS_HEADER) FileData; + if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L) + { + perror("Input file is not a PE image.\n"); + free(FileData); + exit(1); + } + + /* Locate PE file header */ + /* sizeof(ULONG) = sizeof(MAGIC) */ + PEFileHeader = (PIMAGE_FILE_HEADER)((char *) FileData + PEDosHeader->e_lfanew + sizeof(ULONG)); + + /* Locate optional header */ + assert(sizeof(ULONG) == 4); + PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1); + ImageBase = PEOptHeader->ImageBase; + + /* Locate PE section headers */ + PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *) PEOptHeader + PEFileHeader->SizeOfOptionalHeader); + + if (GetStabInfo(FileData, PEFileHeader, PESectionHeaders, &StabsLength, &StabBase, + &StabStringsLength, &StabStringBase)) + { + free(FileData); + exit(1); + } + + IterateStabs( StabsLength, StabBase, StabStringsLength, StabStringBase, + ImageBase, PEFileHeader, PESectionHeaders); + + free(FileData); + + return 0; +} diff --git a/reactos/tools/rsym.h b/reactos/tools/rsym.h index 77e406bc1aa..b9346058f61 100644 --- a/reactos/tools/rsym.h +++ b/reactos/tools/rsym.h @@ -179,9 +179,42 @@ typedef struct _STAB_ENTRY { ULONG n_value; /* value of symbol */ } STAB_ENTRY, *PSTAB_ENTRY; -#define N_FUN 0x24 -#define N_SLINE 0x44 -#define N_SO 0x64 +/* http://www.math.utah.edu/docs/info/stabs_12.html */ +#define N_GYSM 0x20 +#define N_FNAME 0x22 +#define N_FUN 0x24 +#define N_STSYM 0x26 +#define N_LCSYM 0x28 +#define N_MAIN 0x2A +#define N_PC 0x30 +#define N_NSYMS 0x32 +#define N_NOMAP 0x34 +#define N_RSYM 0x40 +#define N_M2C 0x42 +#define N_SLINE 0x44 +#define N_DSLINE 0x46 +#define N_BSLINE 0x48 +#define N_BROWS 0x48 +#define N_DEFD 0x4A +#define N_EHDECL 0x50 +#define N_MOD2 0x50 +#define N_CATCH 0x54 +#define N_SSYM 0x60 +#define N_SO 0x64 +#define N_LSYM 0x80 +#define N_BINCL 0x82 +#define N_SOL 0x84 +#define N_PSYM 0xA0 +#define N_EINCL 0xA2 +#define N_ENTRY 0xA4 +#define N_LBRAC 0xC0 +#define N_EXCL 0xC2 +#define N_SCOPE 0xC4 +#define N_RBRAC 0xE0 +#define N_BCOMM 0xE2 +#define N_ECOMM 0xE4 +#define N_ECOML 0xE8 +#define N_LENG 0xFE /* COFF symbol table */