Skip to content

Commit 72d98d1

Browse files
mickael-gueneChristophe Lyon
authored andcommitted
[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
1 parent 9c35a52 commit 72d98d1

16 files changed

Lines changed: 458 additions & 6 deletions

‎bfd/bfd-in2.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3516,6 +3516,12 @@ pc-relative or some form of GOT-indirect relocation. */
35163516
/* ARM support for STT_GNU_IFUNC. */
35173517
BFD_RELOC_ARM_IRELATIVE,
35183518

3519+
/* Thumb1 relocations to support execute-only code. */
3520+
BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC,
3521+
BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC,
3522+
BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC,
3523+
BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC,
3524+
35193525
/* These relocs are only used within the ARM assembler. They are not
35203526
(at present) written to any object files. */
35213527
BFD_RELOC_ARM_IMMEDIATE,

‎bfd/elf32-arm.c‎

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,6 +1689,60 @@ static reloc_howto_type elf32_arm_howto_table_1[] =
16891689
0x00000000, /* src_mask */
16901690
0x00000000, /* dst_mask */
16911691
FALSE), /* pcrel_offset */
1692+
EMPTY_HOWTO (130),
1693+
EMPTY_HOWTO (131),
1694+
HOWTO (R_ARM_THM_ALU_ABS_G0_NC,/* type. */
1695+
0, /* rightshift. */
1696+
1, /* size (0 = byte, 1 = short, 2 = long). */
1697+
16, /* bitsize. */
1698+
FALSE, /* pc_relative. */
1699+
0, /* bitpos. */
1700+
complain_overflow_bitfield,/* complain_on_overflow. */
1701+
bfd_elf_generic_reloc, /* special_function. */
1702+
"R_ARM_THM_ALU_ABS_G0_NC",/* name. */
1703+
FALSE, /* partial_inplace. */
1704+
0x00000000, /* src_mask. */
1705+
0x00000000, /* dst_mask. */
1706+
FALSE), /* pcrel_offset. */
1707+
HOWTO (R_ARM_THM_ALU_ABS_G1_NC,/* type. */
1708+
0, /* rightshift. */
1709+
1, /* size (0 = byte, 1 = short, 2 = long). */
1710+
16, /* bitsize. */
1711+
FALSE, /* pc_relative. */
1712+
0, /* bitpos. */
1713+
complain_overflow_bitfield,/* complain_on_overflow. */
1714+
bfd_elf_generic_reloc, /* special_function. */
1715+
"R_ARM_THM_ALU_ABS_G1_NC",/* name. */
1716+
FALSE, /* partial_inplace. */
1717+
0x00000000, /* src_mask. */
1718+
0x00000000, /* dst_mask. */
1719+
FALSE), /* pcrel_offset. */
1720+
HOWTO (R_ARM_THM_ALU_ABS_G2_NC,/* type. */
1721+
0, /* rightshift. */
1722+
1, /* size (0 = byte, 1 = short, 2 = long). */
1723+
16, /* bitsize. */
1724+
FALSE, /* pc_relative. */
1725+
0, /* bitpos. */
1726+
complain_overflow_bitfield,/* complain_on_overflow. */
1727+
bfd_elf_generic_reloc, /* special_function. */
1728+
"R_ARM_THM_ALU_ABS_G2_NC",/* name. */
1729+
FALSE, /* partial_inplace. */
1730+
0x00000000, /* src_mask. */
1731+
0x00000000, /* dst_mask. */
1732+
FALSE), /* pcrel_offset. */
1733+
HOWTO (R_ARM_THM_ALU_ABS_G3_NC,/* type. */
1734+
0, /* rightshift. */
1735+
1, /* size (0 = byte, 1 = short, 2 = long). */
1736+
16, /* bitsize. */
1737+
FALSE, /* pc_relative. */
1738+
0, /* bitpos. */
1739+
complain_overflow_bitfield,/* complain_on_overflow. */
1740+
bfd_elf_generic_reloc, /* special_function. */
1741+
"R_ARM_THM_ALU_ABS_G3_NC",/* name. */
1742+
FALSE, /* partial_inplace. */
1743+
0x00000000, /* src_mask. */
1744+
0x00000000, /* dst_mask. */
1745+
FALSE), /* pcrel_offset. */
16921746
};
16931747

