ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pefixup.c
Go to the documentation of this file.
00001 /*
00002  * PE Fixup Utility
00003  * Copyright (C) 2005 Filip Navara
00004  *
00005  * The purpose of this utility is fix PE binaries generated by binutils and
00006  * to manipulate flags that can't be set by binutils.
00007  *
00008  * Currently two features are implemented:
00009  *
00010  * - Setting flags on PE sections for use by drivers. The sections
00011  *   .text, .data, .idata, .bss are marked as non-pageable and
00012  *   non-discarable, section PAGE is marked as pageable and section
00013  *   INIT is marked as discaradable.
00014  *
00015  * - Sorting of export name table in executables. DLLTOOL has bug
00016  *   in sorting algorithm when the --kill-at flag is used. The exports
00017  *   are sorted in the decorated form and so the fastcall symbols are
00018  *   incorrectly put at the beginning of export table. This option
00019  *   allow to correct sort the table, so binary search can be used
00020  *   to process them.
00021  */
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <fcntl.h>
00027 #include <unistd.h>
00028 
00029 #ifndef O_BINARY
00030 #define O_BINARY 0
00031 #endif
00032 
00033 /* The following definitions are ripped from MinGW W32API headers. We don't
00034    use these headers directly in order to allow compilation on Linux hosts. */
00035 
00036 typedef unsigned char BYTE, *PBYTE;
00037 typedef unsigned short WORD;
00038 typedef unsigned int DWORD;
00039 typedef int LONG;
00040 typedef long LONG_PTR;
00041 
00042 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
00043 #define IMAGE_SIZEOF_SHORT_NAME 8
00044 #define IMAGE_DOS_SIGNATURE 0x5A4D
00045 #define IMAGE_NT_SIGNATURE 0x00004550
00046 #define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
00047 #define IMAGE_SCN_MEM_NOT_PAGED 0x8000000
00048 #define FIELD_OFFSET(t,f) ((LONG)(LONG_PTR)&(((t*)0)->f))
00049 #define IMAGE_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((unsigned long)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader))
00050 #define IMAGE_DIRECTORY_ENTRY_EXPORT 0
00051 
00052 #pragma pack(2)
00053 typedef struct _IMAGE_DOS_HEADER {
00054     WORD e_magic;
00055     WORD e_cblp;
00056     WORD e_cp;
00057     WORD e_crlc;
00058     WORD e_cparhdr;
00059     WORD e_minalloc;
00060     WORD e_maxalloc;
00061     WORD e_ss;
00062     WORD e_sp;
00063     WORD e_csum;
00064     WORD e_ip;
00065     WORD e_cs;
00066     WORD e_lfarlc;
00067     WORD e_ovno;
00068     WORD e_res[4];
00069     WORD e_oemid;
00070     WORD e_oeminfo;
00071     WORD e_res2[10];
00072     LONG e_lfanew;
00073 } IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
00074 #pragma pack(4)
00075 #pragma pack(4)
00076 typedef struct _IMAGE_EXPORT_DIRECTORY {
00077     DWORD Characteristics;
00078     DWORD TimeDateStamp;
00079     WORD MajorVersion;
00080     WORD MinorVersion;
00081     DWORD Name;
00082     DWORD Base;
00083     DWORD NumberOfFunctions;
00084     DWORD NumberOfNames;
00085     DWORD AddressOfFunctions;
00086     DWORD AddressOfNames;
00087     DWORD AddressOfNameOrdinals;
00088 } IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
00089 typedef struct _IMAGE_FILE_HEADER {
00090     WORD Machine;
00091     WORD NumberOfSections;
00092     DWORD TimeDateStamp;
00093     DWORD PointerToSymbolTable;
00094     DWORD NumberOfSymbols;
00095     WORD SizeOfOptionalHeader;
00096     WORD Characteristics;
00097 } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
00098 typedef struct _IMAGE_DATA_DIRECTORY {
00099     DWORD VirtualAddress;
00100     DWORD Size;
00101 } IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
00102 typedef struct _IMAGE_OPTIONAL_HEADER {
00103     WORD Magic;
00104     BYTE MajorLinkerVersion;
00105     BYTE MinorLinkerVersion;
00106     DWORD SizeOfCode;
00107     DWORD SizeOfInitializedData;
00108     DWORD SizeOfUninitializedData;
00109     DWORD AddressOfEntryPoint;
00110     DWORD BaseOfCode;
00111     DWORD BaseOfData;
00112     DWORD ImageBase;
00113     DWORD SectionAlignment;
00114     DWORD FileAlignment;
00115     WORD MajorOperatingSystemVersion;
00116     WORD MinorOperatingSystemVersion;
00117     WORD MajorImageVersion;
00118     WORD MinorImageVersion;
00119     WORD MajorSubsystemVersion;
00120     WORD MinorSubsystemVersion;
00121     DWORD Reserved1;
00122     DWORD SizeOfImage;
00123     DWORD SizeOfHeaders;
00124     DWORD CheckSum;
00125     WORD Subsystem;
00126     WORD DllCharacteristics;
00127     DWORD SizeOfStackReserve;
00128     DWORD SizeOfStackCommit;
00129     DWORD SizeOfHeapReserve;
00130     DWORD SizeOfHeapCommit;
00131     DWORD LoaderFlags;
00132     DWORD NumberOfRvaAndSizes;
00133     IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
00134 } IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
00135 typedef struct _IMAGE_NT_HEADERS {
00136     DWORD Signature;
00137     IMAGE_FILE_HEADER FileHeader;
00138     IMAGE_OPTIONAL_HEADER OptionalHeader;
00139 } IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;
00140 typedef struct _IMAGE_SECTION_HEADER {
00141     BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
00142     union {
00143         DWORD PhysicalAddress;
00144         DWORD VirtualSize;
00145     } Misc;
00146     DWORD VirtualAddress;
00147     DWORD SizeOfRawData;
00148     DWORD PointerToRawData;
00149     DWORD PointerToRelocations;
00150     DWORD PointerToLinenumbers;
00151     WORD NumberOfRelocations;
00152     WORD NumberOfLinenumbers;
00153     DWORD Characteristics;
00154 } IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;
00155 #pragma pack(4)
00156 
00157 /* End of ripped definitions */
00158 
00159 typedef struct _export_t {
00160    DWORD name;
00161    WORD ordinal;
00162 } export_t;
00163 
00164 unsigned char *buffer;
00165 PIMAGE_DOS_HEADER dos_header;
00166 PIMAGE_NT_HEADERS nt_header;
00167 
00168 static inline WORD dtohs(WORD in)
00169 {
00170     PBYTE in_ptr = (PBYTE)&in;
00171     return in_ptr[0] | (in_ptr[1] << 8);
00172 }
00173 
00174 static inline WORD htods(WORD in)
00175 {
00176     WORD out;
00177     PBYTE out_ptr = (PBYTE)&out;
00178     out_ptr[0] = in; out_ptr[1] = in >> 8;
00179     return out;
00180 }
00181 
00182 static inline DWORD dtohl(DWORD in)
00183 {
00184     PBYTE in_ptr = (PBYTE)&in;
00185     return in_ptr[0] | (in_ptr[1] << 8) | (in_ptr[2] << 16) | (in_ptr[3] << 24);
00186 }
00187 
00188 static inline DWORD htodl(DWORD in)
00189 {
00190     DWORD out;
00191     PBYTE out_ptr = (PBYTE)&out;
00192     out_ptr[0] = in      ; out_ptr[1] = in >> 8;
00193     out_ptr[2] = in >> 16; out_ptr[3] = in >> 24;
00194     return out;
00195 }
00196 
00197 void *rva_to_ptr(DWORD rva)
00198 {
00199    PIMAGE_SECTION_HEADER section_header;
00200    unsigned int i;
00201 
00202    for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
00203         i < dtohl(nt_header->FileHeader.NumberOfSections);
00204         i++, section_header++)
00205    {
00206       if (rva >= dtohl(section_header->VirtualAddress) &&
00207           rva < dtohl(section_header->VirtualAddress) +
00208                 dtohl(section_header->Misc.VirtualSize))
00209       {
00210          return buffer + rva - dtohl(section_header->VirtualAddress) +
00211                 dtohl(section_header->PointerToRawData);
00212       }
00213    }
00214 
00215    return NULL;
00216 }
00217 
00218 int export_compare_func(const void *a, const void *b)
00219 {
00220    const export_t *ap = a;
00221    const export_t *bp = b;
00222    char *an = rva_to_ptr(ap->name);
00223    char *bn = rva_to_ptr(bp->name);
00224    return strcmp(an, bn);
00225 }
00226 
00227 int main(int argc, char **argv)
00228 {
00229    int fd_in, fd_out;
00230    long len;
00231    char hdrbuf[4] = { }, elfhdr[4] = { '\177', 'E', 'L', 'F' };
00232    PIMAGE_SECTION_HEADER section_header;
00233    PIMAGE_DATA_DIRECTORY data_dir;
00234    unsigned int i;
00235    unsigned long checksum;
00236    int fixup_exports = 0;
00237    int fixup_sections = 0;
00238 
00239    /*
00240     * Process parameters.
00241     */
00242 
00243    if (argc < 2)
00244    {
00245       printf("Usage: %s <filename> <options>\n"
00246              "Options:\n"
00247              " -sections Sets section flags for PE image.\n"
00248              " -exports Sort the names in export table.\n",
00249              argv[0]);
00250       return 1;
00251    }
00252 
00253    for (i = 2; i < argc; i++)
00254    {
00255       if (!strcmp(argv[i], "-sections"))
00256          fixup_sections = 1;
00257       else if (!strcmp(argv[i], "-exports"))
00258          fixup_exports = 1;
00259       else
00260          { fprintf(stderr, "Invalid option: %s\n", argv[i]); return 1; }
00261    }
00262 
00263    /*
00264     * Nothing to do.
00265     */
00266    if (fixup_sections == 0 && fixup_exports == 0)
00267       return 0;
00268 
00269    /*
00270     * Read the whole file to memory.
00271     */
00272 
00273    fd_in = open(argv[1], O_RDONLY | O_BINARY);
00274    if (fd_in == 0)
00275    {
00276       fprintf(stderr, "Can't open input file.\n");
00277       return 1;
00278    }
00279 
00280    /*
00281     * PowerPC ReactOS uses elf, so doesn't need pefixup
00282     */
00283    len = read(fd_in, hdrbuf, sizeof(elfhdr));
00284    if (!memcmp(hdrbuf, elfhdr, sizeof(elfhdr)))
00285    {
00286       close(fd_in);
00287       return 0;
00288    }
00289 
00290    len = lseek(fd_in, 0, SEEK_END);
00291    if (len < sizeof(IMAGE_DOS_HEADER))
00292    {
00293       close(fd_in);
00294       fprintf(stderr, "'%s' isn't a PE image (too short)\n", argv[1]);
00295       return 1;
00296    }
00297 
00298    /* Lower down we overwrite the byte at len, so here, we need at least
00299     * one more byte than len.  We'll be guaranteed one or two now. */
00300    buffer = malloc((len + 2) & ~1);
00301    if (buffer == NULL)
00302    {
00303       close(fd_in);
00304       fprintf(stderr, "Not enough memory available.\n");
00305       return 1;
00306    }
00307 
00308    /* Read the whole input file into a buffer */
00309    lseek(fd_in, 0, SEEK_SET);
00310    read(fd_in, buffer, len);
00311    /* Here is where the block end overwrite was */
00312    if (len & 1)
00313       buffer[len] = 0;
00314 
00315    close(fd_in);
00316 
00317    /*
00318     * Check the headers and save pointers to them.
00319     */
00320 
00321    dos_header = (PIMAGE_DOS_HEADER)buffer;
00322    nt_header = (PIMAGE_NT_HEADERS)(buffer + dtohl(dos_header->e_lfanew));
00323 
00324    if (dtohs(dos_header->e_magic) != IMAGE_DOS_SIGNATURE ||
00325        dtohl(nt_header->Signature) != IMAGE_NT_SIGNATURE)
00326    {
00327       fprintf(stderr, "'%s' isn't a PE image (bad headers)\n", argv[1]);
00328       free(buffer);
00329       return 1;
00330    }
00331 
00332    if (fixup_exports)
00333    {
00334       /* Sort export directory */
00335       data_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
00336       if (dtohl(data_dir->Size) != 0)
00337       {
00338          PIMAGE_EXPORT_DIRECTORY export_directory;
00339          DWORD *name_ptr;
00340          WORD *ordinal_ptr;
00341          export_t *exports;
00342 
00343          export_directory = (PIMAGE_EXPORT_DIRECTORY)rva_to_ptr(dtohl(data_dir->VirtualAddress));
00344          if (export_directory != NULL)
00345          {
00346             exports = malloc(sizeof(export_t) * dtohl(export_directory->NumberOfNames));
00347             if (exports == NULL)
00348             {
00349                fprintf(stderr, "Not enough memory.\n");
00350                free(buffer);
00351                return 1;
00352             }
00353 
00354             name_ptr = (DWORD *)rva_to_ptr(dtohl(export_directory->AddressOfNames));
00355             ordinal_ptr = (WORD *)rva_to_ptr(dtohl(export_directory->AddressOfNameOrdinals));
00356 
00357             for (i = 0; i < dtohl(export_directory->NumberOfNames); i++)
00358             {
00359                exports[i].name = dtohl(name_ptr[i]);
00360                exports[i].ordinal = dtohl(ordinal_ptr[i]);
00361             }
00362 
00363             qsort(exports, dtohl(export_directory->NumberOfNames), sizeof(export_t),
00364                   export_compare_func);
00365 
00366             for (i = 0; i < dtohl(export_directory->NumberOfNames); i++)
00367             {
00368                name_ptr[i] = htodl(exports[i].name);
00369                ordinal_ptr[i] = htodl(exports[i].ordinal);
00370             }
00371 
00372             free(exports);
00373          }
00374       }
00375    }
00376 
00377    if (fixup_sections)
00378    {
00379       /* Update section flags */
00380       for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
00381            i < dtohl(nt_header->OptionalHeader.NumberOfRvaAndSizes);
00382            i++, section_header++)
00383       {
00384          if (!strcmp((char*)section_header->Name, ".text") ||
00385              !strcmp((char*)section_header->Name, ".data") ||
00386              !strcmp((char*)section_header->Name, ".idata") ||
00387              !strcmp((char*)section_header->Name, ".rdata") ||
00388              !strcmp((char*)section_header->Name, ".bss"))
00389          {
00390             section_header->Characteristics |= htodl(IMAGE_SCN_MEM_NOT_PAGED);
00391             section_header->Characteristics &= htodl(~IMAGE_SCN_MEM_DISCARDABLE);
00392          }
00393          else if (!strcmp((char*)section_header->Name, "INIT"))
00394          {
00395             section_header->Characteristics |= htodl(IMAGE_SCN_MEM_DISCARDABLE);
00396          }
00397          else if (!strcmp((char*)section_header->Name, "PAGE"))
00398          {
00399             section_header->Characteristics |= htodl(IMAGE_SCN_MEM_NOT_PAGED);
00400          }
00401       }
00402    }
00403 
00404    /* Recalculate checksum */
00405    nt_header->OptionalHeader.CheckSum = 0;
00406    checksum = 0;
00407    for (i = 0; i < len; i += 2)
00408    {
00409       checksum += *(unsigned short *)(buffer + i);
00410       checksum = (checksum + (checksum >> 16)) & 0xffff;
00411    }
00412    checksum += len;
00413    nt_header->OptionalHeader.CheckSum = htods(checksum);
00414 
00415    /* Write the output file */
00416    fd_out = open(argv[1], O_WRONLY | O_BINARY);
00417    write(fd_out, buffer, len);
00418    close(fd_out);
00419 
00420    return 0;
00421 }

Generated on Sat May 26 2012 04:36:36 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.