xref: /reactos/sdk/tools/geninc/geninc.c (revision 7e22dc05)
1 /*
2  *  Generates assembly definitions from the target headers.
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdint.h>
9 
10 #define IMAGE_FILE_MACHINE_I386  0x014c
11 #define IMAGE_FILE_MACHINE_AMD64 0x8664
12 #define IMAGE_FILE_MACHINE_ARMNT 0x01c4
13 #define IMAGE_FILE_MACHINE_ARM64 0xaa64
14 
15 #ifdef _MSC_VER
16 #define PRIx64 "I64x"
17 #else
18 #include <inttypes.h>
19 #define _stricmp strcasecmp
20 #endif
21 
22 typedef struct
23 {
24     char Type;
25     char Name[55];
26     uint64_t Value;
27 } ASMGENDATA;
28 
29 #define TYPE_END 0
30 #define TYPE_RAW 1
31 #define TYPE_CONSTANT 2
32 #define TYPE_HEADER 3
33 
34 int main(int argc, char* argv[])
35 {
36     FILE *input, *output;
37     ASMGENDATA data;
38     int i, result = -1;
39     int ms_format = 0;
40     char header[20];
41     uint32_t e_lfanew, signature;
42     uint16_t Machine, NumberOfSections, SizeOfOptionalHeader;
43     typedef struct
44     {
45         char Name[8];
46         uint32_t VirtualSize;
47         uint32_t VirtualAddress;
48         uint32_t RawSize;
49         uint32_t RawAddress;
50         uint32_t RelocAddress;
51         uint32_t LineNumbers;
52         uint16_t RelocationsNumber;
53         uint16_t LineNumbersNumber;
54         uint32_t Characteristics;
55     } SECTION;
56     SECTION section;
57 
58     if (argc >= 4 && _stricmp(argv[3], "-ms") == 0) ms_format = 1;
59 
60     /* Open the input file */
61     input = fopen(argv[1], "rb");
62     if (!input)
63     {
64         fprintf(stderr, "Could not open input file '%s'\n", argv[1]);
65         return -1;
66     }
67 
68     /* Open the output file */
69     output = fopen(argv[2], "w");
70     if (!output)
71     {
72         fclose(input);
73         fprintf(stderr, "Could not open output file '%s'\n", argv[2]);
74         return -1;
75     }
76 
77     /* Read the DOS header */
78     if (fread(&header, 1, 2, input) != 2)
79     {
80         fprintf(stderr, "Error reading header.\n");
81         goto quit;
82     }
83 
84     if (header[0] != 0x4d || header[1] != 0x5a)
85     {
86         fprintf(stderr, "Not a PE file.\n");
87         goto quit;
88     }
89 
90     fseek(input, 0x3C, SEEK_SET);
91     if (fread(&e_lfanew, 1, 4, input) != 4)
92     {
93         fprintf(stderr, "Could not read e_lfanew.\n");
94         goto quit;
95     }
96 
97     fseek(input, e_lfanew, SEEK_SET);
98     if (fread(&signature, 1, 4, input) != 4)
99     {
100         fprintf(stderr, "Could not read signature.\n");
101         goto quit;
102     }
103 
104     /* Verify the PE signature */
105     if (signature != 0x4550)
106     {
107         fprintf(stderr, "Invalid signature: 0x%x.\n", signature);
108         goto quit;
109     }
110 
111     /* Read Machine */
112     fseek(input, e_lfanew + 4, SEEK_SET);
113     if (fread(&Machine, 1, 2, input) != 2)
114     {
115         fprintf(stderr, "Could not read ExportDirectoryRVA.\n");
116         goto quit;
117     }
118 
119     if ((Machine != IMAGE_FILE_MACHINE_I386) &&
120         (Machine != IMAGE_FILE_MACHINE_AMD64) &&
121         (Machine != IMAGE_FILE_MACHINE_ARMNT) &&
122         (Machine != IMAGE_FILE_MACHINE_ARM64))
123     {
124         fprintf(stderr, "Invalid Machine: 0x%x.\n", Machine);
125         goto quit;
126     }
127 
128     /* Read NumberOfSections */
129     if (fread(&NumberOfSections, 1, 2, input) != 2)
130     {
131         fprintf(stderr, "Could not read NumberOfSections.\n");
132         goto quit;
133     }
134 
135     fseek(input, e_lfanew + 0x14, SEEK_SET);
136     if (fread(&SizeOfOptionalHeader, 1, 2, input) != 2)
137     {
138         fprintf(stderr, "Could not read SizeOfOptionalHeader.\n");
139         goto quit;
140     }
141 
142     /* Read the section table */
143     fseek(input, e_lfanew + 0x18 + SizeOfOptionalHeader, SEEK_SET);
144 
145     /* Search for the .asmdef section */
146     for (i = 0; i < NumberOfSections; i++)
147     {
148         if (fread(&section, 1, sizeof(SECTION), input) !=  sizeof(SECTION))
149         {
150             fprintf(stderr, "Could not read section.\n");
151             goto quit;
152         }
153 
154         if (strcmp(section.Name, ".asmdef") == 0)
155         {
156             break;
157         }
158     }
159 
160     if (i == NumberOfSections)
161     {
162         fprintf(stderr, "Could not find section.\n");
163         goto quit;
164     }
165 
166     /* Read the section table */
167     fseek(input, section.RawAddress, SEEK_SET);
168 
169     while (1)
170     {
171         /* Read one entry */
172         if (fread(&data, 1, sizeof(data), input) != sizeof(data))
173         {
174             fprintf(stderr, "Error reading input file.\n");
175             goto quit;
176         }
177 
178         switch(data.Type)
179         {
180             case TYPE_END:
181                 break;
182 
183             case TYPE_RAW:
184                 fprintf(output, "%s\n", data.Name);
185                 continue;
186 
187             case TYPE_CONSTANT:
188                 if (ms_format)
189                 {
190                     if (Machine == IMAGE_FILE_MACHINE_ARMNT)
191                     {
192                         fprintf(output, "%s equ 0x%"PRIx64"\n", data.Name, data.Value);
193                     }
194                     else
195                     {
196                         fprintf(output, "%s equ 0%"PRIx64"h\n", data.Name, data.Value);
197                     }
198                 }
199                 else
200                 {
201                     fprintf(output, "%s = 0x%"PRIx64"\n", data.Name, data.Value);
202                 }
203                 continue;
204 
205             case TYPE_HEADER:
206                 if (ms_format)
207                 {
208                     fprintf(output, "\n; %s\n", data.Name);
209                 }
210                 else
211                 {
212                     fprintf(output, "\n/* %s */\n", data.Name);
213                 }
214                 continue;
215         }
216 
217         break;
218     }
219 
220     result = 0;
221 
222 quit:
223     /* Close files */
224     fclose(input);
225     fclose(output);
226 
227     return result;
228 }
229