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(§ion, 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