https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0b948581fc279f262cfef…
commit 0b948581fc279f262cfef1aa517229bd29ac8736
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Mon Apr 13 12:20:47 2020 +0200
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Fri Apr 17 17:47:24 2020 +0200
[SDK][HOST-TOOLS] Add load_config workaround for gcc builds
Since binutils can not add this, we re-introduce pefixup.
It searches for the exported symbol '_load_config_used',
and uses that to fill out the LOAD_CONFIG directory in the PE header
---
CMakeLists.txt | 2 +-
modules/rostests/apitests/CMakeLists.txt | 6 +-
.../rostests/apitests/loadconfig/CMakeLists.txt | 8 +-
.../apitests/loadconfig/loadconfig_apitest.spec | 3 +
sdk/cmake/gcc.cmake | 8 +
sdk/cmake/msvc.cmake | 4 +
sdk/tools/CMakeLists.txt | 5 +-
sdk/tools/pefixup.c | 543 ++++++---------------
8 files changed, 185 insertions(+), 394 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 777a0335304..50fbf192c4b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -98,7 +98,7 @@ if(NOT CMAKE_CROSSCOMPILING)
set(NATIVE_TARGETS bin2c widl gendib cabman fatten hpp isohybrid mkhive mkisofs
obj2bin spec2def geninc mkshelllink utf16le xml2sdb)
if(NOT MSVC)
- list(APPEND NATIVE_TARGETS rsym)
+ list(APPEND NATIVE_TARGETS rsym pefixup)
endif()
export(TARGETS ${NATIVE_TARGETS} FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake
NAMESPACE native- )
diff --git a/modules/rostests/apitests/CMakeLists.txt
b/modules/rostests/apitests/CMakeLists.txt
index abb0fb8209b..2662835eeeb 100644
--- a/modules/rostests/apitests/CMakeLists.txt
+++ b/modules/rostests/apitests/CMakeLists.txt
@@ -22,11 +22,7 @@ add_subdirectory(gdi32)
add_subdirectory(gditools)
add_subdirectory(iphlpapi)
add_subdirectory(kernel32)
-if(NOT GCC)
- # gcc / binutils are unable to add an IMAGE_LOAD_CONFIG_DIRECTORY
- # So maybe we should resuscitate sdk/tools/pefixup.c
- add_subdirectory(loadconfig)
-endif()
+add_subdirectory(loadconfig)
add_subdirectory(localspl)
add_subdirectory(mountmgr)
add_subdirectory(msgina)
diff --git a/modules/rostests/apitests/loadconfig/CMakeLists.txt
b/modules/rostests/apitests/loadconfig/CMakeLists.txt
index a09e73e90b1..8c0860b7c13 100644
--- a/modules/rostests/apitests/loadconfig/CMakeLists.txt
+++ b/modules/rostests/apitests/loadconfig/CMakeLists.txt
@@ -1,12 +1,16 @@
+spec2def(loadconfig_apitest.exe loadconfig_apitest.spec)
+
list(APPEND SOURCE
common.c
stacktrace.c
loadconfig.h)
-add_executable(loadconfig_apitest ${SOURCE} testlist.c)
+add_executable(loadconfig_apitest ${SOURCE} testlist.c
${CMAKE_CURRENT_BINARY_DIR}/loadconfig_apitest.def)
target_link_libraries(loadconfig_apitest wine ${PSEH_LIB})
set_module_type(loadconfig_apitest win32cui)
add_importlibs(loadconfig_apitest msvcrt kernel32 ntdll)
-add_pch(loadconfig_apitest loadconfig.h SOURCE)
+#add_pch(loadconfig_apitest loadconfig.h SOURCE)
add_rostests_file(TARGET loadconfig_apitest)
+
+fixup_load_config(loadconfig_apitest)
diff --git a/modules/rostests/apitests/loadconfig/loadconfig_apitest.spec
b/modules/rostests/apitests/loadconfig/loadconfig_apitest.spec
new file mode 100644
index 00000000000..8eb80758252
--- /dev/null
+++ b/modules/rostests/apitests/loadconfig/loadconfig_apitest.spec
@@ -0,0 +1,3 @@
+
+# Export this symbol so we can do binutils job
+@ extern _load_config_used
diff --git a/sdk/cmake/gcc.cmake b/sdk/cmake/gcc.cmake
index 5f0ea13b23a..7d42f327ecf 100644
--- a/sdk/cmake/gcc.cmake
+++ b/sdk/cmake/gcc.cmake
@@ -345,6 +345,14 @@ if(NOT ARCH STREQUAL "i386")
set(DECO_OPTION "-@")
endif()
+function(fixup_load_config _target)
+ get_target_property(PEFIXUP native-pefixup IMPORTED_LOCATION_NOCONFIG)
+ add_custom_command(TARGET ${_target} POST_BUILD
+ COMMAND "${PEFIXUP}"
+ "$<TARGET_FILE:${_target}>"
+ COMMENT "Patching in LOAD_CONFIG")
+endfunction()
+
function(generate_import_lib _libname _dllname _spec_file)
# Generate the def for the import lib
add_custom_command(
diff --git a/sdk/cmake/msvc.cmake b/sdk/cmake/msvc.cmake
index 0662fd24692..ce526ed979f 100644
--- a/sdk/cmake/msvc.cmake
+++ b/sdk/cmake/msvc.cmake
@@ -371,6 +371,10 @@ function(add_delay_importlibs _module)
target_link_libraries(${_module} delayimp)
endfunction()
+function(fixup_load_config _target)
+ # msvc knows how to generate a load_config so no hacks here
+endfunction()
+
function(generate_import_lib _libname _dllname _spec_file)
set(_def_file ${CMAKE_CURRENT_BINARY_DIR}/${_libname}_exp.def)
diff --git a/sdk/tools/CMakeLists.txt b/sdk/tools/CMakeLists.txt
index 7fab47e68ba..f9e0e19f5f4 100644
--- a/sdk/tools/CMakeLists.txt
+++ b/sdk/tools/CMakeLists.txt
@@ -4,8 +4,6 @@ function(add_host_tool _tool)
set_target_properties(${_tool} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TOOLS_FOLDER})
endfunction()
-#add_executable(pefixup pefixup.c)
-
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -DHAVE_IO_H=1)
add_compile_flags_language("/EHsc" "CXX")
@@ -40,4 +38,7 @@ add_subdirectory(xml2sdb)
if(NOT MSVC)
add_subdirectory(log2lines)
add_subdirectory(rsym)
+
+ add_host_tool(pefixup pefixup.c)
+ target_link_libraries(pefixup PRIVATE host_includes)
endif()
diff --git a/sdk/tools/pefixup.c b/sdk/tools/pefixup.c
index be25015e48b..97529747ae1 100644
--- a/sdk/tools/pefixup.c
+++ b/sdk/tools/pefixup.c
@@ -1,421 +1,196 @@
/*
* PE Fixup Utility
* Copyright (C) 2005 Filip Navara
+ * Copyright (C) 2020 Mark Jansen
*
* 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:
+ * Currently one features is 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.
+ * - Updating the PE header to use a LOAD_CONFIG,
+ * when the struct is exported with the name '_load_config_used'
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#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);
-}
+// host_includes
+#include <typedefs.h>
+#include <pecoff.h>
+#include "../../dll/win32/dbghelp/compat.h"
-static inline WORD htods(WORD in)
+void *rva_to_ptr(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header, DWORD rva)
{
- WORD out;
- PBYTE out_ptr = (PBYTE)&out;
- out_ptr[0] = in; out_ptr[1] = in >> 8;
- return out;
+ unsigned int i;
+ PIMAGE_SECTION_HEADER section_header = IMAGE_FIRST_SECTION(nt_header);
+
+ for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++, section_header++)
+ {
+ if (rva >= section_header->VirtualAddress &&
+ rva < section_header->VirtualAddress +
section_header->Misc.VirtualSize)
+ {
+ return buffer + rva - section_header->VirtualAddress +
section_header->PointerToRawData;
+ }
+ }
+
+ return NULL;
}
-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)
+static void fix_checksum(unsigned char *buffer, long len, PIMAGE_NT_HEADERS nt_header)
{
- 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;
-}
+ unsigned int checksum = 0;
+ long n;
-void *rva_to_ptr(DWORD rva)
-{
- PIMAGE_SECTION_HEADER section_header;
- unsigned int i;
+ nt_header->OptionalHeader.CheckSum = 0;
- 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);
- }
- }
+ for (n = 0; n < len; n += 2)
+ {
+ checksum += *(unsigned short *)(buffer + n);
+ checksum = (checksum + (checksum >> 16)) & 0xffff;
+ }
- return NULL;
+ checksum += len;
+ nt_header->OptionalHeader.CheckSum = checksum;
}
-int export_compare_func(const void *a, const void *b)
+static int add_loadconfig(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header)
{
- 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);
+ PIMAGE_DATA_DIRECTORY export_dir;
+ PIMAGE_EXPORT_DIRECTORY export_directory;
+
+ export_dir =
&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+ if (export_dir->Size != 0)
+ {
+ export_directory = rva_to_ptr(buffer, nt_header, export_dir->VirtualAddress);
+ if (export_directory != NULL)
+ {
+ DWORD *name_ptr, *function_ptr, n;
+ WORD *ordinal_ptr;
+
+ name_ptr = rva_to_ptr(buffer, nt_header,
export_directory->AddressOfNames);
+ ordinal_ptr = rva_to_ptr(buffer, nt_header,
export_directory->AddressOfNameOrdinals);
+ function_ptr = rva_to_ptr(buffer, nt_header,
export_directory->AddressOfFunctions);
+
+ for (n = 0; n < export_directory->NumberOfNames; n++)
+ {
+ const char* name = rva_to_ptr(buffer, nt_header, name_ptr[n]);
+ if (!strcmp(name, "_load_config_used"))
+ {
+ PIMAGE_DATA_DIRECTORY load_config_dir;
+ DWORD load_config_rva = function_ptr[ordinal_ptr[n]];
+ DWORD* load_config_ptr = rva_to_ptr(buffer, nt_header,
load_config_rva);
+
+ /* Update the DataDirectory pointer / size
+ The first entry of the LOAD_CONFIG struct is the size, use that as
DataDirectory.Size */
+ load_config_dir =
&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
+ load_config_dir->VirtualAddress = load_config_rva;
+ load_config_dir->Size = *load_config_ptr;
+
+ return 0;
+ }
+ }
+
+ fprintf(stderr, "Export '_load_config_used' not found\n");
+ }
+ else
+ {
+ fprintf(stderr, "Invalid rva for export directory\n");
+ }
+ }
+ else
+ {
+ fprintf(stderr, "No export directory\n");
+ }
+
+ return 1;
}
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
- { fprintf(stderr, "Invalid option: %s\n", argv[i]); return 1; }
- }
-
- /*
- * Nothing to do.
- */
- if (fixup_sections == 0 && fixup_exports == 0)
- return 0;
-
- /*
- * Read the whole file to memory.
- */
-
- fd_in = open(argv[1], O_RDONLY | O_BINARY);
- if (fd_in == 0)
- {
- fprintf(stderr, "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)))
- {
- close(fd_in);
- return 0;
- }
-
- len = lseek(fd_in, 0, SEEK_END);
- if (len < sizeof(IMAGE_DOS_HEADER))
- {
- close(fd_in);
- fprintf(stderr, "'%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);
- fprintf(stderr, "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)
- {
- fprintf(stderr, "'%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)
+ FILE* file;
+ long len;
+ unsigned char *buffer;
+ PIMAGE_DOS_HEADER dos_header;
+ int result = 1;
+
+ if (argc < 2)
+ {
+ printf("Usage: %s <filename>\n", argv[0]);
+ return 1;
+ }
+
+ /* Read the whole file to memory. */
+ file = fopen(argv[1], "r+b");
+ if (!file)
+ {
+ fprintf(stderr, "Can't open '%s'.\n", argv[1]);
+ return 1;
+ }
+
+ fseek(file, 0, SEEK_END);
+ len = ftell(file);
+ if (len < sizeof(IMAGE_DOS_HEADER))
+ {
+ fclose(file);
+ fprintf(stderr, "'%s' isn't a PE image (too short)\n",
argv[1]);
+ return 1;
+ }
+
+ /* Add one byte extra for the case where the input file size is odd.
+ We rely on this in our crc calculation */
+ buffer = calloc(len + 1, 1);
+ if (buffer == NULL)
+ {
+ fclose(file);
+ fprintf(stderr, "Not enough memory available.\n");
+ return 1;
+ }
+
+ /* Read the whole input file into a buffer */
+ fseek(file, 0, SEEK_SET);
+ fread(buffer, 1, len, file);
+
+ /* Check the headers and save pointers to them. */
+ dos_header = (PIMAGE_DOS_HEADER)buffer;
+ if (dos_header->e_magic == IMAGE_DOS_SIGNATURE)
+ {
+ PIMAGE_NT_HEADERS nt_header;
+
+ nt_header = (PIMAGE_NT_HEADERS)(buffer + dos_header->e_lfanew);
+
+ if (nt_header->Signature == IMAGE_NT_SIGNATURE)
+ {
+ if (!add_loadconfig(buffer, nt_header))
{
- fprintf(stderr, "Not enough memory.\n");
- free(buffer);
- return 1;
- }
+ fix_checksum(buffer, len, nt_header);
- name_ptr = (DWORD *)rva_to_ptr(dtohl(export_directory->AddressOfNames));
- ordinal_ptr = (WORD
*)rva_to_ptr(dtohl(export_directory->AddressOfNameOrdinals));
+ /* We could 'optimize by only writing the changed parts, but keep it
simple for now */
+ fseek(file, 0, SEEK_SET);
+ fwrite(buffer, 1, len, file);
- for (i = 0; i < dtohl(export_directory->NumberOfNames); i++)
- {
- exports[i].name = dtohl(name_ptr[i]);
- exports[i].ordinal = dtohl(ordinal_ptr[i]);
+ /* Success */
+ result = 0;
}
-
- qsort(exports, dtohl(export_directory->NumberOfNames), sizeof(export_t),
- export_compare_func);
-
- for (i = 0; i < dtohl(export_directory->NumberOfNames); i++)
+ else
{
- name_ptr[i] = htodl(exports[i].name);
- ordinal_ptr[i] = htodl(exports[i].ordinal);
+ /* Error already printed inside add_loadconfig */
}
-
- free(exports);
- }
- }
- }
-
- if (fixup_sections)
- {
- /* Update section flags */
- for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
- i < dtohl(nt_header->FileHeader.NumberOfSections);
- 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, ".rdata") ||
- !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;
+ }
+ else
+ {
+ fprintf(stderr, "'%s' Invalid PE signature: %x\n", argv[1],
nt_header->Signature);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "'%s' Invalid DOS signature: %x\n", argv[1],
dos_header->e_magic);
+ }
+
+ free(buffer);
+ fclose(file);
+
+ return result;
}