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;
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;
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;
{
segment_info_type *seginfo = seg_info (sec);
fixS *fixp;
+ valueT val;
if (seginfo == NULL)
return;
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");