This patch series re-works the function elfNN_c64_resize_sections. The function is called early on in linking to ensure that the range of sections which need to be reachable via the PCC can be precisely bounded by the CHERI capability format. It also handles padding and alignign individual sections if there are any relocations to symbols which will be given a size spanning the entire section (i.e. section start linker defined symbols).
We hit a few problems in this function trying to link glibc, and discovered some more while working on the function. This patch series is a combination of the changes we've applied. I plan to apply it as a series of patches rather than as one large patch to keep the mapping between change and rationale.
Overall, the changes are about two things:
The first is making these padding and alignment adjustments to sections in such a way that they are robust against changes earlier on in the linker script instead of relying on making the adjustments in section-VMA order and having no changes earlier on in the linker script after any adjustment has been made.
The fact that the PCC bounds span multiple sections means that we can't rely on making adjustments in section-VMA order (increasing the alignment of the first section in the PCC bounds will mean a change earlier on than any section in the PCC bounds, while changes on the sections inside these bounds can adjust the alignment needed on the PCC).
The second set of changes are around performing the padding and alignment changes in more valid cases. We notice that data-only PURECAP shared libraries (i.e. objects without C64 code) could still have relocations in them pointing to section-start symbols (though won't need a non-existent PCC bounds to be precise), and we fix a bug that did not account for section starting symbols defined in the section they are supposed to mark.
A summary of the patch series: 1) Add padding by setting "dot" to the *expression* "dot + padding required" rather than the value of "dot + padding required". This means that adjustments to alignment of sections before the one being padded cause changes which get propagated past this section. We also include the padding in the section size, which trades unnecessary zerod data in the final binary against having the precisely bounded size clear in the final binary. 2) Set the alignment of sections to what is needed for precise bounds even if the existing VMA happens to be aligned enough. This means that if earlier sections are adjusted then the linker will ensure this section stays aligned correctly. 3) Ensure that PCC bounds are precise independent of whether there are any section-start symbols requiring specific sections to be precisely bounded. (bugfix). 4) Pad and align sections for data-only executables if they are made from PURECAP objects and need it due to their relocations. 5) Refactor the function based on above changes so that rather than construct a list of adjustments to make and sorting that list before applying the adjustments, we simply make adjustments as we find the requirement (possible because the adjustments are now robust against adjustments on earlier sections). 6) Testsuite updates and new tests. 7) Adjust section padding on a section if there is a section start symbol *in that section* (as well as just before it). I.e. if there is a __data_relro_start symbol in the .data.rel.ro section then we adjust the .data.rel.ro section (rather than checking to see if the next section has the same start address as the end address of the current section and padding the next section if that's the case). This is a little tricky since we don't know the position of a symbol within a section at this point, but like the existing code we handle that lack of knowledge by overfitting and adjusting any section that may be relevent.
The entire patch series has been regression tested on AArch64 bare-metal purecap with no regressions.
Thanks, Matthew
Entire patch series attached to cover letter.
When adding padding to ensure section bounds do not overlap we were implementing the padding using `lang_add_newdot`. This interacts with what is essentially an in-memory linker script that the linker will use at the very end to emit its sections according to those rules that have been built up.
`lang_add_newdot` is essentially the same as defining the position to be the given address in a linker script. This means that all sections after this point in the linker script will be at an address starting from this known address.
I.e. the method by which we add padding is essentially changing the description of how we will lay a binary out from:
<sections before the padded one> <section to be padded> <sections after the padded one>
to the description: <sections before the padded one> <section to be padded> <current position must be 0x[number calculated now]> <sections after the padded one>
This works fine in most cases. The address we calculate is a known-good value and sections after this "point" are moved to after the known-good value.
However, the fact that we choose a specific value when we call `c64_pad_section` means that adjusting sections which occur *before* the current point will not change anything that occurs after it.
I.e. a description of
<sections before the padded one> <section to be padded> <current position must be 0x[number calculated now]> <sections after the padded one>
being changed to a description of
<sections before section X> <New padding> <sections before padded one> <section to be padded> <current position must be 0x[number calculated now]> <sections after the padded one>
leaves the `<sections after the padded one>` with the same address. This can lead to the padded section and the section after it overlapping.
This rarely happens, because our padding always happens after a section and we iterate over sections in memory order. However, when we align the very start of the PCC range in order to produce precise bounds across this range that can change the start position of the first section that should be spanned by the PCC range.
Since it can change the start position we can hit the problem described above. This happens when attempting to build glibc. It causes an error message like the one below. section .got LMA [000000000053c0c0,000000000053cfff] overlaps section .data.rel.ro LMA [0000000000525fe0,000000000053d08f]
This patch solves this problem by adding an entry into this in-memory linker script that describes padding without specifying a given address. I.e. the outline of the script we produce becomes
<sections before the padded one> <section to be padded> <current position goes from P to P+0x[padding calculated now]> <sections after the padded one>
This is safe w.r.t. adjustments occuring before the padding we have inserted, and it avoids the warning we noticed when trying to build glibc.
We also fix up some other bugs in this area around double-padding sections.
First, the calculation of the padding required was based on the output section VMA and size. The calculation was done by taking the current start and end VMA then finding the resulting start and end VMA that we want using c64_valid_cap_range. Then we calculated the padding we wanted by finding the difference between the current and requested end VMA's. This ignored the fact that the output section was also getting aligned, which would change the start VMA -- hence the resulting end VMA would not end up where we wanted. Here we do the calculation of how much padding to add based on the size we want rather than based on the ending VMA we want.
Second, the reported size of the output section was not changing after adding our padding. This meant that the second time around this loop (if for example a relocation into a given section was used in more than one place and hence this section was enqueued twice) we would again find that the section size was not padded and try again. We fix this by introducing the padding statement to the output section statement children rather than to the main statement list. This means that the padding will be accounted for in the output section size and hence the loop will avoid padding this section again.
Just to note: LLD does not report the sizes of sections including their padding. This is so that programs which read binary information (such as readelf and objdump) do not need to read the padded zeros in the file. We choose to include this padding in the section size information on the premise that it is usually quite small and that the output from these programs is then more readable. The bug that we fixed by including this padding in the size of the output section could be fixed in another way.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index f33388629164b59e07cdbac7bb4bce82e2f62b8b..f3f058934ea203cb735b9b4baf77ba8e8f854066 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -5040,7 +5040,7 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, if (queue->sec->alignment_power < align) queue->sec->alignment_power = align;
- padding = high - queue->sec->vma - queue->sec->size; + padding = high - low - queue->sec->size;
if (queue->sec != pcc_high_sec) { @@ -5066,7 +5066,10 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, if (pcc_low_sec->alignment_power < align) pcc_low_sec->alignment_power = align;
- padding = pcc_high - pcc_high_sec->vma - pcc_high_sec->size; + bfd_vma current_length = + (pcc_high_sec->vma + pcc_high_sec->size) - pcc_low_sec->vma; + bfd_vma desired_length = (pcc_high - pcc_low); + padding = desired_length - current_length; c64_pad_section (pcc_high_sec, padding); } } diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em index 95cee025e3dc7f0f573ed170db3a0f050b375e6f..8a123106e3df3a0236cf818051430b5ef27eca8e 100644 --- a/ld/emultempl/aarch64elf.em +++ b/ld/emultempl/aarch64elf.em @@ -216,7 +216,10 @@ elf64_c64_pad_section (asection *osec, bfd_vma padding) lang_output_section_statement_type *os = lang_output_section_get (osec);
lang_list_init (&list); - lang_add_newdot (&list, osec->vma + osec->size + padding); + lang_add_assignment_internal (&list, + exp_assign (".", + exp_binop ('+', exp_nameop (NAME, "."), exp_intop (padding)), + FALSE));
if (list.head == NULL) { @@ -224,8 +227,8 @@ elf64_c64_pad_section (asection *osec, bfd_vma padding) return; }
- *(list.tail) = os->header.next; - os->header.next = list.head; + *(list.tail) = NULL; + *(os->children.tail) = list.head; } }
diff --git a/ld/ldlang.h b/ld/ldlang.h index 6074e2cb0129f60d7efbd44c8d9a14050b44f7c2..89ee85e557363811c63ac168ddc7aca9271e8d21 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -561,6 +561,8 @@ extern lang_assignment_statement_type *lang_add_assignment (union etree_union *); extern void lang_add_attribute (enum statement_enum); +extern void lang_add_assignment_internal + (lang_statement_list_type *, etree_type *); extern void lang_add_newdot (lang_statement_list_type *, bfd_vma); extern void lang_startup diff --git a/ld/ldlang.c b/ld/ldlang.c index fb9340603c2aa2f0dbf038ea975b192d0e95349f..09feb5b7e1fc63d0d1cde59754fc991fc3bf2dce 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -8370,6 +8370,15 @@ lang_add_assignment (etree_type *exp) return new_stmt; }
+void +lang_add_assignment_internal (lang_statement_list_type *ptr, etree_type *exp) +{ + lang_assignment_statement_type *new_stmt; + + new_stmt = new_stat (lang_assignment_statement, ptr); + new_stmt->exp = exp; +} + void lang_add_newdot (lang_statement_list_type *ptr, bfd_vma newdot) {
Before this patch we would only change the alignment of a section if it did not have a start and end address that was aligned properly.
This meant that there was nothing stopping the alignment of this section degrading in the future. On first glance this looks like it would not be a problem since this function only adjusts sections in order of increasing VMA (hence it would seem that the alignment of the current section can not be reduced).
However, in some cases layout_sections_again can be seen to reduce the alignment of sections if there was some initial space before the .text section that it shrinks for some reason. This led to a degredation of the alignment of all sections after that point (until another highly aligned section).
The testcase added for this change (in the final "testsuite" commit of this patch series) is a good example of this, on first entry to the elfNN_c64_resize_sections function .text happened to have a start address of 0xb0 (which meant that .data.rel.ro was also aligned to such a boundary and the function did not believe there was a need to align .data.rel.ro to a 16 byte boundary). However after the first call to layout_sections_again this changed to 0x78, reducing the alignment of .data.rel.ro in the process.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index f3f058934ea203cb735b9b4baf77ba8e8f854066..fb50608b72c41fae81b1d2b3a655161ce8c55e8d 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -4872,7 +4872,8 @@ record_section_change (asection *sec, struct sec_change_queue **queue) bfd_vma high = sec->vma + sec->size; unsigned alignment;
- if (!c64_valid_cap_range (&low, &high, &alignment)) + if (!c64_valid_cap_range (&low, &high, &alignment) + || sec->alignment_power < alignment) queue_section_padding (queue, sec); }
@@ -5037,9 +5038,6 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info,
if (!c64_valid_cap_range (&low, &high, &align)) { - if (queue->sec->alignment_power < align) - queue->sec->alignment_power = align; - padding = high - low - queue->sec->size;
if (queue->sec != pcc_high_sec) @@ -5048,6 +5046,8 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, padding = 0; } } + if (queue->sec->alignment_power < align) + queue->sec->alignment_power = align;
/* If we have crossed all sections within the PCC range, set up alignment and padding for the PCC range. */ @@ -5063,15 +5063,14 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info,
if (!c64_valid_cap_range (&pcc_low, &pcc_high, &align)) { - if (pcc_low_sec->alignment_power < align) - pcc_low_sec->alignment_power = align; - bfd_vma current_length = (pcc_high_sec->vma + pcc_high_sec->size) - pcc_low_sec->vma; bfd_vma desired_length = (pcc_high - pcc_low); padding = desired_length - current_length; c64_pad_section (pcc_high_sec, padding); } + if (pcc_low_sec->alignment_power < align) + pcc_low_sec->alignment_power = align; }
(*htab->layout_sections_again) (); diff --git a/ld/testsuite/ld-aarch64/morello-sec-always-align.d b/ld/testsuite/ld-aarch64/morello-sec-always-align.d new file mode 100644 index 0000000000000000000000000000000000000000..f46ebdfb821eac114f84dee8b385d1ab1648af30 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-always-align.d @@ -0,0 +1,20 @@ +#as: -march=morello+c64 +#ld: -static -T morello-sec-round-adjust.ld +#objdump: -x +#... +Sections: +Idx Name Size VMA LMA File off Algn +#... + 0 .text 00000100 0000000000000080 [0-9a-f]+ [0-9a-f]+ 2**4 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data.rel.ro 00008000 0000000000000180 [0-9a-f]+ [0-9a-f]+ 2**4 + CONTENTS, ALLOC, LOAD, DATA + 2 .got 00000030 0000000000008180 [0-9a-f]+ [0-9a-f]+ 2**4 + CONTENTS, ALLOC, LOAD, DATA + 3 .got.plt 00000030 00000000000081b0 [0-9a-f]+ [0-9a-f]+ 2**4 + CONTENTS, ALLOC, LOAD, DATA + 4 .rela.dyn 000000b8 00000000000081e0 [0-9a-f]+ [0-9a-f]+ 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA +#pass + + diff --git a/ld/testsuite/ld-aarch64/morello-sec-always-align.ld b/ld/testsuite/ld-aarch64/morello-sec-always-align.ld new file mode 100644 index 0000000000000000000000000000000000000000..87613d0f3b3fa1321c26160b8cf421c541ba004d --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-always-align.ld @@ -0,0 +1,17 @@ +SECTIONS { + . = SIZEOF_HEADERS; + .text : + { + *(.text) + } + .data.rel.ro : + { + __data_rel_ro_startsym = .; + *(.data.rel.ro) + } + .got : { *(.got) } + .iplt : { *(.iplt) } + .data : { *(.data) } + .rela.dyn : { *(.rela.dyn) } + .interp : { *(.interp) } +} diff --git a/ld/testsuite/ld-aarch64/morello-sec-always-align.s b/ld/testsuite/ld-aarch64/morello-sec-always-align.s new file mode 100644 index 0000000000000000000000000000000000000000..1a3992dd93363f6182cf34e34465069114b79cae --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-always-align.s @@ -0,0 +1,22 @@ +.text +__start: + # Use a GOT relocation because the linker currently doesn't do the + # padding and alignment unless we have GOT relocations. This is + # another linker bug that we need to fix. + adrp c0, :got:__data_rel_ro_startsym + ret +.zero 0x0f8 +.section .data.rel.ro,"aw",@progbits +# We use a linker defined symbol that points into .data.rel.ro so that the +# linker will need to ensure this section is aligned and padded so that its +# bounds can be precisely represented by a capability. This is done in the +# linker script. +# +# Here we ensure that the size of the section is large enough that it will need +# padding. +.zero 0x8000 +.section .got,"aw",@progbits +.capinit __data_rel_ro_startsym +.xword 0 +.xword 0 +
The mechanism by which we were ensuring the PCC bounds were made precise for Morello happened to only work if there were some sections which needed to be made precisely representable for Morello individually. This was because we included the PCC bounds calculation in the `queue` iteration that only iterated over adjustments to individual sections.
Here we move the PCC bounds calculation to after the `queue` iteration so that we always perform this operation.
We suspect the original implementation was chosen to ensure that padding was added in sequential section ordering. This ordering seems to have been in order to ensure that padding at one position would not adjust sections that had already been adjusted (because padding one section changes the location of the sections after it).
We have already found in previous patches that this approach was not sufficient to ensure an adjustment being permanent. The alignment change to the first section that the PCC should span can change the location of all sections after it, or the linker can simply have extra space before .text that it removes on a call to layout_sections_again.
In the patches to fix those problems, we have adjusted the code here to represent the padding in a way that stays stable across changes. That has meant that the iteration in VMA order is no longer necessary, and that means that our movement of the PCC bounds calculation to outside of the `queue` iteration loop can be performed.
One interesting part of this adjustment is that given a set of sections, the length of memory that they span can change if the first sections alignment is adjusted. For example, if we have the below: sectionA VMA 0xf size 0x1 alignment 0x1 sectionB VMA 0x10 size 0x10 alignment 0x10 Then aligning sectionA to 0x10 gives the below: sectionA VMA 0x10 size 0x1 alignment 0x10 sectionB VMA 0x20 size 0x10 alignment 0x10 The total range of the first case is [0xf -> 0x20] for a size of 0x11 and of the second case it is [0x10 -> 0x30] for a size of 0x20.
This means that we should handle the alignment adjustment for the PCC bounds first, and must handle it in a loop to ensure that we handle the case that this change in length requires an extra alignment. Only then do we know the size that we want to add into the last section in the range so that the entire bounds are correct.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index fb50608b72c41fae81b1d2b3a655161ce8c55e8d..d75c1eea52e19806304b0605291937112bbaed41 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -4899,6 +4899,7 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info); bfd_vma low = (bfd_vma) -1, high = 0; bfd *input_bfd; + unsigned align = 0;
htab->layout_sections_again = layout_sections_again;
@@ -5030,7 +5031,6 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, and whether they need to be padded or aligned. */ while (queue) { - unsigned align = 0; bfd_vma padding = 0;
low = queue->sec->vma; @@ -5049,30 +5049,6 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, if (queue->sec->alignment_power < align) queue->sec->alignment_power = align;
- /* If we have crossed all sections within the PCC range, set up alignment - and padding for the PCC range. */ - if (pcc_high_sec != NULL && pcc_low_sec != NULL - && (queue->next == NULL - || queue->next->sec->vma > pcc_high_sec->vma)) - { - /* Layout sections since it affects the final range of PCC. */ - (*htab->layout_sections_again) (); - - pcc_low = pcc_low_sec->vma; - pcc_high = pcc_high_sec->vma + pcc_high_sec->size + padding; - - if (!c64_valid_cap_range (&pcc_low, &pcc_high, &align)) - { - bfd_vma current_length = - (pcc_high_sec->vma + pcc_high_sec->size) - pcc_low_sec->vma; - bfd_vma desired_length = (pcc_high - pcc_low); - padding = desired_length - current_length; - c64_pad_section (pcc_high_sec, padding); - } - if (pcc_low_sec->alignment_power < align) - pcc_low_sec->alignment_power = align; - } - (*htab->layout_sections_again) ();
struct sec_change_queue *queue_free = queue; @@ -5081,10 +5057,56 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, free (queue_free); }
- if (pcc_low_sec) - { - if (!pcc_high_sec) - abort (); + /* Always ensure that the PCC range has precise Morello bounds. + Whether or not there are any individual sections that need to be adjusted + to give precise bounds. */ + if (pcc_low_sec != NULL) + { + BFD_ASSERT (pcc_high_sec); + + bfd_vma pcc_low_tmp; + bfd_vma pcc_high_tmp; + + /* We have to be a little careful about the padding we introduce. The + padding we could calculate here may not be the padding that we would + want after the very first section in the PCC bounds has been aligned + properly. That change in the start address propagated through a few + different sections with their own alignment requirements can easily + change the length of the region we want the PCC to span. + Even more tricky, that change in length could change the alignment we + want. We don't proove that the alignment requirement converges, + but believe that it should (there is only so much space that existing + alignment requirements could trigger to be added -- a section with an + alignment requirement of 16 can only really add 15 bytes to the + length). */ + bfd_boolean valid_range = FALSE; + while (TRUE) { + pcc_low_tmp = pcc_low_sec->vma; + pcc_high_tmp = pcc_high_sec->vma + pcc_high_sec->size; + valid_range = + c64_valid_cap_range (&pcc_low_tmp, &pcc_high_tmp, &align); + if (pcc_low_sec->alignment_power >= align) + break; + pcc_low_sec->alignment_power = align; + (*htab->layout_sections_again) (); + } + + /* We have calculated the bottom and top address that we want in the + above call to c64_valid_cap_range. We have also aligned the lowest + section in the PCC range to where we want it. Just have to add the + padding remaining if needs be. */ + if (!valid_range) + { + BFD_ASSERT (pcc_low_tmp == pcc_low_sec->vma); + bfd_vma current_length = + (pcc_high_sec->vma + pcc_high_sec->size) - pcc_low_sec->vma; + bfd_vma desired_length = (pcc_high_tmp - pcc_low_tmp); + bfd_vma padding = desired_length - current_length; + c64_pad_section (pcc_high_sec, padding); + } + /* Layout sections since it affects the final range of PCC. */ + (*htab->layout_sections_again) (); + pcc_low = pcc_low_sec->vma; pcc_high = pcc_high_sec->vma + pcc_high_sec->size; } diff --git a/ld/testsuite/ld-aarch64/morello-sec-always-align.d b/ld/testsuite/ld-aarch64/morello-sec-always-align.d index f46ebdfb821eac114f84dee8b385d1ab1648af30..9e69e1c3d1ecdf79cc01d393ae0fd2d83e06a895 100644 --- a/ld/testsuite/ld-aarch64/morello-sec-always-align.d +++ b/ld/testsuite/ld-aarch64/morello-sec-always-align.d @@ -13,7 +13,7 @@ Idx Name Size VMA LMA File off Algn CONTENTS, ALLOC, LOAD, DATA 3 .got.plt 00000030 00000000000081b0 [0-9a-f]+ [0-9a-f]+ 2**4 CONTENTS, ALLOC, LOAD, DATA - 4 .rela.dyn 000000b8 00000000000081e0 [0-9a-f]+ [0-9a-f]+ 2**3 + 4 .rela.dyn 00000030 00000000000081e0 [0-9a-f]+ [0-9a-f]+ 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA #pass
Before this change individual sections would not be padded or aligned if there was no C64 code or if there were no capability GOT relocations in the binary. This meant that if we had a data-only PURECAP shared library with a CAPINIT relocation in it pointing at something, then the section that relocation pointed into would not be padded accordingly.
This patch changes this so that we look for sections which may need individual padding if we see the PURECAP elf header flag, and if there is a `srelcaps` section (i.e. the RELATIVE capability relocations).
We keep the behaviour that we do not adjust the size of sections unless there is a static relocation pointing at a zero-sized symbol at that section. That is, we do not make any adjustment to try and handle section padding in the case where other binaries would dynamically link against such symbols. We do this since the "symbol pointing to section start implies spanning entire section" decision is a hack to enable some linker script uses, and we don't want to extend it without a known motivating example.
Finally, this patch ignores padding PCC bounds on PURECAP binaries if there is no C64 code in this binary, but ensures that the PCC bounds are made precise even if there are no static relocations in the file. We could still get the current PCC and offset it using `adr` if there are no static relocations, but without there being any C64 code there will be no PCC to bound and hence we don't need the bounds on a hypothetical PCC to be precise.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index d75c1eea52e19806304b0605291937112bbaed41..f5dc1bd62faf1a89a0a34a69031924ba13968790 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -4895,15 +4895,20 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, void (*c64_pad_section) (asection *, bfd_vma), void (*layout_sections_again) (void)) { - asection *sec, *pcc_low_sec = NULL, *pcc_high_sec = NULL; + asection *sec; struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info); - bfd_vma low = (bfd_vma) -1, high = 0; bfd *input_bfd; unsigned align = 0;
htab->layout_sections_again = layout_sections_again;
- if (!htab->c64_output) + /* If this is not a PURECAP binary, and has no C64 code in it, then this is + just a stock AArch64 binary and the section padding is not necessary. + We can have PURECAP shared libraries that are data-only, so just checking + if there is C64 code in this executable is not enough. We can have HYBRID + binaries, so just checking for PURECAP is not enough. */ + if (!(htab->c64_output + || (elf_elfheader (output_bfd)->e_flags & EF_AARCH64_CHERI_PURECAP))) return;
struct sec_change_queue *queue = NULL; @@ -4912,7 +4917,18 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, defined and ldscript defined symbols since we set their range to their output sections. */ for (input_bfd = info->input_bfds; - htab->c64_rel && input_bfd != NULL; input_bfd = input_bfd->link.next) + /* No point iterating over all relocations to ensure each section that + needs to give the bounds for a capability is padded accordingly if + there are no capability relocations in the GOT and there are no + CAPINIT relocations. + N.b. It is possible that when creating a dynamic object a + section-spanning symbol could be used by some other executable + linking to it when we don't have a relocation to it in the given + dynamic library. Rather than pad every section which has a linker + defined symbol pointing into it we choose to allow such use-cases to + have sizes which bleed into another section. */ + (htab->c64_rel || htab->srelcaps) && input_bfd != NULL; + input_bfd = input_bfd->link.next) { Elf_Internal_Shdr *symtab_hdr;
@@ -4987,10 +5003,48 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, } }
+ /* Sequentially add alignment and padding as required. */ + while (queue) + { + bfd_vma low = queue->sec->vma; + bfd_vma high = queue->sec->vma + queue->sec->size; + + if (!c64_valid_cap_range (&low, &high, &align)) + { + bfd_vma padding = high - low - queue->sec->size; + c64_pad_section (queue->sec, padding); + } + if (queue->sec->alignment_power < align) + queue->sec->alignment_power = align; + + (*htab->layout_sections_again) (); + + struct sec_change_queue *queue_free = queue; + + queue = queue->next; + free (queue_free); + } + /* Next, walk through output sections to find the PCC span and add a padding at the end to ensure that PCC bounds don't bleed into neighbouring sections. For now PCC needs to encompass all code sections, .got, .plt - and .got.plt. */ + and .got.plt. + If there is no C64 code in this binary, then we do not need to care about + PCC bounds, hence skip this bit. + It's tempting to also avoid padding the PCC range when we have no static + relocations in this binary, since it would seem that we can never end up + trying to access something "outside" the PCC bounds (any PCC bounded + capability provided to an outside dynamic object would be sealed by the + runtime, and hence can't be offset). Unfortunately it is still possible, + since an `adr c0, 0` gives an unsealed capability to the current code + which could then be offset by some other means. + While that seems unlikely to happen, having no relocations in a file also + seems quite unlikely, so we may as well play it safe. */ + if (!htab->c64_output) + return; + + bfd_vma low = (bfd_vma) -1, high = 0; + asection *pcc_low_sec = NULL, *pcc_high_sec = NULL; for (sec = output_bfd->sections; sec != NULL; sec = sec->next) { /* XXX This is a good place to figure out if there are any readable or @@ -5025,41 +5079,8 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, #undef NOT_OP_SECTION }
- /* Sequentially add alignment and padding as required. We also need to - account for the PCC-related alignment and padding here since its - requirements could change based on the range of sections it encompasses - and whether they need to be padded or aligned. */ - while (queue) - { - bfd_vma padding = 0; - - low = queue->sec->vma; - high = queue->sec->vma + queue->sec->size; - - if (!c64_valid_cap_range (&low, &high, &align)) - { - padding = high - low - queue->sec->size; - - if (queue->sec != pcc_high_sec) - { - c64_pad_section (queue->sec, padding); - padding = 0; - } - } - if (queue->sec->alignment_power < align) - queue->sec->alignment_power = align; - - (*htab->layout_sections_again) (); - - struct sec_change_queue *queue_free = queue; - - queue = queue->next; - free (queue_free); - } - - /* Always ensure that the PCC range has precise Morello bounds. - Whether or not there are any individual sections that need to be adjusted - to give precise bounds. */ + /* Set the PCC range to have precise bounds to ensure that PCC relative loads + can not access outside of their given range. */ if (pcc_low_sec != NULL) { BFD_ASSERT (pcc_high_sec); @@ -5073,12 +5094,11 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, properly. That change in the start address propagated through a few different sections with their own alignment requirements can easily change the length of the region we want the PCC to span. - Even more tricky, that change in length could change the alignment we - want. We don't proove that the alignment requirement converges, - but believe that it should (there is only so much space that existing - alignment requirements could trigger to be added -- a section with an - alignment requirement of 16 can only really add 15 bytes to the - length). */ + Also, that change in length could change the alignment we want. We + don't proove that the alignment requirement converges, but believe + that it should (there is only so much space that existing alignment + requirements could trigger to be added -- a section with an alignment + requirement of 16 can only really add 15 bytes to the length). */ bfd_boolean valid_range = FALSE; while (TRUE) { pcc_low_tmp = pcc_low_sec->vma; @@ -5103,9 +5123,8 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, bfd_vma desired_length = (pcc_high_tmp - pcc_low_tmp); bfd_vma padding = desired_length - current_length; c64_pad_section (pcc_high_sec, padding); + (*htab->layout_sections_again) (); } - /* Layout sections since it affects the final range of PCC. */ - (*htab->layout_sections_again) ();
pcc_low = pcc_low_sec->vma; pcc_high = pcc_high_sec->vma + pcc_high_sec->size;
Now instead of iterating through relocations recording changes to make and sorting those changes according to the section VMA before going on to make the changes in section VMA order, we instead modify the sections as we iterate through relocations.
This change can be done now that the alignment is always done, even if the VMA of the start and end was good for precise bounds and now that padding is added via an expression rather than setting the point to a specific location. Having these two things means that changing the layout of earlier sections does not affect the precise bounds property of later sections.
It also makes things easier that we keep the padding of a section inside that section, so can tell whether a section has the correct size just from the size of the section rather recording in an out-of-bounds manner which sections have had their padding assigned.
This patch makes no functional change, but simply changes the code to be more readable.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index f5dc1bd62faf1a89a0a34a69031924ba13968790..9bec87163d30d8493b243f0cae69f6c7ab0b7fd6 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -4828,53 +4828,33 @@ c64_valid_cap_range (bfd_vma *basep, bfd_vma *limitp, unsigned *alignmentp) return FALSE; }
-struct sec_change_queue -{ - asection *sec; - struct sec_change_queue *next; -}; - -/* Queue up the change, sorted in order of the output section vma. */ - -static void -queue_section_padding (struct sec_change_queue **queue, asection *sec) +/* Check if the bounds of section SEC will get rounded off in the Morello + capability format and if it would, adjust the section to ensure any + capability spanning this section would have its bounds precise. */ +static inline void +ensure_precisely_bounded_section (asection *sec, + struct elf_aarch64_link_hash_table *htab, + void (*c64_pad_section) (asection *, bfd_vma)) { - struct sec_change_queue *q = *queue, *last_q = NULL, *n; + bfd_vma low = sec->vma; + bfd_vma high = sec->vma + sec->size; + unsigned alignment;
- while (q != NULL) + bfd_boolean did_change = FALSE; + if (!c64_valid_cap_range (&low, &high, &alignment)) { - if (q->sec->vma > sec->vma) - break; - last_q = q; - q = q->next; + bfd_vma padding = high - low - sec->size; + c64_pad_section (sec, padding); + did_change = TRUE; } - - n = bfd_zmalloc (sizeof (struct sec_change_queue)); - - if (last_q == NULL) - *queue = n; - else + if (sec->alignment_power < alignment) { - n->next = q; - last_q->next = n; + sec->alignment_power = alignment; + did_change = TRUE; }
- n->sec = sec; -} - -/* Check if the bounds covering all sections between LOW_SEC and HIGH_SEC will - get rounded off in the Morello capability format and if it does, queue up a - change to fix up the section layout. */ -static inline void -record_section_change (asection *sec, struct sec_change_queue **queue) -{ - bfd_vma low = sec->vma; - bfd_vma high = sec->vma + sec->size; - unsigned alignment; - - if (!c64_valid_cap_range (&low, &high, &alignment) - || sec->alignment_power < alignment) - queue_section_padding (queue, sec); + if (did_change) + (*htab->layout_sections_again) (); }
/* Make sure that all capabilities that refer to sections have bounds that @@ -4911,8 +4891,6 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, || (elf_elfheader (output_bfd)->e_flags & EF_AARCH64_CHERI_PURECAP))) return;
- struct sec_change_queue *queue = NULL; - /* First, walk through all the relocations to find those referring to linker defined and ldscript defined symbols since we set their range to their output sections. */ @@ -4975,7 +4953,7 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, os = h->root.u.def.section->output_section;
if (h->root.linker_def) - record_section_change (os, &queue); + ensure_precisely_bounded_section (os, htab, c64_pad_section); else if (h->root.ldscript_def) { const char *name = h->root.root.string; @@ -4991,40 +4969,20 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, section_start_symbol, &value);
if (os != NULL) - record_section_change (os, &queue); + ensure_precisely_bounded_section (os, htab, + c64_pad_section); } /* XXX We're overfitting here because the offset of H within the output section is not yet resolved and ldscript defined symbols do not have input section information. */ else - record_section_change (os, &queue); + ensure_precisely_bounded_section (os, htab, + c64_pad_section); } } } }
- /* Sequentially add alignment and padding as required. */ - while (queue) - { - bfd_vma low = queue->sec->vma; - bfd_vma high = queue->sec->vma + queue->sec->size; - - if (!c64_valid_cap_range (&low, &high, &align)) - { - bfd_vma padding = high - low - queue->sec->size; - c64_pad_section (queue->sec, padding); - } - if (queue->sec->alignment_power < align) - queue->sec->alignment_power = align; - - (*htab->layout_sections_again) (); - - struct sec_change_queue *queue_free = queue; - - queue = queue->next; - free (queue_free); - } - /* Next, walk through output sections to find the PCC span and add a padding at the end to ensure that PCC bounds don't bleed into neighbouring sections. For now PCC needs to encompass all code sections, .got, .plt
Unfortunately writing a test for many of these changes was difficult since we needed to check that thing A pointed to place B or that thing A had a length that spanned places B and C. Hence quite a few of the added testcases check for literal values.
These are problematic for a few different reasons, both that they may not work with different configurations and because unrelated updates need to update the tests.
We need to figure out a better way to test this. We believe the testsuite doesn't have facilities for checking this. For now we're leaving making the tests robust for later.
Here we add all the tests which the recent patch series changes and include updates to the existing tests.
Updated existing tests:
emit-relocs-morello-2.d needed updating since the new alignment meant the relocation fragment pointed to a different place. emit-relocs-morello-7.d Needed updating because we added some padding, and re-laid the sections. This just ended up with a layout with the .text section at a different location and with a different range. emit-relocs-morello-8.d Just needed updating because the extra padding moved the .data.rel.ro section a bit. The position of the relocation was not part of the test so we replaced that with an "any number" regex. emit-morello-reloc-markers-{2,3}.d Needed updating because the PCC bounds required extra alignment and that was put on the first section in the PCC bounds. That happened to be the section we were looking at. morello-capinit.d Needed updating because this change actually fixed a problem with our calculation of the pcc bounds. Now we calculate the pcc_low and pcc_high *after* having made all our adjustments, the bounds we add on the capability start at the first section we want to contain. morello-stubs.d Updated just becase the location of our functions was changed due to the text section change. morello-stubs-static.d Updated because the location of the .text_low section changed along with all the code in it. Hence our stubs that needed to point to these functions also changed. c64-ifunc-{2,2-local,3a}.d Updated because the .text section moved and hence the address of the foo function we wanted to point to was adjusted. morello-sizeless-{got,global,local}-syms.d Again, .data .bss and .got sections ended up moved so addresses of the capabilities we wanted to point at all changed.
############### Attachment also inlined for ease of reply ###############
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 01f65dc934de3f012b6e134ff2ccebd1f4207650..837b9df877276029cf8d036d75de02f70e224bc0 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -262,6 +262,12 @@ run_dump_test_lp64 "morello-capinit" run_dump_test_lp64 "morello-stubs" run_dump_test_lp64 "morello-stubs-static" run_dump_test_lp64 "morello-sec-round" +run_dump_test_lp64 "morello-sec-round-adjust" +run_dump_test_lp64 "morello-sec-always-align" +run_dump_test_lp64 "morello-sec-round-pcc-needed" +run_dump_test_lp64 "morello-sec-round-data-only" +run_dump_test_lp64 "morello-sec-round-include-relro" +run_dump_test_lp64 "morello-pcc-bounds-include-readonly" run_dump_test_lp64 "morello-tlsdesc" run_dump_test_lp64 "morello-tlsdesc-static" run_dump_test_lp64 "morello-tlsdesc-staticpie" diff --git a/ld/testsuite/ld-aarch64/c64-ifunc-2-local.d b/ld/testsuite/ld-aarch64/c64-ifunc-2-local.d index 8c7fe038cd5b09eee772fbb00a7fe620cfcaef59..c85443fe71acb15f04d749cbb159fc002893d46c 100644 --- a/ld/testsuite/ld-aarch64/c64-ifunc-2-local.d +++ b/ld/testsuite/ld-aarch64/c64-ifunc-2-local.d @@ -5,9 +5,9 @@ #source: ifunc-2-local.s
#... -0+(110|180|1a0) <__GI_foo>: +0+(110|180|1a0|1b8) <__GI_foo>: #... -[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<*ABS*+0x(110|180|1a0)@plt> +[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<*ABS*+0x(110|180|1a0|1b8)@plt> [ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+c0, 0 <.*> -[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+c0, c0, #0x(101|171|191) +[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+c0, c0, #0x(101|171|191|1a9) #pass diff --git a/ld/testsuite/ld-aarch64/c64-ifunc-2.d b/ld/testsuite/ld-aarch64/c64-ifunc-2.d index 64a8b808f91856dccf1b3ea4617b91446a8ea94b..b87908b27a4366a181ddee8b7e4b7343ebd3f4b7 100644 --- a/ld/testsuite/ld-aarch64/c64-ifunc-2.d +++ b/ld/testsuite/ld-aarch64/c64-ifunc-2.d @@ -5,9 +5,9 @@ #source: ifunc-2.s
#... -0+(130|1a0|1c8) <foo>: +0+(130|1a0|1c8|1e0) <foo>: #... -[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<*ABS*+0x(130|1a0|1c8)@plt> +[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<*ABS*+0x(130|1a0|1c8|1e0)@plt> [ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+c0, 0 <.*> -[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+c0, c0, #0x(120|190|1b8) +[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+c0, c0, #0x(120|190|1b8|1d0) #pass diff --git a/ld/testsuite/ld-aarch64/c64-ifunc-3a.d b/ld/testsuite/ld-aarch64/c64-ifunc-3a.d index d680cde1c762149d3cd02eb612908bb0f23d98e0..bd36b23545e800cd5d952d730ac36ad3c40d0a31 100644 --- a/ld/testsuite/ld-aarch64/c64-ifunc-3a.d +++ b/ld/testsuite/ld-aarch64/c64-ifunc-3a.d @@ -5,7 +5,7 @@ #objdump: -dw
#... -0+(150|1d0|1e8) <__GI_foo>: +0+(150|1d0|1e8|200) <__GI_foo>: #... -[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<*ABS*+0x(150|1d0|1e8)@plt> +[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<*ABS*+0x(150|1d0|1e8|200)@plt> #pass diff --git a/ld/testsuite/ld-aarch64/emit-morello-reloc-markers-2.d b/ld/testsuite/ld-aarch64/emit-morello-reloc-markers-2.d index c2fcd5001fb2bc99977d7407ef9ed9165f440a44..f65f859deaa51c442079a4b0b4598b499b32e4bc 100644 --- a/ld/testsuite/ld-aarch64/emit-morello-reloc-markers-2.d +++ b/ld/testsuite/ld-aarch64/emit-morello-reloc-markers-2.d @@ -12,7 +12,7 @@
Sections: Idx Name Size VMA LMA File off Algn - 0 .rela.dyn 00000030 0000000000000000 0000000000000000 00010000 2**3 + 0 .rela.dyn 00000030 0000000000000000 0000000000000000 00010000 .* CONTENTS, ALLOC, LOAD, READONLY, DATA .* .got .* .* diff --git a/ld/testsuite/ld-aarch64/emit-morello-reloc-markers-3.d b/ld/testsuite/ld-aarch64/emit-morello-reloc-markers-3.d index 8ebf8420ca354daa4166883329526ce711a3793a..ea373cd24260c330ef92e836705fafc0392fd74b 100644 --- a/ld/testsuite/ld-aarch64/emit-morello-reloc-markers-3.d +++ b/ld/testsuite/ld-aarch64/emit-morello-reloc-markers-3.d @@ -12,7 +12,7 @@
Sections: Idx Name Size VMA LMA File off Algn - 0 .rela.dyn 00000018 0000000000000000 0000000000000000 00010000 2**3 + 0 .rela.dyn 00000018 0000000000000000 0000000000000000 00010000 .* CONTENTS, ALLOC, LOAD, READONLY, DATA .* .got .* .* diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-2.d b/ld/testsuite/ld-aarch64/emit-relocs-morello-2.d index a7077214be83beb1a099b57805498dfaa6fb263f..fe59dee85f7bbbc8a11ca36168068ae3dfbd1564 100644 --- a/ld/testsuite/ld-aarch64/emit-relocs-morello-2.d +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-2.d @@ -23,7 +23,7 @@ Disassembly of section .got:
Disassembly of section .data:
-.* <str>: +0000000000010360 <str>: .*: 6c6c6548 .* .*: 6874206f .* .*: 20657265 .* @@ -34,11 +34,11 @@ Disassembly of section .data: .*: R_AARCH64_RELATIVE *ABS*+.*
.* <ptr>: -.*: 00010350 .* +.*: 00010360 .* ...
.* <cap>: -.*: 00010350 .* +.*: 00010360 .* .*: R_MORELLO_RELATIVE *ABS* .*: 00000000 .* .*: 0000001b .* diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-7.d b/ld/testsuite/ld-aarch64/emit-relocs-morello-7.d index bbf451ec9425df80631988aff699bc822189bbfd..c32d307eb7e05d5c5d06944f09b823246f8e9474 100644 --- a/ld/testsuite/ld-aarch64/emit-relocs-morello-7.d +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-7.d @@ -12,13 +12,13 @@ # # Point here is that the __text_start and __data_other symbols should end up # pointing into the text section, which should mean that they have PCC bounds -# and their value includes an addend. These are the symbols used in the first -# and last LDR's in the function. +# and the value of the __data_other symbol should include an addend. These are +# the symbols used in the first and last LDR's in the function. # # Meanwhile, the __text_other symbol should have bounds of everything remaining # in the section *before* it (which is nothing), and the __data_start symbol -# should have bounds spanning the entire section *after* it (which is the data -# section). +# should have bounds spanning the entire section *after* it (which happens to +# be the .interp section). # #source: emit-relocs-morello-7.s #as: -march=morello+c64 @@ -30,7 +30,7 @@
Disassembly of section .text:
-.* <obj>: +0000000000000230 <obj>: .*: c2400400 ldr c0, [c0, #16] .*: c2401000 ldr c0, [c0, #64] .*: c2400c00 ldr c0, [c0, #48] @@ -44,24 +44,24 @@ Disassembly of section .data: Disassembly of section .got:
0000000000001000 <.got>: - 1000: 00000120 .* + 1000: [0-9a-f]+ .* ... - 1010: 000001e8 .* - 1010: R_MORELLO_RELATIVE *ABS*+0x38 + 1010: 00000230 .* + 1010: R_MORELLO_RELATIVE *ABS* 1014: 00000000 .* - 1018: 00000e68 .* + 1018: 00000e20 .* 101c: 04000000 .* - 1020: 000001e8 .* - 1020: R_MORELLO_RELATIVE *ABS*+0x48 + 1020: 00000230 .* + 1020: R_MORELLO_RELATIVE *ABS*+0x10 1024: 00000000 .* - 1028: 00000e68 .* + 1028: 00000e20 .* 102c: 04000000 .* - 1030: 00000230 .* + 1030: 00000240 .* 1030: R_MORELLO_RELATIVE *ABS* 1034: 00000000 .* 1038: 0000000d .* 103c: 01000000 .* - 1040: 00000220 .* + 1040: 00000230 .* 1040: R_MORELLO_RELATIVE *ABS* ... 104c: 02000000 .* diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-7.s b/ld/testsuite/ld-aarch64/emit-relocs-morello-7.s index 3ed82287423bb2f399db384b17277c04cf3c84a9..43104fd430b0ba7f146dd10b58f94bdca6cbe31b 100644 --- a/ld/testsuite/ld-aarch64/emit-relocs-morello-7.s +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-7.s @@ -8,7 +8,7 @@ # should get this compatibility hack (and some linker script defined symbols # that should not get the compatibility hack). .arch morello+c64 - .section othersection,"aw" + .section .othersection,"aw",@progbits .asciz "Hello there ;-)" .data .word 10 diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-8.d b/ld/testsuite/ld-aarch64/emit-relocs-morello-8.d index e907f7de72e084263acd208374c09e91d6bd065f..3bf1e62be303d4b788ad4d1f657b4ec905a3afce 100644 --- a/ld/testsuite/ld-aarch64/emit-relocs-morello-8.d +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-8.d @@ -12,7 +12,7 @@ Disassembly of section .data.rel.ro:
0.* <.LC1>: .*: 00001000 udf #4096 - 101e0: R_MORELLO_RELATIVE *ABS* + [0-9a-f]+: R_MORELLO_RELATIVE *ABS* .*: 00000000 udf #0 .*: 00000004 udf #4 .*: 02000000 add c0, c0, #0x0 diff --git a/ld/testsuite/ld-aarch64/morello-capinit.d b/ld/testsuite/ld-aarch64/morello-capinit.d index 54b981a60b9518d9d9fcba28c38019e44828162c..0050df311ac03275d00d69bb57ad7ab48f92eeea 100644 --- a/ld/testsuite/ld-aarch64/morello-capinit.d +++ b/ld/testsuite/ld-aarch64/morello-capinit.d @@ -20,37 +20,37 @@ Disassembly of section .inspectionsection:
[0-9a-f]+ <ct_outer_start>: .*: [0-9a-f]+ .* - .*: R_MORELLO_RELATIVE *ABS*+0x[0-9a-f]+ + .*: R_MORELLO_RELATIVE *ABS* .*: 00000000 .* -.*: 00000270 .* +.*: 00000278 .* .*: 04000000 .*
[0-9a-f]+ <ct_start>: .*: [0-9a-f]+ .* - .*: R_MORELLO_RELATIVE *ABS*+0x[0-9a-f]+ + .*: R_MORELLO_RELATIVE *ABS* .*: 00000000 .* -.*: 00000270 .* +.*: 00000278 .* .*: 04000000 .*
[0-9a-f]+ <ct1_start>: .*: [0-9a-f]+ .* .*: R_MORELLO_RELATIVE *ABS*+0x[0-9a-f]+ .*: 00000000 .* -.*: 00000270 .* +.*: 00000278 .* .*: 04000000 .*
[0-9a-f]+ <ct1_end>: .*: [0-9a-f]+ .* .*: R_MORELLO_RELATIVE *ABS*+0x[0-9a-f]+ .*: 00000000 .* -.*: 00000270 .* +.*: 00000278 .* .*: 04000000 .*
[0-9a-f]+ <ct_end>: .*: [0-9a-f]+ .* .*: R_MORELLO_RELATIVE *ABS*+0x[0-9a-f]+ .*: 00000000 .* -.*: 00000270 .* +.*: 00000278 .* .*: 04000000 .*
[0-9a-f]+ <cd_outer_start>: diff --git a/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.d b/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.d new file mode 100644 index 0000000000000000000000000000000000000000..9c4aa81b9699a03dc4f661d86323a15532180d4f --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.d @@ -0,0 +1,39 @@ +# Checking that we include READONLY ALLOC sections in PCC bounds. +# +# Check is done using the fragment values to show what the size of the PCC +# bounds is given as, and we reorder sections so that the READONLY ALLOC +# section is after all executable sections and RELRO sections. +# +# Test is implemented by ensuring that .othersection is outside of RELRO and is +# the last section that should be included in PCC bounds, and that .data is +# directly after it. This is done with a linker script. If we don't +# include READONLY ALLOC sections in our PCC bounds then .othersection will not +# be within the range of the `obj` capability. +# +#source: morello-pcc-bounds-include-readonly.s +#as: -march=morello+c64 +#ld: -static -pie -T morello-pcc-bounds-include-readonly.ld +#objdump: -j .data -j .text -j .othersection -DR + +.*: file format .* + + +Disassembly of section .text: + +00000000000001a0 <obj>: +#... + +Disassembly of section .othersection: + +0000000000012000 <othersection_start>: +#... + +Disassembly of section .data: + +0000000000014000 <data_start>: + [0-9a-f]+: 000001a0 udf #416 + 14000: R_MORELLO_RELATIVE *ABS* + [0-9a-f]+: 00000000 udf #0 + [0-9a-f]+: 00011f00 .inst 0x00011f00 ; undefined + [0-9a-f]+: 04000000 add z0.b, p0/m, z0.b, z0.b + diff --git a/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.ld b/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.ld new file mode 100644 index 0000000000000000000000000000000000000000..53a94a79d68174163eb67314226af2e7195028da --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.ld @@ -0,0 +1,11 @@ +SECTIONS { + . = SEGMENT_START("text-segment", 0x1a0); + .text : { *(.text) } + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + . = DATA_SEGMENT_RELRO_END (0, .); + .othersection ALIGN(0x2000) : { *(.othersection*) } + .data ALIGN(0x2000) : { *(.data) } + . = DATA_SEGMENT_END (.); +} diff --git a/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.s b/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.s new file mode 100644 index 0000000000000000000000000000000000000000..5727022ca9a69e97857841f32144967c16c57920 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-pcc-bounds-include-readonly.s @@ -0,0 +1,18 @@ +.arch morello+c64 + + .section .othersection,"a",@progbits +othersection_start: + .asciz "Hello there ;-)" + + .data +data_start: + .chericap obj + .text + +obj: + + ldr c0, [c0] + ldr c0, [c0] + ldr c0, [c0] + ldr c0, [c0] + diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-adjust.d b/ld/testsuite/ld-aarch64/morello-sec-round-adjust.d new file mode 100644 index 0000000000000000000000000000000000000000..f00e6a0212857a7d9159c4809aa9d68caa9bdeeb --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-adjust.d @@ -0,0 +1,19 @@ +#as: -march=morello+c64 +#ld: -static -T morello-sec-round-adjust.ld +#objdump: -x +#... +Sections: +Idx Name Size VMA LMA File off Algn +#... + 0 .text 00000109 0000000000000200 [0-9a-f]+ [0-9a-f]+ 2**9 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data.rel.ro 00100200 0000000000000400 0000000000000400 00000400 2**9 + CONTENTS, ALLOC, LOAD, DATA + 2 .got 00000030 0000000000100600 0000000000100600 00100600 2**4 + CONTENTS, ALLOC, LOAD, DATA + 3 .got.plt 00000030 0000000000100630 0000000000100630 00100630 2**4 + CONTENTS, ALLOC, LOAD, DATA + 4 .rela.dyn 000001a0 0000000000100660 0000000000100660 00100660 2**3 + CONTENTS, ALLOC, LOAD, READONLY, DATA +#pass + diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-adjust.ld b/ld/testsuite/ld-aarch64/morello-sec-round-adjust.ld new file mode 100644 index 0000000000000000000000000000000000000000..87613d0f3b3fa1321c26160b8cf421c541ba004d --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-adjust.ld @@ -0,0 +1,17 @@ +SECTIONS { + . = SIZEOF_HEADERS; + .text : + { + *(.text) + } + .data.rel.ro : + { + __data_rel_ro_startsym = .; + *(.data.rel.ro) + } + .got : { *(.got) } + .iplt : { *(.iplt) } + .data : { *(.data) } + .rela.dyn : { *(.rela.dyn) } + .interp : { *(.interp) } +} diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-adjust.s b/ld/testsuite/ld-aarch64/morello-sec-round-adjust.s new file mode 100644 index 0000000000000000000000000000000000000000..09de3cf246a63f3e662a83b2328fcab3d27d3575 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-adjust.s @@ -0,0 +1,22 @@ +.text +__start: + # Use a GOT relocation because the linker currently doesn't do the + # padding and alignment unless we have GOT relocations. This is + # another linker bug that we need to fix. + adrp c0, :got:__data_rel_ro_startsym + ret +.zero 0x100 +.byte 1 +.section .data.rel.ro,"aw",@progbits +# We use a linker defined symbol that points into .data.rel.ro so that the +# linker will need to ensure this section is aligned and padded so that its +# bounds can be precisely represented by a capability. This is done in the +# linker script. +# +# Here we ensure that the size of the section is large enough that it will need +# padding. +.zero 0x100001 +.section .got,"aw",@progbits +.capinit __data_rel_ro_startsym +.xword 0 +.xword 0 diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-data-only.d b/ld/testsuite/ld-aarch64/morello-sec-round-data-only.d new file mode 100644 index 0000000000000000000000000000000000000000..d3761e0eaf0175ccc9d395e064961f38589d760a --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-data-only.d @@ -0,0 +1,15 @@ +#as: -march=morello+c64 +#ld: -static -T morello-sec-round-adjust.ld +#objdump: -x +#... +Sections: +Idx Name Size VMA LMA File off Algn +#... + 0 .text 00000101 0000000000000078 [0-9a-f]+ [0-9a-f]+ 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data.rel.ro 00100200 [0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 2**9 + CONTENTS, ALLOC, LOAD, DATA +#... + 3 .rela.dyn 00000018 [0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 2**3 +#pass + diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-data-only.ld b/ld/testsuite/ld-aarch64/morello-sec-round-data-only.ld new file mode 100644 index 0000000000000000000000000000000000000000..87613d0f3b3fa1321c26160b8cf421c541ba004d --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-data-only.ld @@ -0,0 +1,17 @@ +SECTIONS { + . = SIZEOF_HEADERS; + .text : + { + *(.text) + } + .data.rel.ro : + { + __data_rel_ro_startsym = .; + *(.data.rel.ro) + } + .got : { *(.got) } + .iplt : { *(.iplt) } + .data : { *(.data) } + .rela.dyn : { *(.rela.dyn) } + .interp : { *(.interp) } +} diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-data-only.s b/ld/testsuite/ld-aarch64/morello-sec-round-data-only.s new file mode 100644 index 0000000000000000000000000000000000000000..0082c5701638506d3dbc07dc1f7febe8052e1985 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-data-only.s @@ -0,0 +1,17 @@ +.text +.zero 0x100 +.byte 1 +.section .data.rel.ro,"aw",@progbits +# We use a linker defined symbol that points into .data.rel.ro so that the +# linker will need to ensure this section is aligned and padded so that its +# bounds can be precisely represented by a capability. This is done in the +# linker script. +# +# Here we ensure that the size of the section is large enough that it will need +# padding. +.zero 0x100001 +.section .got,"aw",@progbits +.capinit __data_rel_ro_startsym +.xword 0 +.xword 0 + diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.d b/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.d new file mode 100644 index 0000000000000000000000000000000000000000..1848e83ec1243e4446282214e0fa51ec0adda206 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.d @@ -0,0 +1,41 @@ +# Checking that we include RELRO sections in PCC bounds. +# +# Check is done using the fragment values to show what the size of the PCC +# bounds is given as, and we reorder sections so that at least one RELRO +# section is ater all READONLY ALLOC section. +# +# Test only works if we have relro, so is unsupported bare-metal. +# +# Test is implemented by ensuring that the .data.rel.ro is the last section in +# the RELRO segment, and that .data is directly after it. This is ensured with +# a linker script. If we don't include RELRO in our PCC bounds then +# .data.rel.ro will not be within the range of the `obj` capability (since the +# .data.rel.ro section itself is marked as being writeable). +# +#target: [check_relro_support] +#source: morello-sec-round-include-relro.s +#as: -march=morello+c64 +#ld: -static -pie -z relro -z now -T morello-sec-round-include-relro.ld +#objdump: -j .data -j .text -j .data.rel.ro -DR + +.*: file format .* + + +Disassembly of section .text: + +00000000000001a0 <obj>: +#... + +Disassembly of section .data.rel.ro: + +0000000000010ff0 <data_relro_start>: +#... + +Disassembly of section .data: + +0000000000011000 <data_start>: + 11000: 000001a0 udf #416 + 11000: R_MORELLO_RELATIVE *ABS* + 11004: 00000000 udf #0 + 11008: 00010e60 .inst 0x00010e60 ; undefined + 1100c: 04000000 add z0.b, p0/m, z0.b, z0.b diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.ld b/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.ld new file mode 100644 index 0000000000000000000000000000000000000000..f44b5e920082a0b3601819cf7114b1a6dcee6b62 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.ld @@ -0,0 +1,12 @@ +SECTIONS { + . = SEGMENT_START("text-segment", SIZEOF_HEADERS); + .text : { *(.text) } + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + .data.rel.ro : { *(.data.rel.ro*) } + . = DATA_SEGMENT_RELRO_END (0, .); + .data : { *(.data) } + . = DATA_SEGMENT_END (.); +} + diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.s b/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.s new file mode 100644 index 0000000000000000000000000000000000000000..afba11eb609ec43fdba637c6cd75834918cb65f7 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-include-relro.s @@ -0,0 +1,17 @@ +.arch morello+c64 + + .section .data.rel.ro.local,"aw",@progbits +data_relro_start: + .asciz "Hello there ;-)" + + .data +data_start: + .chericap obj + .text + +obj: + + ldr c0, [c0] + ldr c0, [c0] + ldr c0, [c0] + ldr c0, [c0] diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-pcc-needed.d b/ld/testsuite/ld-aarch64/morello-sec-round-pcc-needed.d new file mode 100644 index 0000000000000000000000000000000000000000..4aebfccce9a615f204c81a09b09c75cc25355c61 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-pcc-needed.d @@ -0,0 +1,14 @@ +#as: -march=morello+c64 +#ld: -static +#objdump: -x +#... +Sections: +Idx Name Size VMA LMA File off Algn +#... + 0 .text 00003000 [0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 2**3 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .alt 00003000 [0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE +#pass + + diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-pcc-needed.s b/ld/testsuite/ld-aarch64/morello-sec-round-pcc-needed.s new file mode 100644 index 0000000000000000000000000000000000000000..1d616778df4e6c04d4d6157689cbe89589a0da90 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-pcc-needed.s @@ -0,0 +1,10 @@ +# Here we want to make sure that if we have a set of sections which do not need +# to be adjusted for morello precise bounds, but the total PCC range *does* +# need to be adjusted for Morello precise bounds then we adjust that PCC range. +.text + .global _start +_start: + ret + .zero 0x2ffc +.section .alt,"ax",@progbits + .zero 0x3000 diff --git a/ld/testsuite/ld-aarch64/morello-sec-round.d b/ld/testsuite/ld-aarch64/morello-sec-round.d index b553a604acd92a2b0c5e151546e2c19a04101f70..0b8a9b982e06f75688245917357bb5c4822bb0e1 100644 --- a/ld/testsuite/ld-aarch64/morello-sec-round.d +++ b/ld/testsuite/ld-aarch64/morello-sec-round.d @@ -5,7 +5,7 @@ Sections: Idx Name Size VMA LMA File off Algn #... - 1 .text_sec 00020004 ...........20000 [0-9a-f]+ [0-9a-f]+ 2**17 + 1 .text_sec 00020040 ...........20000 [0-9a-f]+ [0-9a-f]+ 2**17 CONTENTS, ALLOC, LOAD, READONLY, CODE 2 ..* [0-9a-f]+ ...........40040 [0-9a-f]+ [0-9a-f]+ .* #pass diff --git a/ld/testsuite/ld-aarch64/morello-sizeless-global-syms.d b/ld/testsuite/ld-aarch64/morello-sizeless-global-syms.d index 629cc44cad520e9212ab96740d7c78fdde3063fc..89c7963b789dba65b7bb00c07c7197bb5759a8d9 100644 --- a/ld/testsuite/ld-aarch64/morello-sizeless-global-syms.d +++ b/ld/testsuite/ld-aarch64/morello-sizeless-global-syms.d @@ -9,21 +9,21 @@ Disassembly of section .data:
[0-9a-f]+ <ptr3>: - [0-9a-f]+: 00010440.* + [0-9a-f]+: 00010450.* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000.* [0-9a-f]+: 00000000.* [0-9a-f]+: 02000000.*
[0-9a-f]+ <ptr2>: - [0-9a-f]+: 00010444.* + [0-9a-f]+: 00010454.* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000.* [0-9a-f]+: 00000000.* [0-9a-f]+: 02000000.*
[0-9a-f]+ <ptr1>: - [0-9a-f]+: 00010448.* + [0-9a-f]+: 00010458.* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000.* [0-9a-f]+: 00000000.* @@ -31,7 +31,7 @@ Disassembly of section .data:
Disassembly of section .bss:
-0000000000010440 <baz>: +0000000000010450 <baz>: [0-9a-f]+: 00000000.*
[0-9a-f]+ <bar>: diff --git a/ld/testsuite/ld-aarch64/morello-sizeless-got-syms.d b/ld/testsuite/ld-aarch64/morello-sizeless-got-syms.d index b28fca9f70d42fa1dea1a9ab92c57ccc324426ee..82131d11dde1995214bff673c46d925facd2650b 100644 --- a/ld/testsuite/ld-aarch64/morello-sizeless-got-syms.d +++ b/ld/testsuite/ld-aarch64/morello-sizeless-got-syms.d @@ -9,17 +9,17 @@ Disassembly of section .text:
[0-9a-f]+ <get_foo>: [0-9a-f]+: 90800080 adrp c0, 10000 .* - [0-9a-f]+: c240d800 ldr c0, [c0, #864] + [0-9a-f]+: c240dc00 ldr c0, [c0, #880] [0-9a-f]+: c2c253c0 ret c30
[0-9a-f]+ <get_bar>: [0-9a-f]+: 90800080 adrp c0, 10000 .* - [0-9a-f]+: c240dc00 ldr c0, [c0, #880] + [0-9a-f]+: c240e000 ldr c0, [c0, #896] [0-9a-f]+: c2c253c0 ret c30
[0-9a-f]+ <get_baz>: [0-9a-f]+: 90800080 adrp c0, 10000 .* - [0-9a-f]+: c240d400 ldr c0, [c0, #848] + [0-9a-f]+: c240d800 ldr c0, [c0, #864] [0-9a-f]+: c2c253c0 ret c30
[0-9a-f]+ <_start>: @@ -27,22 +27,22 @@ Disassembly of section .text:
Disassembly of section .got:
-0000000000010340 <.got>: +0000000000010350 <.got>: [0-9a-f]+: .* [0-9a-f]+: .* [0-9a-f]+: .* [0-9a-f]+: .* - [0-9a-f]+: 000103b0 .* + [0-9a-f]+: 000103c0 .* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000 .* [0-9a-f]+: 00000000 .* [0-9a-f]+: 02000000 .* - [0-9a-f]+: 000103b8 .* + [0-9a-f]+: 000103c8 .* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000 .* [0-9a-f]+: 00000000 .* [0-9a-f]+: 02000000 .* - [0-9a-f]+: 000103b4 .* + [0-9a-f]+: 000103c4 .* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000 .* [0-9a-f]+: 00000000 .* @@ -50,7 +50,7 @@ Disassembly of section .got:
Disassembly of section .bss:
-00000000000103b0 <baz>: +00000000000103c0 <baz>: [0-9a-f]+: 00000000 .*
[0-9a-f]+ <bar>: diff --git a/ld/testsuite/ld-aarch64/morello-sizeless-local-syms.d b/ld/testsuite/ld-aarch64/morello-sizeless-local-syms.d index 5439d54b66c0c786087c25a6a74fb27630b8eb22..2f74b7a643ded8078e206daf81b40997705926ba 100644 --- a/ld/testsuite/ld-aarch64/morello-sizeless-local-syms.d +++ b/ld/testsuite/ld-aarch64/morello-sizeless-local-syms.d @@ -9,21 +9,21 @@ Disassembly of section .data:
[0-9a-f]+ <ptr3>: - [0-9a-f]+: 00010440.* + [0-9a-f]+: 00010450.* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000.* [0-9a-f]+: 00000000.* [0-9a-f]+: 02000000.*
[0-9a-f]+ <ptr2>: - [0-9a-f]+: 00010444.* + [0-9a-f]+: 00010454.* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000.* [0-9a-f]+: 00000000.* [0-9a-f]+: 02000000.*
[0-9a-f]+ <ptr1>: - [0-9a-f]+: 00010448.* + [0-9a-f]+: 00010458.* [0-9a-f]+: R_MORELLO_RELATIVE *ABS* [0-9a-f]+: 00000000.* [0-9a-f]+: 00000000.* @@ -31,7 +31,7 @@ Disassembly of section .data:
Disassembly of section .bss:
-0000000000010440 <baz>: +0000000000010450 <baz>: [0-9a-f]+: 00000000.*
[0-9a-f]+ <bar>: diff --git a/ld/testsuite/ld-aarch64/morello-stubs-static.d b/ld/testsuite/ld-aarch64/morello-stubs-static.d index 53269ac9d2dc4356055c39ef57a585d2c293f7bc..d7627dcbf0571dcb9c8dc5b826385a61941821f0 100644 --- a/ld/testsuite/ld-aarch64/morello-stubs-static.d +++ b/ld/testsuite/ld-aarch64/morello-stubs-static.d @@ -8,29 +8,29 @@
Disassembly of section .text_low:
-00000000000000b0 <foo>: - b0: 9400000c bl e0 <__baz_a64c64_veneer> - b4: c2c1d041 mov c1, c2 - b8: d65f03c0 ret - -00000000000000bc <baz2>: - bc: 14000009 b e0 <__baz_a64c64_veneer> - c0: c2c253c0 ret c30 - c4: 00000000 .* - c8: 1400000a b f0 <__baz_a64c64_veneer+0x10> - cc: d503201f nop - -00000000000000d0 <__baz_veneer>: - d0: 90878010 adrp c16, f000000 <baz3> - d4: 02002610 add c16, c16, #0x9 - d8: c2c21200 br c16 - dc: 00000000 .* - -00000000000000e0 <__baz_a64c64_veneer>: - e0: c2c273e0 bx #4 - e4: 90878010 adrp c16, f000000 <baz3> - e8: 02002610 add c16, c16, #0x9 - ec: c2c21200 br c16 +0000000000010000 <foo>: + 10000: 9400000c bl 10030 <__baz_a64c64_veneer> + 10004: c2c1d041 mov c1, c2 + 10008: d65f03c0 ret + +000000000001000c <baz2>: + 1000c: 14000009 b 10030 <__baz_a64c64_veneer> + 10010: c2c253c0 ret c30 + 10014: 00000000 .* + 10018: 1400000a b 10040 <__baz_a64c64_veneer+0x10> + 1001c: d503201f nop + +0000000000010020 <__baz_veneer>: + 10020: 90877f90 adrp c16, f000000 <baz3> + 10024: 02002610 add c16, c16, #0x9 + 10028: c2c21200 br c16 + 1002c: 00000000 .* + +0000000000010030 <__baz_a64c64_veneer>: + 10030: c2c273e0 bx #4 + 10034: 90877f90 adrp c16, f000000 <baz3> + 10038: 02002610 add c16, c16, #0x9 + 1003c: c2c21200 br c16
Disassembly of section .text_high:
@@ -45,13 +45,13 @@ Disassembly of section .text_high: f000014: d503201f nop
000000000f000018 <__foo_c64a64_veneer>: - f000018: 90f88010 adrp c16, 100000000 <___veneer+0xf0ffffd8> - f00001c: 0202c210 add c16, c16, #0xb0 + f000018: 90f88090 adrp c16, 100010000 <___veneer+0xf100ffd8> + f00001c: 02000210 add c16, c16, #0x0 f000020: c2c21200 br c16 f000024: 00000000 .*
000000000f000028 <___veneer>: - f000028: 90f88010 adrp x16, 0 <foo-0xb0> - f00002c: 9102c210 add x16, x16, #0xb0 + f000028: 90f88090 adrp x16, 10000 <foo> + f00002c: 91000210 add x16, x16, #0x0 f000030: d61f0200 br x16 ... diff --git a/ld/testsuite/ld-aarch64/morello-stubs.d b/ld/testsuite/ld-aarch64/morello-stubs.d index d73bdf6ad90b924d953091422cafa4d4c7cdafd6..d81e58539b5040cc4ec9f25ab04f923da05452a4 100644 --- a/ld/testsuite/ld-aarch64/morello-stubs.d +++ b/ld/testsuite/ld-aarch64/morello-stubs.d @@ -21,7 +21,7 @@ Disassembly of section .text_low: .*: d503201f nop
.* <__baz_veneer>: -.*: 90078010 adrp x16, [0-9a-f]+ <baz3> +.*: 900..... adrp x16, [0-9a-f]+ <baz3> .*: 910...10 add x16, x16, #0x[0-9a-f]+ .*: d61f0200 br x16 ... @@ -39,13 +39,13 @@ Disassembly of section .text_high: .*: d503201f nop
.* <__foo_c64a64_veneer>: -.*: 90f88010 adrp c16, [0-9a-f]+ <.*> +.*: 90f..... adrp c16, [0-9a-f]+ <.*> .*: 020...10 add c16, c16, #0x[0-9a-f]+ .*: c2c21200 br c16 .*: 00000000 .*
.* <___veneer>: -.*: 90f88010 adrp x16, .* <.*> +.*: 90f..... adrp x16, .* <.*> .*: 910...10 add x16, x16, #0x[0-9a-f]+ .*: d61f0200 br x16 ...
Before this change we would ensure the ability for precise bounds on any section which had a linker defined symbol pointing in it *unless* that linker defined symbol looked like a section starting symbol.
In that case we would adjust the *next* section if the current section had no padding between this one and the next.
I believe this was a mistake. The testcase we add here is a simple case of having a `__data_relro_start` symbol in the .data.rel.ro section, and that would not ensure that the .data.rel.ro section were precisely padded. The change we make here is to perform padding for precise bounds on all sections with linker defined symbols in them *and* the next section if there is no padding between this and the next section.
This is a huge overfit and we do it for the reason described in the existing comment (that we have no information on the offset of this symbol within the output section).
In the future we may want to remove this padding for linker script defined symbols which do not look like section start symbols. We would do this in conjunction with changing the bounds we put on such linker script defined symbols. This would be for another patch.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 9bec87163d30d8493b243f0cae69f6c7ab0b7fd6..c8311e9095d10bdd669de1c595d726f619475d14 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -4958,26 +4958,21 @@ elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info, { const char *name = h->root.root.string; size_t len = strlen (name); + asection *altos = NULL; + bfd_vma value = os->vma + os->size;
if (len > 8 && name[0] == '_' && name[1] == '_' && (!strncmp (name + 2, "start_", 6) - || !strcmp (name + len - 6, "_start"))) - { - bfd_vma value = os->vma + os->size; - - os = bfd_sections_find_if (info->output_bfd, - section_start_symbol, &value); - - if (os != NULL) - ensure_precisely_bounded_section (os, htab, - c64_pad_section); - } + || !strcmp (name + len - 6, "_start")) + && ((altos = bfd_sections_find_if + (info->output_bfd, section_start_symbol, &value)) + != NULL)) + ensure_precisely_bounded_section (altos, htab, + c64_pad_section); /* XXX We're overfitting here because the offset of H within the output section is not yet resolved and ldscript defined symbols do not have input section information. */ - else - ensure_precisely_bounded_section (os, htab, - c64_pad_section); + ensure_precisely_bounded_section (os, htab, c64_pad_section); } } } diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 837b9df877276029cf8d036d75de02f70e224bc0..721d16e09bc1392fbc5e7920a080962bb4b374a2 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -268,6 +268,7 @@ run_dump_test_lp64 "morello-sec-round-pcc-needed" run_dump_test_lp64 "morello-sec-round-data-only" run_dump_test_lp64 "morello-sec-round-include-relro" run_dump_test_lp64 "morello-pcc-bounds-include-readonly" +run_dump_test_lp64 "morello-sec-round-choose-linker-syms" run_dump_test_lp64 "morello-tlsdesc" run_dump_test_lp64 "morello-tlsdesc-static" run_dump_test_lp64 "morello-tlsdesc-staticpie" diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.d b/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.d new file mode 100644 index 0000000000000000000000000000000000000000..e13aee24916e857dc33c69db0b3f94dd3bbb9c81 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.d @@ -0,0 +1,23 @@ +# Checking that we include RELRO sections in PCC bounds. +# +# Check is done using the fragment values to show what the size of the PCC +# bounds is given as, and we reorder sections so that at least one RELRO +# section is ater all READONLY ALLOC section. +# +# Test only works if we have relro, so is unsupported bare-metal. +# +# Test is implemented by ensuring that the .data.rel.ro is the last section in +# the RELRO segment, and that .data is directly after it. This is ensured with +# a linker script. If we don't include RELRO in our PCC bounds then +# .data.rel.ro will not be within the range of the `obj` capability (since the +# .data.rel.ro section itself is marked as being writeable). +# +#source: morello-sec-round-choose-linker-syms.s +#as: -march=morello+c64 +#ld: -static -T morello-sec-round-choose-linker-syms.ld +#objdump: --section-headers -j .data.rel.ro + +.*: file format .* +#... +.* .data.rel.ro 00010020 [0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 2**5 +#pass diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.ld b/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.ld new file mode 100644 index 0000000000000000000000000000000000000000..20529f8b49500a1947bfa8dfa16c7af71fd78965 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.ld @@ -0,0 +1,12 @@ +SECTIONS { + . = SEGMENT_START("text-segment", SIZEOF_HEADERS); + .text : { *(.text) } + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + .data.rel.ro : { + __data_relro_start = .; + *(.data.rel.ro*) + } + .data : { *(.data) } +} + diff --git a/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.s b/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.s new file mode 100644 index 0000000000000000000000000000000000000000..bc91e90c2ff1c7e2f0d5e90c103c3bf50789c8ab --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-round-choose-linker-syms.s @@ -0,0 +1,16 @@ +.arch morello+c64 + + .section .data.rel.ro.local,"aw",@progbits + .asciz "Hello there ;-)" + .zero 0x10000 + + .data +data_start: + .chericap __data_relro_start + .text + +obj: + + adrp c0, data_start + add c0, c0, :lo12:data_start + ldr c0, [c0]
gnu-morello@op-lists.linaro.org