This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] ARM: Add support for thumb1 PCROP relocations.


Hi all,

This is a proposal for a patch that implements the new ARM relocations
needed to support execute-only code segment for thumb1 code sequences.

Some STM32 MCUs implement a security feature called 'Proprietary Code
Read-Out Protection' aka PCROP that forbids data read access to some
code areas (only fetch access is allowed).
This protection prevents usage of literal pools (since one cannot load
data from code sections), so compilers have to use specific code
sequence to generate constants. This is particularly a problem to
generate symbol addresses.

For armv7-m architecture compilers can generate movt/movw pair
instructions relying on R_ARM_THM_MOVW_ABS_NC and R_ARM_THM_MOVT_ABS
relocations support.
For armv6-m there is currently no possibility to generate such symbol
addresses.
This is why the ARM ABI defines four new relocations that allow
symbol address generation in armv6-m architecture using a sequence of
movs/adds/lsls instructions.

This patch implements this feature in gas and bfd.

Unit tests have be written to check correct implementation for both
gas and bfd.
No regressions have been observed for arm-linux-gnueabi,
arm-linux-gnueabihf, arm-none-eabi, arm-none-nacl and
armeb-linux-gnueabihf targets on 64 bits linux host.

Changelogs:

include/ChangeLog:

2015-11-17  Mickael Guene <mickael.guene@st.com>

	* elf/arm.h: Add new arm relocations.

bfd/ChangeLog:

2015-11-17  Mickael Guene <mickael.guene@st.com>

	* bfd-in2.h: Regenerate.
	* reloc.c: Add new relocations.
	* libbfd.h (bfd_reloc_code_real_names): Add new relocations display
	names.
	* elf32-arm.c (elf32_arm_howto_table_1): Add HOWTO for new relocations.
	(elf32_arm_reloc_map): Add bfd/arm mapping for new relocations.
	(elf32_arm_final_link_relocate): Implement new relocations resolution.

gas/ChangeLog:

2015-11-17  Mickael Guene <mickael.guene@st.com>

	* config/tc-arm.c (group_reloc_table): Add mapping between gas syntax
	and new relocations.
	(do_t_add_sub): Keep new relocations for add operand.
	(do_t_mov_cmp): Keep new relocations for mov operand.
	(insns): Use 'shifter operand with possible group relocation' operand
	parse code for movs operand.
	(md_apply_fix): Implement mov and add encoding when new relocations
	on them.
	(tc_gen_reloc): Add new relocations.
	(arm_fix_adjustable): Since offset has a limited range ([0:255]) we
	disable adjust_reloc_syms() for new relocations.

gas/testsuite/ChangeLog:

2015-11-17  Mickael Guene <mickael.guene@st.com>

	* gas/arm/adds-thumb1-reloc-local.d: New
	* gas/arm/adds-thumb1-reloc-local.s: New
	* gas/arm/movs-thumb1-reloc-local.d: New
	* gas/arm/movs-thumb1-reloc-local.s: New

ld/testsuite/ChangeLog:

2015-11-17  Mickael Guene <mickael.guene@st.com>

	* ld-arm/arm-elf.exp (armelftests_common): Add new relocations tests.
	* ld-arm/thumb1-adds.d: New
	* ld-arm/thumb1-adds.s: New
	* ld-arm/thumb1-movs.d: New
	* ld-arm/thumb1-movs.s: New
>From 0f43cd955385c615ea91de88c4a09a586d400dbf Mon Sep 17 00:00:00 2001
From: Mickael Guene <mickael.guene@st.com>
Date: Fri, 9 Oct 2015 10:01:33 +0200
Subject: [PATCH]  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, #:high_high:#foo
	lsls	r3, #8
	adds	r3, #:high_low:#foo
	lsls	r3, #8
	adds	r3, #:low_high:#foo
	lsls	r3, #8
	adds	r3, #:low_low:#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
