diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/bfd-in2.h | 6 | ||||
-rw-r--r-- | bfd/elf32-arm.c | 87 | ||||
-rw-r--r-- | bfd/libbfd.h | 4 | ||||
-rw-r--r-- | bfd/reloc.c | 11 |
4 files changed, 107 insertions, 1 deletions
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 606d11b..39eb19a 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3516,6 +3516,12 @@ pc-relative or some form of GOT-indirect relocation. */ /* ARM support for STT_GNU_IFUNC. */ BFD_RELOC_ARM_IRELATIVE, +/* Thumb1 relocations to support execute-only code. */ + BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC, + BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC, + BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC, + BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC, + /* These relocs are only used within the ARM assembler. They are not (at present) written to any object files. */ BFD_RELOC_ARM_IMMEDIATE, diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 49dfc53..49d6469 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -1689,6 +1689,60 @@ static reloc_howto_type elf32_arm_howto_table_1[] = 0x00000000, /* src_mask */ 0x00000000, /* dst_mask */ FALSE), /* pcrel_offset */ + EMPTY_HOWTO (130), + EMPTY_HOWTO (131), + HOWTO (R_ARM_THM_ALU_ABS_G0_NC,/* type. */ + 0, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long). */ + 16, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield,/* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_ARM_THM_ALU_ABS_G0_NC",/* name. */ + FALSE, /* partial_inplace. */ + 0x00000000, /* src_mask. */ + 0x00000000, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + HOWTO (R_ARM_THM_ALU_ABS_G1_NC,/* type. */ + 0, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long). */ + 16, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield,/* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_ARM_THM_ALU_ABS_G1_NC",/* name. */ + FALSE, /* partial_inplace. */ + 0x00000000, /* src_mask. */ + 0x00000000, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + HOWTO (R_ARM_THM_ALU_ABS_G2_NC,/* type. */ + 0, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long). */ + 16, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield,/* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_ARM_THM_ALU_ABS_G2_NC",/* name. */ + FALSE, /* partial_inplace. */ + 0x00000000, /* src_mask. */ + 0x00000000, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + HOWTO (R_ARM_THM_ALU_ABS_G3_NC,/* type. */ + 0, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long). */ + 16, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield,/* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_ARM_THM_ALU_ABS_G3_NC",/* name. */ + FALSE, /* partial_inplace. */ + 0x00000000, /* src_mask. */ + 0x00000000, /* dst_mask. */ + FALSE), /* pcrel_offset. */ }; /* 160 onwards: */ @@ -1889,7 +1943,11 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] = {BFD_RELOC_ARM_LDC_SB_G0, R_ARM_LDC_SB_G0}, {BFD_RELOC_ARM_LDC_SB_G1, R_ARM_LDC_SB_G1}, {BFD_RELOC_ARM_LDC_SB_G2, R_ARM_LDC_SB_G2}, - {BFD_RELOC_ARM_V4BX, R_ARM_V4BX} + {BFD_RELOC_ARM_V4BX, R_ARM_V4BX}, + {BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC, R_ARM_THM_ALU_ABS_G3_NC}, + {BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC, R_ARM_THM_ALU_ABS_G2_NC}, + {BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC, R_ARM_THM_ALU_ABS_G1_NC}, + {BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC, R_ARM_THM_ALU_ABS_G0_NC} }; static reloc_howto_type * @@ -11023,6 +11081,33 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, } return bfd_reloc_ok; + case R_ARM_THM_ALU_ABS_G0_NC: + case R_ARM_THM_ALU_ABS_G1_NC: + case R_ARM_THM_ALU_ABS_G2_NC: + case R_ARM_THM_ALU_ABS_G3_NC: + { + const int shift_array[4] = {0, 8, 16, 24}; + bfd_vma insn = bfd_get_16 (input_bfd, hit_data); + bfd_vma addr = value; + int shift = shift_array[r_type - R_ARM_THM_ALU_ABS_G0_NC]; + + /* Compute address. */ + if (globals->use_rel) + signed_addend = insn & 0xff; + addr += signed_addend; + if (branch_type == ST_BRANCH_TO_THUMB) + addr |= 1; + /* Clean imm8 insn. */ + insn &= 0xff00; + /* And update with correct part of address. */ + insn |= (addr >> shift) & 0xff; + /* Update insn. */ + bfd_put_16 (input_bfd, insn, hit_data); + } + + *unresolved_reloc_p = FALSE; + return bfd_reloc_ok; + default: return bfd_reloc_notsupported; } diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 1c93c91..8765bee 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1545,6 +1545,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARM_LDC_SB_G2", "BFD_RELOC_ARM_V4BX", "BFD_RELOC_ARM_IRELATIVE", + "BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC", + "BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC", + "BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC", + "BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC", "BFD_RELOC_ARM_IMMEDIATE", "BFD_RELOC_ARM_ADRL_IMMEDIATE", "BFD_RELOC_ARM_T32_IMMEDIATE", diff --git a/bfd/reloc.c b/bfd/reloc.c index 593e7c7..869503c 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -3272,6 +3272,17 @@ ENUMDOC ARM support for STT_GNU_IFUNC. ENUM + BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC +ENUMX + BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC +ENUMX + BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC +ENUMX + BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC +ENUMDOC + Thumb1 relocations to support execute-only code. + +ENUM BFD_RELOC_ARM_IMMEDIATE ENUMX BFD_RELOC_ARM_ADRL_IMMEDIATE |