aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-11-24 15:55:41 +0000
committerMichael Brown <mcb30@ipxe.org>2023-11-24 16:45:11 +0000
commit03ff1bb99a28230397fb583853ab2160ff227e77 (patch)
treee820b89dd53c6e9c9572aaf5d059054f759aec87
parent18582a05fc65fc8835220c27528ef8902f5da60e (diff)
downloadipxe-03ff1bb99a28230397fb583853ab2160ff227e77.zip
ipxe-03ff1bb99a28230397fb583853ab2160ff227e77.tar.gz
ipxe-03ff1bb99a28230397fb583853ab2160ff227e77.tar.bz2
[efi] Do not assume canonical PE section ordering
The BaseOfCode (and, in PE32, BaseOfData) fields imply an assumption that binaries are laid out as code followed by initialised data followed by uninitialised data. This assumption may not be valid for complex binaries such as wimboot. Remove this implicit assumption, and use arguably justifiable values for the assorted summary start and size fields within the PE headers. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/util/elf2efi.c93
1 files changed, 37 insertions, 56 deletions
diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c
index 171e2b5..72d50d3 100644
--- a/src/util/elf2efi.c
+++ b/src/util/elf2efi.c
@@ -602,31 +602,29 @@ static struct pe_section * process_section ( struct elf_file *elf,
size_t name_len;
size_t section_memsz;
size_t section_filesz;
- unsigned long code_start;
- unsigned long code_end;
- unsigned long data_start;
- unsigned long data_mid;
- unsigned long data_end;
- unsigned long start;
- unsigned long end;
- unsigned long *applicable_start;
- unsigned long *applicable_end;
+ uint32_t start;
+ uint32_t end;
+ uint32_t *code_start;
+ uint32_t *data_start;
+ uint32_t *code_size;
+ uint32_t *data_size;
+ uint32_t *bss_size;
+ uint32_t *applicable_start;
+ uint32_t *applicable_size;
/* Get section name */
name = elf_string ( elf, elf->ehdr->e_shstrndx, shdr->sh_name );
- /* Extract current RVA limits from file header */
- code_start = pe_header->nt.OptionalHeader.BaseOfCode;
- code_end = ( code_start + pe_header->nt.OptionalHeader.SizeOfCode );
+ /* Identify start and size limit fields from file header */
+ code_start = &pe_header->nt.OptionalHeader.BaseOfCode;
+ code_size = &pe_header->nt.OptionalHeader.SizeOfCode;
#if defined(EFI_TARGET32)
- data_start = pe_header->nt.OptionalHeader.BaseOfData;
+ data_start = &pe_header->nt.OptionalHeader.BaseOfData;
#elif defined(EFI_TARGET64)
- data_start = code_end;
+ data_start = NULL;
#endif
- data_mid = ( data_start +
- pe_header->nt.OptionalHeader.SizeOfInitializedData );
- data_end = ( data_mid +
- pe_header->nt.OptionalHeader.SizeOfUninitializedData );
+ data_size = &pe_header->nt.OptionalHeader.SizeOfInitializedData;
+ bss_size = &pe_header->nt.OptionalHeader.SizeOfUninitializedData;
/* Allocate PE section */
section_memsz = shdr->sh_size;
@@ -659,7 +657,7 @@ static struct pe_section * process_section ( struct elf_file *elf,
new->hidden = 1;
}
- /* Fill in section characteristics and update RVA limits */
+ /* Fill in section characteristics and identify applicable limits */
if ( ( shdr->sh_type == SHT_PROGBITS ) &&
( shdr->sh_flags & SHF_WRITE ) ) {
/* .data-type section */
@@ -668,8 +666,8 @@ static struct pe_section * process_section ( struct elf_file *elf,
EFI_IMAGE_SCN_MEM_NOT_PAGED |
EFI_IMAGE_SCN_MEM_READ |
EFI_IMAGE_SCN_MEM_WRITE );
- applicable_start = &data_start;
- applicable_end = &data_mid;
+ applicable_start = data_start;
+ applicable_size = data_size;
} else if ( ( shdr->sh_type == SHT_PROGBITS ) &&
( shdr->sh_flags & SHF_EXECINSTR ) ) {
/* .text-type section */
@@ -678,16 +676,16 @@ static struct pe_section * process_section ( struct elf_file *elf,
EFI_IMAGE_SCN_MEM_NOT_PAGED |
EFI_IMAGE_SCN_MEM_EXECUTE |
EFI_IMAGE_SCN_MEM_READ );
- applicable_start = &code_start;
- applicable_end = &code_end;
+ applicable_start = code_start;
+ applicable_size = code_size;
} else if ( shdr->sh_type == SHT_PROGBITS ) {
/* .rodata-type section */
new->hdr.Characteristics =
( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
EFI_IMAGE_SCN_MEM_NOT_PAGED |
EFI_IMAGE_SCN_MEM_READ );
- applicable_start = &data_start;
- applicable_end = &data_mid;
+ applicable_start = data_start;
+ applicable_size = data_size;
} else if ( shdr->sh_type == SHT_NOBITS ) {
/* .bss-type section */
new->hdr.Characteristics =
@@ -695,8 +693,8 @@ static struct pe_section * process_section ( struct elf_file *elf,
EFI_IMAGE_SCN_MEM_NOT_PAGED |
EFI_IMAGE_SCN_MEM_READ |
EFI_IMAGE_SCN_MEM_WRITE );
- applicable_start = &data_mid;
- applicable_end = &data_end;
+ applicable_start = data_start;
+ applicable_size = bss_size;
} else {
eprintf ( "Unrecognised characteristics for section %s\n",
name );
@@ -709,41 +707,24 @@ static struct pe_section * process_section ( struct elf_file *elf,
shdr->sh_size );
}
- /* Update RVA limits */
+ /* Update file header fields */
start = new->hdr.VirtualAddress;
- end = ( start + new->hdr.Misc.VirtualSize );
- 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 )
- data_mid = data_start;
- if ( data_end < data_mid )
- data_end = data_mid;
-
- /* Write RVA limits back to file header */
- pe_header->nt.OptionalHeader.BaseOfCode = code_start;
- pe_header->nt.OptionalHeader.SizeOfCode = ( code_end - code_start );
-#if defined(EFI_TARGET32)
- pe_header->nt.OptionalHeader.BaseOfData = data_start;
-#endif
- pe_header->nt.OptionalHeader.SizeOfInitializedData =
- ( data_mid - data_start );
- pe_header->nt.OptionalHeader.SizeOfUninitializedData =
- ( data_end - data_mid );
-
- /* Update remaining file header fields */
if ( ! new->hidden ) {
pe_header->nt.FileHeader.NumberOfSections++;
pe_header->nt.OptionalHeader.SizeOfHeaders +=
sizeof ( new->hdr );
+ if ( applicable_start && ( ( *applicable_start == 0 ) ||
+ ( start < *applicable_start ) ) ) {
+ *applicable_start = start;
+ }
+ if ( applicable_size ) {
+ *applicable_size += section_memsz;
+ }
+ }
+ end = efi_image_align ( start + section_memsz );
+ if ( end > pe_header->nt.OptionalHeader.SizeOfImage ) {
+ pe_header->nt.OptionalHeader.SizeOfImage = end;
}
- pe_header->nt.OptionalHeader.SizeOfImage =
- efi_image_align ( data_end );
return new;
}