Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / sdk / tools / dumpstab.c
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 }