diff options
author | Mark Harmstone <mark@harmstone.com> | 2022-12-14 00:54:34 +0000 |
---|---|---|
committer | Mark Harmstone <mark@harmstone.com> | 2023-01-10 23:30:44 +0000 |
commit | b152649d51b52e4e82176fb835b8b91a9ca08ad4 (patch) | |
tree | 635d2ed5c44c70a897110aa4855a5dcf10ed1f63 /bfd | |
parent | 5093b5a5e7e3e51116207eb2dec81846140fc604 (diff) | |
download | gdb-b152649d51b52e4e82176fb835b8b91a9ca08ad4.zip gdb-b152649d51b52e4e82176fb835b8b91a9ca08ad4.tar.gz gdb-b152649d51b52e4e82176fb835b8b91a9ca08ad4.tar.bz2 |
Add pe-aarch64 relocations
This adds the remaining pe-aarch64 relocations, and gets them working.
It also brings in the constant directives from ELF, as otherwise .word
would be 2 rather than 4 bytes, and .xword and .dword wouldn't be
defined.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/coff-aarch64.c | 674 | ||||
-rw-r--r-- | bfd/config.bfd | 6 |
2 files changed, 660 insertions, 20 deletions
diff --git a/bfd/coff-aarch64.c b/bfd/coff-aarch64.c index 236cbb7..d6c48eb 100644 --- a/bfd/coff-aarch64.c +++ b/bfd/coff-aarch64.c @@ -39,59 +39,310 @@ #include "libcoff.h" +static bfd_reloc_status_type +coff_aarch64_addr64_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint64_t val = reloc_entry->addend; + + bfd_putl64 (val, data + reloc_entry->address); + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +coff_aarch64_addr32_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint64_t val; + + if ((int64_t) reloc_entry->addend > 0x7fffffff + || (int64_t) reloc_entry->addend < -0x7fffffff) + return bfd_reloc_overflow; + + val = reloc_entry->addend; + + bfd_putl32 ((uint32_t) val, data + reloc_entry->address); + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +coff_aarch64_branch26_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint32_t op; + int32_t param; + + op = bfd_getl32 (data + reloc_entry->address); + param = reloc_entry->addend; + + if (param > 0x7ffffff || param < -0x8000000) + return bfd_reloc_overflow; + + op &= 0xfc000000; + op |= (param >> 2) & 0x3ffffff; + + bfd_putl32 (op, data + reloc_entry->address); + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +coff_aarch64_rel21_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint32_t op; + int32_t param; + + op = bfd_getl32 (data + reloc_entry->address); + param = reloc_entry->addend; + + if (param > 0xfffff || param < -0x100000) + return bfd_reloc_overflow; + + op &= 0x9f00001f; + op |= (param & 0x1ffffc) << 3; + op |= (param & 0x3) << 29; + + bfd_putl32 (op, data + reloc_entry->address); + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +coff_aarch64_po12l_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint32_t op; + int32_t param; + uint8_t shift; + + op = bfd_getl32 (data + reloc_entry->address); + param = reloc_entry->addend & 0xfff; + + if ((op & 0xff800000) == 0x3d800000) + { + /* LDR / STR with q register */ + shift = 4; + } + else + { + /* top two bits represent how much addend should be shifted */ + shift = op >> 30; + } + + if (param & ((1 << shift) - 1)) + return bfd_reloc_overflow; + + param >>= shift; + + op &= 0xffc003ff; + op |= param << 10; + + bfd_putl32 (op, data + reloc_entry->address); + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +coff_aarch64_branch19_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint32_t op; + int32_t param; + + op = bfd_getl32 (data + reloc_entry->address); + param = reloc_entry->addend; + + if (param > 0xfffff || param < -0x100000) + return bfd_reloc_overflow; + + op &= 0xff00001f; + op |= ((param >> 2) & 0x7ffff) << 5; + + bfd_putl32 (op, data + reloc_entry->address); + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +coff_aarch64_branch14_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint32_t op; + int32_t param; + + op = bfd_getl32 (data + reloc_entry->address); + param = reloc_entry->addend; + + if (param > 0x7fff || param < -0x8000) + return bfd_reloc_overflow; + + op &= 0xfff8001f; + op |= ((param >> 2) & 0x3fff) << 5; + + bfd_putl32 (op, data + reloc_entry->address); + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +coff_aarch64_po12a_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint32_t op; + int32_t param; + + op = bfd_getl32 (data + reloc_entry->address); + param = reloc_entry->addend; + + op &= 0xffc003ff; + op |= (param & 0xfff) << 10; + + bfd_putl32 (op, data + reloc_entry->address); + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +coff_aarch64_addr32nb_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void *data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + uint64_t val; + + if ((int64_t) reloc_entry->addend > 0x7fffffff + || (int64_t) reloc_entry->addend < -0x7fffffff) + return bfd_reloc_overflow; + + val = reloc_entry->addend; + + bfd_putl32 ((uint32_t) val, data + reloc_entry->address); + + return bfd_reloc_ok; +} + /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ #define MINUS_ONE (~ (bfd_vma) 0) +static const reloc_howto_type arm64_reloc_howto_abs = HOWTO(IMAGE_REL_ARM64_ABSOLUTE, 0, 1, 0, false, 0, + complain_overflow_dont, + NULL, "IMAGE_REL_ARM64_ABSOLUTE", + false, 0, 0, false); + static const reloc_howto_type arm64_reloc_howto_64 = HOWTO(IMAGE_REL_ARM64_ADDR64, 0, 8, 64, false, 0, complain_overflow_bitfield, - NULL, "64", + coff_aarch64_addr64_reloc, "IMAGE_REL_ARM64_ADDR64", false, MINUS_ONE, MINUS_ONE, false); static const reloc_howto_type arm64_reloc_howto_32 = HOWTO (IMAGE_REL_ARM64_ADDR32, 0, 4, 32, false, 0, complain_overflow_bitfield, - NULL, "32", + coff_aarch64_addr32_reloc, "IMAGE_REL_ARM64_ADDR32", false, 0xffffffff, 0xffffffff, false); static const reloc_howto_type arm64_reloc_howto_32_pcrel = HOWTO (IMAGE_REL_ARM64_REL32, 0, 4, 32, true, 0, complain_overflow_bitfield, - NULL, "DISP32", + NULL, "IMAGE_REL_ARM64_REL32", false, 0xffffffff, 0xffffffff, true); static const reloc_howto_type arm64_reloc_howto_branch26 = HOWTO (IMAGE_REL_ARM64_BRANCH26, 0, 4, 26, true, 0, complain_overflow_bitfield, - NULL, "BRANCH26", + coff_aarch64_branch26_reloc, "IMAGE_REL_ARM64_BRANCH26", false, 0x03ffffff, 0x03ffffff, true); static const reloc_howto_type arm64_reloc_howto_page21 = HOWTO (IMAGE_REL_ARM64_PAGEBASE_REL21, 12, 4, 21, true, 0, complain_overflow_signed, - NULL, "PAGE21", + coff_aarch64_rel21_reloc, "IMAGE_REL_ARM64_PAGEBASE_REL21", false, 0x1fffff, 0x1fffff, false); static const reloc_howto_type arm64_reloc_howto_lo21 = HOWTO (IMAGE_REL_ARM64_REL21, 0, 4, 21, true, 0, complain_overflow_signed, - NULL, "LO21", + coff_aarch64_rel21_reloc, "IMAGE_REL_ARM64_REL21", false, 0x1fffff, 0x1fffff, true); -static const reloc_howto_type arm64_reloc_howto_pgoff12 = HOWTO (IMAGE_REL_ARM64_PAGEOFFSET_12L, 1, 4, 12, true, 0, +static const reloc_howto_type arm64_reloc_howto_pgoff12l = HOWTO (IMAGE_REL_ARM64_PAGEOFFSET_12L, 1, 4, 12, true, 0, complain_overflow_signed, - NULL, "PGOFF12", + coff_aarch64_po12l_reloc, "IMAGE_REL_ARM64_PAGEOFFSET_12L", false, 0xffe, 0xffe, true); static const reloc_howto_type arm64_reloc_howto_branch19 = HOWTO (IMAGE_REL_ARM64_BRANCH19, 2, 4, 19, true, 0, complain_overflow_signed, - NULL, "BRANCH19", + coff_aarch64_branch19_reloc, "IMAGE_REL_ARM64_BRANCH19", false, 0x7ffff, 0x7ffff, true); +static const reloc_howto_type arm64_reloc_howto_branch14 = HOWTO (IMAGE_REL_ARM64_BRANCH14, 2, 4, 14, true, 0, + complain_overflow_signed, + coff_aarch64_branch14_reloc, "IMAGE_REL_ARM64_BRANCH14", + false, 0x3fff, 0x3fff, true); + +static const reloc_howto_type arm64_reloc_howto_pgoff12a = HOWTO (IMAGE_REL_ARM64_PAGEOFFSET_12A, 2, 4, 12, true, 10, + complain_overflow_dont, + coff_aarch64_po12a_reloc, "IMAGE_REL_ARM64_PAGEOFFSET_12A", + false, 0x3ffc00, 0x3ffc00, false); + +static const reloc_howto_type arm64_reloc_howto_32nb = HOWTO (IMAGE_REL_ARM64_ADDR32NB, 0, 4, 32, false, 0, + complain_overflow_bitfield, + coff_aarch64_addr32nb_reloc, "IMAGE_REL_ARM64_ADDR32NB", + false, 0xffffffff, 0xffffffff, false); static const reloc_howto_type* const arm64_howto_table[] = { + &arm64_reloc_howto_abs, &arm64_reloc_howto_64, &arm64_reloc_howto_32, &arm64_reloc_howto_32_pcrel, &arm64_reloc_howto_branch26, &arm64_reloc_howto_page21, &arm64_reloc_howto_lo21, - &arm64_reloc_howto_pgoff12, - &arm64_reloc_howto_branch19 + &arm64_reloc_howto_pgoff12l, + &arm64_reloc_howto_branch19, + &arm64_reloc_howto_branch14, + &arm64_reloc_howto_pgoff12a, + &arm64_reloc_howto_32nb }; #ifndef NUM_ELEM @@ -118,13 +369,24 @@ coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real case BFD_RELOC_AARCH64_JUMP26: return &arm64_reloc_howto_branch26; case BFD_RELOC_AARCH64_ADR_HI21_PCREL: + case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL: return &arm64_reloc_howto_page21; + case BFD_RELOC_AARCH64_TSTBR14: + return &arm64_reloc_howto_branch14; case BFD_RELOC_AARCH64_ADR_LO21_PCREL: return &arm64_reloc_howto_lo21; + case BFD_RELOC_AARCH64_ADD_LO12: + return &arm64_reloc_howto_pgoff12a; + case BFD_RELOC_AARCH64_LDST8_LO12: case BFD_RELOC_AARCH64_LDST16_LO12: - return &arm64_reloc_howto_pgoff12; + case BFD_RELOC_AARCH64_LDST32_LO12: + case BFD_RELOC_AARCH64_LDST64_LO12: + case BFD_RELOC_AARCH64_LDST128_LO12: + return &arm64_reloc_howto_pgoff12l; case BFD_RELOC_AARCH64_BRANCH19: return &arm64_reloc_howto_branch19; + case BFD_RELOC_RVA: + return &arm64_reloc_howto_32nb; default: BFD_FAIL (); return NULL; @@ -155,6 +417,8 @@ coff_aarch64_rtype_lookup (unsigned int code) { switch (code) { + case IMAGE_REL_ARM64_ABSOLUTE: + return &arm64_reloc_howto_abs; case IMAGE_REL_ARM64_ADDR64: return &arm64_reloc_howto_64; case IMAGE_REL_ARM64_ADDR32: @@ -168,9 +432,15 @@ coff_aarch64_rtype_lookup (unsigned int code) case IMAGE_REL_ARM64_REL21: return &arm64_reloc_howto_lo21; case IMAGE_REL_ARM64_PAGEOFFSET_12L: - return &arm64_reloc_howto_pgoff12; + return &arm64_reloc_howto_pgoff12l; case IMAGE_REL_ARM64_BRANCH19: return &arm64_reloc_howto_branch19; + case IMAGE_REL_ARM64_BRANCH14: + return &arm64_reloc_howto_branch14; + case IMAGE_REL_ARM64_PAGEOFFSET_12A: + return &arm64_reloc_howto_pgoff12a; + case IMAGE_REL_ARM64_ADDR32NB: + return &arm64_reloc_howto_32nb; default: BFD_FAIL (); return NULL; @@ -188,6 +458,7 @@ coff_aarch64_rtype_lookup (unsigned int code) #define bfd_pe_print_pdata NULL #endif +#ifdef COFF_WITH_PE /* Return TRUE if this relocation should appear in the output .reloc section. */ @@ -197,9 +468,384 @@ in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED, { return !howto->pc_relative; } +#endif + +static bool +coff_pe_aarch64_relocate_section (bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + struct internal_reloc *relocs, + struct internal_syment *syms, + asection **sections) +{ + struct internal_reloc *rel; + struct internal_reloc *relend; + + if (bfd_link_relocatable (info)) + return true; + + rel = relocs; + relend = rel + input_section->reloc_count; + + /* The addend for a relocation is stored in the immediate bits of each + opcode. So for each relocation, we need to extract the immediate value, + use this to calculate what it should be for the symbol, and rewrite the + opcode into the section stream. */ + + for (; rel < relend; rel++) + { + long symndx; + struct coff_link_hash_entry *h; + bfd_vma sym_value; + asection *sec = NULL; + uint64_t dest_vma; + + /* skip trivial relocations */ + if (rel->r_type == IMAGE_REL_ARM64_ADDR32 + || rel->r_type == IMAGE_REL_ARM64_ADDR64 + || rel->r_type == IMAGE_REL_ARM64_ABSOLUTE) + continue; + + symndx = rel->r_symndx; + sym_value = syms[symndx].n_value; + + h = obj_coff_sym_hashes (input_bfd)[symndx]; + + if (h && h->root.type == bfd_link_hash_defined) + { + sec = h->root.u.def.section; + sym_value = h->root.u.def.value; + } + else + { + sec = sections[symndx]; + } + + if (!sec) + continue; + + if (bfd_is_und_section (sec)) + continue; + + if (discarded_section (sec)) + continue; + + dest_vma = sec->output_section->vma + sec->output_offset + sym_value; + + if (symndx < 0 + || (unsigned long) symndx >= obj_raw_syment_count (input_bfd)) + continue; + + switch (rel->r_type) + { + case IMAGE_REL_ARM64_ADDR32NB: + { + uint64_t val; + int32_t addend; + + addend = bfd_getl32 (contents + rel->r_vaddr); + + dest_vma += addend; + + val = dest_vma; + val -= pe_data (output_bfd)->pe_opthdr.ImageBase; + + if (val > 0xffffffff) + (*info->callbacks->reloc_overflow) + (info, h ? &h->root : NULL, syms[symndx]._n._n_name, + "IMAGE_REL_ARM64_ADDR32NB", 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_BRANCH26: + { + uint64_t cur_vma; + uint32_t opcode; + int64_t addend, val; + + opcode = bfd_getl32 (contents + rel->r_vaddr); + + addend = (opcode & 0x3ffffff) << 2; + + if (addend & 0x8000000) + addend |= 0xfffffffff0000000; + + dest_vma += addend; + cur_vma = input_section->output_section->vma + + input_section->output_offset + + rel->r_vaddr; + + val = (dest_vma >> 2) - (cur_vma >> 2); + + if (val > 0x1ffffff || val < -0x2000000) + (*info->callbacks->reloc_overflow) + (info, h ? &h->root : NULL, syms[symndx]._n._n_name, + "IMAGE_REL_ARM64_BRANCH26", addend, input_bfd, + input_section, rel->r_vaddr - input_section->vma); + + opcode &= 0xfc000000; + opcode |= val & 0x3ffffff; + + bfd_putl32 (opcode, contents + rel->r_vaddr); + rel->r_type = IMAGE_REL_ARM64_ABSOLUTE; + + break; + } + + case IMAGE_REL_ARM64_BRANCH19: + { + uint64_t cur_vma; + uint32_t opcode; + int64_t addend, val; + + opcode = bfd_getl32 (contents + rel->r_vaddr); + + addend = (opcode & 0xffffe0) >> 3; + + if (addend & 0x100000) + addend |= 0xffffffffffe00000; + + dest_vma += addend; + cur_vma = input_section->output_section->vma + + input_section->output_offset + + rel->r_vaddr; + + val = (dest_vma >> 2) - (cur_vma >> 2); + + if (val > 0x3ffff || val < -0x40000) + (*info->callbacks->reloc_overflow) + (info, h ? &h->root : NULL, syms[symndx]._n._n_name, + "IMAGE_REL_ARM64_BRANCH19", addend, input_bfd, + input_section, rel->r_vaddr - input_section->vma); + + opcode &= 0xff00001f; + opcode |= (val & 0x7ffff) << 5; + + bfd_putl32 (opcode, contents + rel->r_vaddr); + rel->r_type = IMAGE_REL_ARM64_ABSOLUTE; + + break; + } + + case IMAGE_REL_ARM64_BRANCH14: + { + uint64_t cur_vma; + uint32_t opcode; + int64_t addend, val; + + opcode = bfd_getl32 (contents + rel->r_vaddr); + + addend = (opcode & 0x7ffe0) >> 3; + + if (addend & 0x8000) + addend |= 0xffffffffffff0000; + + dest_vma += addend; + cur_vma = input_section->output_section->vma + + input_section->output_offset + + rel->r_vaddr; + + val = (dest_vma >> 2) - (cur_vma >> 2); + + if (val > 0x1fff || val < -0x2000) + (*info->callbacks->reloc_overflow) + (info, h ? &h->root : NULL, syms[symndx]._n._n_name, + "IMAGE_REL_ARM64_BRANCH14", addend, input_bfd, + input_section, rel->r_vaddr - input_section->vma); + + opcode &= 0xfff8001f; + opcode |= (val & 0x3fff) << 5; + + bfd_putl32 (opcode, contents + rel->r_vaddr); + rel->r_type = IMAGE_REL_ARM64_ABSOLUTE; + + break; + } + + case IMAGE_REL_ARM64_PAGEBASE_REL21: + { + uint64_t cur_vma; + uint32_t opcode; + int64_t addend, val; + + opcode = bfd_getl32 (contents + rel->r_vaddr); + + addend = ((opcode & 0xffffe0) >> 3) + | ((opcode & 0x60000000) >> 29); + + if (addend & 0x100000) + addend |= 0xffffffffffe00000; + + dest_vma += addend; + cur_vma = input_section->output_section->vma + + input_section->output_offset + + rel->r_vaddr; + + val = (dest_vma >> 12) - (cur_vma >> 12); + + if (val > 0xfffff || val < -0x100000) + (*info->callbacks->reloc_overflow) + (info, h ? &h->root : NULL, syms[symndx]._n._n_name, + "IMAGE_REL_ARM64_PAGEBASE_REL21", addend, input_bfd, + input_section, rel->r_vaddr - input_section->vma); + + opcode &= 0x9f00001f; + opcode |= (val & 0x3) << 29; + opcode |= (val & 0x1ffffc) << 3; + + bfd_putl32 (opcode, contents + rel->r_vaddr); + rel->r_type = IMAGE_REL_ARM64_ABSOLUTE; + + break; + } + + case IMAGE_REL_ARM64_REL21: + { + uint64_t cur_vma; + uint32_t opcode; + int64_t addend, val; + + opcode = bfd_getl32 (contents + rel->r_vaddr); + + addend = ((opcode & 0xffffe0) >> 3) + | ((opcode & 0x60000000) >> 29); + + if (addend & 0x100000) + addend |= 0xffffffffffe00000; + + dest_vma += addend; + cur_vma = input_section->output_section->vma + + input_section->output_offset + + rel->r_vaddr; + + val = dest_vma - cur_vma; + + if (val > 0xfffff || val < -0x100000) + (*info->callbacks->reloc_overflow) + (info, h ? &h->root : NULL, syms[symndx]._n._n_name, + "IMAGE_REL_ARM64_REL21", addend, input_bfd, + input_section, rel->r_vaddr - input_section->vma); + + opcode &= 0x9f00001f; + opcode |= (val & 0x3) << 29; + opcode |= (val & 0x1ffffc) << 3; + + bfd_putl32 (opcode, contents + rel->r_vaddr); + rel->r_type = IMAGE_REL_ARM64_ABSOLUTE; + + break; + } + + case IMAGE_REL_ARM64_PAGEOFFSET_12L: + { + uint32_t opcode, val; + uint8_t shift; + int32_t addend; + + opcode = bfd_getl32 (contents + rel->r_vaddr); + + addend = (opcode & 0x3ffc00) >> 10; + + if ((opcode & 0xff800000) == 0x3d800000) + { + /* LDR / STR with q register */ + shift = 4; + } + else + { + /* top two bits represent how much addend should be shifted */ + shift = opcode >> 30; + } + + addend <<= shift; + + dest_vma += addend; + + /* only interested in bottom 12 bits */ + val = dest_vma & 0xfff; + + if (val & ((1 << shift) - 1)) + (*info->callbacks->reloc_overflow) + (info, h ? &h->root : NULL, syms[symndx]._n._n_name, + "IMAGE_REL_ARM64_PAGEOFFSET_12L", addend, input_bfd, + input_section, rel->r_vaddr - input_section->vma); + + val >>= shift; + + opcode &= 0xffc003ff; + opcode |= val << 10; + + bfd_putl32 (opcode, contents + rel->r_vaddr); + rel->r_type = IMAGE_REL_ARM64_ABSOLUTE; + + break; + } + + case IMAGE_REL_ARM64_PAGEOFFSET_12A: + { + uint32_t opcode, val; + int32_t addend; + + opcode = bfd_getl32 (contents + rel->r_vaddr); + + addend = (opcode & 0x3ffc00) >> 10; + + dest_vma += addend; + + /* only interested in bottom 12 bits */ + val = dest_vma & 0xfff; + + opcode &= 0xffc003ff; + opcode |= val << 10; + + bfd_putl32 (opcode, contents + rel->r_vaddr); + rel->r_type = IMAGE_REL_ARM64_ABSOLUTE; + + break; + } + + default: + info->callbacks->einfo (_("%F%P: Unhandled relocation type %u\n"), + rel->r_type); + BFD_FAIL (); + return false; + } + } + + return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd, + input_section, contents, + relocs, syms, sections); +} + +#define coff_relocate_section coff_pe_aarch64_relocate_section #include "coffcode.h" +/* Prevent assertion in md_apply_fix by forcing use_rela_p on for new + sections. */ +static bool +coff_aarch64_new_section_hook (bfd *abfd, asection *section) +{ + if (!coff_new_section_hook (abfd, section)) + return false; + + section->use_rela_p = 1; + + return true; +} + +#define coff_aarch64_close_and_cleanup coff_close_and_cleanup +#define coff_aarch64_bfd_free_cached_info coff_bfd_free_cached_info +#define coff_aarch64_get_section_contents coff_get_section_contents +#define coff_aarch64_get_section_contents_in_window coff_get_section_contents_in_window + /* Target vectors. */ const bfd_target #ifdef TARGET_SYM @@ -266,7 +912,7 @@ const bfd_target _bfd_bool_bfd_false_error }, - BFD_JUMP_TABLE_GENERIC (coff), + BFD_JUMP_TABLE_GENERIC (coff_aarch64), BFD_JUMP_TABLE_COPY (coff), BFD_JUMP_TABLE_CORE (_bfd_nocore), BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), diff --git a/bfd/config.bfd b/bfd/config.bfd index 3672b6a..800afa8 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -1493,12 +1493,6 @@ case "${targ}" in ;; esac -if test x"$targ_defvec" = x"aarch64-pe"; then - # Not currently complete (and probably not stable), warn user - echo "*** WARNING BFD aarch64-pe support not complete nor stable" - echo "*** Do not rely on this for production purposes" -fi - # All MIPS ELF targets need a 64-bit bfd_vma. case "${targ_defvec} ${targ_selvecs}" in *mips_elf*) |