[PEFIXUP]
[reactos.git] / reactos / tools / pefixup.c
index 710537e..d6ec1f4 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
+#include <unistd.h>
 
 #ifndef O_BINARY
 #define O_BINARY 0
 /* 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;
+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
@@ -43,7 +45,7 @@ typedef int LONG;
 #define IMAGE_NT_SIGNATURE 0x00004550
 #define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
 #define IMAGE_SCN_MEM_NOT_PAGED 0x8000000
-#define FIELD_OFFSET(t,f) ((LONG)&(((t*)0)->f))
+#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
 
@@ -163,21 +165,50 @@ 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);
+}
+
+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)&in;
+    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 < nt_header->OptionalHeader.NumberOfRvaAndSizes;
+        i < dtohl(nt_header->FileHeader.NumberOfSections);
         i++, section_header++)
    {
-      if (rva >= section_header->VirtualAddress &&
-          rva < section_header->VirtualAddress +
-                section_header->Misc.VirtualSize)
+      if (rva >= dtohl(section_header->VirtualAddress) &&
+          rva < dtohl(section_header->VirtualAddress) +
+                dtohl(section_header->Misc.VirtualSize))
       {
-         return buffer + rva - section_header->VirtualAddress +
-                section_header->PointerToRawData;
+         return buffer + rva - dtohl(section_header->VirtualAddress) +
+                dtohl(section_header->PointerToRawData);
       }
    }
 
@@ -197,6 +228,7 @@ 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;
@@ -225,14 +257,14 @@ int main(int argc, char **argv)
       else if (!strcmp(argv[i], "-exports"))
          fixup_exports = 1;
       else
-         { printf("Invalid option: %s\n", argv[i]); return 1; }
+         { fprintf(stderr, "Invalid option: %s\n", argv[i]); return 1; }
    }
 
+   /*
+    * Nothing to do.
+    */
    if (fixup_sections == 0 && fixup_exports == 0)
-   {
-      printf("Nothing to do.\n");
       return 0;
-   }
 
    /*
     * Read the whole file to memory.
@@ -241,15 +273,22 @@ int main(int argc, char **argv)
    fd_in = open(argv[1], O_RDONLY | O_BINARY);
    if (fd_in == 0)
    {
-      printf("Can't open input file.\n");
+      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)))
+      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]);
+      fprintf(stderr, "'%s' isn't a PE image (too short)\n", argv[1]);
       return 1;
    }
 
@@ -259,7 +298,7 @@ int main(int argc, char **argv)
    if (buffer == NULL)
    {
       close(fd_in);
-      printf("Not enough memory available.\n");
+      fprintf(stderr, "Not enough memory available.\n");
       return 1;
    }
 
@@ -277,12 +316,12 @@ int main(int argc, char **argv)
     */
 
    dos_header = (PIMAGE_DOS_HEADER)buffer;
-   nt_header = (PIMAGE_NT_HEADERS)(buffer + dos_header->e_lfanew);
-   
-   if (dos_header->e_magic != IMAGE_DOS_SIGNATURE ||
-       nt_header->Signature != IMAGE_NT_SIGNATURE)
+   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 (headers %x,%x)\n", argv[1], dos_header->e_magic, nt_header->Signature);
+      fprintf(stderr, "'%s' isn't a PE image (bad headers)\n", argv[1]);
       free(buffer);
       return 1;
    }
@@ -291,40 +330,40 @@ int main(int argc, char **argv)
    {
       /* Sort export directory */
       data_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
-      if (data_dir->Size != 0)
+      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(data_dir->VirtualAddress);
+         export_directory = (PIMAGE_EXPORT_DIRECTORY)rva_to_ptr(dtohl(data_dir->VirtualAddress));
          if (export_directory != NULL)
          {
-            exports = malloc(sizeof(export_t) * export_directory->NumberOfNames);
+            exports = malloc(sizeof(export_t) * dtohl(export_directory->NumberOfNames));
             if (exports == NULL)
             {
-               printf("Not enough memory.\n");
+               fprintf(stderr, "Not enough memory.\n");
                free(buffer);
                return 1;
             }
 
-            name_ptr = (DWORD *)rva_to_ptr(export_directory->AddressOfNames);
-            ordinal_ptr = (WORD *)rva_to_ptr(export_directory->AddressOfNameOrdinals);
+            name_ptr = (DWORD *)rva_to_ptr(dtohl(export_directory->AddressOfNames));
+            ordinal_ptr = (WORD *)rva_to_ptr(dtohl(export_directory->AddressOfNameOrdinals));
 
-            for (i = 0; i < export_directory->NumberOfNames; i++)
+            for (i = 0; i < dtohl(export_directory->NumberOfNames); i++)
             {
-               exports[i].name = name_ptr[i];
-               exports[i].ordinal = ordinal_ptr[i];
+               exports[i].name = dtohl(name_ptr[i]);
+               exports[i].ordinal = dtohl(ordinal_ptr[i]);
             }
 
-            qsort(exports, export_directory->NumberOfNames, sizeof(export_t),
+            qsort(exports, dtohl(export_directory->NumberOfNames), sizeof(export_t),
                   export_compare_func);
 
-            for (i = 0; i < export_directory->NumberOfNames; i++)
+            for (i = 0; i < dtohl(export_directory->NumberOfNames); i++)
             {
-               name_ptr[i] = exports[i].name;
-               ordinal_ptr[i] = exports[i].ordinal;
+               name_ptr[i] = htodl(exports[i].name);
+               ordinal_ptr[i] = htodl(exports[i].ordinal);
             }
 
             free(exports);
@@ -336,24 +375,25 @@ int main(int argc, char **argv)
    {
       /* Update section flags */
       for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
-           i < nt_header->OptionalHeader.NumberOfRvaAndSizes;
+           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, ".rdata") ||
              !strcmp((char*)section_header->Name, ".bss"))
          {
-            section_header->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;
-            section_header->Characteristics &= ~IMAGE_SCN_MEM_DISCARDABLE;
+            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 |= IMAGE_SCN_MEM_DISCARDABLE;
+            section_header->Characteristics |= htodl(IMAGE_SCN_MEM_DISCARDABLE);
          }
          else if (!strcmp((char*)section_header->Name, "PAGE"))
          {
-            section_header->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;
+            section_header->Characteristics |= htodl(IMAGE_SCN_MEM_NOT_PAGED);
          }
       }
    }
@@ -367,7 +407,7 @@ int main(int argc, char **argv)
       checksum = (checksum + (checksum >> 16)) & 0xffff;
    }
    checksum += len;
-   nt_header->OptionalHeader.CheckSum = checksum;
+   nt_header->OptionalHeader.CheckSum = htods(checksum);
 
    /* Write the output file */
    fd_out = open(argv[1], O_WRONLY | O_BINARY);