diff options
author | Zac Walker <zacwalker@microsoft.com> | 2024-01-31 20:15:48 +0100 |
---|---|---|
committer | Christophe Lyon <christophe.lyon@linaro.org> | 2024-02-19 13:02:00 +0000 |
commit | f87eaf8ff3995a5888c6dc4996a20c770e6bcd36 (patch) | |
tree | cdbae78664071dc1196fae6d6c9ed62f0db99619 /gas | |
parent | 046a94c18c543793ab4a8f3f9b2cb0d1280e7b41 (diff) | |
download | gdb-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')
-rw-r--r-- | gas/write.c | 13 |
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"); |