1 /* 2 * Usage: dumpstab input-file 3 * 4 * There are two sources of information: the .stab/.stabstr 5 * sections of the executable and the COFF symbol table. Most 6 * of the information is in the .stab/.stabstr sections. 7 * However, most of our asm files don't contain .stab directives, 8 * so routines implemented in assembler won't show up in the 9 * .stab section. They are present in the COFF symbol table. 10 * So, we mostly use the .stab/.stabstr sections, but we augment 11 * the info there with info from the COFF symbol table when 12 * possible. 13 * 14 * This is a tool and is compiled using the host compiler, 15 * i.e. on Linux gcc and not mingw-gcc (cross-compiler). 16 * Therefore we can't include SDK headers and we have to 17 * duplicate some definitions here. 18 * Also note that the internal functions are "old C-style", 19 * returning an int, where a return of 0 means success and 20 * non-zero is failure. 21 */ 22 23 #include <stdio.h> 24 #include <string.h> 25 #include <stdlib.h> 26 #include <assert.h> 27 28 #include "rsym.h" 29 30 const char* 31 stab_type_name ( int stab_type ) 32 { 33 static char buf[32]; 34 switch ( stab_type ) 35 { 36 #define X(n) case n: return #n; 37 X(N_GYSM) 38 X(N_FNAME) 39 X(N_FUN) 40 X(N_STSYM) 41 X(N_LCSYM) 42 X(N_MAIN) 43 X(N_PC) 44 X(N_NSYMS) 45 X(N_NOMAP) 46 X(N_RSYM) 47 X(N_M2C) 48 X(N_SLINE) 49 X(N_DSLINE) 50 X(N_BSLINE) 51 //X(N_BROWS) 52 X(N_DEFD) 53 X(N_EHDECL) 54 //X(N_MOD2) 55 X(N_CATCH) 56 X(N_SSYM) 57 X(N_SO) 58 X(N_LSYM) 59 X(N_BINCL) 60 X(N_SOL) 61 X(N_PSYM) 62 X(N_EINCL) 63 X(N_ENTRY) 64 X(N_LBRAC) 65 X(N_EXCL) 66 X(N_SCOPE) 67 X(N_RBRAC) 68 X(N_BCOMM) 69 X(N_ECOMM) 70 X(N_ECOML) 71 X(N_LENG) 72 } 73 sprintf ( buf, "%lu", stab_type ); 74 return buf; 75 } 76 77 static int 78 GetStabInfo(void *FileData, PIMAGE_FILE_HEADER PEFileHeader, 79 PIMAGE_SECTION_HEADER PESectionHeaders, 80 ULONG *StabSymbolsLength, void **StabSymbolsBase, 81 ULONG *StabStringsLength, void **StabStringsBase) 82 { 83 ULONG Idx; 84 85 /* Load .stab and .stabstr sections if available */ 86 *StabSymbolsBase = NULL; 87 *StabSymbolsLength = 0; 88 *StabStringsBase = NULL; 89 *StabStringsLength = 0; 90 91 for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) 92 { 93 /* printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); */ 94 if ((strncmp((char*)PESectionHeaders[Idx].Name, ".stab", 5) == 0) 95 && (PESectionHeaders[Idx].Name[5] == 0)) 96 { 97 /* printf(".stab section found. Size %d\n", 98 PESectionHeaders[Idx].SizeOfRawData); */ 99 100 *StabSymbolsLength = PESectionHeaders[Idx].SizeOfRawData; 101 *StabSymbolsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData); 102 } 103 104 if (strncmp((char*)PESectionHeaders[Idx].Name, ".stabstr", 8) == 0) 105 { 106 /* printf(".stabstr section found. Size %d\n", 107 PESectionHeaders[Idx].SizeOfRawData); */ 108 109 *StabStringsLength = PESectionHeaders[Idx].SizeOfRawData; 110 *StabStringsBase = (void *)((char *) FileData + PESectionHeaders[Idx].PointerToRawData); 111 } 112 } 113 114 return 0; 115 } 116 117 static void 118 IterateStabs(ULONG StabSymbolsLength, void *StabSymbolsBase, 119 ULONG StabStringsLength, void *StabStringsBase, 120 ULONG_PTR ImageBase, PIMAGE_FILE_HEADER PEFileHeader, 121 PIMAGE_SECTION_HEADER PESectionHeaders) 122 { 123 PSTAB_ENTRY e; 124 ULONG Count, i; 125 126 e = StabSymbolsBase; 127 Count = StabSymbolsLength / sizeof(STAB_ENTRY); 128 if (Count == 0) /* No symbol info */ 129 return; 130 131 printf ( "type,other,desc,value,str\n" ); 132 for (i = 0; i < Count; i++) 133 { 134 printf ( "%s,%lu(0x%x),%lu(0x%x),%lu(0x%x),%s\n", 135 stab_type_name(e[i].n_type), 136 e[i].n_other, 137 e[i].n_other, 138 e[i].n_desc, 139 e[i].n_desc, 140 e[i].n_value, 141 e[i].n_value, 142 (char *) StabStringsBase + e[i].n_strx ); 143 } 144 } 145 146 int main(int argc, char* argv[]) 147 { 148 PIMAGE_DOS_HEADER PEDosHeader; 149 PIMAGE_FILE_HEADER PEFileHeader; 150 PIMAGE_OPTIONAL_HEADER PEOptHeader; 151 PIMAGE_SECTION_HEADER PESectionHeaders; 152 ULONG ImageBase; 153 void *StabBase; 154 ULONG StabsLength; 155 void *StabStringBase; 156 ULONG StabStringsLength; 157 char* path1; 158 size_t FileSize; 159 void *FileData; 160 161 if (2 != argc) 162 { 163 fprintf(stderr, "Usage: dumpstabs <exefile>\n"); 164 exit(1); 165 } 166 167 path1 = convert_path(argv[1]); 168 169 FileData = load_file ( path1, &FileSize ); 170 if ( !FileData ) 171 { 172 fprintf ( stderr, "An error occured loading '%s'\n", path1 ); 173 exit(1); 174 } 175 176 /* Check if MZ header exists */ 177 PEDosHeader = (PIMAGE_DOS_HEADER) FileData; 178 if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || PEDosHeader->e_lfanew == 0L) 179 { 180 perror("Input file is not a PE image.\n"); 181 free(FileData); 182 exit(1); 183 } 184 185 /* Locate PE file header */ 186 /* sizeof(ULONG) = sizeof(MAGIC) */ 187 PEFileHeader = (PIMAGE_FILE_HEADER)((char *) FileData + PEDosHeader->e_lfanew + sizeof(ULONG)); 188 189 /* Locate optional header */ 190 assert(sizeof(ULONG) == 4); 191 PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1); 192 ImageBase = PEOptHeader->ImageBase; 193 194 /* Locate PE section headers */ 195 PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *) PEOptHeader + PEFileHeader->SizeOfOptionalHeader); 196 197 if (GetStabInfo(FileData, PEFileHeader, PESectionHeaders, &StabsLength, &StabBase, 198 &StabStringsLength, &StabStringBase)) 199 { 200 free(FileData); 201 exit(1); 202 } 203 204 IterateStabs( StabsLength, StabBase, StabStringsLength, StabStringBase, 205 ImageBase, PEFileHeader, PESectionHeaders); 206 207 free(FileData); 208 209 return 0; 210 } 211