aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-04-10 16:47:45 +0100
committerMichael Brown <mcb30@ipxe.org>2023-04-10 16:50:10 +0100
commit46088be95b8fab45383620fcc9e69794b5cc23de (patch)
tree2042e0ed0e385d78adc5f46054c0e12ad9b56460
parent8439ddeeaf7922464e74f36789a3f4856c119a25 (diff)
downloadipxe-wimboot.zip
ipxe-wimboot.tar.gz
ipxe-wimboot.tar.bz2
-rw-r--r--src/util/elf2efi.c64
1 files changed, 54 insertions, 10 deletions
diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c
index 7c3e0b1..295f22f 100644
--- a/src/util/elf2efi.c
+++ b/src/util/elf2efi.c
@@ -186,6 +186,7 @@ struct pe_section {
struct pe_section *next;
EFI_IMAGE_SECTION_HEADER hdr;
void ( * fixup ) ( struct pe_section *section );
+ int hidden;
uint8_t contents[0];
};
@@ -635,6 +636,8 @@ static struct pe_section * process_section ( struct elf_file *elf,
new->hdr.SizeOfRawData = section_filesz;
if ( shdr->sh_type == SHT_PROGBITS ) {
new->hdr.PointerToRawData = elf_lma ( elf, shdr, name );
+ if ( new->hdr.PointerToRawData == 0 )
+ new->hidden = 1;
}
/* Fill in section characteristics and update RVA limits */
@@ -690,10 +693,12 @@ static struct pe_section * process_section ( struct elf_file *elf,
/* Update RVA limits */
start = new->hdr.VirtualAddress;
end = ( start + new->hdr.Misc.VirtualSize );
- if ( ( ! *applicable_start ) || ( *applicable_start >= start ) )
- *applicable_start = start;
- if ( *applicable_end < end )
- *applicable_end = end;
+ if ( ! new->hidden ) {
+ if ( ( ! *applicable_start ) || ( *applicable_start >= start ) )
+ *applicable_start = start;
+ if ( *applicable_end < end )
+ *applicable_end = end;
+ }
if ( data_start < code_end )
data_start = code_end;
if ( data_mid < data_start )
@@ -713,8 +718,11 @@ static struct pe_section * process_section ( struct elf_file *elf,
( data_end - data_mid );
/* Update remaining file header fields */
- pe_header->nt.FileHeader.NumberOfSections++;
- pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( new->hdr );
+ if ( ! new->hidden ) {
+ pe_header->nt.FileHeader.NumberOfSections++;
+ pe_header->nt.OptionalHeader.SizeOfHeaders +=
+ sizeof ( new->hdr );
+ }
pe_header->nt.OptionalHeader.SizeOfImage =
efi_image_align ( data_end );
@@ -722,6 +730,37 @@ static struct pe_section * process_section ( struct elf_file *elf,
}
/**
+ * Update image base address
+ *
+ * @v pe_header PE file header
+ * @v pe_sections List of PE sections
+ */
+static void update_image_base ( struct pe_header *pe_header,
+ struct pe_section *pe_sections ) {
+ struct pe_section *section;
+ unsigned long base;
+
+ /* Set ImageBase to the highest possible value, leaving space
+ * for the PE header itself (if not deliberately overlapped).
+ */
+ for ( section = pe_sections ; section ; section = section->next ) {
+ base = ( section->hdr.VirtualAddress -
+ section->hdr.PointerToRawData );
+ if ( ( pe_header->nt.OptionalHeader.ImageBase == 0 ) ||
+ ( pe_header->nt.OptionalHeader.ImageBase > base ) ) {
+ pe_header->nt.OptionalHeader.ImageBase = base;
+ }
+ }
+ base = pe_header->nt.OptionalHeader.ImageBase;
+
+ /* Adjust RVA of all sections to match ImageBase */
+ for ( section = pe_sections ; section ; section = section->next ) {
+ section->hdr.VirtualAddress -= base;
+ }
+ pe_header->nt.OptionalHeader.SizeOfImage -= base;
+}
+
+/**
* Process relocation record
*
* @v elf ELF file
@@ -948,6 +987,7 @@ create_debug_section ( struct pe_header *pe_header, const char *filename ) {
EFI_IMAGE_SCN_MEM_NOT_PAGED |
EFI_IMAGE_SCN_MEM_READ );
debug->fixup = fixup_debug_section;
+ debug->hidden = 1;
/* Create section contents */
contents->debug.TimeDateStamp = 0x10d1a884;
@@ -962,10 +1002,6 @@ create_debug_section ( struct pe_header *pe_header, const char *filename ) {
filename );
/* Update file header details */
- pe_header->nt.FileHeader.NumberOfSections++;
- pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( debug->hdr );
- pe_header->nt.OptionalHeader.SizeOfImage +=
- efi_image_align ( section_memsz );
debugdir = &(pe_header->nt.OptionalHeader.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
debugdir->VirtualAddress = debug->hdr.VirtualAddress;
@@ -986,6 +1022,7 @@ static void write_pe_file ( struct pe_header *pe_header,
FILE *pe ) {
struct pe_section *section;
unsigned long fpos = 0;
+ unsigned int count = 0;
/* Align length of headers */
fpos = pe_header->nt.OptionalHeader.SizeOfHeaders =
@@ -1045,12 +1082,16 @@ static void write_pe_file ( struct pe_header *pe_header,
/* Write section headers */
for ( section = pe_sections ; section ; section = section->next ) {
+ if ( section->hidden )
+ continue;
if ( fwrite ( &section->hdr, sizeof ( section->hdr ),
1, pe ) != 1 ) {
perror ( "Could not write section header" );
exit ( 1 );
}
+ count++;
}
+ assert ( count == pe_header->nt.FileHeader.NumberOfSections );
}
/**
@@ -1112,6 +1153,9 @@ static void elf2pe ( const char *elf_name, const char *pe_name,
}
}
+ /* Update image base address */
+ update_image_base ( &pe_header, pe_sections );
+
/* Create the .reloc section */
*(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab );
next_pe_section = &(*next_pe_section)->next;