Ard Biesheuvel
2015-06-23 15:30:52 UTC
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 <***@linaro.org>
---
BaseTools/Source/C/GenFw/Elf64Convert.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 41 insertions(+), 10 deletions(-)
diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c
index 25b90e2f7b51..2266e487cec7 100644
--- a/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -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:
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 <***@linaro.org>
---
BaseTools/Source/C/GenFw/Elf64Convert.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 41 insertions(+), 10 deletions(-)
diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c
index 25b90e2f7b51..2266e487cec7 100644
--- a/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -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:
--
1.9.1
1.9.1