diff options
author | Mickael Guene <mickael.guene@st.com> | 2015-12-16 10:09:05 +0100 |
---|---|---|
committer | Christophe Lyon <christophe.lyon@linaro.org> | 2015-12-16 10:19:51 +0100 |
commit | 72d98d16ed09584660d0cbb759d90f8dfeef2343 (patch) | |
tree | 6a1f1e78ca24f2306e718025bf4d90d891956880 /bfd | |
parent | 9c35a5290213e9a28e6cc691e1cc7ba5055653f7 (diff) | |
download | fsf-binutils-gdb-72d98d16ed09584660d0cbb759d90f8dfeef2343.zip fsf-binutils-gdb-72d98d16ed09584660d0cbb759d90f8dfeef2343.tar.gz fsf-binutils-gdb-72d98d16ed09584660d0cbb759d90f8dfeef2343.tar.bz2 |
[ARM] Add support for thumb1 pcrop relocations.
To support thumb1 execute-only code we need to support four new
relocations (R_ARM_THM_ALU_ABS_G0_NC, R_ARM_THM_ALU_ABS_G1_NC,
R_ARM_THM_ALU_ABS_G2_NC and R_ARM_THM_ALU_ABS_G3_NC).
These relocations allow the static linker to finalize construction
of symbol address.
Typical sequence of code to get address of the symbol foo is then
the following :
movs r3, #:upper8_15:#foo
lsls r3, #8
adds r3, #:upper0_7:#foo
lsls r3, #8
adds r3, #:lower8_15:#foo
lsls r3, #8
adds r3, #:lower0_7:#foo
This will give following sequence of text and relocations after
assembly :
4: 2300 movs r3, #0
4: R_ARM_THM_ALU_ABS_G3_NC foo
6: 021b lsls r3, r3, #8
8: 3300 adds r3, #0
8: R_ARM_THM_ALU_ABS_G2_NC foo
a: 021b lsls r3, r3, #8
c: 3300 adds r3, #0
c: R_ARM_THM_ALU_ABS_G1_NC foo
e: 021b lsls r3, r3, #8
10: 3300 adds r3, #0
10: R_ARM_THM_ALU_ABS_G0_NC foo
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 |