---
 bfd/bfd-in2.h                                   |   6 ++
 bfd/elf32-arm.c                                 |  87 ++++++++++++++++++-
 bfd/libbfd.h                                    |   4 +
 bfd/reloc.c                                     |  11 +++
 gas/config/tc-arm.c                             | 107 ++++++++++++++++++++++--
 gas/testsuite/gas/arm/adds-thumb1-reloc-local.d |  16 ++++
 gas/testsuite/gas/arm/adds-thumb1-reloc-local.s |  13 +++
 gas/testsuite/gas/arm/movs-thumb1-reloc-local.d |  16 ++++
 gas/testsuite/gas/arm/movs-thumb1-reloc-local.s |  13 +++
 include/elf/arm.h                               |   5 ++
 ld/testsuite/ld-arm/arm-elf.exp                 |   6 ++
 ld/testsuite/ld-arm/thumb1-adds.d               |  38 +++++++++
 ld/testsuite/ld-arm/thumb1-adds.s               |  42 ++++++++++
 ld/testsuite/ld-arm/thumb1-movs.d               |  38 +++++++++
 ld/testsuite/ld-arm/thumb1-movs.s               |  42 ++++++++++
 15 files changed, 437 insertions(+), 7 deletions(-)
 create mode 100644 gas/testsuite/gas/arm/adds-thumb1-reloc-local.d
 create mode 100644 gas/testsuite/gas/arm/adds-thumb1-reloc-local.s
 create mode 100644 gas/testsuite/gas/arm/movs-thumb1-reloc-local.d
 create mode 100644 gas/testsuite/gas/arm/movs-thumb1-reloc-local.s
 create mode 100644 ld/testsuite/ld-arm/thumb1-adds.d
 create mode 100644 ld/testsuite/ld-arm/thumb1-adds.s
 create mode 100644 ld/testsuite/ld-arm/thumb1-movs.d
 create mode 100644 ld/testsuite/ld-arm/thumb1-movs.s

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index bca5181..77d57f1 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3469,6 +3469,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 9fd5720..a3cd1fd 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 *
@@ -10406,6 +10464,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 1c54d0f..84f7244 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1525,6 +1525,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 ba73ef7..55ccfaa 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -3250,6 +3250,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
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 2ab8bbe..567e904 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -5305,7 +5305,28 @@ static struct group_reloc_table_entry group_reloc_table[] =
       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.  */
+    { "low_low",
+      BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC,/* ALU.  */
+      0,				/* LDR.  */
+      0,				/* LDRS.  */
+      0 },				/* LDC.  */
+    { "low_high",
+      BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC,/* ALU.  */
+      0,				/* LDR.  */
+      0,				/* LDRS.  */
+      0 },				/* LDC.  */
+    { "high_low",
+      BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC,/* ALU.  */
+      0,				/* LDR.  */
+      0,				/* LDRS.  */
+      0 },				/* LDC.  */
+    { "high_high",
+      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
@@ -10234,7 +10255,9 @@ do_t_add_sub (void)
 		{
 		  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;
 		}
@@ -11585,9 +11608,12 @@ do_t_mov_cmp (void)
 	      inst.instruction = THUMB_OP16 (opcode);
 	      inst.instruction |= Rn << 8;
 	      if (inst.size_req == 2)
-		inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
-	      else
-		inst.relax = opcode;
+		{
+		  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;
 	    }
 	  else
 	    {
@@ -18409,7 +18435,7 @@ static const struct asm_opcode insns[] =
   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),
 
@@ -22942,6 +22968,65 @@ md_apply_fix (fixS *	fixP,
 	}
       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);
