@@ -734,13 +734,33 @@ WriteSections64 (
break;
case R_AARCH64_ADR_PREL_PG_HI21:
- // TODO : AArch64 'small' memory model.
- Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation R_AARCH64_ADR_PREL_PG_HI21.", mInImageName);
- break;
-
case R_AARCH64_ADD_ABS_LO12_NC:
- // TODO : AArch64 'small' memory model.
- Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation R_AARCH64_ADD_ABS_LO12_NC.", mInImageName);
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ case R_AARCH64_LDST16_ABS_LO12_NC:
+ case R_AARCH64_LDST32_ABS_LO12_NC:
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ case R_AARCH64_LDST128_ABS_LO12_NC:
+ //
+ // These are static PC relative relocation pairs that will already have been resolved
+ // during static linking of the ELF shared object. So no need to do anything here if
+ // a) the original ELF .text section and the derived PE/COFF .text section are placed at
+ // the same relative alignment with respect to the nearest 4K aligned boundary;
+ // b) the section containing the symbol that the relocation pair refers to is at
+ // the same relative offset in both binaries;
+ // c) it is guaranteed that the load time alignment of the PE/COFF binary is
+ // at least 4 KB.
+ //
+ // While conditions a) and b) could be met by recalculating the immediates based on
+ // the actual placement of the PE/COFF sections if their offsets and/or alignments
+ // deviate, condition c) is a necessary condition that applies universally when
+ // ADRP based symbol references are used. It thus requires the appropriate 'Align=4K'
+ // declarations in the platform .FDF.
+ //
+ if ((SecOffset % 4096) != (SecShdr->sh_addr % 4096) ||
+ (mCoffSectionsOffset[Sym->st_shndx] - SecOffset) != (SymShdr->sh_addr - SecShdr->sh_addr)) {
+ // TODO: recalculate the two immediates based on the actual placement
+ Error (NULL, 0, 3000, "Invalid", "AArch64: ADRP/ADD and ADRP/LDR pairs must retain relative sym offset and relative alignment to 4 KB!.");
+ }
break;
// Absolute relocations.
@@ -825,13 +845,24 @@ WriteRelocations64 (
break;
case R_AARCH64_ADR_PREL_PG_HI21:
- // TODO : AArch64 'small' memory model.
- Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_AARCH64 relocation R_AARCH64_ADR_PREL_PG_HI21.", mInImageName);
break;
case R_AARCH64_ADD_ABS_LO12_NC:
- // TODO : AArch64 'small' memory model.
- Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_AARCH64 relocation R_AARCH64_ADD_ABS_LO12_NC.", mInImageName);
+ break;
+
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ break;
+
+ case R_AARCH64_LDST16_ABS_LO12_NC:
+ break;
+
+ case R_AARCH64_LDST32_ABS_LO12_NC:
+ break;
+
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ break;
+
+ case R_AARCH64_LDST128_ABS_LO12_NC:
break;
case R_AARCH64_ABS64:
This updates GenFw's ELF conversion for AArch64 so that relocation pairs that operate on ADRP/ADD, ADRP/LDR or ADRP/STR instruction combinations are allowed under the following conditions: - the relative alignment to the nearest 4 KB boundary of the target of the relocation must be identical between the ELF and the PE/COFF versions of the binary; - the offset between the relocation target and the symbol it refers to is identical between the ELF and the PE/COFF versions, even if the symbol lives in another section. These two conditions can be met by using a carefully crafted GNU ld script that reflects the placement logic of GenFw. Note that such binaries need to be loaded at a 4 KB aligned load address. This is a preliminary step towards allowing AArch64 binaries to be built with the standard 'small' C model. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> --- BaseTools/Source/C/GenFw/Elf64Convert.c | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-)