-/*\r
- * PE Fixup Utility\r
- * Copyright (C) 2005 Filip Navara\r
- *\r
- * The purpose of this utility is fix PE binaries generated by binutils and\r
- * to manipulate flags that can't be set by binutils.\r
- *\r
- * Currently two features are implemented:\r
- *\r
- * - Setting flags on PE sections for use by drivers. The sections\r
- * .text, .data, .idata, .bss are marked as non-pageable and\r
- * non-discarable, section PAGE is marked as pageable and section\r
- * INIT is marked as discaradable.\r
- *\r
- * - Sorting of export name table in executables. DLLTOOL has bug\r
- * in sorting algorithm when the --kill-at flag is used. The exports\r
- * are sorted in the decorated form and so the fastcall symbols are\r
- * incorrectly put at the beginning of export table. This option\r
- * allow to correct sort the table, so binary search can be used\r
- * to process them.\r
- */\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <fcntl.h>\r
-\r
-/* The following definitions are ripped from MinGW W32API headers. We don't\r
- use these headers directly in order to allow compilation on Linux hosts. */\r
-\r
-typedef unsigned char BYTE;\r
-typedef unsigned short WORD;\r
-typedef unsigned int DWORD;\r
-typedef int LONG;\r
-\r
-#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16\r
-#define IMAGE_SIZEOF_SHORT_NAME 8\r
-#define IMAGE_DOS_SIGNATURE 0x5A4D\r
-#define IMAGE_NT_SIGNATURE 0x00004550\r
-#define IMAGE_SCN_MEM_DISCARDABLE 0x2000000\r
-#define IMAGE_SCN_MEM_NOT_PAGED 0x8000000\r
-#define FIELD_OFFSET(t,f) ((LONG)&(((t*)0)->f))\r
-#define IMAGE_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((DWORD)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader))\r
-#define IMAGE_DIRECTORY_ENTRY_EXPORT 0\r
-\r
-#pragma pack(push,2)\r
-typedef struct _IMAGE_DOS_HEADER {\r
- WORD e_magic;\r
- WORD e_cblp;\r
- WORD e_cp;\r
- WORD e_crlc;\r
- WORD e_cparhdr;\r
- WORD e_minalloc;\r
- WORD e_maxalloc;\r
- WORD e_ss;\r
- WORD e_sp;\r
- WORD e_csum;\r
- WORD e_ip;\r
- WORD e_cs;\r
- WORD e_lfarlc;\r
- WORD e_ovno;\r
- WORD e_res[4];\r
- WORD e_oemid;\r
- WORD e_oeminfo;\r
- WORD e_res2[10];\r
- LONG e_lfanew;\r
-} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;\r
-#pragma pack(pop)\r
-#pragma pack(push,4)\r
-typedef struct _IMAGE_EXPORT_DIRECTORY {\r
- DWORD Characteristics;\r
- DWORD TimeDateStamp;\r
- WORD MajorVersion;\r
- WORD MinorVersion;\r
- DWORD Name;\r
- DWORD Base;\r
- DWORD NumberOfFunctions;\r
- DWORD NumberOfNames;\r
- DWORD AddressOfFunctions;\r
- DWORD AddressOfNames;\r
- DWORD AddressOfNameOrdinals;\r
-} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;\r
-typedef struct _IMAGE_FILE_HEADER {\r
- WORD Machine;\r
- WORD NumberOfSections;\r
- DWORD TimeDateStamp;\r
- DWORD PointerToSymbolTable;\r
- DWORD NumberOfSymbols;\r
- WORD SizeOfOptionalHeader;\r
- WORD Characteristics;\r
-} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;\r
-typedef struct _IMAGE_DATA_DIRECTORY {\r
- DWORD VirtualAddress;\r
- DWORD Size;\r
-} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;\r
-typedef struct _IMAGE_OPTIONAL_HEADER {\r
- WORD Magic;\r
- BYTE MajorLinkerVersion;\r
- BYTE MinorLinkerVersion;\r
- DWORD SizeOfCode;\r
- DWORD SizeOfInitializedData;\r
- DWORD SizeOfUninitializedData;\r
- DWORD AddressOfEntryPoint;\r
- DWORD BaseOfCode;\r
- DWORD BaseOfData;\r
- DWORD ImageBase;\r
- DWORD SectionAlignment;\r
- DWORD FileAlignment;\r
- WORD MajorOperatingSystemVersion;\r
- WORD MinorOperatingSystemVersion;\r
- WORD MajorImageVersion;\r
- WORD MinorImageVersion;\r
- WORD MajorSubsystemVersion;\r
- WORD MinorSubsystemVersion;\r
- DWORD Reserved1;\r
- DWORD SizeOfImage;\r
- DWORD SizeOfHeaders;\r
- DWORD CheckSum;\r
- WORD Subsystem;\r
- WORD DllCharacteristics;\r
- DWORD SizeOfStackReserve;\r
- DWORD SizeOfStackCommit;\r
- DWORD SizeOfHeapReserve;\r
- DWORD SizeOfHeapCommit;\r
- DWORD LoaderFlags;\r
- DWORD NumberOfRvaAndSizes;\r
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];\r
-} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;\r
-typedef struct _IMAGE_NT_HEADERS {\r
- DWORD Signature;\r
- IMAGE_FILE_HEADER FileHeader;\r
- IMAGE_OPTIONAL_HEADER OptionalHeader;\r
-} IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;\r
-typedef struct _IMAGE_SECTION_HEADER {\r
- BYTE Name[IMAGE_SIZEOF_SHORT_NAME];\r
- union {\r
- DWORD PhysicalAddress;\r
- DWORD VirtualSize;\r
- } Misc;\r
- DWORD VirtualAddress;\r
- DWORD SizeOfRawData;\r
- DWORD PointerToRawData;\r
- DWORD PointerToRelocations;\r
- DWORD PointerToLinenumbers;\r
- WORD NumberOfRelocations;\r
- WORD NumberOfLinenumbers;\r
- DWORD Characteristics;\r
-} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;\r
-#pragma pack(pop)\r
-\r
-/* End of ripped definitions */\r
-\r
-typedef struct _export_t {\r
- DWORD name;\r
- WORD ordinal;\r
-} export_t;\r
-\r
-unsigned char *buffer;\r
-PIMAGE_DOS_HEADER dos_header;\r
-PIMAGE_NT_HEADERS nt_header;\r
-\r
-void *rva_to_ptr(DWORD rva)\r
-{\r
- PIMAGE_SECTION_HEADER section_header;\r
- unsigned int i;\r
-\r
- for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);\r
- i < nt_header->OptionalHeader.NumberOfRvaAndSizes;\r
- i++, section_header++)\r
- {\r
- if (rva >= section_header->VirtualAddress &&\r
- rva < section_header->VirtualAddress +\r
- section_header->Misc.VirtualSize)\r
- {\r
- return buffer + rva - section_header->VirtualAddress +\r
- section_header->PointerToRawData;\r
- }\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-int export_compare_func(const void *a, const void *b)\r
-{\r
- const export_t *ap = a;\r
- const export_t *bp = b;\r
- char *an = rva_to_ptr(ap->name);\r
- char *bn = rva_to_ptr(bp->name);\r
- return strcmp(an, bn);\r
-}\r
-\r
-int main(int argc, char **argv)\r
-{\r
- int fd_in, fd_out;\r
- long len;\r
- PIMAGE_SECTION_HEADER section_header;\r
- PIMAGE_DATA_DIRECTORY data_dir;\r
- unsigned int i;\r
- unsigned long checksum;\r
- int fixup_exports = 0;\r
- int fixup_sections = 0;\r
-\r
- /*\r
- * Process parameters.\r
- */\r
-\r
- if (argc < 2)\r
- {\r
- printf("Usage: %s <filename> <options>\n"\r
- "Options:\n"\r
- " -sections Sets section flags for PE image.\n"\r
- " -exports Sort the names in export table.\n",\r
- argv[0]);\r
- return 1;\r
- }\r
-\r
- for (i = 2; i < argc; i++)\r
- {\r
- if (!strcmp(argv[i], "-sections"))\r
- fixup_sections = 1;\r
- else if (!strcmp(argv[i], "-exports"))\r
- fixup_exports = 1;\r
- else\r
- { printf("Invalid option: %s\n", argv[i]); return 1; }\r
- }\r
-\r
- if (fixup_sections == 0 && fixup_exports == 0)\r
- {\r
- printf("Nothing to do.\n");\r
- return 0;\r
- }\r
-\r
- /*\r
- * Read the whole file to memory.\r
- */\r
-\r
- fd_in = open(argv[1], O_RDONLY | O_BINARY);\r
- if (fd_in == 0)\r
- {\r
- printf("Can't open input file.\n");\r
- return 1;\r
- }\r
-\r
- len = lseek(fd_in, 0, SEEK_END);\r
- if (len < sizeof(IMAGE_DOS_HEADER))\r
- {\r
- close(fd_in);\r
- printf("'%s' isn't a PE image.\n", argv[1]);\r
- return 1;\r
- }\r
-\r
- buffer = malloc((len + 1) & ~1);\r
- if (buffer == NULL)\r
- {\r
- close(fd_in);\r
- printf("Not enough memory available.\n");\r
- return 1;\r
- }\r
-\r
- /* Read the whole input file into a buffer */\r
- lseek(fd_in, 0, SEEK_SET);\r
- read(fd_in, buffer, len);\r
- if (len & 1)\r
- buffer[len] = 0;\r
-\r
- close(fd_in);\r
-\r
- /*\r
- * Check the headers and save pointers to them.\r
- */\r
-\r
- dos_header = (PIMAGE_DOS_HEADER)buffer;\r
- nt_header = (PIMAGE_NT_HEADERS)(buffer + dos_header->e_lfanew);\r
- \r
- if (dos_header->e_magic != IMAGE_DOS_SIGNATURE ||\r
- nt_header->Signature != IMAGE_NT_SIGNATURE)\r
- {\r
- printf("'%s' isn't a PE image.\n", argv[1]);\r
- free(buffer);\r
- return 1;\r
- }\r
-\r
- if (fixup_exports)\r
- {\r
- /* Sort export directory */\r
- data_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];\r
- if (data_dir->Size != 0)\r
- {\r
- PIMAGE_EXPORT_DIRECTORY export_directory;\r
- DWORD *name_ptr;\r
- WORD *ordinal_ptr;\r
- export_t *exports;\r
-\r
- export_directory = (PIMAGE_EXPORT_DIRECTORY)rva_to_ptr(data_dir->VirtualAddress);\r
- if (export_directory != NULL)\r
- {\r
- exports = malloc(sizeof(export_t) * export_directory->NumberOfNames);\r
- if (exports == NULL)\r
- {\r
- printf("Not enough memory.\n");\r
- free(buffer);\r
- return 1;\r
- }\r
-\r
- name_ptr = (DWORD *)rva_to_ptr(export_directory->AddressOfNames);\r
- ordinal_ptr = (WORD *)rva_to_ptr(export_directory->AddressOfNameOrdinals);\r
-\r
- for (i = 0; i < export_directory->NumberOfNames; i++)\r
- {\r
- exports[i].name = name_ptr[i];\r
- exports[i].ordinal = ordinal_ptr[i];\r
- }\r
-\r
- qsort(exports, export_directory->NumberOfNames, sizeof(export_t),\r
- export_compare_func);\r
-\r
- for (i = 0; i < export_directory->NumberOfNames; i++)\r
- {\r
- name_ptr[i] = exports[i].name;\r
- ordinal_ptr[i] = exports[i].ordinal;\r
- }\r
-\r
- free(exports);\r
- }\r
- }\r
- }\r
-\r
- if (fixup_sections)\r
- {\r
- /* Update section flags */\r
- for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);\r
- i < nt_header->OptionalHeader.NumberOfRvaAndSizes;\r
- i++, section_header++)\r
- {\r
- if (!strcmp(section_header->Name, ".text") ||\r
- !strcmp(section_header->Name, ".data") ||\r
- !strcmp(section_header->Name, ".idata") ||\r
- !strcmp(section_header->Name, ".bss"))\r
- {\r
- section_header->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;\r
- section_header->Characteristics &= ~IMAGE_SCN_MEM_DISCARDABLE;\r
- }\r
- else if (!strcmp(section_header->Name, "INIT"))\r
- {\r
- section_header->Characteristics |= IMAGE_SCN_MEM_DISCARDABLE;\r
- }\r
- else if (!strcmp(section_header->Name, "PAGE"))\r
- {\r
- section_header->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;\r
- }\r
- }\r
- }\r
-\r
- /* Recalculate checksum */\r
- nt_header->OptionalHeader.CheckSum = 0;\r
- checksum = 0;\r
- for (i = 0; i < len; i += 2)\r
- {\r
- checksum += *(unsigned short *)(buffer + i);\r
- checksum = (checksum + (checksum >> 16)) & 0xffff;\r
- }\r
- checksum += len;\r
- nt_header->OptionalHeader.CheckSum = checksum;\r
-\r
- /* Write the output file */\r
- fd_out = open(argv[1], O_WRONLY | O_BINARY);\r
- write(fd_out, buffer, len);\r
- close(fd_out);\r
-\r
- return 0;\r
-}\r
+/*
+ * PE Fixup Utility
+ * Copyright (C) 2005 Filip Navara
+ *
+ * The purpose of this utility is fix PE binaries generated by binutils and
+ * to manipulate flags that can't be set by binutils.
+ *
+ * Currently two features are implemented:
+ *
+ * - Setting flags on PE sections for use by drivers. The sections
+ * .text, .data, .idata, .bss are marked as non-pageable and
+ * non-discarable, section PAGE is marked as pageable and section
+ * INIT is marked as discaradable.
+ *
+ * - Sorting of export name table in executables. DLLTOOL has bug
+ * in sorting algorithm when the --kill-at flag is used. The exports
+ * are sorted in the decorated form and so the fastcall symbols are
+ * incorrectly put at the beginning of export table. This option
+ * allow to correct sort the table, so binary search can be used
+ * to process them.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* The following definitions are ripped from MinGW W32API headers. We don't
+ use these headers directly in order to allow compilation on Linux hosts. */
+
+typedef unsigned char BYTE, *PBYTE;
+typedef unsigned short WORD;
+typedef unsigned int DWORD;
+typedef int LONG;
+typedef long LONG_PTR;
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+#define IMAGE_SIZEOF_SHORT_NAME 8
+#define IMAGE_DOS_SIGNATURE 0x5A4D
+#define IMAGE_NT_SIGNATURE 0x00004550
+#define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
+#define IMAGE_SCN_MEM_NOT_PAGED 0x8000000
+#define FIELD_OFFSET(t,f) ((LONG)(LONG_PTR)&(((t*)0)->f))
+#define IMAGE_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((unsigned long)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader))
+#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
+
+#pragma pack(2)
+typedef struct _IMAGE_DOS_HEADER {
+ WORD e_magic;
+ WORD e_cblp;
+ WORD e_cp;
+ WORD e_crlc;
+ WORD e_cparhdr;
+ WORD e_minalloc;
+ WORD e_maxalloc;
+ WORD e_ss;
+ WORD e_sp;
+ WORD e_csum;
+ WORD e_ip;
+ WORD e_cs;
+ WORD e_lfarlc;
+ WORD e_ovno;
+ WORD e_res[4];
+ WORD e_oemid;
+ WORD e_oeminfo;
+ WORD e_res2[10];
+ LONG e_lfanew;
+} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
+#pragma pack(4)
+#pragma pack(4)
+typedef struct _IMAGE_EXPORT_DIRECTORY {
+ DWORD Characteristics;
+ DWORD TimeDateStamp;
+ WORD MajorVersion;
+ WORD MinorVersion;
+ DWORD Name;
+ DWORD Base;
+ DWORD NumberOfFunctions;
+ DWORD NumberOfNames;
+ DWORD AddressOfFunctions;
+ DWORD AddressOfNames;
+ DWORD AddressOfNameOrdinals;
+} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
+typedef struct _IMAGE_FILE_HEADER {
+ WORD Machine;
+ WORD NumberOfSections;
+ DWORD TimeDateStamp;
+ DWORD PointerToSymbolTable;
+ DWORD NumberOfSymbols;
+ WORD SizeOfOptionalHeader;
+ WORD Characteristics;
+} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
+typedef struct _IMAGE_DATA_DIRECTORY {
+ DWORD VirtualAddress;
+ DWORD Size;
+} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
+typedef struct _IMAGE_OPTIONAL_HEADER {
+ WORD Magic;
+ BYTE MajorLinkerVersion;
+ BYTE MinorLinkerVersion;
+ DWORD SizeOfCode;
+ DWORD SizeOfInitializedData;
+ DWORD SizeOfUninitializedData;
+ DWORD AddressOfEntryPoint;
+ DWORD BaseOfCode;
+ DWORD BaseOfData;
+ DWORD ImageBase;
+ DWORD SectionAlignment;
+ DWORD FileAlignment;
+ WORD MajorOperatingSystemVersion;
+ WORD MinorOperatingSystemVersion;
+ WORD MajorImageVersion;
+ WORD MinorImageVersion;
+ WORD MajorSubsystemVersion;
+ WORD MinorSubsystemVersion;
+ DWORD Reserved1;
+ DWORD SizeOfImage;
+ DWORD SizeOfHeaders;
+ DWORD CheckSum;
+ WORD Subsystem;
+ WORD DllCharacteristics;
+ DWORD SizeOfStackReserve;
+ DWORD SizeOfStackCommit;
+ DWORD SizeOfHeapReserve;
+ DWORD SizeOfHeapCommit;
+ DWORD LoaderFlags;
+ DWORD NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
+typedef struct _IMAGE_NT_HEADERS {
+ DWORD Signature;
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_OPTIONAL_HEADER OptionalHeader;
+} IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;
+typedef struct _IMAGE_SECTION_HEADER {
+ BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ DWORD PhysicalAddress;
+ DWORD VirtualSize;
+ } Misc;
+ DWORD VirtualAddress;
+ DWORD SizeOfRawData;
+ DWORD PointerToRawData;
+ DWORD PointerToRelocations;
+ DWORD PointerToLinenumbers;
+ WORD NumberOfRelocations;
+ WORD NumberOfLinenumbers;
+ DWORD Characteristics;
+} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;
+#pragma pack(4)
+
+/* End of ripped definitions */
+
+typedef struct _export_t {
+ DWORD name;
+ WORD ordinal;
+} export_t;
+
+unsigned char *buffer;
+PIMAGE_DOS_HEADER dos_header;
+PIMAGE_NT_HEADERS nt_header;
+
+static inline WORD dtohs(WORD in)
+{
+ PBYTE in_ptr = (PBYTE)∈
+ return in_ptr[0] | (in_ptr[1] << 8);
+}
+
+static inline WORD htods(WORD in)
+{
+ WORD out;
+ PBYTE out_ptr = (PBYTE)&out;
+ out_ptr[0] = in; out_ptr[1] = in >> 8;
+ return out;
+}
+
+static inline DWORD dtohl(DWORD in)
+{
+ PBYTE in_ptr = (PBYTE)∈
+ return in_ptr[0] | (in_ptr[1] << 8) | (in_ptr[2] << 16) | (in_ptr[3] << 24);
+}
+
+static inline DWORD htodl(DWORD in)
+{
+ DWORD out;
+ PBYTE out_ptr = (PBYTE)&out;
+ out_ptr[0] = in ; out_ptr[1] = in >> 8;
+ out_ptr[2] = in >> 16; out_ptr[3] = in >> 24;
+ return out;
+}
+
+void *rva_to_ptr(DWORD rva)
+{
+ PIMAGE_SECTION_HEADER section_header;
+ unsigned int i;
+
+ for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
+ i < dtohl(nt_header->FileHeader.NumberOfSections);
+ i++, section_header++)
+ {
+ if (rva >= dtohl(section_header->VirtualAddress) &&
+ rva < dtohl(section_header->VirtualAddress) +
+ dtohl(section_header->Misc.VirtualSize))
+ {
+ return buffer + rva - dtohl(section_header->VirtualAddress) +
+ dtohl(section_header->PointerToRawData);
+ }
+ }
+
+ return NULL;
+}
+
+int export_compare_func(const void *a, const void *b)
+{
+ const export_t *ap = a;
+ const export_t *bp = b;
+ char *an = rva_to_ptr(ap->name);
+ char *bn = rva_to_ptr(bp->name);
+ return strcmp(an, bn);
+}
+
+int main(int argc, char **argv)
+{
+ int fd_in, fd_out;
+ long len;
+ char hdrbuf[4] = { }, elfhdr[4] = { '\177', 'E', 'L', 'F' };
+ PIMAGE_SECTION_HEADER section_header;
+ PIMAGE_DATA_DIRECTORY data_dir;
+ unsigned int i;
+ unsigned long checksum;
+ int fixup_exports = 0;
+ int fixup_sections = 0;
+
+ /*
+ * Process parameters.
+ */
+
+ if (argc < 2)
+ {
+ printf("Usage: %s <filename> <options>\n"
+ "Options:\n"
+ " -sections Sets section flags for PE image.\n"
+ " -exports Sort the names in export table.\n",
+ argv[0]);
+ return 1;
+ }
+
+ for (i = 2; i < argc; i++)
+ {
+ if (!strcmp(argv[i], "-sections"))
+ fixup_sections = 1;
+ else if (!strcmp(argv[i], "-exports"))
+ fixup_exports = 1;
+ else
+ { printf("Invalid option: %s\n", argv[i]); return 1; }
+ }
+
+ if (fixup_sections == 0 && fixup_exports == 0)
+ {
+ printf("Nothing to do.\n");
+ return 0;
+ }
+
+ /*
+ * Read the whole file to memory.
+ */
+
+ fd_in = open(argv[1], O_RDONLY | O_BINARY);
+ if (fd_in == 0)
+ {
+ printf("Can't open input file.\n");
+ return 1;
+ }
+
+ /*
+ * PowerPC ReactOS uses elf, so doesn't need pefixup
+ */
+ len = read(fd_in, hdrbuf, sizeof(elfhdr));
+ if (!memcmp(hdrbuf, elfhdr, sizeof(elfhdr)))
+ return 0;
+
+ len = lseek(fd_in, 0, SEEK_END);
+ if (len < sizeof(IMAGE_DOS_HEADER))
+ {
+ close(fd_in);
+ printf("'%s' isn't a PE image (too short)\n", argv[1]);
+ return 1;
+ }
+
+ /* Lower down we overwrite the byte at len, so here, we need at least
+ * one more byte than len. We'll be guaranteed one or two now. */
+ buffer = malloc((len + 2) & ~1);
+ if (buffer == NULL)
+ {
+ close(fd_in);
+ printf("Not enough memory available.\n");
+ return 1;
+ }
+
+ /* Read the whole input file into a buffer */
+ lseek(fd_in, 0, SEEK_SET);
+ read(fd_in, buffer, len);
+ /* Here is where the block end overwrite was */
+ if (len & 1)
+ buffer[len] = 0;
+
+ close(fd_in);
+
+ /*
+ * Check the headers and save pointers to them.
+ */
+
+ dos_header = (PIMAGE_DOS_HEADER)buffer;
+ nt_header = (PIMAGE_NT_HEADERS)(buffer + dtohl(dos_header->e_lfanew));
+
+ if (dtohs(dos_header->e_magic) != IMAGE_DOS_SIGNATURE ||
+ dtohl(nt_header->Signature) != IMAGE_NT_SIGNATURE)
+ {
+ printf("'%s' isn't a PE image (bad headers)\n", argv[1]);
+ free(buffer);
+ return 1;
+ }
+
+ if (fixup_exports)
+ {
+ /* Sort export directory */
+ data_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+ if (dtohl(data_dir->Size) != 0)
+ {
+ PIMAGE_EXPORT_DIRECTORY export_directory;
+ DWORD *name_ptr;
+ WORD *ordinal_ptr;
+ export_t *exports;
+
+ export_directory = (PIMAGE_EXPORT_DIRECTORY)rva_to_ptr(dtohl(data_dir->VirtualAddress));
+ if (export_directory != NULL)
+ {
+ exports = malloc(sizeof(export_t) * dtohl(export_directory->NumberOfNames));
+ if (exports == NULL)
+ {
+ printf("Not enough memory.\n");
+ free(buffer);
+ return 1;
+ }
+
+ name_ptr = (DWORD *)rva_to_ptr(dtohl(export_directory->AddressOfNames));
+ ordinal_ptr = (WORD *)rva_to_ptr(dtohl(export_directory->AddressOfNameOrdinals));
+
+ for (i = 0; i < dtohl(export_directory->NumberOfNames); i++)
+ {
+ exports[i].name = dtohl(name_ptr[i]);
+ exports[i].ordinal = dtohl(ordinal_ptr[i]);
+ }
+
+ qsort(exports, dtohl(export_directory->NumberOfNames), sizeof(export_t),
+ export_compare_func);
+
+ for (i = 0; i < dtohl(export_directory->NumberOfNames); i++)
+ {
+ name_ptr[i] = htodl(exports[i].name);
+ ordinal_ptr[i] = htodl(exports[i].ordinal);
+ }
+
+ free(exports);
+ }
+ }
+ }
+
+ if (fixup_sections)
+ {
+ /* Update section flags */
+ for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
+ i < dtohl(nt_header->OptionalHeader.NumberOfRvaAndSizes);
+ i++, section_header++)
+ {
+ if (!strcmp((char*)section_header->Name, ".text") ||
+ !strcmp((char*)section_header->Name, ".data") ||
+ !strcmp((char*)section_header->Name, ".idata") ||
+ !strcmp((char*)section_header->Name, ".bss"))
+ {
+ section_header->Characteristics |= htodl(IMAGE_SCN_MEM_NOT_PAGED);
+ section_header->Characteristics &= htodl(~IMAGE_SCN_MEM_DISCARDABLE);
+ }
+ else if (!strcmp((char*)section_header->Name, "INIT"))
+ {
+ section_header->Characteristics |= htodl(IMAGE_SCN_MEM_DISCARDABLE);
+ }
+ else if (!strcmp((char*)section_header->Name, "PAGE"))
+ {
+ section_header->Characteristics |= htodl(IMAGE_SCN_MEM_NOT_PAGED);
+ }
+ }
+ }
+
+ /* Recalculate checksum */
+ nt_header->OptionalHeader.CheckSum = 0;
+ checksum = 0;
+ for (i = 0; i < len; i += 2)
+ {
+ checksum += *(unsigned short *)(buffer + i);
+ checksum = (checksum + (checksum >> 16)) & 0xffff;
+ }
+ checksum += len;
+ nt_header->OptionalHeader.CheckSum = htods(checksum);
+
+ /* Write the output file */
+ fd_out = open(argv[1], O_WRONLY | O_BINARY);
+ write(fd_out, buffer, len);
+ close(fd_out);
+
+ return 0;
+}