xref: /reactos/sdk/tools/dumpstab.c (revision 40462c92)
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