[SDK][HOST-TOOLS] Add load_config workaround for gcc builds 2542/head
authorMark Jansen <mark.jansen@reactos.org>
Mon, 13 Apr 2020 10:20:47 +0000 (12:20 +0200)
committerMark Jansen <mark.jansen@reactos.org>
Fri, 17 Apr 2020 15:47:24 +0000 (17:47 +0200)
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
modules/rostests/apitests/CMakeLists.txt
modules/rostests/apitests/loadconfig/CMakeLists.txt
modules/rostests/apitests/loadconfig/loadconfig_apitest.spec [new file with mode: 0644]
sdk/cmake/gcc.cmake
sdk/cmake/msvc.cmake
sdk/tools/CMakeLists.txt
sdk/tools/pefixup.c

index 777a033..50fbf19 100644 (file)
@@ -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- )
index abb0fb8..2662835 100644 (file)
@@ -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)
index a09e73e..8c0860b 100644 (file)
@@ -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 (file)
index 0000000..8eb8075
--- /dev/null
@@ -0,0 +1,3 @@
+
+# Export this symbol so we can do binutils job
+@ extern _load_config_used
index 5f0ea13..7d42f32 100644 (file)
@@ -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(
index 0662fd2..ce526ed 100644 (file)
@@ -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)
index 7fab47e..f9e0e19 100644 (file)
@@ -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()
index be25015..9752974 100644 (file)
 /*
  * 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)&in;
-    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)&in;
-    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;
 }