[efi] Maximise image base address

iPXE images are linked with a starting virtual address of zero.  Other
images (such as wimboot) may use a non-zero starting virtual address.

There is no direct equivalent of the PE ImageBase address field within
ELF object files.  Choose to use the highest possible address that
accommodates all sections and the PE header itself, since this will
minimise the memory allocated to hold the loaded image.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/1082/head
Michael Brown 2023-11-24 12:26:43 +00:00
parent 03ff1bb99a
commit b829b1750d
1 changed files with 44 additions and 0 deletions

View File

@ -729,6 +729,47 @@ static struct pe_section * process_section ( struct elf_file *elf,
return new;
}
/**
* Update image base address
*
* @v pe_header PE file header
* @v pe_sections List of PE sections
* @v pe_reltab PE relocation table
*/
static void update_image_base ( struct pe_header *pe_header,
struct pe_section *pe_sections,
struct pe_relocs *pe_reltab ) {
struct pe_section *section;
struct pe_relocs *pe_rel;
unsigned long base = -1UL;
/* Set ImageBase to the highest possible value, leaving space
* for the PE header itself.
*/
for ( section = pe_sections ; section ; section = section->next ) {
if ( ! section->hidden ) {
if ( base > section->hdr.VirtualAddress )
base = section->hdr.VirtualAddress;
}
}
base -= EFI_IMAGE_ALIGN;
pe_header->nt.OptionalHeader.ImageBase = base;
/* Adjust RVAs to match ImageBase */
pe_header->nt.OptionalHeader.AddressOfEntryPoint -= base;
pe_header->nt.OptionalHeader.BaseOfCode -= base;
#if defined(EFI_TARGET32)
pe_header->nt.OptionalHeader.BaseOfData -= base;
#endif
pe_header->nt.OptionalHeader.SizeOfImage -= base;
for ( section = pe_sections ; section ; section = section->next ) {
section->hdr.VirtualAddress -= base;
}
for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
pe_rel->start_rva -= base;
}
}
/**
* Process relocation record
*
@ -1113,6 +1154,9 @@ static void elf2pe ( const char *elf_name, const char *pe_name,
}
}
/* Update image base address */
update_image_base ( &pe_header, pe_sections, pe_reltab );
/* Create the .reloc section */
*(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab );
next_pe_section = &(*next_pe_section)->next;