aboutsummaryrefslogtreecommitdiff
path: root/gas/write.c
diff options
context:
space:
mode:
authorZac Walker <zacwalker@microsoft.com>2024-01-31 20:15:48 +0100
committerChristophe Lyon <christophe.lyon@linaro.org>2024-02-19 13:02:00 +0000
commitf87eaf8ff3995a5888c6dc4996a20c770e6bcd36 (patch)
treecdbae78664071dc1196fae6d6c9ed62f0db99619 /gas/write.c
parent046a94c18c543793ab4a8f3f9b2cb0d1280e7b41 (diff)
downloadgdb-f87eaf8ff3995a5888c6dc4996a20c770e6bcd36.zip
gdb-f87eaf8ff3995a5888c6dc4996a20c770e6bcd36.tar.gz
gdb-f87eaf8ff3995a5888c6dc4996a20c770e6bcd36.tar.bz2
aarch64: Add new relocations and limit COFF AArch64 relocation offsets
The patch adds support for the IMAGE_REL_ARM64_REL32 coff relocation type. This is needed for 32-bit relative address. It also adds a check for relocation offsets over 21 bits. Offsets inside coff files are stored in instruction code. In the case of ADRP the actual value is stored, not a downshifted page offset. This means values over 21 bits would otherwise be truncated. Finally it adds a mapping for BFD_RELOC_AARCH64_ADR_GOT_PAGE and BFD_RELOC_AARCH64_LD64_GOT_LO12_NC that were previously skipped. ChangeLog: * bfd/coff-aarch64.c (coff_aarch64_reloc_type_lookup): Add BFD_RELOC_AARCH64_ADR_GOT_PAGE, BFD_RELOC_AARCH64_LD64_GOT_LO12_NC and IMAGE_REL_ARM64_REL32 relocations. (coff_pe_aarch64_relocate_section): Likewise. * gas/write.c (adjust_reloc_syms): COFF AArch64 relocation offsets need to be limited to 21bits (defined): Likewise.
Diffstat (limited to 'gas/write.c')
-rw-r--r--gas/write.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/gas/write.c b/gas/write.c
index 98ead0b..18cf18f 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -779,6 +779,7 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
{
segment_info_type *seginfo = seg_info (sec);
fixS *fixp;
+ valueT val;
if (seginfo == NULL)
return;
@@ -890,10 +891,20 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
if ((symsec->flags & SEC_THREAD_LOCAL) != 0)
continue;
+ val = S_GET_VALUE (sym);
+
+#if defined(TC_AARCH64) && defined(OBJ_COFF)
+ /* coff aarch64 relocation offsets need to be limited to 21bits.
+ This is because addend may need to be stored in an ADRP instruction.
+ In this case the addend cannot be stored down shifted otherwise rounding errors occur. */
+ if ((val + 0x100000) > 0x1fffff)
+ continue;
+#endif
+
/* We refetch the segment when calling section_symbol, rather
than using symsec, because S_GET_VALUE may wind up changing
the section when it calls resolve_symbol_value. */
- fixp->fx_offset += S_GET_VALUE (sym);
+ fixp->fx_offset += val;
fixp->fx_addsy = section_symbol (S_GET_SEGMENT (sym));
#ifdef DEBUG5
fprintf (stderr, "\nadjusted fixup:\n");