16941748
/* 160 onwards: */
@@ -1889,7 +1943,11 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
18891943
{BFD_RELOC_ARM_LDC_SB_G0, R_ARM_LDC_SB_G0},
18901944
{BFD_RELOC_ARM_LDC_SB_G1, R_ARM_LDC_SB_G1},
18911945
{BFD_RELOC_ARM_LDC_SB_G2, R_ARM_LDC_SB_G2},
1892-
{BFD_RELOC_ARM_V4BX, R_ARM_V4BX}
1946+
{BFD_RELOC_ARM_V4BX, R_ARM_V4BX},
1947+
{BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC, R_ARM_THM_ALU_ABS_G3_NC},
1948+
{BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC, R_ARM_THM_ALU_ABS_G2_NC},
1949+
{BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC, R_ARM_THM_ALU_ABS_G1_NC},
1950+
{BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC, R_ARM_THM_ALU_ABS_G0_NC}
18931951
};
18941952

18951953
static reloc_howto_type *
@@ -11023,6 +11081,33 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
1102311081
}
1102411082
return bfd_reloc_ok;
1102511083

11084+
case R_ARM_THM_ALU_ABS_G0_NC:
11085+
case R_ARM_THM_ALU_ABS_G1_NC:
11086+
case R_ARM_THM_ALU_ABS_G2_NC:
11087+
case R_ARM_THM_ALU_ABS_G3_NC:
11088+
{
11089+
const int shift_array[4] = {0, 8, 16, 24};
11090+
bfd_vma insn = bfd_get_16 (input_bfd, hit_data);
11091+
bfd_vma addr = value;
11092+
int shift = shift_array[r_type - R_ARM_THM_ALU_ABS_G0_NC];
11093+
11094+
/* Compute address. */
11095+
if (globals->use_rel)
11096+
signed_addend = insn & 0xff;
11097+
addr += signed_addend;
11098+
if (branch_type == ST_BRANCH_TO_THUMB)
11099+
addr |= 1;
11100+
/* Clean imm8 insn. */
11101+
insn &= 0xff00;
11102+
/* And update with correct part of address. */
11103+
insn |= (addr >> shift) & 0xff;
11104+
/* Update insn. */
11105+
bfd_put_16 (input_bfd, insn, hit_data);
11106+
}
11107+
11108+
*unresolved_reloc_p = FALSE;
11109+
return bfd_reloc_ok;
11110+
1102611111
default:
1102711112
return bfd_reloc_notsupported;
1102811113
}

‎bfd/libbfd.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
15451545
"BFD_RELOC_ARM_LDC_SB_G2",
15461546
"BFD_RELOC_ARM_V4BX",
15471547
"BFD_RELOC_ARM_IRELATIVE",
1548+
"BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC",
1549+
"BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC",
1550+
"BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC",
1551+
"BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC",
15481552
"BFD_RELOC_ARM_IMMEDIATE",
15491553
"BFD_RELOC_ARM_ADRL_IMMEDIATE",
15501554
"BFD_RELOC_ARM_T32_IMMEDIATE",

‎bfd/reloc.c‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3271,6 +3271,17 @@ ENUM
32713271
ENUMDOC
32723272
ARM support for STT_GNU_IFUNC.
32733273
3274+
ENUM
3275+
BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC
3276+
ENUMX
3277+
BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC
3278+
ENUMX
3279+
BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC
3280+
ENUMX
3281+
BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC
3282+
ENUMDOC
3283+
Thumb1 relocations to support execute-only code.
3284+
32743285
ENUM
32753286
BFD_RELOC_ARM_IMMEDIATE
32763287
ENUMX

‎gas/config/tc-arm.c‎

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5273,7 +5273,28 @@ static struct group_reloc_table_entry group_reloc_table[] =
52735273
BFD_RELOC_ARM_ALU_SB_G2, /* ALU */
52745274
BFD_RELOC_ARM_LDR_SB_G2, /* LDR */
52755275
BFD_RELOC_ARM_LDRS_SB_G2, /* LDRS */
5276-
BFD_RELOC_ARM_LDC_SB_G2 } }; /* LDC */
5276+
BFD_RELOC_ARM_LDC_SB_G2 }, /* LDC */
5277+
/* Absolute thumb alu relocations. */
5278+
{ "lower0_7",
5279+
BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC,/* ALU. */
5280+
0, /* LDR. */
5281+
0, /* LDRS. */
5282+
0 }, /* LDC. */
5283+
{ "lower8_15",
5284+
BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC,/* ALU. */
5285+
0, /* LDR. */
5286+
0, /* LDRS. */
5287+
0 }, /* LDC. */
5288+
{ "upper0_7",
5289+
BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC,/* ALU. */
5290+
0, /* LDR. */
5291+
0, /* LDRS. */
5292+
0 }, /* LDC. */
5293+
{ "upper8_15",
5294+
BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC,/* ALU. */
5295+
0, /* LDR. */
5296+
0, /* LDRS. */
5297+
0 } }; /* LDC. */
52775298

