Bob, Liming, Leif: any thoughts?

On Sun, 21 Aug 2022 at 16:33, Rebecca Cran <rebe...@bsdio.com> wrote:
>
> Tested-by: Rebecca Cran <rebe...@bsdio.com>
>
>
> On 8/21/22 08:16, Ard Biesheuvel wrote:
> > Rebecca reports that builds of AArch64 DSCs that involve PIE linking
> > when using ELF based toolchains are failing in some cases, resulting in
> > an error message like
> >
> >    bad definition for symbol '_GLOBAL_OFFSET_TABLE_'@0x72d8 or
> >    unsupported symbol type.  For example, absolute and undefined symbols
> >    are not supported.
> >
> > The reason turns out to be that, while GenFw does carry some logic to
> > convert GOT based symbol references into direct ones (which is always
> > possible given that our ELF to PE/COFF conversion only supports fully
> > linked executables), it does not support all possible combinations of
> > relocations that the linker may emit to load symbol addresses from the
> > GOT.
> >
> > In particular, when performing a non-LTO link on object code built with
> > GCC using -fpie, we may end up with GOT based references such as the one
> > below, where the address of the GOT itself is taken, and the ofset of
> > the symbol in the GOT is reflected in the immediate offset of the
> > subsequent LDR instruction.
> >
> >    838:   adrp    x0, 16000
> >    838: R_AARCH64_ADR_PREL_PG_HI21 _GLOBAL_OFFSET_TABLE_
> >    83c:   ldr     x0, [x0, #2536]
> >    83c: R_AARCH64_LD64_GOTPAGE_LO15        
> > _gPcd_BinaryPatch_PcdFdBaseAddress
> >
> > The reason that we omit GOT based symbol references when performing ELF to
> > PE/COFF conversion is that the GOT is not described by static ELF
> > relocations, which means that the ELF file lacks the metadata to
> > generate the PE/COFF relocations covering the GOT table in the PE/COFF
> > executable. Given that none of the usual motivations for using a GOT
> > (copy on write footprint, shared libraries) apply to EFI executables in
> > the first place, the easiest way around this is to convert all GOT based
> > symbol address loads to PC relative ADR/ADRP instructions.
> >
> > So implement this handling for R_AARCH64_LD64_GOTPAGE_LO15 and
> > R_AARCH64_LD64_GOTOFF_LO15 relocations as well, and turn the LDR
> > instructions in question into ADR instructions that generate the
> > address immediately.
> >
> > This leaves the reference to _GLOBAL_OFFSET_TABLE_ itself, which is what
> > generated the error to begin with. Considering that this symbol is never
> > referenced (i.e., it doesn't appear anywhere in the code) and is only
> > meaningful in combination with R_*_GOT_* based relocations that follow
> > it, we can just disregard any references to it entirely, given that we
> > convert all of those followup relocations into direct references.
> >
> > Cc: Rebecca Cran <rebe...@bsdio.com>
> > Cc: Bob Feng <bob.c.f...@intel.com>
> > Cc: Liming Gao <gaolim...@byosoft.com.cn>
> > Cc: "Kinney, Michael D" <michael.d.kin...@intel.com>
> > Cc: Leif Lindholm <quic_llind...@quicinc.com>
> > Signed-off-by: Ard Biesheuvel <a...@kernel.org>
> > ---
> >
> > This patch can be tested using the following method:
> >
> > - add the following lines to 
> > ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
> >
> > [BuildOptions]
> >    GCC:*_*_AARCH64_CC_FLAGS = -fpie
> >    GCC:*_*_AARCH64_DLINK_FLAGS = -Wl,-Bsymbolic,-pie
> >
> > - build ArmVirtPkg/ArmVirtQemuKernel.dsc in DEBUG mode using GCC49
> >    (other combos might work as well) and observe the build failure
> >
> > - apply this patch and observe that the build failure is gone
> >
> > - boot the resulting image in QEMU using the -kernel ../QEMU_EFI.fd
> >    command line option and observe that the image boots as usual
> >
> >   BaseTools/Source/C/GenFw/Elf64Convert.c | 35 ++++++++++++++++++++
> >   1 file changed, 35 insertions(+)
> >
> > diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c 
> > b/BaseTools/Source/C/GenFw/Elf64Convert.c
> > index 35e96dd05bc2..3173ca9280f4 100644
> > --- a/BaseTools/Source/C/GenFw/Elf64Convert.c
> > +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
> > @@ -1305,6 +1305,22 @@ WriteSections64 (
> >           Elf_Shdr *SymShdr;
> >           UINT8    *Targ;
> >
> > +        //
> > +        // The _GLOBAL_OFFSET_TABLE_ symbol is not actually an absolute 
> > symbol,
> > +        // but carries the SHN_ABS section index for historical reasons.
> > +        // It must be accompanied by a R_*_GOT_* type relocation on a
> > +        // subsequent instruction, which we handle below, specifically to 
> > avoid
> > +        // the GOT indirection, and to refer to the symbol directly. This 
> > means
> > +        // we can simply disregard direct references to the GOT symbol 
> > itself,
> > +        // as the resulting value will never be used.
> > +        //
> > +        if (Sym->st_shndx == SHN_ABS) {
> > +          const UINT8 *SymName = GetSymName (Sym);
> > +          if (strcmp ((CHAR8 *)SymName, "_GLOBAL_OFFSET_TABLE_") == 0) {
> > +            continue;
> > +          }
> > +        }
> > +
> >           //
> >           // Check section header index found in symbol table and get the 
> > section
> >           // header location.
> > @@ -1448,6 +1464,23 @@ WriteSections64 (
> >             switch (ELF_R_TYPE(Rel->r_info)) {
> >               INT64 Offset;
> >
> > +          case R_AARCH64_LD64_GOTOFF_LO15:
> > +          case R_AARCH64_LD64_GOTPAGE_LO15:
> > +            //
> > +            // Convert into an ADR instruction that refers to the symbol 
> > directly.
> > +            //
> > +            Offset = Sym->st_value - Rel->r_offset;
> > +
> > +            *(UINT32 *)Targ &= 0x1000001f;
> > +            *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset 
> > & 0x3) << 29);
> > +
> > +            if (Offset < -0x100000 || Offset > 0xfffff) {
> > +              Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s 
> > failed to relax GOT based symbol reference - image is too big (>1 MiB).",
> > +                mInImageName);
> > +              break;
> > +            }
> > +            break;
> > +
> >             case R_AARCH64_LD64_GOT_LO12_NC:
> >               //
> >               // Convert into an ADD instruction - see 
> > R_AARCH64_ADR_GOT_PAGE below.
> > @@ -1686,6 +1719,8 @@ WriteRelocations64 (
> >               case R_AARCH64_LDST128_ABS_LO12_NC:
> >               case R_AARCH64_ADR_GOT_PAGE:
> >               case R_AARCH64_LD64_GOT_LO12_NC:
> > +            case R_AARCH64_LD64_GOTOFF_LO15:
> > +            case R_AARCH64_LD64_GOTPAGE_LO15:
> >                 //
> >                 // No fixups are required for relative relocations, 
> > provided that
> >                 // the relative offsets between sections have been 
> > preserved in


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#93211): https://edk2.groups.io/g/devel/message/93211
Mute This Topic: https://groups.io/mt/93162057/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to