update for HEAD-2003050101
[reactos.git] / 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   char* buf;
163   int n_in;
164   int n_out;
165    
166    if (argc != 3)
167      {
168         fprintf(stderr, "Too many arguments\n");
169         exit(1);
170      }
171    
172    path1 = convert_path(argv[1]);
173    path2 = convert_path(argv[2]);
174    
175    in = fopen(path1, "rb");
176    if (in == NULL)
177      {
178         perror("Cannot open input file");
179         exit(1);
180      }
181
182    out = fopen(path2, "wb");
183    if (out == NULL)
184      {
185         perror("Cannot open output file");
186         fclose(in);
187         exit(1);
188      }
189
190   /* Check if MZ header exists  */
191   n_in = fread(&PEDosHeader, 1, sizeof(PEDosHeader), in);
192   if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC && PEDosHeader.e_lfanew != 0L)
193     {
194       perror("Input file is not a PE image.\n");
195     }
196
197   /* Read PE file header  */
198   /* sizeof(ULONG) = sizeof(MAGIC) */
199   fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET);
200   n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in);
201
202   /* Read PE section headers  */
203   PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
204   fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)
205     + sizeof(IMAGE_OPTIONAL_HEADER), SEEK_SET);
206   n_in = fread(PESectionHeaders, 1, PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), in);
207
208   /* Copy .stab and .stabstr sections if available */
209   SymbolsBase = NULL;
210   SymbolsLength = 0;
211   SymbolStringsBase = NULL;
212   SymbolStringsLength = 0;
213
214   for (Idx = 0; Idx < PEFileHeader.NumberOfSections; Idx++)
215     {
216       //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name);
217       if ((strncmp(PESectionHeaders[Idx].Name, ".stab", 5) == 0)
218         && (PESectionHeaders[Idx].Name[5] == 0))
219         {
220            //printf(".stab section found. Size %d\n", 
221            //  PESectionHeaders[Idx].SizeOfRawData);
222
223            SymbolsLength = PESectionHeaders[Idx].SizeOfRawData;
224            SymbolsBase = malloc(SymbolsLength);
225
226            fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
227            n_in = fread(SymbolsBase, 1, SymbolsLength, in);
228         }
229
230       if (strncmp(PESectionHeaders[Idx].Name, ".stabstr", 8) == 0)
231         {
232            //printf(".stabstr section found. Size %d\n", 
233            //  PESectionHeaders[Idx].SizeOfRawData);
234
235            SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData;
236            SymbolStringsBase = malloc(SymbolStringsLength);
237
238            fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET);
239            n_in = fread(SymbolStringsBase, 1, SymbolStringsLength, in);
240         }
241     }
242
243   SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER);
244   SymbolFileHeader.StabsLength = SymbolsLength;
245   SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolsLength;
246   SymbolFileHeader.StabstrLength = SymbolStringsLength;
247
248   n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out);
249   n_out = fwrite(SymbolsBase, 1, SymbolsLength, out);
250   n_out = fwrite(SymbolStringsBase, 1, SymbolStringsLength, out);
251
252   exit(0);
253 }