summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorMatthew Malcomson <matthew.malcomson@arm.com>2022-01-18 10:54:15 +0000
committerMatthew Malcomson <matthew.malcomson@arm.com>2022-01-18 10:54:15 +0000
commitc50aec7291154cf4c97c2a011a8b656bcd8c46da (patch)
treeb7825ed56b39213cca8c7e00d29d39ef32d2cc0c /bfd
parentd6cf562af412479f6b86666450c8ef1109f4e4a0 (diff)
downloadbinutils-gdb-c50aec7291154cf4c97c2a011a8b656bcd8c46da.tar.gz
Bugfixes in MORELLO GOT relocations
Trying to link code against newlib with the current BFD Morello linker we get quite a lot of cases of the error below. "relocation truncated to fit: R_MORELLO_LD128_GOT_LO12_NC against symbol `<whatever>' defined in .text.<whatever> section in <filename>" This happens because the relocation gets transformed into a relocation pointing into the GOT in elfNN_aarch64_final_link_relocate, but the h->target_internal flag that indicates whether this is a C64 function symbol or not is then added to the *end* value rather than the value that is stored in the GOT. This then correctly falls foul of a check in _bfd_aarch64_elf_put_addend that ensures the value we get from this relocation is 8-byte aligned since it must be pointing to the start of a valid entry in the GOT. Here we ensure that this LSB is set on the value newly added into the GOT rather than on the offset pointing into the GOT. This both means that loading function symbols from the GOT will have the LSB correctly set (hence we stay in C64 mode when branching to this function as we should) and it means that the error about a misaligned GOT address is fixed. In this patch we also ensure that we add a dynamic relocation to initialise the correct GOT entry when we are resolving a MORELLO relocation that requires an entry in the GOT. This was already handled in the case of a global symbol, but had not been handled in the case of a local symbol. This is why we set `relative_reloc` to TRUE in if resolving a MORELLO GOT relocation against a static executable. In writing the testcase for this patch we found an existing bug to do with static relocations of this kind (of this kind meaning that are handled in this case statement). The assembler often chooses to create the relocation against the section symbol rather than the original symbol, and make up for that by giving the relocation an addend. The linker does not have any mechanism to create "symbol plus addend" entries in the GOT -- it indexes into the GOT based on the symbol only. Hence all relocations which are a section symbol plus addend end up pointing at one value in the GOT just containing the value of the symbol. We do not fix this existing bug, but just note it given that this is in the same area.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/elfnn-aarch64.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 9888ab5a489..45f0782db80 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -7077,6 +7077,9 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
off = symbol_got_offset (input_bfd, h, r_symndx);
base_got = globals->root.sgot;
+ bfd_boolean c64_reloc =
+ (bfd_r_type == BFD_RELOC_MORELLO_LD128_GOT_LO12_NC
+ || bfd_r_type == BFD_RELOC_MORELLO_ADR_GOT_PAGE);
if (base_got == NULL)
BFD_ASSERT (h != NULL);
@@ -7085,9 +7088,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
if (h != NULL)
{
bfd_vma addend = 0;
- bfd_boolean c64_reloc =
- (bfd_r_type == BFD_RELOC_MORELLO_LD128_GOT_LO12_NC
- || bfd_r_type == BFD_RELOC_MORELLO_ADR_GOT_PAGE);
/* If a symbol is not dynamic and is not undefined weak, bind it
locally and generate a RELATIVE relocation under PIC mode.
@@ -7108,7 +7108,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
&& !symbol_got_offset_mark_p (input_bfd, h, r_symndx))
relative_reloc = TRUE;
- value = aarch64_calculate_got_entry_vma (h, globals, info, value,
+ value = aarch64_calculate_got_entry_vma (h, globals, info,
+ value | h->target_internal,
output_bfd,
unresolved_reloc_p);
/* Record the GOT entry address which will be used when generating
@@ -7122,7 +7123,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
place, value,
addend, weak_undef_p);
- value |= h->target_internal;
}
else
{
@@ -7146,14 +7146,17 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
{
- bfd_put_64 (output_bfd, value, base_got->contents + off);
+ bfd_put_64 (output_bfd, value | sym->st_target_internal,
+ base_got->contents + off);
/* For local symbol, we have done absolute relocation in static
linking stage. While for shared library, we need to update the
content of GOT entry according to the shared object's runtime
base address. So, we need to generate a R_AARCH64_RELATIVE reloc
for dynamic linker. */
- if (bfd_link_pic (info))
+ if (bfd_link_pic (info)
+ || (!bfd_link_pic (info) && bfd_link_executable (info)
+ && c64_reloc))
relative_reloc = TRUE;
symbol_got_offset_mark (input_bfd, h, r_symndx);
@@ -7169,8 +7172,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
place, value,
addend, weak_undef_p);
-
- value |= sym->st_target_internal;
}
if (relative_reloc)
@@ -7184,8 +7185,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
/* For a C64 relative relocation, also add size and permissions into
the frag. */
- if (bfd_r_type == BFD_RELOC_MORELLO_LD128_GOT_LO12_NC
- || bfd_r_type == BFD_RELOC_MORELLO_ADR_GOT_PAGE)
+ if (c64_reloc)
{
bfd_reloc_status_type ret;