+      if (!seg->use_rela_p)
+	{
+	  bfd_vma insn;
+	  bfd_boolean is_mov;
+	  bfd_vma encoded_addend = value;
+
+	  /* check that addend can be encoded.  */
+	  if (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)
+	    {
+	      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.  */
+	      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:
@@ -23279,6 +23364,10 @@ tc_gen_reloc (asection *section, fixS *fixp)
     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;
 
@@ -23581,6 +23670,12 @@ arm_fix_adjustable (fixS * fixP)
       || 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) */
diff --git a/gas/testsuite/gas/arm/adds-thumb1-reloc-local.d b/gas/testsuite/gas/arm/adds-thumb1-reloc-local.d
new file mode 100644
index 0000000..190f0ab
--- /dev/null
+++ b/gas/testsuite/gas/arm/adds-thumb1-reloc-local.d
@@ -0,0 +1,16 @@
+#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
+#...
diff --git a/gas/testsuite/gas/arm/adds-thumb1-reloc-local.s b/gas/testsuite/gas/arm/adds-thumb1-reloc-local.s
new file mode 100644
index 0000000..65e921c
--- /dev/null
+++ b/gas/testsuite/gas/arm/adds-thumb1-reloc-local.s
@@ -0,0 +1,13 @@
+.arch armv6s-m
+.text
+.syntax unified
+.thumb
+foo:
+adds r0, #:high_high:#bar
+adds r0, #:high_low:#bar
+adds r0, #:low_high:#bar
+adds r0, #:low_low:#bar
+
+.space 0x10000
+
+bar:
diff --git a/gas/testsuite/gas/arm/movs-thumb1-reloc-local.d b/gas/testsuite/gas/arm/movs-thumb1-reloc-local.d
new file mode 100644
index 0000000..3febca3
--- /dev/null
+++ b/gas/testsuite/gas/arm/movs-thumb1-reloc-local.d
@@ -0,0 +1,16 @@
+#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
+#...
diff --git a/gas/testsuite/gas/arm/movs-thumb1-reloc-local.s b/gas/testsuite/gas/arm/movs-thumb1-reloc-local.s
new file mode 100644
index 0000000..868cab5
--- /dev/null
+++ b/gas/testsuite/gas/arm/movs-thumb1-reloc-local.s
@@ -0,0 +1,13 @@
+.arch armv6s-m
+.text
+.syntax unified
+.thumb
+foo:
+movs r0, #:high_high:#bar
+movs r0, #:high_low:#bar
+movs r0, #:low_high:#bar
+movs r0, #:low_low:#bar
+
+.space 0x10000
+
+bar:
diff --git a/include/elf/arm.h b/include/elf/arm.h
index 34afdfd..92101c0 100644
--- a/include/elf/arm.h
+++ b/include/elf/arm.h
@@ -231,6 +231,11 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
   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?  */
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 3c8cc68..36bcaae 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -207,6 +207,12 @@ set armelftests_common {
      "" {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 {
diff --git a/ld/testsuite/ld-arm/thumb1-adds.d b/ld/testsuite/ld-arm/thumb1-adds.d
new file mode 100644
index 0000000..68ef68e
--- /dev/null
+++ b/ld/testsuite/ld-arm/thumb1-adds.d
@@ -0,0 +1,38 @@
+
+.*:     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
diff --git a/ld/testsuite/ld-arm/thumb1-adds.s b/ld/testsuite/ld-arm/thumb1-adds.s
new file mode 100644
index 0000000..8009d7d
--- /dev/null
+++ b/ld/testsuite/ld-arm/thumb1-adds.s
@@ -0,0 +1,42 @@
+	.text
+	.arch armv6s-m
+	.syntax unified
+	.global	_start
+	.thumb_func
+	.type	_start, %function
+	.type	thumb1, %function
+_start:
+thumb1:
+	adds r0, #:high_high:#thumb3
+	adds r1, #:high_low:#thumb3
+	adds r2, #:low_high:#thumb1
+	adds r3, #:low_low:#thumb1
+	adds r4, #:low_low:#thumb3
+	adds r5, #:low_high:#thumb3
+	adds r6, #:high_low:#thumb1
+	adds r7, #:high_high:#thumb1
+	.thumb_func
+	.type	thumb2, %function
+thumb2:
+	adds r0, #:high_high:#thumb3
+	adds r1, #:high_low:#(var2 + 1)
+	adds r2, #:low_high:#(thumb3 + 255)
+	adds r3, #:low_low:#(var1 + 0xaa)
+	adds r7, #:high_high:#var1 + 4
+	adds r6, #:high_low:#thumb3
+	adds r5, #:low_high:#var2 + 0xff
+	adds r4, #:low_low:#var2 - (-2)
+var1:
+	.byte 1
+var2:
+	.byte 2
+
+	.section .far, "ax", %progbits
+	.thumb_func
+	.type	thumb3, %function
+thumb3:
+	adds r0, #:high_high:#thumb1
+	adds r1, #:high_low:#thumb2
+	adds r2, #:low_high:#thumb3
+	adds r3, #:low_low:#thumb1
+
diff --git a/ld/testsuite/ld-arm/thumb1-movs.d b/ld/testsuite/ld-arm/thumb1-movs.d
new file mode 100644
index 0000000..6a72bc1
--- /dev/null
+++ b/ld/testsuite/ld-arm/thumb1-movs.d
@@ -0,0 +1,38 @@
+
+.*:     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
diff --git a/ld/testsuite/ld-arm/thumb1-movs.s b/ld/testsuite/ld-arm/thumb1-movs.s
new file mode 100644
index 0000000..06fa7fb
--- /dev/null
+++ b/ld/testsuite/ld-arm/thumb1-movs.s
@@ -0,0 +1,42 @@
+	.text
+	.arch armv6s-m
+	.syntax unified
+	.global	_start
+	.thumb_func
+	.type	_start, %function
+	.type	thumb1, %function
+_start:
+thumb1:
+	movs r0, #:high_high:#thumb3
+	movs r1, #:high_low:#thumb3
+	movs r2, #:low_high:#thumb1
+	movs r3, #:low_low:#thumb1
+	movs r4, #:low_low:#thumb3
+	movs r5, #:low_high:#thumb3
+	movs r6, #:high_low:#thumb1
+	movs r7, #:high_high:#thumb1
+	.thumb_func
+	.type	thumb2, %function
+thumb2:
+	movs r0, #:high_high:#(thumb3 + 0)
+	movs r1, #:high_low:#(thumb2 + 1)
+	movs r2, #:low_high:#(var1 + 255)
+	movs r3, #:low_low:#var1
+	movs r7, #:high_high:#var1 + 4
+	movs r6, #:high_low:#var2
+	movs r5, #:low_high:#var2 + 0xff
+	movs r4, #:low_low:#var2 - (-1)
+var1:
+	.byte 1
+var2:
+	.byte 2
+
+	.section .far, "ax", %progbits
+	.thumb_func
+	.type	thumb3, %function
+thumb3:
+	movs r0, #:high_high:#thumb1
+	movs r1, #:high_low:#thumb2
+	movs r2, #:low_high:#thumb3
+	movs r3, #:low_low:#thumb1
+
-- 
2.6.2


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]