Hi,
This patch deals with the interaction between the code that attempts to make bounds precise (for both the PCC bounds and for some individual sections) and the code that adds stubs (e.g. long-branch veneers and interworking stubs) in the AArch64 backend.
We aim to set precise bounds for the PCC span and some individual sections in elfNN_c64_resize_sections. However, it transpires that elfNN_aarch64_size_stubs can change the layout in ways that extend sections that should be covered under the PCC span outside of the bounds set in elfNN_c64_resize_sections. The introduction of stubs can also change (even reduce) the amount of padding required to make the bounds on any given section precise.
To address this problem, we move the core logic from elfNN_c64_size_sections into a new function, c64_resize_sections, that is safe to be called repeatedly. Similarly, we move the core logic from elfNN_aarch64_size_stubs into a new function aarch64_size_stubs which again can be called repeatedly.
We then adjust elfNN_aarch64_size_stubs to call aarch64_size_stubs and c64_resize_sections in a loop, stopping when c64_resize_sections no longer makes any changes to the layout.
An important observation made above is that the introduction of stubs can change the amount of padding needed to make bounds precise. Likewise, introducing padding can in theory necessitate the introduction of stubs (e.g. if the change in layout necessitates a long-branch veneer). This is why we run the resizing/stubs code in a loop until no further changes are necessary.
Since the amount of padding needed to achieve precise bounds for a section can change (indeed reduce) with the introduction of stubs, we need a mechanism to update the amount of padding applied to a section in a subsequent iteration of c64_resize_sections. We achieve this by introducing a new interface in ld/emultempl/aarch64elf.em. We have the functions:
static void c64_set_section_padding (asection *osec, bfd_vma padding, void **cookie);
static void c64_get_section_padding (void *cookie);
Here, the "cookie" value is, to consumers of this interface (i.e. bfd/elfnn-aarch64.c), an opaque handle used to refer to the padding that was introduced for a given section. The consuming code then passes back the cookie to later query the amount of padding already installed or to update the amount of padding.
Internally, within aarch64elf.em, the "cookie" is just a pointer to the node in the ldexp tree containing the integer amount of padding inserted.
In the AArch64 ELF backend, we then maintain a (lazily-allocated) mapping between output sections and cookies in order to be able to update the padding we installed in subsequent iterations of c64_resize_sections.
While working on this patch, an edge case became apparent: the case where pcc_high_sec requires precise bounds (i.e. where we call ensure_precisely_bounded_section on pcc_high_sec). As it stands, in this case, the code to ensure precise PCC bounds may in fact make the bounds on pcc_high_sec itself no longer representable (even if we previously ensured this by calling ensure_precisely_bounded_section). In general, it is not always possible to choose an amount of padding to add to the end of pcc_high_sec to make both pcc_high_sec and the PCC span itself have precise bounds (without introducing an unreasonably large alignment requirement on pcc_high_sec).
To handle the edge case above, we decouple these two problems by adding a separate amount of padding *after* pcc_high_sec to make the PCC bounds precise. If pcc_high_sec is required to have precise bounds, then that can be done in the usual way by adding padding to pcc_high_sec in ensure_precisely_bounded_section. The new mechanism for adding padding after an output section is implemented in aarch64elf.em:c64_pad_after_section.
To avoid having to add yet another mechanism to update the padding *after* pcc_high_sec, we avoid adding this padding until all other resizing / bounds-setting work is done. This is not possible for individual sections since padding introduced there may have a knock-on effect requiring further work, but we believe this isn't the case for the padding added after pcc_high_sec to make the PCC bounds precise.
This patch also reveals a pre-existing issue whereby we end up calling ensure_precisely_bounded_section on the *ABS* section. Without a further change to prevent this, this can lead to a null pointer dereference in ensure_precisely_bounded_section, since the "owner" field on the *ABS* pointer is NULL, and we use this field to obtain a pointer to the output BFD in the new c64_get_section_padding_info function.
Of course, it doesn't make sense for ensure_precisely_bounded_section to be called on the *ABS* section in the first place. This can happen when there are relocations against ldscript-defined symbols which are defined at the top level of the ldscript (i.e. not in a particular output section). Those symbols initially have their output section set to the *ABS* section. Later, we resolve such symbols to their correct output section in ldexp_finalize_syms, but the code in c64_resize_sections is running in ldemul_after_allocation, which comes before the call to ldexp_finalize_syms in the lang_process flow.
For now, we just skip such symbols when looking for sections that need precise bounds in c64_resize_sections, but this issue will later need fixing properly. We choose to avoid fixing the pre-existing issue in this patch to avoid over-complicating an already complex change.
Tested on aarch64-none-elf and aarch64-none-linux-gnu, OK for the Morello branch?
Thanks, Alex
OK for the Morello branch.
Thanks!
On 10/4/22 17:31, Alex Coplan wrote:
Hi,
This patch deals with the interaction between the code that attempts to make bounds precise (for both the PCC bounds and for some individual sections) and the code that adds stubs (e.g. long-branch veneers and interworking stubs) in the AArch64 backend.
We aim to set precise bounds for the PCC span and some individual sections in elfNN_c64_resize_sections. However, it transpires that elfNN_aarch64_size_stubs can change the layout in ways that extend sections that should be covered under the PCC span outside of the bounds set in elfNN_c64_resize_sections. The introduction of stubs can also change (even reduce) the amount of padding required to make the bounds on any given section precise.
To address this problem, we move the core logic from elfNN_c64_size_sections into a new function, c64_resize_sections, that is safe to be called repeatedly. Similarly, we move the core logic from elfNN_aarch64_size_stubs into a new function aarch64_size_stubs which again can be called repeatedly.
We then adjust elfNN_aarch64_size_stubs to call aarch64_size_stubs and c64_resize_sections in a loop, stopping when c64_resize_sections no longer makes any changes to the layout.
An important observation made above is that the introduction of stubs can change the amount of padding needed to make bounds precise. Likewise, introducing padding can in theory necessitate the introduction of stubs (e.g. if the change in layout necessitates a long-branch veneer). This is why we run the resizing/stubs code in a loop until no further changes are necessary.
Since the amount of padding needed to achieve precise bounds for a section can change (indeed reduce) with the introduction of stubs, we need a mechanism to update the amount of padding applied to a section in a subsequent iteration of c64_resize_sections. We achieve this by introducing a new interface in ld/emultempl/aarch64elf.em. We have the functions:
static void c64_set_section_padding (asection *osec, bfd_vma padding, void **cookie);
static void c64_get_section_padding (void *cookie);
Here, the "cookie" value is, to consumers of this interface (i.e. bfd/elfnn-aarch64.c), an opaque handle used to refer to the padding that was introduced for a given section. The consuming code then passes back the cookie to later query the amount of padding already installed or to update the amount of padding.
Internally, within aarch64elf.em, the "cookie" is just a pointer to the node in the ldexp tree containing the integer amount of padding inserted.
In the AArch64 ELF backend, we then maintain a (lazily-allocated) mapping between output sections and cookies in order to be able to update the padding we installed in subsequent iterations of c64_resize_sections.
While working on this patch, an edge case became apparent: the case where pcc_high_sec requires precise bounds (i.e. where we call ensure_precisely_bounded_section on pcc_high_sec). As it stands, in this case, the code to ensure precise PCC bounds may in fact make the bounds on pcc_high_sec itself no longer representable (even if we previously ensured this by calling ensure_precisely_bounded_section). In general, it is not always possible to choose an amount of padding to add to the end of pcc_high_sec to make both pcc_high_sec and the PCC span itself have precise bounds (without introducing an unreasonably large alignment requirement on pcc_high_sec).
To handle the edge case above, we decouple these two problems by adding a separate amount of padding *after* pcc_high_sec to make the PCC bounds precise. If pcc_high_sec is required to have precise bounds, then that can be done in the usual way by adding padding to pcc_high_sec in ensure_precisely_bounded_section. The new mechanism for adding padding after an output section is implemented in aarch64elf.em:c64_pad_after_section.
To avoid having to add yet another mechanism to update the padding *after* pcc_high_sec, we avoid adding this padding until all other resizing / bounds-setting work is done. This is not possible for individual sections since padding introduced there may have a knock-on effect requiring further work, but we believe this isn't the case for the padding added after pcc_high_sec to make the PCC bounds precise.
This patch also reveals a pre-existing issue whereby we end up calling ensure_precisely_bounded_section on the *ABS* section. Without a further change to prevent this, this can lead to a null pointer dereference in ensure_precisely_bounded_section, since the "owner" field on the *ABS* pointer is NULL, and we use this field to obtain a pointer to the output BFD in the new c64_get_section_padding_info function.
Of course, it doesn't make sense for ensure_precisely_bounded_section to be called on the *ABS* section in the first place. This can happen when there are relocations against ldscript-defined symbols which are defined at the top level of the ldscript (i.e. not in a particular output section). Those symbols initially have their output section set to the *ABS* section. Later, we resolve such symbols to their correct output section in ldexp_finalize_syms, but the code in c64_resize_sections is running in ldemul_after_allocation, which comes before the call to ldexp_finalize_syms in the lang_process flow.
For now, we just skip such symbols when looking for sections that need precise bounds in c64_resize_sections, but this issue will later need fixing properly. We choose to avoid fixing the pre-existing issue in this patch to avoid over-complicating an already complex change.
Tested on aarch64-none-elf and aarch64-none-linux-gnu, OK for the Morello branch?
Thanks, Alex
gnu-morello@op-lists.linaro.org