Reviewed-by: Liming Gao <[email protected]> -----Original Message----- From: edk2-devel [mailto:[email protected]] On Behalf Of Ard Biesheuvel Sent: Monday, December 07, 2015 6:08 PM To: [email protected]; Cohen, Eugene Cc: Ard Biesheuvel; Laszlo Ersek; Leif Lindholm; Gao, Liming Subject: Re: [edk2] [PATCH v3 2/3] BaseTools/GenFw RVCT: fix relocation processing of PT_DYNAMIC sections
On 2 December 2015 at 17:06, Ard Biesheuvel <[email protected]> wrote: > Unlike GNU ld, which can be instructed to emit symbol based static > relocations into fully linked binaries using the --emit-relocs command > line switch, the RVCT armlink tool can only emit dynamic relocations > into the PT_DYNAMIC segment. > > This has two consequences > . we can only identify absolute relocations, so there is no way to fix > up relative relocations between sections, or check their validity in > the PE/COFF layout > . the r_offset fields of the PT_DYNAMIC DT_REL entries are relative > either to the base of the image or to any of its segments but *not* to > the base of the input section that contains the location they refer > to, and converting them to PE/COFF image offsets is non-trivial unless > the sections are laid out in the same way in the ELF and PE/COFF > versions of the binary. > > There is really only one way to deal with this, and that is to require > that the ELF and PE/COFF versions of the binary are identical in memory. > So enforce that in the code. > > Also, fix the utterly broken relocation fixup code that dereferences > ELF32_R_SYM(r_info) both as a 1-based program header index and a > 0-based section header index. If this code ever produced working > binaries, it was purely by chance. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ard Biesheuvel <[email protected]> > --- > BaseTools/Source/C/GenFw/Elf32Convert.c | 36 ++++++++++++++------ > 1 file changed, 26 insertions(+), 10 deletions(-) > @Liming, Yonghong If there are no objections to this patch (if affects EM_ARM only), I would like to proceed and apply it. Thanks, Ard. > diff --git a/BaseTools/Source/C/GenFw/Elf32Convert.c > b/BaseTools/Source/C/GenFw/Elf32Convert.c > index 469394540e6a..eede64576940 100644 > --- a/BaseTools/Source/C/GenFw/Elf32Convert.c > +++ b/BaseTools/Source/C/GenFw/Elf32Convert.c > @@ -804,9 +804,7 @@ WriteRelocations32 ( > UINTN RelSize; > UINTN RelOffset; > UINTN K; > - UINT8 *Targ; > Elf32_Phdr *DynamicSegment; > - Elf32_Phdr *TargetSegment; > > for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) > { > Elf_Shdr *RelShdr = GetShdrByIndex(Index); @@ -957,6 +955,31 @@ > WriteRelocations32 ( > Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic > relocations.", mInImageName); > } > > + for (Index = 0; Index < mEhdr->e_shnum; Index++) { > + Elf_Shdr *shdr = GetShdrByIndex(Index); > + > + // > + // The PT_DYNAMIC section contains DT_REL relocations whose > r_offset > + // field is relative to the base of a segment (or the entire > image), > + // and not to the base of an ELF input section as is the case for > + // SHT_REL sections. This means that we cannot fix up such > relocations > + // unless we cross-reference ELF sections and segments, considering > + // that the output placement recorded in mCoffSectionsOffset[] is > + // section based, not segment based. > + // > + // Fortunately, there is a simple way around this: we require that > the > + // in-memory layout of the ELF and PE/COFF versions of the binary > is > + // identical. That way, r_offset will retain its validity as a > PE/COFF > + // image offset, and we can record it in the COFF fixup table > + // unmodified. > + // > + if (shdr->sh_addr != mCoffSectionsOffset[Index]) { > + Error (NULL, 0, 3000, > + "Invalid", "%s: PT_DYNAMIC relocations require identical ELF > and PE/COFF section offsets.", > + mInImageName); > + } > + } > + > for (K = 0; K < RelSize; K += RelElementSize) { > > if (DynamicSegment->p_paddr == 0) { @@ -973,14 +996,7 @@ > WriteRelocations32 ( > break; > > case R_ARM_RABS32: > - TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1); > - > - // Note: r_offset in a memory address. Convert it to a pointer > in the coff file. > - Targ = mCoffFile + mCoffSectionsOffset[ ELF32_R_SYM( Rel->r_info > ) ] + Rel->r_offset - TargetSegment->p_vaddr; > - > - *(UINT32 *)Targ = *(UINT32 *)Targ + mCoffSectionsOffset > [ELF32_R_SYM( Rel->r_info )]; > - > - CoffAddFixup (mCoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + > (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW); > + CoffAddFixup (Rel->r_offset, > + EFI_IMAGE_REL_BASED_HIGHLOW); > break; > > default: > -- > 1.9.1 > _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

