From 2cc0b085fb82e80d43cc08c8376dff9f9532a72d Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sat, 27 Jan 2018 20:29:05 +0000 Subject: [PATCH] gnuefi: preserve .gnu.hash sections (unbreaks elilo on IA-64) Gentoo has slightly modified linker defaults: --hash-style=gnu This means all ELF files in system have '.gnu.hash' section but no '.hash' section. gnuefi's ldscript did not account for it and as a result one symbol 'ImageBase' did not resolve locally for elilo.so and caused 'elilo' to fail to load by ia64 EFI: Loading.: Gentoo (try new elilo) ImageAddress: pointer is outside of image ImageAddress: pointer is outside of image Those two relocations come from crt0-efi-ia64.S PE32 entry point fdescr: ``` #define IMAGE_REL_BASED_DIR64<->10 .section .reloc, "a" data4 _start_plabel // Page RVA data4 12 // Block Size (2*4+2*2) data2 (IMAGE_REL_BASED_DIR64<<12) + 0 // reloc for plabel's entry point data2 (IMAGE_REL_BASED_DIR64<<12) + 8 // reloc for plabel's global pointer ``` These refer ImageBase. The change adds '.gnu.hash' collection (follows existing '.hash' collection). Tested on IA-64 by successfully booting elilo-3.16. Bug: https://bugs.gentoo.org/575300 Signed-off-by: Sergei Trofimovich --- README.gnuefi | 8 +++++++- gnuefi/elf_ia32_efi.lds | 4 +++- gnuefi/elf_ia32_fbsd_efi.lds | 4 +++- gnuefi/elf_ia64_efi.lds | 4 +++- gnuefi/elf_x86_64_efi.lds | 4 +++- gnuefi/elf_x86_64_fbsd_efi.lds | 4 +++- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/README.gnuefi b/README.gnuefi index a7feec0..512698c 100644 --- a/README.gnuefi +++ b/README.gnuefi @@ -231,11 +231,17 @@ and page sized.These eight sections are used to group together the much greater number of sections that are typically present in ELF object files. Specifically: - .hash + .hash (and/or .gnu.hash) Collects the ELF .hash info (this section _must_ be the first section in order to build a shared object file; the section is not actually loaded or used at runtime). + GNU binutils provides a mechanism to generate different hash info + via --hash-style= option. In this case output + shared object will contain .hash section, .gnu.hash section or + both. In order to generate correct output linker script preserves + both types of hash sections. + .text Collects all sections containing executable code. diff --git a/gnuefi/elf_ia32_efi.lds b/gnuefi/elf_ia32_efi.lds index 6cc4ce1..f27fe5f 100644 --- a/gnuefi/elf_ia32_efi.lds +++ b/gnuefi/elf_ia32_efi.lds @@ -5,7 +5,9 @@ SECTIONS { . = 0; ImageBase = .; - .hash : { *(.hash) } /* this MUST come first! */ + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } . = ALIGN(4096); .text : { diff --git a/gnuefi/elf_ia32_fbsd_efi.lds b/gnuefi/elf_ia32_fbsd_efi.lds index 77d6fad..cd309e2 100644 --- a/gnuefi/elf_ia32_fbsd_efi.lds +++ b/gnuefi/elf_ia32_fbsd_efi.lds @@ -5,7 +5,9 @@ SECTIONS { . = 0; ImageBase = .; - .hash : { *(.hash) } /* this MUST come first! */ + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } . = ALIGN(4096); .text : { diff --git a/gnuefi/elf_ia64_efi.lds b/gnuefi/elf_ia64_efi.lds index baca962..190792a 100644 --- a/gnuefi/elf_ia64_efi.lds +++ b/gnuefi/elf_ia64_efi.lds @@ -5,7 +5,9 @@ SECTIONS { . = 0; ImageBase = .; - .hash : { *(.hash) } /* this MUST come first! */ + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } . = ALIGN(4096); .text : { diff --git a/gnuefi/elf_x86_64_efi.lds b/gnuefi/elf_x86_64_efi.lds index 942d1f3..7be5902 100644 --- a/gnuefi/elf_x86_64_efi.lds +++ b/gnuefi/elf_x86_64_efi.lds @@ -6,7 +6,9 @@ SECTIONS { . = 0; ImageBase = .; - .hash : { *(.hash) } /* this MUST come first! */ + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } . = ALIGN(4096); .eh_frame : { diff --git a/gnuefi/elf_x86_64_fbsd_efi.lds b/gnuefi/elf_x86_64_fbsd_efi.lds index 6fd2031..fe1f334 100644 --- a/gnuefi/elf_x86_64_fbsd_efi.lds +++ b/gnuefi/elf_x86_64_fbsd_efi.lds @@ -6,7 +6,9 @@ SECTIONS { . = 0; ImageBase = .; - .hash : { *(.hash) } /* this MUST come first! */ + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } . = ALIGN(4096); .eh_frame : {