bin2coff.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*
  2. * bin2coff: converts a data object into a Win32 linkable COFF binary object
  3. * Copyright (c) 2011 Pete Batard <pete@akeo.ie>
  4. * This file is part of the libwdi project: http://libwdi.sf.net
  5. * Modifications Copyright (c) 2018 by Artifex Software
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. /*
  21. * References:
  22. * http://www.vortex.masmcode.com/ (another bin2coff, without source)
  23. * http://msdn.microsoft.com/en-us/library/ms680198.aspx
  24. * http://webster.cs.ucr.edu/Page_TechDocs/pe.txt
  25. * http://www.delorie.com/djgpp/doc/coff/
  26. * http://pierrelib.pagesperso-orange.fr/exec_formats/MS_Symbol_Type_v1.0.pdf
  27. */
  28. /*
  29. Updates from Artifex Software Inc.
  30. + Automatically rename '-' to '_' in generated symbols.
  31. + Accept 'Win32' and 'x64' as flags.
  32. */
  33. #define _CRT_SECURE_NO_WARNINGS
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <stdlib.h>
  37. #if !defined(_MSC_VER)
  38. #include <stdint.h>
  39. #else
  40. typedef signed char int8_t;
  41. typedef unsigned char uint8_t;
  42. typedef short int16_t;
  43. typedef unsigned short uint16_t;
  44. typedef int int32_t;
  45. typedef unsigned uint32_t;
  46. typedef long long int64_t;
  47. typedef unsigned long long uint64_t;
  48. #endif
  49. #define SIZE_LABEL_SUFFIX "_size"
  50. #define SIZE_TYPE uint32_t
  51. #define IMAGE_SIZEOF_SHORT_NAME 8
  52. /* File header defines */
  53. #define IMAGE_FILE_MACHINE_ANY 0x0000
  54. #define IMAGE_FILE_MACHINE_I386 0x014c
  55. #define IMAGE_FILE_MACHINE_IA64 0x0200
  56. #define IMAGE_FILE_MACHINE_AMD64 0x8664
  57. #define IMAGE_FILE_MACHINE_ARM64 0xAA64
  58. #define IMAGE_FILE_RELOCS_STRIPPED 0x0001
  59. #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
  60. #define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
  61. #define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
  62. #define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 /* Obsolete */
  63. #define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
  64. #define IMAGE_FILE_16BIT_MACHINE 0x0040
  65. #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 /* Obsolete */
  66. #define IMAGE_FILE_32BIT_MACHINE 0x0100
  67. #define IMAGE_FILE_DEBUG_STRIPPED 0x0200
  68. #define IMAGE_FILE_REM_RUN_FROM_SWAP 0x0400
  69. #define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800
  70. #define IMAGE_FILE_SYSTEM 0x1000
  71. #define IMAGE_FILE_DLL 0x2000
  72. #define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
  73. #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 /* Obsolete */
  74. /* Section header defines */
  75. #define IMAGE_SCN_TYPE_REG 0x00000000 /* Reserved */
  76. #define IMAGE_SCN_TYPE_DSECT 0x00000001 /* Reserved */
  77. #define IMAGE_SCN_TYPE_NOLOAD 0x00000002 /* Reserved */
  78. #define IMAGE_SCN_TYPE_GROUP 0x00000003 /* Reserved */
  79. #define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Obsolete */
  80. #define IMAGE_SCN_TYPE_COPY 0x00000010 /* Reserved */
  81. #define IMAGE_SCN_CNT_CODE 0x00000020
  82. #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
  83. #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
  84. #define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved */
  85. #define IMAGE_SCN_LNK_INFO 0x00000200
  86. #define IMAGE_SCN_TYPE_OVER 0x00000400 /* Reserved */
  87. #define IMAGE_SCN_LNK_REMOVE 0x00000800
  88. #define IMAGE_SCN_LNK_COMDAT 0x00001000
  89. #define IMAGE_SCN_MEM_FARDATA 0x00008000 /* Reserved */
  90. #define IMAGE_SCN_MEM_PURGEABLE 0x00020000 /* Reserved */
  91. #define IMAGE_SCN_MEM_16BIT 0x00020000 /* Reserved */
  92. #define IMAGE_SCN_MEM_LOCKED 0x00040000 /* Reserved */
  93. #define IMAGE_SCN_MEM_PRELOAD 0x00080000 /* Reserved */
  94. #define IMAGE_SCN_ALIGN_1BYTES 0x00100000
  95. #define IMAGE_SCN_ALIGN_2BYTES 0x00200000
  96. #define IMAGE_SCN_ALIGN_4BYTES 0x00300000
  97. #define IMAGE_SCN_ALIGN_8BYTES 0x00400000
  98. #define IMAGE_SCN_ALIGN_16BYTES 0x00500000
  99. #define IMAGE_SCN_ALIGN_32BYTES 0x00600000
  100. #define IMAGE_SCN_ALIGN_64BYTES 0x00700000
  101. #define IMAGE_SCN_ALIGN_128BYTES 0x00800000
  102. #define IMAGE_SCN_ALIGN_256BYTES 0x00900000
  103. #define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
  104. #define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
  105. #define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
  106. #define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
  107. #define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
  108. #define IMAGE_SCN_ALIGN_MASK 0x00F00000
  109. #define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
  110. #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
  111. #define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
  112. #define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
  113. #define IMAGE_SCN_MEM_SHARED 0x10000000
  114. #define IMAGE_SCN_MEM_EXECUTE 0x20000000
  115. #define IMAGE_SCN_MEM_READ 0x40000000
  116. #define IMAGE_SCN_MEM_WRITE 0x80000000
  117. /* Symbol entry defines */
  118. #define IMAGE_SYM_UNDEFINED (int16_t)0
  119. #define IMAGE_SYM_ABSOLUTE (int16_t)-1
  120. #define IMAGE_SYM_DEBUG (int16_t)-2
  121. #define IMAGE_SYM_TYPE_NULL 0x0000
  122. #define IMAGE_SYM_TYPE_VOID 0x0001
  123. #define IMAGE_SYM_TYPE_CHAR 0x0002
  124. #define IMAGE_SYM_TYPE_SHORT 0x0003
  125. #define IMAGE_SYM_TYPE_INT 0x0004
  126. #define IMAGE_SYM_TYPE_LONG 0x0005
  127. #define IMAGE_SYM_TYPE_FLOAT 0x0006
  128. #define IMAGE_SYM_TYPE_DOUBLE 0x0007
  129. #define IMAGE_SYM_TYPE_STRUCT 0x0008
  130. #define IMAGE_SYM_TYPE_UNION 0x0009
  131. #define IMAGE_SYM_TYPE_ENUM 0x000A
  132. #define IMAGE_SYM_TYPE_MOE 0x000B
  133. #define IMAGE_SYM_TYPE_BYTE 0x000C
  134. #define IMAGE_SYM_TYPE_WORD 0x000D
  135. #define IMAGE_SYM_TYPE_UINT 0x000E
  136. #define IMAGE_SYM_TYPE_DWORD 0x000F
  137. #define IMAGE_SYM_TYPE_PCODE 0x8000
  138. #define IMAGE_SYM_DTYPE_NULL 0
  139. #define IMAGE_SYM_DTYPE_POINTER 1
  140. #define IMAGE_SYM_DTYPE_FUNCTION 2
  141. #define IMAGE_SYM_DTYPE_ARRAY 3
  142. #define IMAGE_SYM_CLASS_END_OF_FUNCTION (uint8_t)-1
  143. #define IMAGE_SYM_CLASS_NULL 0x00
  144. #define IMAGE_SYM_CLASS_AUTOMATIC 0x01
  145. #define IMAGE_SYM_CLASS_EXTERNAL 0x02
  146. #define IMAGE_SYM_CLASS_STATIC 0x03
  147. #define IMAGE_SYM_CLASS_REGISTER 0x04
  148. #define IMAGE_SYM_CLASS_EXTERNAL_DEF 0x05
  149. #define IMAGE_SYM_CLASS_LABEL 0x06
  150. #define IMAGE_SYM_CLASS_UNDEFINED_LABEL 0x07
  151. #define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 0x08
  152. #define IMAGE_SYM_CLASS_ARGUMENT 0x09
  153. #define IMAGE_SYM_CLASS_STRUCT_TAG 0x0A
  154. #define IMAGE_SYM_CLASS_MEMBER_OF_UNION 0x0B
  155. #define IMAGE_SYM_CLASS_UNION_TAG 0x0C
  156. #define IMAGE_SYM_CLASS_TYPE_DEFINITION 0x0D
  157. #define IMAGE_SYM_CLASS_UNDEFINED_STATIC 0x0E
  158. #define IMAGE_SYM_CLASS_ENUM_TAG 0x0F
  159. #define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 0x10
  160. #define IMAGE_SYM_CLASS_REGISTER_PARAM 0x11
  161. #define IMAGE_SYM_CLASS_BIT_FIELD 0x12
  162. #define IMAGE_SYM_CLASS_FAR_EXTERNAL 0x44
  163. #define IMAGE_SYM_CLASS_BLOCK 0x64
  164. #define IMAGE_SYM_CLASS_FUNCTION 0x65
  165. #define IMAGE_SYM_CLASS_END_OF_STRUCT 0x66
  166. #define IMAGE_SYM_CLASS_FILE 0x67
  167. #define IMAGE_SYM_CLASS_SECTION 0x68
  168. #define IMAGE_SYM_CLASS_WEAK_EXTERNAL 0x69
  169. #define IMAGE_SYM_CLASS_CLR_TOKEN 0x6B
  170. #pragma pack(push, 2)
  171. /* Microsoft COFF File Header */
  172. typedef struct {
  173. uint16_t Machine;
  174. uint16_t NumberOfSections;
  175. uint32_t TimeDateStamp;
  176. uint32_t PointerToSymbolTable;
  177. uint32_t NumberOfSymbols;
  178. uint16_t SizeOfOptionalHeader;
  179. uint16_t Characteristics;
  180. } IMAGE_FILE_HEADER;
  181. /* Microsoft COFF Section Header */
  182. typedef struct {
  183. char Name[IMAGE_SIZEOF_SHORT_NAME];
  184. uint32_t VirtualSize;
  185. uint32_t VirtualAddress;
  186. uint32_t SizeOfRawData;
  187. uint32_t PointerToRawData;
  188. uint32_t PointerToRelocations;
  189. uint32_t PointerToLinenumbers;
  190. uint16_t NumberOfRelocations;
  191. uint16_t NumberOfLinenumbers;
  192. uint32_t Characteristics;
  193. } IMAGE_SECTION_HEADER;
  194. /* Microsoft COFF Symbol Entry */
  195. typedef struct {
  196. union {
  197. char ShortName[IMAGE_SIZEOF_SHORT_NAME];
  198. struct {
  199. uint32_t Zeroes;
  200. uint32_t Offset;
  201. } LongName;
  202. } N;
  203. int32_t Value;
  204. int16_t SectionNumber;
  205. uint16_t Type;
  206. uint8_t StorageClass;
  207. uint8_t NumberOfAuxSymbols;
  208. } IMAGE_SYMBOL;
  209. /* COFF String Table */
  210. typedef struct {
  211. uint32_t TotalSize;
  212. char Strings[0];
  213. } IMAGE_STRINGS;
  214. #pragma pack(pop)
  215. typedef enum
  216. {
  217. MACHINE_X86 = 0,
  218. MACHINE_X64 = 1,
  219. MACHINE_ARM64 = 2
  220. } machine_type;
  221. static int check_machine(const char *arg, machine_type *machine)
  222. {
  223. if ((strcmp(arg, "32bit") == 0) || (strcmp(arg, "Win32") == 0))
  224. *machine = MACHINE_X86;
  225. else if ((strcmp(arg, "64bit") == 0) || (strcmp(arg, "x64") == 0))
  226. *machine = MACHINE_X64;
  227. else if ((strcmp(arg, "ARM64") == 0) || (strcmp(arg, "aarch64") == 0))
  228. *machine = MACHINE_ARM64;
  229. else
  230. return 0;
  231. return 1;
  232. }
  233. int
  234. #ifdef DDKBUILD
  235. __cdecl
  236. #endif
  237. main (int argc, char *argv[])
  238. {
  239. const uint16_t endian_test = 0xBE00;
  240. int x86_32, short_label, short_size, last_arg;
  241. machine_type machine;
  242. int i, r = 1;
  243. char* label;
  244. FILE *fd = NULL;
  245. size_t size, alloc_size;
  246. uint8_t* buffer = NULL;
  247. IMAGE_FILE_HEADER* file_header;
  248. IMAGE_SECTION_HEADER* section_header;
  249. IMAGE_SYMBOL* symbol_table;
  250. IMAGE_STRINGS* string_table;
  251. SIZE_TYPE* data_size;
  252. if ((argc < 3) || (argc > 5)) {
  253. fprintf(stderr, "\nUsage: bin2coff bin obj [label] [64bit|Win32|x64|ARM64|aarch64]\n\n");
  254. fprintf(stderr, " bin : source binary data\n");
  255. fprintf(stderr, " obj : target object file, in MS COFF format.\n");
  256. fprintf(stderr, " label: identifier for the extern data. If not provided, the name of the\n");
  257. fprintf(stderr, " binary file without extension is used.\n");
  258. fprintf(stderr, " Win32:\n x86 : produce a 32 bit compatible object - \n");
  259. fprintf(stderr, " machine type is set to x86.\n\n");
  260. fprintf(stderr, " 64bit:\n x64 : produce a 64 bit compatible object - symbols are generated without\n");
  261. fprintf(stderr, " leading underscores and machine type is set to x86_x64.\n\n");
  262. fprintf(stderr, " ARM64:\n aarch64: produce an ARM 64 bit compatible object -\n");
  263. fprintf(stderr, " machine type is set to ARM64.\n\n");
  264. fprintf(stderr, "With your linker set properly, typical access from a C source is:\n\n");
  265. fprintf(stderr, " extern uint8_t label[] /* binary data */\n");
  266. fprintf(stderr, " extern uint32_t label_size /* size of binary data */\n\n");
  267. exit(1);
  268. }
  269. if (((uint8_t*)&endian_test)[0] == 0xBE) {
  270. fprintf(stderr, "\nThis program is not compatible with Big Endian architectures.\n");
  271. fprintf(stderr, "You are welcome to modify the sourcecode (GPLv3+) to make it so.\n");
  272. exit(1);
  273. }
  274. fd = fopen(argv[1], "rb");
  275. if (fd == NULL) {
  276. fprintf(stderr, "Couldn't open file '%s'.\n", argv[1]);
  277. goto err;
  278. }
  279. fseek(fd, 0, SEEK_END);
  280. size = (size_t)ftell(fd);
  281. fseek(fd, 0, SEEK_SET);
  282. machine = MACHINE_X86;
  283. last_arg = argc;
  284. if (argc >= 4 && check_machine(argv[3], &machine))
  285. last_arg = 4;
  286. else if (argc >= 5 && check_machine(argv[4], &machine))
  287. last_arg = 5;
  288. x86_32 = machine == MACHINE_X86 ? 1 : 0;
  289. /* Label setup */
  290. if (argc < last_arg) {
  291. for (i=(int)strlen(argv[1])-1; i>=0; i--) {
  292. if (argv[1][i] == '.') {
  293. argv[1][i] = 0;
  294. break;
  295. }
  296. }
  297. label = argv[1];
  298. } else {
  299. label = argv[3];
  300. }
  301. {
  302. char *s = label;
  303. while (*s) {
  304. if (*s == '-')
  305. *s = '_';
  306. s++;
  307. }
  308. }
  309. short_label = (strlen(label) + x86_32) <= IMAGE_SIZEOF_SHORT_NAME;
  310. short_size = (strlen(label) + x86_32 + strlen(SIZE_LABEL_SUFFIX)) <= IMAGE_SIZEOF_SHORT_NAME;
  311. alloc_size = sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER) + size + sizeof(SIZE_TYPE) + 2*sizeof(IMAGE_SYMBOL) + sizeof(IMAGE_STRINGS);
  312. if (!short_label) {
  313. alloc_size += x86_32 + strlen(label) + 1;
  314. }
  315. if (!short_size) {
  316. alloc_size += x86_32 + strlen(label) + strlen(SIZE_LABEL_SUFFIX) + 1;
  317. }
  318. buffer = (uint8_t*)calloc(alloc_size, 1);
  319. if (buffer == NULL) {
  320. fprintf(stderr, "Couldn't allocate buffer.\n");
  321. goto err;
  322. }
  323. file_header = (IMAGE_FILE_HEADER*)&buffer[0];
  324. section_header = (IMAGE_SECTION_HEADER*)&buffer[sizeof(IMAGE_FILE_HEADER)];
  325. symbol_table = (IMAGE_SYMBOL*)&buffer[sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER) + size + sizeof(SIZE_TYPE)];
  326. string_table = (IMAGE_STRINGS*)&buffer[sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER) + size + sizeof(SIZE_TYPE) + 2*sizeof(IMAGE_SYMBOL)];
  327. /* Populate file header */
  328. if (machine == MACHINE_X86)
  329. file_header->Machine = IMAGE_FILE_MACHINE_I386;
  330. else if (machine == MACHINE_X64)
  331. file_header->Machine = IMAGE_FILE_MACHINE_AMD64;
  332. else
  333. file_header->Machine = IMAGE_FILE_MACHINE_ARM64;
  334. file_header->NumberOfSections = 1;
  335. file_header->PointerToSymbolTable = sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER) + (uint32_t)size+4;
  336. file_header->NumberOfSymbols = 2;
  337. file_header->Characteristics = IMAGE_FILE_LINE_NUMS_STRIPPED;
  338. /* Populate data section header */
  339. strncpy(section_header->Name, ".data", IMAGE_SIZEOF_SHORT_NAME);
  340. section_header->SizeOfRawData = (uint32_t)size+4;
  341. section_header->PointerToRawData = sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER);
  342. section_header->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
  343. /* Populate data section */
  344. if (fread(&buffer[sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER)], 1, size, fd) != size) {
  345. fprintf(stderr, "Couldn't read file '%s'.\n", argv[1]);
  346. goto err;
  347. }
  348. fclose(fd); fd = NULL;
  349. data_size = (SIZE_TYPE*)&buffer[sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER) + size];
  350. *data_size = (SIZE_TYPE)size;
  351. /* Populate symbol table */
  352. if (short_label) {
  353. symbol_table[0].N.ShortName[0] = '_';
  354. strcpy(&symbol_table[0].N.ShortName[x86_32], label);
  355. } else {
  356. symbol_table[0].N.LongName.Zeroes = 0;
  357. symbol_table[0].N.LongName.Offset = sizeof(IMAGE_STRINGS);
  358. }
  359. /* Ideally, we would use (IMAGE_SYM_DTYPE_ARRAY << 8) | IMAGE_SYM_TYPE_BYTE
  360. * to indicate an array of bytes, but the type is ignored in MS objects. */
  361. symbol_table[0].Type = IMAGE_SYM_TYPE_NULL;
  362. symbol_table[0].StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
  363. symbol_table[0].SectionNumber = 1;
  364. symbol_table[0].Value = 0; /* Offset within the section */
  365. if (short_size) {
  366. symbol_table[1].N.ShortName[1] = '_';
  367. strcpy(&symbol_table[1].N.ShortName[x86_32], label);
  368. strcpy(&symbol_table[1].N.ShortName[x86_32+strlen(label)], SIZE_LABEL_SUFFIX);
  369. } else {
  370. symbol_table[1].N.LongName.Zeroes = 0;
  371. symbol_table[1].N.LongName.Offset = sizeof(IMAGE_STRINGS) + ((short_label)?0:(x86_32 + (uint32_t)strlen(label) + 1));
  372. }
  373. symbol_table[1].Type = IMAGE_SYM_TYPE_NULL;
  374. symbol_table[1].StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
  375. symbol_table[1].SectionNumber = 1;
  376. symbol_table[1].Value = (int32_t)size; /* Offset within the section */
  377. /* Populate string table */
  378. string_table->TotalSize = sizeof(IMAGE_STRINGS);
  379. if (!short_label) {
  380. string_table->Strings[0] = '_';
  381. strcpy(&string_table->Strings[0] + x86_32, label);
  382. string_table->TotalSize += x86_32 + (uint32_t)strlen(label) + 1;
  383. }
  384. if (!short_size) {
  385. string_table->Strings[string_table->TotalSize - sizeof(IMAGE_STRINGS)] = '_';
  386. strcpy(&string_table->Strings[string_table->TotalSize - sizeof(IMAGE_STRINGS)] + x86_32, label);
  387. string_table->TotalSize += x86_32 + (uint32_t)strlen(label);
  388. strcpy(&string_table->Strings[string_table->TotalSize - sizeof(IMAGE_STRINGS)], SIZE_LABEL_SUFFIX);
  389. string_table->TotalSize += (uint32_t)strlen(SIZE_LABEL_SUFFIX) + 1;
  390. }
  391. fd = fopen(argv[2], "wb");
  392. if (fd == NULL) {
  393. fprintf(stderr, "Couldn't create file '%s'.\n", argv[2]);
  394. goto err;
  395. }
  396. if (fwrite(buffer, 1, alloc_size, fd) != alloc_size) {
  397. fprintf(stderr, "Couldn't write file '%s'.\n", argv[2]);
  398. goto err;
  399. }
  400. printf("Successfully created COFF object file '%s'\n", argv[2]);
  401. r = 0;
  402. err:
  403. if (fd != NULL) fclose(fd);
  404. free(buffer);
  405. exit(r);
  406. }