/* 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,
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: */
{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 *
}
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;
}
"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",
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_ALU_SB_G2, /* ALU */
BFD_RELOC_ARM_LDR_SB_G2, /* LDR */
BFD_RELOC_ARM_LDRS_SB_G2, /* LDRS */
- BFD_RELOC_ARM_LDC_SB_G2 } }; /* LDC */
+ BFD_RELOC_ARM_LDC_SB_G2 }, /* LDC */
+ /* Absolute thumb alu relocations. */
+ { "lower0_7",
+ BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC,/* ALU. */
+ 0, /* LDR. */
+ 0, /* LDRS. */
+ 0 }, /* LDC. */
+ { "lower8_15",
+ BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC,/* ALU. */
+ 0, /* LDR. */
+ 0, /* LDRS. */
+ 0 }, /* LDC. */
+ { "upper0_7",
+ BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC,/* ALU. */
+ 0, /* LDR. */
+ 0, /* LDRS. */
+ 0 }, /* LDC. */
+ { "upper8_15",
+ BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC,/* ALU. */
+ 0, /* LDR. */
+ 0, /* LDRS. */
+ 0 } }; /* LDC. */
/* Given the address of a pointer pointing to the textual name of a group
relocation as may appear in assembler source, attempt to find its details
{
inst.instruction = THUMB_OP16(opcode);
inst.instruction |= (Rd << 4) | Rs;
- inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
+ if (inst.reloc.type < BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC
+ || inst.reloc.type > BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC)
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
if (inst.size_req != 2)
inst.relax = opcode;
}
inst.instruction = THUMB_OP16 (opcode);
inst.instruction |= Rn << 8;
if (inst.size_req == 2)
- inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
+ {
+ if (inst.reloc.type < BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC
+ || inst.reloc.type > BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC)
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
+ }
else
- inst.relax = opcode;
+ inst.relax = opcode;
}
else
{
CL("cmnp", 170f000, 2, (RR, SH), cmp),
tCE("mov", 1a00000, _mov, 2, (RR, SH), mov, t_mov_cmp),
- tC3("movs", 1b00000, _movs, 2, (RR, SH), mov, t_mov_cmp),
+ tC3("movs", 1b00000, _movs, 2, (RR, SHG), mov, t_mov_cmp),
tCE("mvn", 1e00000, _mvn, 2, (RR, SH), mov, t_mvn_tst),
tC3("mvns", 1f00000, _mvns, 2, (RR, SH), mov, t_mvn_tst),
}
return;
+ case BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC:
+ case BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC:
+ case BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC:
+ case BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC:
+ gas_assert (!fixP->fx_done);
+ {
+ bfd_vma insn;
+ bfd_boolean is_mov;
+ bfd_vma encoded_addend = value;
+
+ /* Check that addend can be encoded in instruction. */
+ if (!seg->use_rela_p && (value < 0 || value > 255))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("the offset 0x%08lX is not representable"),
+ (unsigned long) encoded_addend);
+
+ /* Extract the instruction. */
+ insn = md_chars_to_number (buf, THUMB_SIZE);
+ is_mov = (insn & 0xf800) == 0x2000;
+
+ /* Encode insn. */
+ if (is_mov)
+ {
+ if (!seg->use_rela_p)
+ insn |= encoded_addend;
+ }
+ else
+ {
+ int rd, rs;
+
+ /* Extract the instruction. */
+ /* Encoding is the following
+ 0x8000 SUB
+ 0x00F0 Rd
+ 0x000F Rs
+ */
+ /* The following conditions must be true :
+ - ADD
+ - Rd == Rs
+ - Rd <= 7
+ */
+ rd = (insn >> 4) & 0xf;
+ rs = insn & 0xf;
+ if ((insn & 0x8000) || (rd != rs) || rd > 7)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("Unable to process relocation for thumb opcode: %lx"),
+ (unsigned long) insn);
+
+ /* Encode as ADD immediate8 thumb 1 code. */
+ insn = 0x3000 | (rd << 8);
+
+ /* Place the encoded addend into the first 8 bits of the
+ instruction. */
+ if (!seg->use_rela_p)
+ insn |= encoded_addend;
+ }
+
+ /* Update the instruction. */
+ md_number_to_chars (buf, insn, THUMB_SIZE);
+ }
+ break;
+
case BFD_RELOC_ARM_ALU_PC_G0_NC:
case BFD_RELOC_ARM_ALU_PC_G0:
case BFD_RELOC_ARM_ALU_PC_G1_NC:
case BFD_RELOC_ARM_LDC_SB_G1:
case BFD_RELOC_ARM_LDC_SB_G2:
case BFD_RELOC_ARM_V4BX:
+ case BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC:
+ case BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC:
+ case BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC:
+ case BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC:
code = fixp->fx_r_type;
break;
|| fixP->fx_r_type == BFD_RELOC_ARM_THUMB_MOVT_PCREL)
return FALSE;
+ /* BFD_RELOC_ARM_THUMB_ALU_ABS_Gx_NC relocations have VERY limited
+ offsets, so keep these symbols. */
+ if (fixP->fx_r_type >= BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC
+ && fixP->fx_r_type <= BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC)
+ return FALSE;
+
return TRUE;
}
#endif /* defined (OBJ_ELF) || defined (OBJ_COFF) */
MOVT r0, #:upper16:foo
@end smallexample
+Relocations @samp{R_ARM_THM_ALU_ABS_G0_NC}, @samp{R_ARM_THM_ALU_ABS_G1_NC},
+@samp{R_ARM_THM_ALU_ABS_G2_NC} and @samp{R_ARM_THM_ALU_ABS_G3_NC} can be
+generated by prefixing the value with @samp{#:lower0_7:#},
+@samp{#:lower8_15:#}, @samp{#:upper0_7:#} and @samp{#:upper8_15:#}
+respectively. For example to load the 32-bit address of foo into r0:
+
+@smallexample
+ MOVS r0, #:upper8_15:#foo
+ LSLS r0, r0, #8
+ ADDS r0, #:upper0_7:#foo
+ LSLS r0, r0, #8
+ ADDS r0, #:lower8_15:#foo
+ LSLS r0, r0, #8
+ ADDS r0, #:lower0_7:#foo
+@end smallexample
+
@node ARM-Neon-Alignment
@subsection NEON Alignment Specifiers
--- /dev/null
+#objdump: -dr --prefix-addresses --show-raw-insn
+#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+#name: ADDS relocations against local symbols for armv6s-m
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0[0-9a-f]+ <[^>]+> 3000 adds r0, #0
+ 0: R_ARM_THM_ALU_ABS_G3_NC bar
+0[0-9a-f]+ <[^>]+> 3000 adds r0, #0
+ 2: R_ARM_THM_ALU_ABS_G2_NC bar
+0[0-9a-f]+ <[^>]+> 3000 adds r0, #0
+ 4: R_ARM_THM_ALU_ABS_G1_NC bar
+0[0-9a-f]+ <[^>]+> 3000 adds r0, #0
+ 6: R_ARM_THM_ALU_ABS_G0_NC bar
+#...
--- /dev/null
+.arch armv6s-m
+.text
+.syntax unified
+.thumb
+foo:
+adds r0, #:upper8_15:#bar
+adds r0, #:upper0_7:#bar
+adds r0, #:lower8_15:#bar
+adds r0, #:lower0_7:#bar
+
+.space 0x10000
+
+bar:
--- /dev/null
+#objdump: -dr --prefix-addresses --show-raw-insn
+#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
+#name: MOVS relocations against local symbols for armv6s-m
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0[0-9a-f]+ <[^>]+> 2000 movs r0, #0
+ 0: R_ARM_THM_ALU_ABS_G3_NC bar
+0[0-9a-f]+ <[^>]+> 2000 movs r0, #0
+ 2: R_ARM_THM_ALU_ABS_G2_NC bar
+0[0-9a-f]+ <[^>]+> 2000 movs r0, #0
+ 4: R_ARM_THM_ALU_ABS_G1_NC bar
+0[0-9a-f]+ <[^>]+> 2000 movs r0, #0
+ 6: R_ARM_THM_ALU_ABS_G0_NC bar
+#...
--- /dev/null
+.arch armv6s-m
+.text
+.syntax unified
+.thumb
+foo:
+movs r0, #:upper8_15:#bar
+movs r0, #:upper0_7:#bar
+movs r0, #:lower8_15:#bar
+movs r0, #:lower0_7:#bar
+
+.space 0x10000
+
+bar:
RELOC_NUMBER (R_ARM_ME_TOO, 128) /* obsolete */
RELOC_NUMBER (R_ARM_THM_TLS_DESCSEQ ,129)
+ RELOC_NUMBER (R_ARM_THM_ALU_ABS_G0_NC,132)
+ RELOC_NUMBER (R_ARM_THM_ALU_ABS_G1_NC,133)
+ RELOC_NUMBER (R_ARM_THM_ALU_ABS_G2_NC,134)
+ RELOC_NUMBER (R_ARM_THM_ALU_ABS_G3_NC,135)
+
RELOC_NUMBER (R_ARM_IRELATIVE, 160)
/* Extensions? R=read-only? */
"" {pcrel-shared.s}
{{readelf -dr pcrel-shared.rd}}
"pcrel-shared.so"}
+ {"MOVS thumb1 relocations" "-static -T arm.ld" "" "" {thumb1-movs.s}
+ {{objdump -dw thumb1-movs.d}}
+ "thumb1-movs"}
+ {"ADDS thumb1 relocations" "-static -T arm.ld" "" "" {thumb1-adds.s}
+ {{objdump -dw thumb1-adds.d}}
+ "thumb1-adds"}
}
set armelftests_nonacl {
--- /dev/null
+
+.*: file format.*
+
+Disassembly of section .text:
+
+00008000 <[^>]*>:
+ 8000: 3012 adds r0, #18
+ 8002: 3134 adds r1, #52 ; 0x34
+ 8004: 3280 adds r2, #128 ; 0x80
+ 8006: 3301 adds r3, #1
+ 8008: 3401 adds r4, #1
+ 800a: 3500 adds r5, #0
+ 800c: 3600 adds r6, #0
+ 800e: 3700 adds r7, #0
+
+00008010 <[^>]*>:
+ 8010: 3012 adds r0, #18
+ 8012: 3100 adds r1, #0
+ 8014: 3200 adds r2, #0
+ 8016: 33ca adds r3, #202 ; 0xca
+ 8018: 3700 adds r7, #0
+ 801a: 3634 adds r6, #52 ; 0x34
+ 801c: 3581 adds r5, #129 ; 0x81
+ 801e: 3423 adds r4, #35 ; 0x23
+
+00008020 <[^>]*>:
+ 8020: 01 .byte 0x01
+
+00008021 <[^>]*>:
+ 8021: 02 .byte 0x02
+
+Disassembly of section .far:
+
+12340000 <[^>]*>:
+12340000: 3000 adds r0, #0
+12340002: 3100 adds r1, #0
+12340004: 3200 adds r2, #0
+12340006: 3301 adds r3, #1
--- /dev/null
+ .text
+ .arch armv6s-m
+ .syntax unified
+ .global _start
+ .thumb_func
+ .type _start, %function
+_start:
+ .thumb_func
+ .type thumb1, %function
+thumb1:
+ adds r0, #:upper8_15:#thumb3
+ adds r1, #:upper0_7:#thumb3
+ adds r2, #:lower8_15:#thumb1
+ adds r3, #:lower0_7:#thumb1
+ adds r4, #:lower0_7:#thumb3
+ adds r5, #:lower8_15:#thumb3
+ adds r6, #:upper0_7:#thumb1
+ adds r7, #:upper8_15:#thumb1
+ .thumb_func
+ .type thumb2, %function
+thumb2:
+ adds r0, #:upper8_15:#thumb3
+ adds r1, #:upper0_7:#(var2 + 1)
+ adds r2, #:lower8_15:#(thumb3 + 255)
+ adds r3, #:lower0_7:#(var1 + 0xaa)
+ adds r7, #:upper8_15:#var1 + 4
+ adds r6, #:upper0_7:#thumb3
+ adds r5, #:lower8_15:#var2 + 0xff
+ adds r4, #:lower0_7:#var2 - (-2)
+var1:
+ .byte 1
+var2:
+ .byte 2
+
+ .section .far, "ax", %progbits
+ .thumb_func
+ .type thumb3, %function
+thumb3:
+ adds r0, #:upper8_15:#thumb1
+ adds r1, #:upper0_7:#thumb2
+ adds r2, #:lower8_15:#thumb3
+ adds r3, #:lower0_7:#thumb1
+
--- /dev/null
+
+.*: file format.*
+
+Disassembly of section .text:
+
+00008000 <[^>]*>:
+ 8000: 2012 movs r0, #18
+ 8002: 2134 movs r1, #52 ; 0x34
+ 8004: 2280 movs r2, #128 ; 0x80
+ 8006: 2301 movs r3, #1
+ 8008: 2401 movs r4, #1
+ 800a: 2500 movs r5, #0
+ 800c: 2600 movs r6, #0
+ 800e: 2700 movs r7, #0
+
+00008010 <[^>]*>:
+ 8010: 2012 movs r0, #18
+ 8012: 2100 movs r1, #0
+ 8014: 2281 movs r2, #129 ; 0x81
+ 8016: 2320 movs r3, #32
+ 8018: 2700 movs r7, #0
+ 801a: 2600 movs r6, #0
+ 801c: 2581 movs r5, #129 ; 0x81
+ 801e: 2422 movs r4, #34 ; 0x22
+
+00008020 <[^>]*>:
+ 8020: 01 .byte 0x01
+
+00008021 <[^>]*>:
+ 8021: 02 .byte 0x02
+
+Disassembly of section .far:
+
+12340000 <[^>]*>:
+12340000: 2000 movs r0, #0
+12340002: 2100 movs r1, #0
+12340004: 2200 movs r2, #0
+12340006: 2301 movs r3, #1
--- /dev/null
+ .text
+ .arch armv6s-m
+ .syntax unified
+ .global _start
+ .thumb_func
+ .type _start, %function
+_start:
+ .thumb_func
+ .type thumb1, %function
+thumb1:
+ movs r0, #:upper8_15:#thumb3
+ movs r1, #:upper0_7:#thumb3
+ movs r2, #:lower8_15:#thumb1
+ movs r3, #:lower0_7:#thumb1
+ movs r4, #:lower0_7:#thumb3
+ movs r5, #:lower8_15:#thumb3
+ movs r6, #:upper0_7:#thumb1
+ movs r7, #:upper8_15:#thumb1
+ .thumb_func
+ .type thumb2, %function
+thumb2:
+ movs r0, #:upper8_15:#(thumb3 + 0)
+ movs r1, #:upper0_7:#(thumb2 + 1)
+ movs r2, #:lower8_15:#(var1 + 255)
+ movs r3, #:lower0_7:#var1
+ movs r7, #:upper8_15:#var1 + 4
+ movs r6, #:upper0_7:#var2
+ movs r5, #:lower8_15:#var2 + 0xff
+ movs r4, #:lower0_7:#var2 - (-1)
+var1:
+ .byte 1
+var2:
+ .byte 2
+
+ .section .far, "ax", %progbits
+ .thumb_func
+ .type thumb3, %function
+thumb3:
+ movs r0, #:upper8_15:#thumb1
+ movs r1, #:upper0_7:#thumb2
+ movs r2, #:lower8_15:#thumb3
+ movs r3, #:lower0_7:#thumb1
+