52785299
/* Given the address of a pointer pointing to the textual name of a group
52795300
relocation as may appear in assembler source, attempt to find its details
@@ -10394,7 +10415,9 @@ do_t_add_sub (void)
1039410415
{
1039510416
inst.instruction = THUMB_OP16(opcode);
1039610417
inst.instruction |= (Rd << 4) | Rs;
10397-
inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
10418+
if (inst.reloc.type < BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC
10419+
|| inst.reloc.type > BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC)
10420+
inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
1039810421
if (inst.size_req != 2)
1039910422
inst.relax = opcode;
1040010423
}
@@ -11745,9 +11768,13 @@ do_t_mov_cmp (void)
1174511768
inst.instruction = THUMB_OP16 (opcode);
1174611769
inst.instruction |= Rn << 8;
1174711770
if (inst.size_req == 2)
11748-
inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
11771+
{
11772+
if (inst.reloc.type < BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC
11773+
|| inst.reloc.type > BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC)
11774+
inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
11775+
}
1174911776
else
11750-
inst.relax = opcode;
11777+
inst.relax = opcode;
1175111778
}
1175211779
else
1175311780
{
@@ -18608,7 +18635,7 @@ static const struct asm_opcode insns[] =
1860818635
CL("cmnp", 170f000, 2, (RR, SH), cmp),
1860918636

1861018637
tCE("mov", 1a00000, _mov, 2, (RR, SH), mov, t_mov_cmp),
18611-
tC3("movs", 1b00000, _movs, 2, (RR, SH), mov, t_mov_cmp),
18638+
tC3("movs", 1b00000, _movs, 2, (RR, SHG), mov, t_mov_cmp),
1861218639
tCE("mvn", 1e00000, _mvn, 2, (RR, SH), mov, t_mvn_tst),
1861318640
tC3("mvns", 1f00000, _mvns, 2, (RR, SH), mov, t_mvn_tst),
1861418641

@@ -23242,6 +23269,68 @@ md_apply_fix (fixS * fixP,
2324223269
}
2324323270
return;
2324423271

23272+
case BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC:
23273+
case BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC:
23274+
case BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC:
23275+
case BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC:
23276+
gas_assert (!fixP->fx_done);
23277+
{
23278+
bfd_vma insn;
23279+
bfd_boolean is_mov;
23280+
bfd_vma encoded_addend = value;
23281+
23282+
/* Check that addend can be encoded in instruction. */
23283+
if (!seg->use_rela_p && (value < 0 || value > 255))
23284+
as_bad_where (fixP->fx_file, fixP->fx_line,
23285+
_("the offset 0x%08lX is not representable"),
23286+
(unsigned long) encoded_addend);
23287+
23288+
/* Extract the instruction. */
23289+
insn = md_chars_to_number (buf, THUMB_SIZE);
23290+
is_mov = (insn & 0xf800) == 0x2000;
23291+
23292+
/* Encode insn. */
23293+
if (is_mov)
23294+
{
23295+
if (!seg->use_rela_p)
23296+
insn |= encoded_addend;
23297+
}
23298+
else
23299+
{
23300+
int rd, rs;
23301+
23302+
/* Extract the instruction. */
23303+
/* Encoding is the following
23304+
0x8000 SUB
23305+
0x00F0 Rd
23306+
0x000F Rs
23307+
*/
23308+
/* The following conditions must be true :
23309+
- ADD
23310+
- Rd == Rs
23311+
- Rd <= 7
23312+
*/
23313+
rd = (insn >> 4) & 0xf;
23314+
rs = insn & 0xf;
23315+
if ((insn & 0x8000) || (rd != rs) || rd > 7)
23316+
as_bad_where (fixP->fx_file, fixP->fx_line,
23317+
_("Unable to process relocation for thumb opcode: %lx"),
23318+
(unsigned long) insn);
23319+
23320+
/* Encode as ADD immediate8 thumb 1 code. */
23321+
insn = 0x3000 | (rd << 8);
23322+
23323+
/* Place the encoded addend into the first 8 bits of the
23324+
instruction. */
23325+
if (!seg->use_rela_p)
23326+
insn |= encoded_addend;
23327+
}
23328+
23329+
/* Update the instruction. */
23330+
md_number_to_chars (buf, insn, THUMB_SIZE);
23331+
}
23332+
break;
23333+
2324523334
case BFD_RELOC_ARM_ALU_PC_G0_NC:
2324623335
case BFD_RELOC_ARM_ALU_PC_G0:
2324723336
case BFD_RELOC_ARM_ALU_PC_G1_NC:
@@ -23579,6 +23668,10 @@ tc_gen_reloc (asection *section, fixS *fixp)
2357923668
case BFD_RELOC_ARM_LDC_SB_G1:
2358023669
case BFD_RELOC_ARM_LDC_SB_G2:
2358123670
case BFD_RELOC_ARM_V4BX:
23671+
case BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC:
23672+
case BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC:
23673+
case BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC:
23674+
case BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC:
2358223675
code = fixp->fx_r_type;
2358323676
break;
2358423677

