Hi Matthew
-ENOPATCH
Hmm ... I'll try one more time just in case it's some magic in the air (and to see if it turns up on my personal email when going to the mailing list), but I expect I'll have to ping the mailing list owners to help me out.
-----Original Message----- From: Matthew Malcomson via Gnu-morello <gnu-morello@op- lists.linaro.org> Sent: Tuesday, October 11, 2022 1:21 PM To: gnu-morello@op-lists.linaro.org Cc: Kyrylo Tkachov Kyrylo.Tkachov@arm.com Subject: [Gnu-morello] [To Be Committed] Various fixes for capability IFUNCs
Enable having a CAPINIT relocation against an IFUNC. We update the `final_link_relocate` switch case around IFUNC's to also handle CAPINIT relocations. The handling of CAPINIT relocations is slightly different than for AARCH64_NN (i.e. ABS64) relocations since we generally need to emit a dynamic relocation.
Handling this relocation also needs to manage the PDE case when a hard-coded address has been put into code to satisfy something like an `adrp`. In these cases the canonical address of the IFUNC becomes its PLT stub rather than the result of the resolver. We then need to use a RELATIVE relocation rather than an IRELATIVE one. N.b. unlike the ABS64 relocation, since a CAPINIT will always emit a dynamic relocation we do not require pointer equality adjustments on a symbol from having seen a CAPINIT. That means we do not need to request that the PLT stub of an IFUNC is treated as the canonical address just from having seen a CAPINIT relocation.
A CAPINIT relocation against an IFUNC needs to be recorded internally so that _bfd_elf_allocate_ifunc_dyn_relocs does not garbage collect the PLT stub and associated IRELATIVE relocation.
See changes in the CAPINIT case of the IFUNC switch of elfNN_aarch64_final_link_relocate, and in the CAPINIT case of elfNN_aarch64_check_relocs.
Ensure that GOT relocations against an IFUNC have their fragment populated with the LSB set.
For GOT relocations against a capability IFUNC we need to introduce a relocation for the runtime to provide us with a valid capability.
See changes in the GOT cases of the IFUNC switch of elfNN_aarch64_final_link_relocate, changes in the elfNN_aarch64_allocate_ifunc_dynrelocs function, and changes around handling an IFUNC GOT entry in elfNN_aarch64_finish_dynamic_symbol.
Ensure that mapping symbols are emitted for the .iplt. Without this many of the testcases here are disassembled incorrectly.
See changes in elfNN_aarch64_output_arch_local_syms.
IRELATIVE relocations are against symbols which are not in the dynamic symbol table, hence they need their fragment populated to inform the dynamic linker the bounds and permissions to call the associated resolver with.
See part of the CAPINIT IFUNC handling in elfNN_aarch64_final_link_relocate, and the IRELATIVE handling in elfNN_aarch64_create_small_pltn_entry.
Disallow an ABS64 relocation against a purecap IFUNC. Such a relocation is expecting a 64-bit value but the function will return a capability. Some handling could be implemented by some communication method to the dynamic linker that this particular value should be 64-bit (maybe by emitting an AARCH64_IRELATIVE relocation rather than a MORELLO_IRELATIVE one), but as yet GCC doesn't generate such a relocation and we believe it's unlikely to be needed.
See new error check in AARCH64_NN clause of elfNN_aarch64_final_link_relocate.
Ensure that for statically linked PDE's, we segregate IRELATIVE and RELATIVE relocations. IRELATIVE relocs should be in the .rela.iplt section, while RELATIVE relocs should be in the .rela.dyn section.
Correspondingly all RELATIVE relocations should be between the __rela_dyn_{start,end} symbols, and all IRELATIVE relocations should be between the __rela_iplt_{start,end} symbols.
This segregation is made based on dynamic relocation type rather than static relocation that generates it. The segregation allows the static libc to more easily handle relocations.
Update testcases accordingly. We introduce some new testcases, morello-ifunc.s contains uses of an IFUNC which has been referenced directly in code. When compiling a PDE this triggers the pointer equality requirement and hence the canonical address for this symbol becomes the PLT stub rather than the result of the resolver.
morello-ifunc1.s does not use the IFUNC directly in code so that the address used everywhere is the result of the resolver.
Both of these have testcases assembled and linked for static, dynamically linked PDE, and PIE. The testcase without a hard-coded access also has a testcase for -shared.
morello-ifunc2.s is written to check that a CAPINIT relocation does indeed stop the garbage collection of an IFUNC's PLT and IRELATIVE relocation.
morello-ifunc3.s tests that we error on an ABS64 relocation against a C64 IFUNC.
morello-ifunc-dynlink.s tests that a CAPINIT relocation against an IFUNC symbol defined in a shared library behaves the same way as one against a FUNC symbol defined in a shared library.
Implementation note: When segregating IRELATIVE and RELATIVE relocs the change for relocations against IFUNC symbols populated in the GOT is straightforward.
For CAPINIT relocations the change is not as straightforward. The problem is that on sight of CAPINIT relocations in check_relocs we immediately allocate space in the srelcaps section. In trying to satisfy the above we need to know whether we're going to be emitting an IRELATIVE relocation or RELATIVE one in order to know which section it should go in. The determining factor between these two kinds of relocations is whether there is a text relocation to this IFUNC symbol, since that determines whether we need to make this CAPINIT relocation a RELATIVE relocation pointing to the PLT stub (in order to satisfy pointer equality) or an IRELATIVE relocation pointing to the resolver.
Whether such a relocation occurs is recorded against each symbol in the pointer_equality_needed member. This can only be known after all relocations have been seen in check_relocs. Hence, when coming across a CAPINIT relocation in check_relocs we do not in general know whether this CAPINIT relocation should end up as an IRELATIVE or RELATIVE relocation.
This patch postpones the decision by recording the number of CAPINIT relocations against a given symbol in a hash table while going through check_relocs and allocating the relevant space in the required section in size_dynamic_sections.
N.b. this is similar in purpose to the dyn_relocs linked list on a symbol. We do not use that existing member which is on every symbol since the structure does not allow any indication of what kind of relocation triggered the need. Moreover the structure is used for different purposes throughout the linker and disentangling the new meaning from the existing ones seems overly confusing.
Overall, the decisions about which sections relocations against an IFUNC should go in are: CAPINIT relocations: If this is a static PDE link, and the symbol does not need pointer equality handling, then this should emit an IRELATIVE relocation and that should go in the .rela.iplt section.
If this is a PIC link, then this should go in the .rela.ifunc section (along with all other dynamic relocations against the IFUNC, as commented in _bfd_elf_allocate_ifunc_dyn_relocs). Otherwise this relocation should go in the srelcaps section (which goes in .rela.dyn).
GOT relocations: If this is a static PDE link, and the symbol does not need pointer equality, then this should emit an IRELATIVE relocation into the .rela.iplt section.
If this is a static PDE link, then this should emit a RELATIVE relocation and that should go in the srelcaps section (which is in .rela.dyn). Otherwise this should go in .rela.got section.
-- Gnu-morello mailing list -- gnu-morello@op-lists.linaro.org To unsubscribe send an email to gnu-morello-leave@op-lists.linaro.org