NtSetInformationFile(): FileRenameInformation: Fixed missing fields
[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 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 }