mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-07 19:45:07 +02:00
BaseTools/GenFw RVCT: fix relocation processing of PT_DYNAMIC sections
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 <ard.biesheuvel@linaro.org> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19236 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
b12ef6b964
commit
088dc24508
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user