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