@@ -23881,6 +23974,12 @@ arm_fix_adjustable (fixS * fixP)
2388123974
|| fixP->fx_r_type == BFD_RELOC_ARM_THUMB_MOVT_PCREL)
2388223975
return FALSE;
2388323976

23977+
/* BFD_RELOC_ARM_THUMB_ALU_ABS_Gx_NC relocations have VERY limited
23978+
offsets, so keep these symbols. */
23979+
if (fixP->fx_r_type >= BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC
23980+
&& fixP->fx_r_type <= BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC)
23981+
return FALSE;
23982+
2388423983
return TRUE;
2388523984
}
2388623985
#endif /* defined (OBJ_ELF) || defined (OBJ_COFF) */

‎gas/doc/c-arm.texi‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,22 @@ respectively. For example to load the 32-bit address of foo into r0:
537537
MOVT r0, #:upper16:foo
538538
@end smallexample
539539

540+
Relocations @samp{R_ARM_THM_ALU_ABS_G0_NC}, @samp{R_ARM_THM_ALU_ABS_G1_NC},
541+
@samp{R_ARM_THM_ALU_ABS_G2_NC} and @samp{R_ARM_THM_ALU_ABS_G3_NC} can be
542+
generated by prefixing the value with @samp{#:lower0_7:#},
543+
@samp{#:lower8_15:#}, @samp{#:upper0_7:#} and @samp{#:upper8_15:#}
544+
respectively. For example to load the 32-bit address of foo into r0:
545+
546+
@smallexample
547+
MOVS r0, #:upper8_15:#foo
548+
LSLS r0, r0, #8
549+
ADDS r0, #:upper0_7:#foo
550+
LSLS r0, r0, #8
551+
ADDS r0, #:lower8_15:#foo
552+
LSLS r0, r0, #8
553+
ADDS r0, #:lower0_7:#foo
554+
@end smallexample
555+
540556
@node ARM-Neon-Alignment
541557
@subsection NEON Alignment Specifiers
542558

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#objdump: -dr --prefix-addresses --show-raw-insn
2+
#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
3+
#name: ADDS relocations against local symbols for armv6s-m
4+
5+
.*: +file format .*arm.*
6+
7+
Disassembly of section .text:
8+
0[0-9a-f]+ <[^>]+> 3000 adds r0, #0
9+
0: R_ARM_THM_ALU_ABS_G3_NC bar
10+
0[0-9a-f]+ <[^>]+> 3000 adds r0, #0
11+
2: R_ARM_THM_ALU_ABS_G2_NC bar
12+
0[0-9a-f]+ <[^>]+> 3000 adds r0, #0
13+
4: R_ARM_THM_ALU_ABS_G1_NC bar
14+
0[0-9a-f]+ <[^>]+> 3000 adds r0, #0
15+
6: R_ARM_THM_ALU_ABS_G0_NC bar
16+
#...
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.arch armv6s-m
2+
.text
3+
.syntax unified
4+
.thumb
5+
foo:
6+
adds r0, #:upper8_15:#bar
7+
adds r0, #:upper0_7:#bar
8+
adds r0, #:lower8_15:#bar
9+
adds r0, #:lower0_7:#bar
10+
11+
.space 0x10000
12+
13+
bar:
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#objdump: -dr --prefix-addresses --show-raw-insn
2+
#skip: *-*-*coff *-*-pe *-*-wince *-*-*aout* *-*-netbsd *-*-riscix*
3+
#name: MOVS relocations against local symbols for armv6s-m
4+
5+
.*: +file format .*arm.*
6+
7+
Disassembly of section .text:
8+
0[0-9a-f]+ <[^>]+> 2000 movs r0, #0
9+
0: R_ARM_THM_ALU_ABS_G3_NC bar
10+
0[0-9a-f]+ <[^>]+> 2000 movs r0, #0
11+
2: R_ARM_THM_ALU_ABS_G2_NC bar
12+
0[0-9a-f]+ <[^>]+> 2000 movs r0, #0
13+
4: R_ARM_THM_ALU_ABS_G1_NC bar
14+
0[0-9a-f]+ <[^>]+> 2000 movs r0, #0
15+
6: R_ARM_THM_ALU_ABS_G0_NC bar
16+
#...
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.arch armv6s-m
2+
.text
3+
.syntax unified
4+
.thumb
5+
foo:
6+
movs r0, #:upper8_15:#bar
7+
movs r0, #:upper0_7:#bar
8+
movs r0, #:lower8_15:#bar
9+
movs r0, #:lower0_7:#bar
10+
11+
.space 0x10000
12+
13+
bar:

0 commit comments

Comments
 (0)