mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-12-15 13:48:26 +08:00
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.
This commit is contained in:
committed by
Christophe Lyon
parent
046a94c18c
commit
f87eaf8ff3
@@ -352,6 +352,7 @@ coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real
|
||||
return &arm64_reloc_howto_branch26;
|
||||
case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
|
||||
case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
|
||||
case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
|
||||
return &arm64_reloc_howto_page21;
|
||||
case BFD_RELOC_AARCH64_TSTBR14:
|
||||
return &arm64_reloc_howto_branch14;
|
||||
@@ -364,6 +365,7 @@ coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real
|
||||
case BFD_RELOC_AARCH64_LDST32_LO12:
|
||||
case BFD_RELOC_AARCH64_LDST64_LO12:
|
||||
case BFD_RELOC_AARCH64_LDST128_LO12:
|
||||
case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
|
||||
return &arm64_reloc_howto_pgoff12l;
|
||||
case BFD_RELOC_AARCH64_BRANCH19:
|
||||
return &arm64_reloc_howto_branch19;
|
||||
@@ -761,6 +763,35 @@ coff_pe_aarch64_relocate_section (bfd *output_bfd,
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_REL_ARM64_REL32:
|
||||
{
|
||||
uint64_t cur_vma;
|
||||
int64_t addend, val;
|
||||
|
||||
addend = bfd_getl32 (contents + rel->r_vaddr);
|
||||
|
||||
if (addend & 0x80000000)
|
||||
addend |= 0xffffffff00000000;
|
||||
|
||||
dest_vma += addend;
|
||||
cur_vma = input_section->output_section->vma
|
||||
+ input_section->output_offset
|
||||
+ rel->r_vaddr;
|
||||
|
||||
val = dest_vma - cur_vma;
|
||||
|
||||
if (val > 0xffffffff || val < -0x100000000)
|
||||
(*info->callbacks->reloc_overflow)
|
||||
(info, h ? &h->root : NULL, syms[symndx]._n._n_name,
|
||||
"IMAGE_REL_ARM64_REL32", addend, input_bfd,
|
||||
input_section, rel->r_vaddr - input_section->vma);
|
||||
|
||||
bfd_putl32 (val, contents + rel->r_vaddr);
|
||||
rel->r_type = IMAGE_REL_ARM64_ABSOLUTE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_REL_ARM64_PAGEOFFSET_12L:
|
||||
{
|
||||
uint32_t opcode, val;
|
||||
|
||||
13
gas/write.c
13
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");
|
||||
|
||||
Reference in New Issue
Block a user