2002-07-13 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / tools / rsym.c
1 /*
2 * Usage: rsym input-file output-file
3 */
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7
8 #define NULL ((void*)0)
9
10 #define IMAGE_DOS_MAGIC 0x5a4d
11 #define IMAGE_PE_MAGIC 0x00004550
12
13 #define IMAGE_SIZEOF_SHORT_NAME 8
14
15 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
16
17 typedef void* PVOID;
18 typedef unsigned char BYTE;
19 typedef unsigned short WORD;
20 typedef unsigned long DWORD;
21 typedef signed long LONG;
22 typedef unsigned long ULONG;
23
24 #pragma pack(push,2)
25 typedef struct _IMAGE_DOS_HEADER {
26 WORD e_magic;
27 WORD e_cblp;
28 WORD e_cp;
29 WORD e_crlc;
30 WORD e_cparhdr;
31 WORD e_minalloc;
32 WORD e_maxalloc;
33 WORD e_ss;
34 WORD e_sp;
35 WORD e_csum;
36 WORD e_ip;
37 WORD e_cs;
38 WORD e_lfarlc;
39 WORD e_ovno;
40 WORD e_res[4];
41 WORD e_oemid;
42 WORD e_oeminfo;
43 WORD e_res2[10];
44 LONG e_lfanew;
45 } IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
46 #pragma pack(pop)
47 #pragma pack(push,4)
48 typedef struct _IMAGE_DATA_DIRECTORY {
49 DWORD VirtualAddress;
50 DWORD Size;
51 } IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
52 typedef struct _IMAGE_OPTIONAL_HEADER {
53 WORD Magic;
54 BYTE MajorLinkerVersion;
55 BYTE MinorLinkerVersion;
56 DWORD SizeOfCode;
57 DWORD SizeOfInitializedData;
58 DWORD SizeOfUninitializedData;
59 DWORD AddressOfEntryPoint;
60 DWORD BaseOfCode;
61 DWORD BaseOfData;
62 DWORD ImageBase;
63 DWORD SectionAlignment;
64 DWORD FileAlignment;
65 WORD MajorOperatingSystemVersion;
66 WORD MinorOperatingSystemVersion;
67 WORD MajorImageVersion;
68 WORD MinorImageVersion;
69 WORD MajorSubsystemVersion;
70 WORD MinorSubsystemVersion;
71 DWORD Reserved1;
72 DWORD SizeOfImage;
73 DWORD SizeOfHeaders;
74 DWORD CheckSum;
75 WORD Subsystem;
76 WORD DllCharacteristics;
77 DWORD SizeOfStackReserve;
78 DWORD SizeOfStackCommit;
79 DWORD SizeOfHeapReserve;
80 DWORD SizeOfHeapCommit;
81 DWORD LoaderFlags;
82 DWORD NumberOfRvaAndSizes;
83 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
84 } IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
85 typedef struct _IMAGE_FILE_HEADER {
86 WORD Machine;
87 WORD NumberOfSections;
88 DWORD TimeDateStamp;
89 DWORD PointerToSymbolTable;
90 DWORD NumberOfSymbols;
91 WORD SizeOfOptionalHeader;
92 WORD Characteristics;
93 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
94 typedef struct _IMAGE_SECTION_HEADER {
95 BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
96 union {
97 DWORD PhysicalAddress;
98 DWORD VirtualSize;
99 } Misc;
100 DWORD VirtualAddress;
101 DWORD SizeOfRawData;
102 DWORD PointerToRawData;
103 DWORD PointerToRelocations;
104 DWORD PointerToLinenumbers;
105 WORD NumberOfRelocations;
106 WORD NumberOfLinenumbers;
107 DWORD Characteristics;
108 } IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;
109 #pragma pack(pop)
110
111 typedef struct _SYMBOLFILE_HEADER {
112 unsigned long StabsOffset;
113 unsigned long StabsLength;
114 unsigned long StabstrOffset;
115 unsigned long StabstrLength;
116 } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
117
118
119 char* convert_path(char* origpath)
120 {
121 char* newpath;
122 int i;
123
124 newpath = strdup(origpath);
125
126 i = 0;
127 while (newpath[i] != 0)
128 {
129 #ifdef UNIX_PATHS
130 if (newpath[i] == '\\')
131 {
132 newpath[i] = '/';
133 }
134 #else
135 #ifdef DOS_PATHS
136 if (newpath[i] == '/')
137 {
138 newpath[i] = '\\';
139 }
140 #endif
141 #endif
142 i++;
143 }
144 return(newpath);
145 }
146
147 #define TRANSFER_SIZE (65536)
148
149 int main(int argc, char* argv[])
150 {
151 SYMBOLFILE_HEADER SymbolFileHeader;
152 IMAGE_DOS_HEADER PEDosHeader;
153 IMAGE_FILE_HEADER PEFileHeader;
154 PIMAGE_SECTION_HEADER PESectionHeaders;
155 PVOID SymbolsBase;
156 ULONG SymbolsLength;
157 PVOID SymbolStringsBase;
158 ULONG SymbolStringsLength;
159 ULONG Idx;
160 char* path1;
161 char* path2;
162 FILE* in;
163 FILE* out;
164 char* buf;
165 int n_in;
166 int n_out;
167
168 if (argc != 3)
169 {
170 fprintf(stderr, "Too many arguments\n");
171 exit(1);
172 }
173
174 path1 = convert_path(argv[1]);
175 path2 = convert_path(argv[2]);
176
177 in = fopen(path1, "rb");
178 if (in == NULL)
179 {
180 perror("Cannot open input file");
181 exit(1);
182 }
183
184 out = fopen(path2, "wb");
185 if (out == NULL)
186 {
187 perror("Cannot open output file");
188 fclose(in);
189 exit(1);
190 }
191
192 /* Check if MZ header exists */
193 n_in = fread(&PEDosHeader, 1, sizeof(PEDosHeader), in);
194 if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC && PEDosHeader.e_lfanew != 0L)
195 {
196 perror("Input file is not a PE image.\n");
197 }
198
199 /* Read PE file header */
200 /* sizeof(ULONG) = sizeof(MAGIC) */
201 fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET);
202 n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in);
203
204 /* Read PE section headers */
205 PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
206 fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)
207 + sizeof(IMAGE_OPTIONAL_HEADER), SEEK_SET);
208 n_in = fread(PESectionHeaders, 1, PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), in);
209
210 /* Copy .stab and .stabstr sections if available */
211 SymbolsBase = NULL;
212 SymbolsLength = 0;
213 SymbolStringsBase = NULL;
214 SymbolStringsLength = 0;
215
216 for (Idx = 0; Idx < PEFileHeader.NumberOfSections; Idx++)
217 {
218 //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name);
219 if ((strncmp(PESectionHeaders[Idx].Name, ".stab", 5) == 0)
220 && (PESectionHeaders[Idx].Name[5] == 0))
221 {
222 //printf(".stab section found. Size %d\n",
223 // PESectionHeaders[Idx].SizeOfRawData);
224
225 SymbolsLength = PESectionHeaders[Idx].SizeOfRawData;
226 SymbolsBase = malloc(SymbolsLength);
227
228 fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
229 n_in = fread(SymbolsBase, 1, SymbolsLength, in);
230 }
231
232 if (strncmp(PESectionHeaders[Idx].Name, ".stabstr", 8) == 0)
233 {
234 //printf(".stabstr section found. Size %d\n",
235 // PESectionHeaders[Idx].SizeOfRawData);
236
237 SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData;
238 SymbolStringsBase = malloc(SymbolStringsLength);
239
240 fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
241 n_in = fread(SymbolStringsBase, 1, SymbolStringsLength, in);
242 }
243 }
244
245 SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER);
246 SymbolFileHeader.StabsLength = SymbolsLength;
247 SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolsLength;
248 SymbolFileHeader.StabstrLength = SymbolStringsLength;
249
250 n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out);
251 n_out = fwrite(SymbolsBase, 1, SymbolsLength, out);
252 n_out = fwrite(SymbolStringsBase, 1, SymbolStringsLength, out);
253
254 exit(0);
255 }