This symbol is defined in a binary when there is a segment which contains both the file header and the program header. The symbol points at the file header. The point of this symbol is to allow the program to robustly examine its own output.
Glibc uses this symbol. This symbol is currently not marked as a linker or linker script defined symbol, and hence does not get its bounds adjusted. The symbol is given zero size, and consequently any capability initialised as a relocation to this symbol is given zero bounds.
In order to allow access to read the headers this symbol points at this patch adds a size to the symbol.
We do not believe that the size of this symbol is used for anything other than CHERI bounds, so we believe that this is a safe change to make. Setting the size of the symbol means that c64_fixup_frag uses that size as the bounds to apply to a capability relocation pointing at that symbol. This allows access to the file and program headers loaded into memory.
An alternative approach would be to *not* set the size of the symbol, but only change the bounds of the relocation generated. This would be done by checking for the `__ehdr_start' name in c64_fixup_frag and setting the size according to the `sizeof_ehdr' and `elf_program_header_size' values stored on the output BFD object.
We chose the approach to set the size on the symbol for code-aesthetic reasons under the belief that having this size on the symbol in the final binary is a slight benefit in readability for a user and causes no downside.
I do not believe that Morello lld sets the bounds of a capability to this symbol correctly. That issue has been raised separately.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elf.c b/bfd/elf.c index 9a5b472cda2c953cae40d2dfcbce493048ed8168..279f15a3aefaa6e9048ee93a54575a2a06004ae1 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -6028,6 +6028,7 @@ assign_file_positions_for_load_sections (bfd *abfd, hash->root.u.def.section = bfd_abs_section_ptr; } + hash->size = bed->s->sizeof_ehdr + elf_program_header_size (abfd); hash->root.type = bfd_link_hash_defined; hash->def_regular = 1; hash->non_elf = 0; diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index f0d2048efc37c2df3f4dfea304c7f93f8fe3a169..adb0081720a48c984e246b838d6ccd0922fa1306 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -258,6 +258,7 @@ run_dump_test_lp64 "morello-sizeless-local-syms" run_dump_test_lp64 "morello-sizeless-global-syms" run_dump_test_lp64 "morello-sizeless-got-syms" run_dump_test_lp64 "morello-disallow-merged-binaries" +run_dump_test_lp64 "c64-ehdr-sized-reloc" run_dump_test_lp64 "morello-capinit" run_dump_test_lp64 "morello-stubs" diff --git a/ld/testsuite/ld-aarch64/c64-ehdr-sized-reloc.d b/ld/testsuite/ld-aarch64/c64-ehdr-sized-reloc.d new file mode 100644 index 0000000000000000000000000000000000000000..41c3cffa32f6bc494e1ef282319331e794b07abe --- /dev/null +++ b/ld/testsuite/ld-aarch64/c64-ehdr-sized-reloc.d @@ -0,0 +1,18 @@ +#as: -march=morello+c64 +#ld: -shared +#objdump: -dR -j .data + +.*: file format .* + + +Disassembly of section .data: + +00000000000[[:xdigit:]]* <val>: + ... + [[:xdigit:]]*: R_MORELLO_RELATIVE *ABS* +# Want to check that the size is non-zero. +# Check that using a negative line match to a zero size. +# In fact, when this size is zero objdump doesn't even print a line here, but +# that just adds extra robustness to our check. +! .*: 00000000 .word 0x00000000 + .*: 01000000 .* diff --git a/ld/testsuite/ld-aarch64/c64-ehdr-sized-reloc.s b/ld/testsuite/ld-aarch64/c64-ehdr-sized-reloc.s new file mode 100644 index 0000000000000000000000000000000000000000..3b750cfbd499d9babd25d1a8fb0b1d573726a855 --- /dev/null +++ b/ld/testsuite/ld-aarch64/c64-ehdr-sized-reloc.s @@ -0,0 +1,11 @@ + .data + .global val +val: + .chericap __ehdr_start + .size val, .-val + + .align 4 + .text + .global _start +_start: + ldr c0, [c0, :got_lo12:val]