]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Align EFI image sections by page size
authorMarvin Häuser <mhaeuser@posteo.de>
Thu, 8 Apr 2021 18:04:16 +0000 (20:04 +0200)
committerMichael Brown <mcb30@ipxe.org>
Sat, 10 Apr 2021 12:43:47 +0000 (13:43 +0100)
For optimal memory permission management, PE sections need to be
aligned by the platform's minimum page size.  Currently, the PE
section alignment is fixed to 32 bytes, which is below the typical 4kB
page size.  Align all sections to 4kB and adjust ELF to PE image
conversion accordingly.

Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
src/scripts/efi.lds
src/util/elf2efi.c

index 36022545d22a9ab1baad567286f7384419c7169e..dd7b3f0195a763846a180ad49017d6af5347626d 100644 (file)
@@ -8,22 +8,22 @@
 SECTIONS {
 
     /* The file starts at a virtual address of zero, and sections are
-     * contiguous.  Each section is aligned to at least _max_align,
-     * which defaults to 32.  Load addresses are equal to virtual
+     * contiguous.  Each section is aligned to at least _page_align,
+     * which defaults to 4096.  Load addresses are equal to virtual
      * addresses.
      */
 
-    _max_align = 32;
+    _page_align = 4096;
 
-    /* Allow plenty of space for file headers */
-    . = 0x1000;
+    /* Allow one page of space for file headers, common PE/COFF layout */
+    . = _page_align;
 
     /*
      * The text section
      *
      */
 
-    . = ALIGN ( _max_align );
+    . = ALIGN ( _page_align );
     .text : {
        _text = .;
        *(.text)
@@ -36,7 +36,7 @@ SECTIONS {
      *
      */
 
-    . = ALIGN ( _max_align );
+    . = ALIGN ( _page_align );
     .rodata : {
        _rodata = .;
        *(.rodata)
@@ -49,7 +49,7 @@ SECTIONS {
      *
      */
 
-    . = ALIGN ( _max_align );
+    . = ALIGN ( _page_align );
     .data : {
        _data = .;
        *(.data)
@@ -65,7 +65,7 @@ SECTIONS {
      *
      */
 
-    . = ALIGN ( _max_align );
+    . = ALIGN ( _page_align );
     .bss : {
        _bss = .;
        *(.bss)
index 38eb299642677e9d09287d4731e88d4abe590db3..b0d5466455ed612ed8fe13932e22cfed18c0e4a8 100644 (file)
 #define R_ARM_V4BX 40
 #endif
 
-#define EFI_FILE_ALIGN 0x20
+#define EFI_FILE_ALIGN  0x20
+#define EFI_IMAGE_ALIGN 0x1000
 
 struct elf_file {
        void *data;
@@ -173,9 +174,9 @@ static struct pe_header efi_pe_header = {
                        .Magic = EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC,
                        .MajorLinkerVersion = 42,
                        .MinorLinkerVersion = 42,
-                       .SectionAlignment = EFI_FILE_ALIGN,
+                       .SectionAlignment = EFI_IMAGE_ALIGN,
                        .FileAlignment = EFI_FILE_ALIGN,
-                       .SizeOfImage = sizeof ( efi_pe_header ),
+                       .SizeOfImage = EFI_IMAGE_ALIGN,
                        .SizeOfHeaders = sizeof ( efi_pe_header ),
                        .NumberOfRvaAndSizes =
                                EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
@@ -216,6 +217,16 @@ static unsigned long efi_file_align ( unsigned long offset ) {
        return ( ( offset + EFI_FILE_ALIGN - 1 ) & ~( EFI_FILE_ALIGN - 1 ) );
 }
 
+/**
+ * Align section within PE image
+ *
+ * @v offset           Unaligned offset
+ * @ret aligned_offset Aligned offset
+ */
+static unsigned long efi_image_align ( unsigned long offset ) {
+       return ( ( offset + EFI_IMAGE_ALIGN - 1 ) & ~( EFI_IMAGE_ALIGN - 1 ) );
+}
+
 /**
  * Generate entry in PE relocation table
  *
@@ -605,7 +616,7 @@ static struct pe_section * process_section ( struct elf_file *elf,
        pe_header->nt.FileHeader.NumberOfSections++;
        pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( new->hdr );
        pe_header->nt.OptionalHeader.SizeOfImage =
-               efi_file_align ( data_end );
+               efi_image_align ( data_end );
 
        return new;
 }
@@ -728,13 +739,15 @@ static struct pe_section *
 create_reloc_section ( struct pe_header *pe_header,
                       struct pe_relocs *pe_reltab ) {
        struct pe_section *reloc;
+       size_t section_rawsz;
        size_t section_memsz;
        size_t section_filesz;
        EFI_IMAGE_DATA_DIRECTORY *relocdir;
 
        /* Allocate PE section */
-       section_memsz = output_pe_reltab ( pe_reltab, NULL );
-       section_filesz = efi_file_align ( section_memsz );
+       section_rawsz = output_pe_reltab ( pe_reltab, NULL );
+       section_filesz = efi_file_align ( section_rawsz );
+       section_memsz = efi_image_align ( section_rawsz );
        reloc = xmalloc ( sizeof ( *reloc ) + section_filesz );
        memset ( reloc, 0, sizeof ( *reloc ) + section_filesz );
 
@@ -754,11 +767,11 @@ create_reloc_section ( struct pe_header *pe_header,
        /* Update file header details */
        pe_header->nt.FileHeader.NumberOfSections++;
        pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( reloc->hdr );
-       pe_header->nt.OptionalHeader.SizeOfImage += section_filesz;
+       pe_header->nt.OptionalHeader.SizeOfImage += section_memsz;
        relocdir = &(pe_header->nt.OptionalHeader.DataDirectory
                     [EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
        relocdir->VirtualAddress = reloc->hdr.VirtualAddress;
-       relocdir->Size = reloc->hdr.Misc.VirtualSize;
+       relocdir->Size = section_rawsz;
 
        return reloc;
 }
@@ -796,8 +809,8 @@ create_debug_section ( struct pe_header *pe_header, const char *filename ) {
        } *contents;
 
        /* Allocate PE section */
-       section_memsz = sizeof ( *contents );
-       section_filesz = efi_file_align ( section_memsz );
+       section_memsz = efi_image_align ( sizeof ( *contents ) );
+       section_filesz = efi_file_align ( sizeof ( *contents ) );
        debug = xmalloc ( sizeof ( *debug ) + section_filesz );
        memset ( debug, 0, sizeof ( *debug ) + section_filesz );
        contents = ( void * ) debug->contents;
@@ -828,7 +841,7 @@ create_debug_section ( struct pe_header *pe_header, const char *filename ) {
        /* Update file header details */
        pe_header->nt.FileHeader.NumberOfSections++;
        pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( debug->hdr );
-       pe_header->nt.OptionalHeader.SizeOfImage += section_filesz;
+       pe_header->nt.OptionalHeader.SizeOfImage += section_memsz;
        debugdir = &(pe_header->nt.OptionalHeader.DataDirectory
                     [EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
        debugdir->VirtualAddress = debug->hdr.VirtualAddress;