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]

TLS descriptors for ARM


This patch adds support for TLS descriptors for ARM. Refer to http://www.codesourcery.com/publications/RFC-TLSDESC-ARM.txt for the current specification.

The patch is a reworking of the patch posted at http://sourceware.org/ml/binutils/2006-08/msg00165.html. Please refer to that email thread for some background.

This version of the patch:
*) uses ARM-blessed reloc numbering (see ELF for ARM Architecture r2.08)
*) adds thumb2 support
*) adds support for out-of-range branches to the PLT trampolines
*) fixes a design issues discovered during implementation

The ARM EABI specifies 2 thumb tlsdesc relocs (R_ARM_THM_TLS_DESCSEQ{16,32}). During implementation I discovered separating these two cases to be both hard (because the assembler needs to know the size of the next instruction) and unnecessary (because the linker has to decode the instruction being pointed at anyway). Thus we implement only a single relocation (using the R_ARM_THM_TLS_DESCSEQ16 number). This change has been blessed by ARM, and I understand there will be an updated ABI document at some point reflecting this.

The design issue concerns local TLS symbols, which turned out to not be supported in the original specification. The new specification says of TLS_DESC dynamic relocations:

'For a local TLS symbol, the first slot is set to the symbol's offset within the TLS segment -- in essence this is an addend. For global symbols that are
lazily resolved, it is set to the symbol's index in the symbol table, ored with 0x80000000 in order to distinguish it from a local symbol offset.'


The x86 ABI has a similar issue, but doesn't need the top bit set to distinguish, as it has two dynamic resolvers to which the first slot can be initialized, and thereby distinguish. The ARM ABI only has a single resolver (and cannot have 2, because of the PLT trampoline it needs), and so must encode this distinction directly in the second slot. This change was also agreed with ARM.

I will be posting gcc and glibc patches later.

built and tested for arm-none-linux-gnueabi, ok?

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery

2011-01-05  Nathan Sidwell  <nathan@codesourcery.com>
	    Glauber de Oliveira Costa  <glommer@gmail.com>

	bfd/
	* reloc.c (BFD_RELOC_ARM_TLS_GOTDESC, BFD_RELOC_ARM_TLS_CALL,
	BFD_RELOC_ARM_THM_TLS_CALL, BFD_RELOC_ARM_TLS_DESCSEQ,
	BFD_RELOC_ARM_THM_TLS_DESCSEQ, BFD_RELOC_ARM_TLS_DESC): New
	relocations.
	* libbfd.h: Rebuilt.
	* bfd-in2.h: Rebuilt.
	* elf32-arm.c (elf32_arm_howto_table_1): Add new relocations.
	(elf32_arm_reloc_map): Likewise.
	(tls_trampoline, dl_tlsdesc_lazy_trampoline): New PLT templates.
	(elf32_arm_stub_long_branch_any_tls_pic,
	elf32_arm_stub_long_branch_v4t_thumb_tls_pic): New stub templates.
	(DEF_STUBS): Add new stubs.
	(struct_elf_arm_obj_data): Add local_tlsdesc_gotent field.
	(elf32_arm_local_tlsdesc_gotent): New.
	(GOT_TLS_GDESC): New mask.
	(GOT_TLS_GD_ANY): Define.
	(struct elf32_arm_link_hash_entry): Add tlsdesc_got field.
	(elf32_arm_compute_jump_table_size): New.
	(struct elf32_arm_link_hash_table): Add next_tls_desc_index,
	num_tls_desc, dt_tlsdesc_plt, dt_tlsdesc_got, tls_trampoline,
	sgotplt_jump_table_size fields.
	(elf32_arm_link_hash_newfunc): Initialize tlsdesc_got field.
	(elf32_arm_link_hash_table_create): Initialize new fields.
	(arm_type_of_stub): Check TLS desc relocs too.
	(elf32_arm_stub_name): TLS desc relocs can be shared.
	(elf32_arm_tls_transition): Determine relaxation.
	(arm_stub_required_alignment): Add tls stubs.
	(elf32_arm_size_stubs): Likewise.
	(elf32_arm_tls_relax): Perform TLS relaxing.
	(elf32_arm_final_link_relocate): Process TLS DESC relocations.
	(IS_ARM_TLS_GNU_RELOC): New.
	(IS_ARM_TLS_RELOC): Use it.
	(elf32_arm_relocate_section): Perform TLS relaxing.
	(elf32_arm_check_relocs): Anticipate TLS relaxing, process tls
	desc relocations.
	(allocate_dynrelocs): Allocate tls desc relcoations.
	(elf32_arm_output_arch_local_syms): Emit tls trampoline mapping
	symbols.
	(elf32_arm_size_dynamic_sections): Allocate tls trampolines and
	got slots.
	(elf32_arm_always_size_sections): New. Create _TLS_MODULE_BASE
	symbol.
	(elf32_arm_finish_dynamic_symbol): Adjust.
	(arm_put_trampoline): New.
	(elf32_arm_finish_dynamic_sections): Emit new dynamic tags and tls
	trampolines.
	(elf_backend_always_size_sections): Define.

	gas/
	* doc/c-arm.texi: Document TLSDESC and TLSCALL relocations, and
	.tlsdescseq directive.
	* config/tc-arm.c (arm_typed_reg_parse): Check for potential reloc
	following a symbol.
	(s_arm_tls_descseq): New directive.
	(md_pseudo_table): Add it.
	(encode_branch): Allow TLS_CALL relocs too.
	(do_t_blx, do_t_branch23): Use encode_branch.
	(reloc_names): Add tlsdesc and tlscall.
	(md_apply_fix): Process tls desc relocations.
	(tc_gen_reloc): Likewise.
	(arm_fix_adjustable): Likewise.

	gas/testsuite/
	* gas/arm/tls.s: Add tlsdesc tests.
	* gas/arm/tls.d: Adjust.

	ld/testsuite/
	* ld-arm/arm-elf.exp: Added tests for new TLS handling
	relocations.
	* ld-arm/tls-descrelax-be32.d: New.
	* ld-arm/tls-descrelax-be32.s: New.
	* ld-arm/tls-descrelax-be8.d: New.
	* ld-arm/tls-descrelax-be8.s: New.
	* ld-arm/tls-descrelax-v7.d: New.
	* ld-arm/tls-descrelax-v7.s: New.
	* ld-arm/tls-descrelax.d: New.
	* ld-arm/tls-descrelax.s: New.
	* ld-arm/tls-descseq.d: New.
	* ld-arm/tls-descseq.r: New.
	* ld-arm/tls-descseq.s: New.
	* ld-arm/tls-gdesc-got.d: New.
	* ld-arm/tls-gdesc-got.s: New.
	* ld-arm/tls-gdesc-nlazy.g: New.
	* ld-arm/tls-gdesc-nlazy.s: New.
	* ld-arm/tls-gdesc.d: New.
	* ld-arm/tls-gdesc.r: New.
	* ld-arm/tls-gdesc.s: New.
	* ld-arm/tls-gdierelax.d: New.
	* ld-arm/tls-gdierelax.s: New.
	* ld-arm/tls-gdierelax2.d: New.
	* ld-arm/tls-gdierelax2.s: New.
	* ld-arm/tls-gdlerelax.d: New.
	* ld-arm/tls-gdlerelax.s: New.
	* ld-arm/tls-lib-loc.d: New.
	* ld-arm/tls-lib-loc.r: New.
	* ld-arm/tls-lib-loc.s: New.
	* ld-arm/tls-longplt-lib.d: New.
	* ld-arm/tls-longplt-lib.s: New.
	* ld-arm/tls-longplt.d: New.
	* ld-arm/tls-longplt.s: New.
	* ld-arm/tls-mixed.r: New.
	* ld-arm/tls-mixed.s: New.
	* ld-arm/tls-thumb1.d: New.
	* ld-arm/tls-thumb1.s: New.
	* ld-arm/arm-elf.exp: New.

	include/elf/
	* arm.h (R_ARM_TLS_DESC, R_ARM_TLS_GOTDESC, R_ARM_TLS_CALL,
	R_ARM_TLS_DESCSEQ, T_ARM_THM_TLS_CALL, R_ARM_THM_TLS_DESCSEQ): New
	relocations.

Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.526
diff -c -3 -p -r1.526 bfd-in2.h
*** bfd/bfd-in2.h	31 Dec 2010 00:33:31 -0000	1.526
--- bfd/bfd-in2.h	5 Jan 2011 11:12:35 -0000
*************** pc-relative or some form of GOT-indirect
*** 3146,3151 ****
--- 3146,3157 ----
    BFD_RELOC_ARM_TLS_TPOFF32,
    BFD_RELOC_ARM_TLS_IE32,
    BFD_RELOC_ARM_TLS_LE32,
+   BFD_RELOC_ARM_TLS_GOTDESC,
+   BFD_RELOC_ARM_TLS_CALL,
+   BFD_RELOC_ARM_THM_TLS_CALL,
+   BFD_RELOC_ARM_TLS_DESCSEQ,
+   BFD_RELOC_ARM_THM_TLS_DESCSEQ,
+   BFD_RELOC_ARM_TLS_DESC,
  
  /* ARM group relocations.  */
    BFD_RELOC_ARM_ALU_PC_G0_NC,
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.251
diff -c -3 -p -r1.251 elf32-arm.c
*** bfd/elf32-arm.c	2 Dec 2010 13:28:35 -0000	1.251
--- bfd/elf32-arm.c	5 Jan 2011 11:12:43 -0000
*************** static reloc_howto_type elf32_arm_howto_
*** 261,278 ****
  	 0xffffffff,		/* dst_mask */
  	 FALSE),		/* pcrel_offset */
  
!   HOWTO (R_ARM_SWI24,		/* type */
  	 0,			/* rightshift */
! 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
! 	 0,			/* bitsize */
  	 FALSE,			/* pc_relative */
  	 0,			/* bitpos */
! 	 complain_overflow_signed,/* complain_on_overflow */
  	 bfd_elf_generic_reloc,	/* special_function */
! 	 "R_ARM_SWI24",		/* name */
  	 FALSE,			/* partial_inplace */
! 	 0x00000000,		/* src_mask */
! 	 0x00000000,		/* dst_mask */
  	 FALSE),		/* pcrel_offset */
  
    HOWTO (R_ARM_THM_SWI8,	/* type */
--- 261,278 ----
  	 0xffffffff,		/* dst_mask */
  	 FALSE),		/* pcrel_offset */
  
!   HOWTO (R_ARM_TLS_DESC,	/* type */
  	 0,			/* rightshift */
! 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
! 	 32,			/* bitsize */
  	 FALSE,			/* pc_relative */
  	 0,			/* bitpos */
! 	 complain_overflow_bitfield,/* complain_on_overflow */
  	 bfd_elf_generic_reloc,	/* special_function */
! 	 "R_ARM_TLS_DESC",	/* name */
  	 FALSE,			/* partial_inplace */
! 	 0xffffffff,		/* src_mask */
! 	 0xffffffff,		/* dst_mask */
  	 FALSE),		/* pcrel_offset */
  
    HOWTO (R_ARM_THM_SWI8,	/* type */
*************** static reloc_howto_type elf32_arm_howto_
*** 1352,1361 ****
  	 0x040f70ff,		/* dst_mask */
  	 FALSE),		/* pcrel_offset */
  
!   EMPTY_HOWTO (90),   /* Unallocated.  */
!   EMPTY_HOWTO (91),
!   EMPTY_HOWTO (92),
!   EMPTY_HOWTO (93),
  
    HOWTO (R_ARM_PLT32_ABS,	/* type */
  	 0,			/* rightshift */
--- 1352,1412 ----
  	 0x040f70ff,		/* dst_mask */
  	 FALSE),		/* pcrel_offset */
  
!   HOWTO (R_ARM_TLS_GOTDESC,	/* type */
! 	 0,			/* rightshift */
! 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
! 	 32,			/* bitsize */
! 	 FALSE,			/* pc_relative */
! 	 0,			/* bitpos */
! 	 complain_overflow_bitfield,/* complain_on_overflow */
! 	 NULL,			/* special_function */
! 	 "R_ARM_TLS_GOTDESC",	/* name */
! 	 TRUE,			/* partial_inplace */
! 	 0xffffffff,		/* src_mask */
! 	 0xffffffff,		/* dst_mask */
! 	 FALSE),		/* pcrel_offset */
! 
!   HOWTO (R_ARM_TLS_CALL,	/* type */
! 	 0,			/* rightshift */
! 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
! 	 24,			/* bitsize */
! 	 FALSE,			/* pc_relative */
! 	 0,			/* bitpos */
! 	 complain_overflow_dont,/* complain_on_overflow */
! 	 bfd_elf_generic_reloc,	/* special_function */
! 	 "R_ARM_TLS_CALL",	/* name */
! 	 FALSE,			/* partial_inplace */
! 	 0x00ffffff,		/* src_mask */
! 	 0x00ffffff,		/* dst_mask */
! 	 FALSE),		/* pcrel_offset */
! 
!   HOWTO (R_ARM_TLS_DESCSEQ,	/* type */
! 	 0,			/* rightshift */
! 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
! 	 0,			/* bitsize */
! 	 FALSE,			/* pc_relative */
! 	 0,			/* bitpos */
! 	 complain_overflow_bitfield,/* complain_on_overflow */
! 	 bfd_elf_generic_reloc,	/* special_function */
! 	 "R_ARM_TLS_DESCSEQ",	/* name */
! 	 FALSE,			/* partial_inplace */
! 	 0x00000000,		/* src_mask */
! 	 0x00000000,		/* dst_mask */
! 	 FALSE),		/* pcrel_offset */
! 
!   HOWTO (R_ARM_THM_TLS_CALL,	/* type */
! 	 0,			/* rightshift */
! 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
! 	 24,			/* bitsize */
! 	 FALSE,			/* pc_relative */
! 	 0,			/* bitpos */
! 	 complain_overflow_dont,/* complain_on_overflow */
! 	 bfd_elf_generic_reloc,	/* special_function */
! 	 "R_ARM_THM_TLS_CALL",	/* name */
! 	 FALSE,			/* partial_inplace */
! 	 0x07ff07ff,		/* src_mask */
! 	 0x07ff07ff,		/* dst_mask */
! 	 FALSE),		/* pcrel_offset */
  
    HOWTO (R_ARM_PLT32_ABS,	/* type */
  	 0,			/* rightshift */
*************** static reloc_howto_type elf32_arm_howto_
*** 1599,1604 ****
--- 1650,1687 ----
  	 0x00000fff,		/* src_mask */
  	 0x00000fff,		/* dst_mask */
  	 FALSE),		/* pcrel_offset */
+ 
+   EMPTY_HOWTO (112),
+   EMPTY_HOWTO (113),
+   EMPTY_HOWTO (114),
+   EMPTY_HOWTO (115),
+   EMPTY_HOWTO (116),
+   EMPTY_HOWTO (117),
+   EMPTY_HOWTO (118),
+   EMPTY_HOWTO (119),
+   EMPTY_HOWTO (120),
+   EMPTY_HOWTO (121),
+   EMPTY_HOWTO (122),
+   EMPTY_HOWTO (123),
+   EMPTY_HOWTO (124),
+   EMPTY_HOWTO (125),
+   EMPTY_HOWTO (126),
+   EMPTY_HOWTO (127),
+   EMPTY_HOWTO (128),
+ 
+   HOWTO (R_ARM_THM_TLS_DESCSEQ,	/* type */
+ 	 0,			/* rightshift */
+ 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+ 	 0,			/* bitsize */
+ 	 FALSE,			/* pc_relative */
+ 	 0,			/* bitpos */
+ 	 complain_overflow_bitfield,/* complain_on_overflow */
+ 	 bfd_elf_generic_reloc,	/* special_function */
+ 	 "R_ARM_THM_TLS_DESCSEQ",/* name */
+ 	 FALSE,			/* partial_inplace */
+ 	 0x00000000,		/* src_mask */
+ 	 0x00000000,		/* dst_mask */
+ 	 FALSE),		/* pcrel_offset */
  };
  
  /* 112-127 private relocations
*************** static const struct elf32_arm_reloc_map 
*** 1730,1735 ****
--- 1813,1824 ----
      {BFD_RELOC_ARM_PREL31,	     R_ARM_PREL31},
      {BFD_RELOC_ARM_TARGET2,	     R_ARM_TARGET2},
      {BFD_RELOC_ARM_PLT32,            R_ARM_PLT32},
+     {BFD_RELOC_ARM_TLS_GOTDESC,      R_ARM_TLS_GOTDESC},
+     {BFD_RELOC_ARM_TLS_CALL,         R_ARM_TLS_CALL},
+     {BFD_RELOC_ARM_THM_TLS_CALL,     R_ARM_THM_TLS_CALL},
+     {BFD_RELOC_ARM_TLS_DESCSEQ,      R_ARM_TLS_DESCSEQ},
+     {BFD_RELOC_ARM_THM_TLS_DESCSEQ,  R_ARM_THM_TLS_DESCSEQ},
+     {BFD_RELOC_ARM_TLS_DESC,         R_ARM_TLS_DESC},
      {BFD_RELOC_ARM_TLS_GD32,	     R_ARM_TLS_GD32},
      {BFD_RELOC_ARM_TLS_LDO32,	     R_ARM_TLS_LDO32},
      {BFD_RELOC_ARM_TLS_LDM32,	     R_ARM_TLS_LDM32},
*************** typedef unsigned short int insn16;
*** 1912,1917 ****
--- 2001,2026 ----
     section.  */
  #define ELF_DYNAMIC_INTERPRETER     "/usr/lib/ld.so.1"
  
+ static const unsigned long tls_trampoline [] =
+   {
+     0xe08e0000,		/* add r0, lr, r0 */
+     0xe5901004,		/* ldr r1, [r0,#4] */
+     0xe12fff11,		/* bx  r1 */
+   };
+ 
+ static const unsigned long dl_tlsdesc_lazy_trampoline [] =
+   {
+     0xe52d2004, /*	push    {r2}			*/
+     0xe59f200c, /*      ldr     r2, [pc, #3f - . - 8]	*/
+     0xe59f100c, /*      ldr     r1, [pc, #4f - . - 8]	*/
+     0xe79f2002, /* 1:   ldr     r2, [pc, r2]		*/
+     0xe081100f, /* 2:   add     r1, pc			*/
+     0xe12fff12, /*      bx      r2			*/
+     0x00000014, /* 3:   .word  _GLOBAL_OFFSET_TABLE_ - 1b - 8
+ 		   		+ dl_tlsdesc_lazy_resolver(GOT)   */
+     0x00000018, /* 4:   .word  _GLOBAL_OFFSET_TABLE_ - 2b - 8 */ 
+   };
+ 
  #ifdef FOUR_WORD_PLT
  
  /* The first entry in a procedure linkage table looks like
*************** static const insn_sequence elf32_arm_stu
*** 2167,2172 ****
--- 2276,2301 ----
      DATA_WORD(0, R_ARM_REL32, 0),     /* dcd  R_ARM_REL32(X) */
    };
  
+ /* Thumb2/ARM -> TLS trampoline.  Lowest common denominator, which is a
+    long PIC stub.  We can use r1 as a scratch -- and cannot use ip.  */
+ static const insn_sequence elf32_arm_stub_long_branch_any_tls_pic[] =
+ {
+     ARM_INSN(0xe59f1000),             /* ldr   r1, [pc] */
+     ARM_INSN(0xe08ff001),             /* add   pc, pc, r1 */
+     DATA_WORD(0, R_ARM_REL32, -4),    /* dcd   R_ARM_REL32(X-4) */
+ };
+ 
+ /* V4T Thumb -> TLS trampoline.  lowest common denominator, which is a
+    long PIC stub.  We can use r1 as a scratch -- and cannot use ip.  */
+ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_tls_pic[] =
+ {
+     THUMB16_INSN(0x4778),             /* bx   pc */
+     THUMB16_INSN(0x46c0),             /* nop */
+     ARM_INSN(0xe59f1000),             /* ldr  r1, [pc, #0] */
+     ARM_INSN(0xe081f00f),             /* add  pc, r1, pc */
+     DATA_WORD(0, R_ARM_REL32, -4),    /* dcd  R_ARM_REL32(X) */
+ };
+ 
  /* Cortex-A8 erratum-workaround stubs.  */
  
  /* Stub used for conditional branches (which may be beyond +/-1MB away, so we
*************** static const insn_sequence elf32_arm_stu
*** 2218,2223 ****
--- 2347,2354 ----
    DEF_STUB(long_branch_v4t_arm_thumb_pic) \
    DEF_STUB(long_branch_v4t_thumb_arm_pic) \
    DEF_STUB(long_branch_thumb_only_pic) \
+   DEF_STUB(long_branch_any_tls_pic) \
+   DEF_STUB(long_branch_v4t_thumb_tls_pic) \
    DEF_STUB(a8_veneer_b_cond) \
    DEF_STUB(a8_veneer_b) \
    DEF_STUB(a8_veneer_bl) \
*************** struct elf_arm_obj_tdata
*** 2426,2431 ****
--- 2557,2565 ----
    /* tls_type for each local got entry.  */
    char *local_got_tls_type;
  
+   /* GOTPLT entries for TLS descriptors.  */
+   bfd_vma *local_tlsdesc_gotent;
+ 
    /* Zero to warn when linking objects with incompatible enum sizes.  */
    int no_enum_size_warning;
  
*************** struct elf_arm_obj_tdata
*** 2439,2444 ****
--- 2573,2581 ----
  #define elf32_arm_local_got_tls_type(bfd) \
    (elf_arm_tdata (bfd)->local_got_tls_type)
  
+ #define elf32_arm_local_tlsdesc_gotent(bfd) \
+   (elf_arm_tdata (bfd)->local_tlsdesc_gotent)
+ 
  #define is_arm_elf(bfd) \
    (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
     && elf_tdata (bfd) != NULL \
*************** struct elf32_arm_link_hash_entry
*** 2478,2485 ****
--- 2615,2628 ----
  #define GOT_NORMAL	1
  #define GOT_TLS_GD	2
  #define GOT_TLS_IE	4
+ #define GOT_TLS_GDESC	8
+ #define GOT_TLS_GD_ANY_P(type)	((type & GOT_TLS_GD) || (type & GOT_TLS_GDESC))
      unsigned char tls_type;
  
+     /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+        starting at the end of the jump table.  */
+     bfd_vma tlsdesc_got;
+ 
      /* The symbol marking the real symbol location for exported thumb
         symbols with Arm stubs.  */
      struct elf_link_hash_entry *export_glue;
*************** struct map_stub
*** 2516,2521 ****
--- 2659,2667 ----
    asection *stub_sec;
  };
  
+ #define elf32_arm_compute_jump_table_size(htab) \
+   ((htab)->next_tls_desc_index * 4)
+ 
  /* ARM ELF linker hash table.  */
  struct elf32_arm_link_hash_table
  {
*************** struct elf32_arm_link_hash_table
*** 2594,2599 ****
--- 2740,2751 ----
    /* True if the target uses REL relocations.  */
    int use_rel;
  
+   /* The index of the next unused R_ARM_TLS_DESC slot in .rel.plt.  */
+   bfd_vma next_tls_desc_index;
+ 
+   /* How many R_ARM_TLS_DESC relocations were generated so far.  */
+   bfd_vma num_tls_desc;
+ 
    /* Short-cuts to get to dynamic linker sections.  */
    asection *sdynbss;
    asection *srelbss;
*************** struct elf32_arm_link_hash_table
*** 2601,2606 ****
--- 2753,2771 ----
    /* The (unloaded but important) VxWorks .rela.plt.unloaded section.  */
    asection *srelplt2;
  
+   /* The offset into splt of the PLT entry for the TLS descriptor
+      resolver.  Special values are 0, if not necessary (or not found
+      to be necessary yet), and -1 if needed but not determined
+      yet.  */
+   bfd_vma dt_tlsdesc_plt;
+ 
+   /* The offset into sgot of the GOT entry used by the PLT entry
+      above.  */
+   bfd_vma dt_tlsdesc_got;    
+ 
+   /* Offset in .plt section of tls_arm_trampoline.  */
+   bfd_vma tls_trampoline;
+ 
    /* Data for R_ARM_TLS_LDM32 relocations.  */
    union
    {
*************** struct elf32_arm_link_hash_table
*** 2614,2619 ****
--- 2779,2788 ----
    /* For convenience in allocate_dynrelocs.  */
    bfd * obfd;
  
+   /* The amount of space used by the reserved portion of the sgotplt
+      section, plus whatever space is used by the jump slots.  */
+   bfd_vma sgotplt_jump_table_size;
+ 
    /* The stub hash table.  */
    struct bfd_hash_table stub_hash_table;
  
*************** elf32_arm_link_hash_newfunc (struct bfd_
*** 2663,2668 ****
--- 2832,2838 ----
      {
        ret->dyn_relocs = NULL;
        ret->tls_type = GOT_UNKNOWN;
+       ret->tlsdesc_got = (bfd_vma) -1;
        ret->plt_thumb_refcount = 0;
        ret->plt_maybe_thumb_refcount = 0;
        ret->plt_got_offset = -1;
*************** elf32_arm_link_hash_table_create (bfd *a
*** 2877,2882 ****
--- 3047,3057 ----
    ret->sdynbss = NULL;
    ret->srelbss = NULL;
    ret->srelplt2 = NULL;
+   ret->dt_tlsdesc_plt = 0;
+   ret->dt_tlsdesc_got = 0;
+   ret->tls_trampoline = 0;
+   ret->next_tls_desc_index = 0;
+   ret->num_tls_desc = 0;
    ret->thumb_glue_size = 0;
    ret->arm_glue_size = 0;
    ret->bx_glue_size = 0;
*************** arm_type_of_stub (struct bfd_link_info *
*** 3075,3081 ****
  
    branch_offset = (bfd_signed_vma)(destination - location);
  
!   if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
      {
        /* Handle cases where:
  	 - this call goes too far (different Thumb/Thumb2 max
--- 3250,3257 ----
  
    branch_offset = (bfd_signed_vma)(destination - location);
  
!   if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24
!       || r_type == R_ARM_THM_TLS_CALL)
      {
        /* Handle cases where:
  	 - this call goes too far (different Thumb/Thumb2 max
*************** arm_type_of_stub (struct bfd_link_info *
*** 3092,3098 ****
  	      && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
  		  || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
  	  || ((st_type != STT_ARM_TFUNC)
! 	      && (((r_type == R_ARM_THM_CALL) && !globals->use_blx)
  		  || (r_type == R_ARM_THM_JUMP24))
  	      && !use_plt))
  	{
--- 3268,3275 ----
  	      && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
  		  || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
  	  || ((st_type != STT_ARM_TFUNC)
! 	      && (((r_type == R_ARM_THM_CALL
! 		    || r_type == R_ARM_THM_TLS_CALL) && !globals->use_blx)
  		  || (r_type == R_ARM_THM_JUMP24))
  	      && !use_plt))
  	{
*************** arm_type_of_stub (struct bfd_link_info *
*** 3143,3160 ****
  		     sym_sec->owner, input_bfd, name);
  		}
  
! 	      stub_type = (info->shared | globals->pic_veneer)
  		/* PIC stubs.  */
! 		? ((globals->use_blx
! 		    && (r_type ==R_ARM_THM_CALL))
! 		   /* V5T and above.  */
! 		   ? arm_stub_long_branch_any_arm_pic
! 		   /* V4T PIC stub.  */
! 		   : arm_stub_long_branch_v4t_thumb_arm_pic)
  
  		/* non-PIC stubs.  */
! 		: ((globals->use_blx
! 		    && (r_type ==R_ARM_THM_CALL))
  		   /* V5T and above.  */
  		   ? arm_stub_long_branch_any_any
  		   /* V4T.  */
--- 3320,3340 ----
  		     sym_sec->owner, input_bfd, name);
  		}
  
! 	      stub_type =
! 		(info->shared | globals->pic_veneer)
  		/* PIC stubs.  */
! 		? (r_type == R_ARM_THM_TLS_CALL
! 		   /* TLS PIC stubs */
! 		   ? (globals->use_blx ? arm_stub_long_branch_any_tls_pic
! 		      : arm_stub_long_branch_v4t_thumb_tls_pic)
! 		   : ((globals->use_blx && r_type == R_ARM_THM_CALL)
! 		      /* V5T PIC and above.  */
! 		      ? arm_stub_long_branch_any_arm_pic
! 		      /* V4T PIC stub.  */
! 		      : arm_stub_long_branch_v4t_thumb_arm_pic))
  
  		/* non-PIC stubs.  */
! 		: ((globals->use_blx && r_type == R_ARM_THM_CALL)
  		   /* V5T and above.  */
  		   ? arm_stub_long_branch_any_any
  		   /* V4T.  */
*************** arm_type_of_stub (struct bfd_link_info *
*** 3170,3176 ****
      }
    else if (r_type == R_ARM_CALL
  	   || r_type == R_ARM_JUMP24
! 	   || r_type == R_ARM_PLT32)
      {
        if (st_type == STT_ARM_TFUNC)
  	{
--- 3350,3357 ----
      }
    else if (r_type == R_ARM_CALL
  	   || r_type == R_ARM_JUMP24
! 	   || r_type == R_ARM_PLT32
! 	   || r_type == R_ARM_TLS_CALL)
      {
        if (st_type == STT_ARM_TFUNC)
  	{
*************** arm_type_of_stub (struct bfd_link_info *
*** 3190,3196 ****
  	     the mode change (bit 24 (H) of BLX encoding).  */
  	  if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2)
  	      || (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET)
! 	      || ((r_type == R_ARM_CALL) && !globals->use_blx)
  	      || (r_type == R_ARM_JUMP24)
  	      || (r_type == R_ARM_PLT32))
  	    {
--- 3371,3377 ----
  	     the mode change (bit 24 (H) of BLX encoding).  */
  	  if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2)
  	      || (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET)
! 	      || (r_type == R_ARM_CALL && !globals->use_blx)
  	      || (r_type == R_ARM_JUMP24)
  	      || (r_type == R_ARM_PLT32))
  	    {
*************** arm_type_of_stub (struct bfd_link_info *
*** 3216,3224 ****
  	  if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET
  	      || (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET))
  	    {
! 	      stub_type = (info->shared | globals->pic_veneer)
  		/* PIC stubs.  */
! 		? arm_stub_long_branch_any_arm_pic
  		/* non-PIC stubs.  */
  		: arm_stub_long_branch_any_any;
  	    }
--- 3397,3409 ----
  	  if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET
  	      || (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET))
  	    {
! 	      stub_type =
! 		(info->shared | globals->pic_veneer)
  		/* PIC stubs.  */
! 		? (r_type == R_ARM_TLS_CALL
! 		   /* TLS PIC Stub */
! 		   ? arm_stub_long_branch_any_tls_pic
! 		   : arm_stub_long_branch_any_arm_pic)
  		/* non-PIC stubs.  */
  		: arm_stub_long_branch_any_any;
  	    }
*************** elf32_arm_stub_name (const asection *inp
*** 3263,3269 ****
  	sprintf (stub_name, "%08x_%x:%x+%x_%d",
  		 input_section->id & 0xffffffff,
  		 sym_sec->id & 0xffffffff,
! 		 (int) ELF32_R_SYM (rel->r_info) & 0xffffffff,
  		 (int) rel->r_addend & 0xffffffff,
  		 (int) stub_type);
      }
--- 3448,3456 ----
  	sprintf (stub_name, "%08x_%x:%x+%x_%d",
  		 input_section->id & 0xffffffff,
  		 sym_sec->id & 0xffffffff,
! 		 ELF32_R_TYPE (rel->r_info) == R_ARM_TLS_CALL
! 		 || ELF32_R_TYPE (rel->r_info) == R_ARM_THM_TLS_CALL
! 		 ? 0 : (int) ELF32_R_SYM (rel->r_info) & 0xffffffff,
  		 (int) rel->r_addend & 0xffffffff,
  		 (int) stub_type);
      }
*************** put_thumb_insn (struct elf32_arm_link_ha
*** 3426,3431 ****
--- 3613,3644 ----
      bfd_putb16 (val, ptr);
  }
  
+ /* If it's possible to change R_TYPE to a more efficient access
+    model, return the new reloc type.  */
+ 
+ static unsigned
+ elf32_arm_tls_transition (struct bfd_link_info *info, int r_type, 
+ 			  struct elf_link_hash_entry *h)
+ {
+   int is_local = (h == NULL);
+ 
+   if (info->shared || (h && h->root.type == bfd_link_hash_undefweak))
+     return r_type;
+ 
+   /* We do not support relaxations for Old TLS models.  */ 
+   switch (r_type)
+     {
+     case R_ARM_TLS_GOTDESC:
+     case R_ARM_TLS_CALL:
+     case R_ARM_THM_TLS_CALL:
+     case R_ARM_TLS_DESCSEQ:
+     case R_ARM_THM_TLS_DESCSEQ:
+       return is_local ? R_ARM_TLS_LE32 : R_ARM_TLS_IE32;
+     }
+ 
+   return r_type;
+ }
+ 
  static bfd_reloc_status_type elf32_arm_final_link_relocate
    (reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *,
     Elf_Internal_Rela *, bfd_vma, struct bfd_link_info *, asection *,
*************** arm_stub_required_alignment (enum elf32_
*** 3453,3458 ****
--- 3666,3673 ----
      case arm_stub_long_branch_v4t_arm_thumb_pic:
      case arm_stub_long_branch_v4t_thumb_arm_pic:
      case arm_stub_long_branch_thumb_only_pic:
+     case arm_stub_long_branch_any_tls_pic:
+     case arm_stub_long_branch_v4t_thumb_tls_pic:
      case arm_stub_a8_veneer_blx:
        return 4;
      
*************** elf32_arm_size_stubs (bfd *output_bfd,
*** 4419,4433 ****
  			free (internal_relocs);
  		      goto error_ret_free_local;
  		    }
! 
! 		  /* Only look for stubs on branch instructions.  */
  		  if ((r_type != (unsigned int) R_ARM_CALL)
  		      && (r_type != (unsigned int) R_ARM_THM_CALL)
  		      && (r_type != (unsigned int) R_ARM_JUMP24)
  		      && (r_type != (unsigned int) R_ARM_THM_JUMP19)
  		      && (r_type != (unsigned int) R_ARM_THM_XPC22)
  		      && (r_type != (unsigned int) R_ARM_THM_JUMP24)
! 		      && (r_type != (unsigned int) R_ARM_PLT32))
  		    continue;
  
  		  /* Now determine the call target, its name, value,
--- 4634,4663 ----
  			free (internal_relocs);
  		      goto error_ret_free_local;
  		    }
! 		  
! 		  hash = NULL;
! 		  if (r_indx >= symtab_hdr->sh_info)
! 		    hash = elf32_arm_hash_entry
! 		      (elf_sym_hashes (input_bfd)
! 		       [r_indx - symtab_hdr->sh_info]);
! 		  
! 		  /* Only look for stubs on branch instructions, or
! 		     non-relaxed TLSCALL  */
  		  if ((r_type != (unsigned int) R_ARM_CALL)
  		      && (r_type != (unsigned int) R_ARM_THM_CALL)
  		      && (r_type != (unsigned int) R_ARM_JUMP24)
  		      && (r_type != (unsigned int) R_ARM_THM_JUMP19)
  		      && (r_type != (unsigned int) R_ARM_THM_XPC22)
  		      && (r_type != (unsigned int) R_ARM_THM_JUMP24)
! 		      && (r_type != (unsigned int) R_ARM_PLT32)
! 		      && !((r_type == (unsigned int) R_ARM_TLS_CALL
! 			    || r_type == (unsigned int) R_ARM_THM_TLS_CALL)
! 			   && r_type == elf32_arm_tls_transition
! 			       (info, r_type, &hash->root)
! 			   && ((hash ? hash->tls_type
! 				: (elf32_arm_local_got_tls_type
! 				   (input_bfd)[r_indx]))
! 			       & GOT_TLS_GDESC) != 0))
  		    continue;
  
  		  /* Now determine the call target, its name, value,
*************** elf32_arm_size_stubs (bfd *output_bfd,
*** 4435,4443 ****
  		  sym_sec = NULL;
  		  sym_value = 0;
  		  destination = 0;
- 		  hash = NULL;
  		  sym_name = NULL;
! 		  if (r_indx < symtab_hdr->sh_info)
  		    {
  		      /* It's a local symbol.  */
  		      Elf_Internal_Sym *sym;
--- 4665,4685 ----
  		  sym_sec = NULL;
  		  sym_value = 0;
  		  destination = 0;
  		  sym_name = NULL;
! 		  
! 		  if (r_type == (unsigned int) R_ARM_TLS_CALL
! 		      || r_type == (unsigned int) R_ARM_THM_TLS_CALL)
! 		    {
! 		      /* A non-relaxed TLS call.  The target is the
! 			 plt-resident trampoline and nothing to do
! 			 with the symbol.  */
! 		      BFD_ASSERT (htab->tls_trampoline > 0);
! 		      sym_sec = htab->root.splt;
! 		      sym_value = htab->tls_trampoline;
! 		      hash = 0;
! 		      st_type = STT_FUNC;
! 		    }
! 		  else if (!hash)
  		    {
  		      /* It's a local symbol.  */
  		      Elf_Internal_Sym *sym;
*************** elf32_arm_size_stubs (bfd *output_bfd,
*** 4485,4496 ****
  		  else
  		    {
  		      /* It's an external symbol.  */
- 		      int e_indx;
- 
- 		      e_indx = r_indx - symtab_hdr->sh_info;
- 		      hash = ((struct elf32_arm_link_hash_entry *)
- 			      elf_sym_hashes (input_bfd)[e_indx]);
- 
  		      while (hash->root.root.type == bfd_link_hash_indirect
  			     || hash->root.root.type == bfd_link_hash_warning)
  			hash = ((struct elf32_arm_link_hash_entry *)
--- 4727,4732 ----
*************** elf32_arm_abs12_reloc (bfd *abfd, void *
*** 6743,6748 ****
--- 6979,7126 ----
    return bfd_reloc_ok;
  }
  
+ /* Handle TLS relaxations.  Relaxing is possible for symbols that use
+    R_ARM_GOTDESC, R_ARM_{,THM_}TLS_CALL or
+    R_ARM_{,THM_}TLS_DESCSEQ relocations, during a static link.
+ 
+    Return bfd_reloc_ok if we're done, bfd_reloc_continue if the caller
+    is to then call final_link_relocate.  Return other values in the
+    case of error.  */
+  
+ 
+ static bfd_reloc_status_type 
+ elf32_arm_tls_relax (struct elf32_arm_link_hash_table *globals,
+ 		     bfd *input_bfd, asection *input_sec, bfd_byte *contents, 
+ 		     Elf_Internal_Rela *rel, unsigned long is_local)
+ {
+   unsigned long insn;
+   
+   switch (ELF32_R_TYPE (rel->r_info))
+     {
+     default:
+       return bfd_reloc_notsupported;
+       
+     case R_ARM_TLS_GOTDESC:
+       if (is_local)
+ 	insn = 0;
+       else
+ 	{
+ 	  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ 	  if (insn & 1)
+ 	    insn -= 5; /* THUMB */
+ 	  else
+ 	    insn -= 8; /* ARM */
+ 	}
+       bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+       return bfd_reloc_continue;
+ 
+     case R_ARM_THM_TLS_DESCSEQ:
+       /* Thumb insn.  */
+       insn = bfd_get_16 (input_bfd, contents + rel->r_offset);
+       if ((insn & 0xff78) == 0x4478)	  /* add rx, pc */
+ 	{
+ 	  if (is_local)
+ 	    /* nop */
+ 	    bfd_put_16 (input_bfd, 0x46c0, contents + rel->r_offset);
+ 	}
+       else if ((insn & 0xffc0) == 0x6840)  /* ldr rx,[ry,#4] */
+ 	{
+ 	  if (is_local)
+ 	    /* nop */
+ 	    bfd_put_16 (input_bfd, 0x46c0, contents + rel->r_offset);
+ 	  else
+ 	    /* ldr rx,[ry] */
+ 	    bfd_put_16 (input_bfd, insn & 0xf83f, contents + rel->r_offset);
+ 	}
+       else if ((insn & 0xff87) == 0x4780)  /* blx rx */
+ 	{
+ 	  if (is_local)
+ 	    /* nop */
+ 	    bfd_put_16 (input_bfd, 0x46c0, contents + rel->r_offset);
+ 	  else
+ 	    /* mov r0, rx */
+ 	    bfd_put_16 (input_bfd, 0x4600 | (insn & 0x78),
+ 			contents + rel->r_offset);
+ 	}
+       else
+ 	{
+ 	  if ((insn & 0xf000) == 0xf000 || (insn & 0xf800) == 0xe800)
+ 	    /* It's a 32 bit instruction, fetch the rest of it for
+ 	       error generation.  */
+ 	    insn = (insn << 16)
+ 	      | bfd_get_16 (input_bfd, contents + rel->r_offset + 2);
+ 	  (*_bfd_error_handler)
+ 	    (_("%B(%A+0x%lx):unexpected Thumb instruction '0x%x' in TLS trampoline"),
+ 	     input_bfd, input_sec, (unsigned long)rel->r_offset, insn);
+ 	  return bfd_reloc_notsupported;
+ 	}
+       break;
+       
+     case R_ARM_TLS_DESCSEQ:
+       /* arm insn.  */
+       insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+       if ((insn & 0xffff0ff0) == 0xe08f0000) /* add rx,pc,ry */
+ 	{
+ 	  if (is_local)
+ 	    /* mov rx, ry */
+ 	    bfd_put_32 (input_bfd, 0xe1a00000 | (insn & 0xffff),
+ 			contents + rel->r_offset);
+ 	}
+       else if ((insn & 0xfff00fff) == 0xe5900004) /* ldr rx,[ry,#4]*/
+ 	{
+ 	  if (is_local)
+ 	    /* nop */
+ 	    bfd_put_32 (input_bfd, 0xe1a00000, contents + rel->r_offset);
+ 	  else
+ 	    /* ldr rx,[ry] */
+ 	    bfd_put_32 (input_bfd, insn & 0xfffff000,
+ 			contents + rel->r_offset);
+ 	}
+       else if ((insn & 0xfffffff0) == 0xe12fff30) /* blx rx */
+ 	{
+ 	  if (is_local)
+ 	    /* nop */
+ 	    bfd_put_32 (input_bfd, 0xe1a00000, contents + rel->r_offset);
+ 	  else
+ 	    /* mov r0, rx */
+ 	    bfd_put_32 (input_bfd, 0xe1a00000 | (insn & 0xf),
+ 			contents + rel->r_offset);
+ 	}
+       else
+ 	{
+ 	  (*_bfd_error_handler)
+ 	    (_("%B(%A+0x%lx):unexpected ARM instruction '0x%x' in TLS trampoline"),
+ 	     input_bfd, input_sec, (unsigned long)rel->r_offset, insn);
+ 	  return bfd_reloc_notsupported;
+ 	}
+       break;
+ 
+     case R_ARM_TLS_CALL:
+       /* GD->IE relaxation, turn the instruction into 'nop' or
+ 	 'ldr r0, [pc,r0]'  */
+       insn = is_local ? 0xe1a00000 : 0xe79f0000;
+       bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+       break;
+       
+     case R_ARM_THM_TLS_CALL:
+       /* GD->IE relaxation */
+       if (!is_local)
+ 	/* add r0,pc; ldr r0, [r0]  */
+ 	insn = 0x44786800;
+       else if (arch_has_thumb2_nop (globals))
+ 	/* nop.w */
+ 	insn = 0xf3af8000;
+       else
+ 	/* nop; nop */
+ 	insn = 0xbf00bf00;
+ 	
+       bfd_put_16 (input_bfd, insn >> 16, contents + rel->r_offset);
+       bfd_put_16 (input_bfd, insn & 0xffff, contents + rel->r_offset + 2);
+       break;
+     }
+   return bfd_reloc_ok;
+ }
+ 
  /* For a given value of n, calculate the value of G_n as required to
     deal with group relocations.  We return it in the form of an
     encoded constant-and-rotation, together with the final residual.  If n is
*************** elf32_arm_final_link_relocate (reloc_how
*** 6834,6839 ****
--- 7212,7218 ----
    unsigned long                 r_symndx;
    bfd_byte *                    hit_data = contents + rel->r_offset;
    bfd_vma *                     local_got_offsets;
+   bfd_vma *                     local_tlsdesc_gotents;
    asection *                    sgot = NULL;
    asection *                    splt = NULL;
    asection *                    sreloc = NULL;
*************** elf32_arm_final_link_relocate (reloc_how
*** 6851,6856 ****
--- 7230,7240 ----
    /* Some relocation types map to different relocations depending on the
       target.  We pick the right one here.  */
    r_type = arm_real_reloc_type (globals, r_type);
+ 
+   /* It is possible to have linker relaxations on some TLS access
+      models.  Update our information here.  */
+   r_type = elf32_arm_tls_transition (info, r_type, h);
+ 
    if (r_type != howto->type)
      howto = elf32_arm_howto_from_type (r_type);
  
*************** elf32_arm_final_link_relocate (reloc_how
*** 6870,6875 ****
--- 7254,7261 ----
    splt = globals->root.splt;
    srelgot = globals->root.srelgot;
    local_got_offsets = elf_local_got_offsets (input_bfd);
+   local_tlsdesc_gotents = elf32_arm_local_tlsdesc_gotent (input_bfd);
+ 
    r_symndx = ELF32_R_SYM (rel->r_info);
  
    if (globals->use_rel)
*************** elf32_arm_final_link_relocate (reloc_how
*** 8010,8026 ****
  					 rel->r_addend);
        }
  
      case R_ARM_TLS_GD32:
      case R_ARM_TLS_IE32:
        {
! 	bfd_vma off;
! 	int indx;
  	char tls_type;
  
! 	if (sgot == NULL)
! 	  abort ();
  
- 	indx = 0;
  	if (h != NULL)
  	  {
  	    bfd_boolean dyn;
--- 8396,8415 ----
  					 rel->r_addend);
        }
  
+     case R_ARM_TLS_CALL:
+     case R_ARM_THM_TLS_CALL:
      case R_ARM_TLS_GD32:
      case R_ARM_TLS_IE32:
+     case R_ARM_TLS_GOTDESC:
+     case R_ARM_TLS_DESCSEQ:
+     case R_ARM_THM_TLS_DESCSEQ:
        {
! 	bfd_vma off, offplt;
! 	int indx = 0;
  	char tls_type;
  
! 	BFD_ASSERT (sgot != NULL);
  
  	if (h != NULL)
  	  {
  	    bfd_boolean dyn;
*************** elf32_arm_final_link_relocate (reloc_how
*** 8033,8050 ****
  		indx = h->dynindx;
  	      }
  	    off = h->got.offset;
  	    tls_type = ((struct elf32_arm_link_hash_entry *) h)->tls_type;
  	  }
  	else
  	  {
! 	    if (local_got_offsets == NULL)
! 	      abort ();
  	    off = local_got_offsets[r_symndx];
  	    tls_type = elf32_arm_local_got_tls_type (input_bfd)[r_symndx];
  	  }
  
! 	if (tls_type == GOT_UNKNOWN)
! 	  abort ();
  
  	if ((off & 1) != 0)
  	  off &= ~1;
--- 8422,8444 ----
  		indx = h->dynindx;
  	      }
  	    off = h->got.offset;
+ 	    offplt = elf32_arm_hash_entry (h)->tlsdesc_got;
  	    tls_type = ((struct elf32_arm_link_hash_entry *) h)->tls_type;
  	  }
  	else
  	  {
! 	    BFD_ASSERT (local_got_offsets != NULL);
  	    off = local_got_offsets[r_symndx];
+ 	    offplt = local_tlsdesc_gotents[r_symndx];
  	    tls_type = elf32_arm_local_got_tls_type (input_bfd)[r_symndx];
  	  }
  
! 	/* Linker relaxations happens from one of the
! 	   R_ARM_{GOTDESC,CALL,DESCSEQ} relocations to IE or LE.  */ 
! 	if (ELF32_R_TYPE(rel->r_info) != r_type)
! 	  tls_type = GOT_TLS_IE; 
! 
! 	BFD_ASSERT (tls_type != GOT_UNKNOWN);
  
  	if ((off & 1) != 0)
  	  off &= ~1;
*************** elf32_arm_final_link_relocate (reloc_how
*** 8065,8076 ****
  		    || h->root.type != bfd_link_hash_undefweak))
  	      {
  		need_relocs = TRUE;
! 		if (srelgot == NULL)
! 		  abort ();
! 		loc = srelgot->contents;
! 		loc += srelgot->reloc_count * RELOC_SIZE (globals);
  	      }
  
  	    if (tls_type & GOT_TLS_GD)
  	      {
  		if (need_relocs)
--- 8459,8507 ----
  		    || h->root.type != bfd_link_hash_undefweak))
  	      {
  		need_relocs = TRUE;
! 		BFD_ASSERT (srelgot != NULL);
  	      }
  
+ 	    if (tls_type & GOT_TLS_GDESC)
+ 	      {
+ 		/* We should have relaxed, unless this is an undefined
+ 		   weak symbol.  */
+ 		BFD_ASSERT ((h && (h->root.type == bfd_link_hash_undefweak))
+ 			    || info->shared);
+ 		BFD_ASSERT (globals->sgotplt_jump_table_size + offplt + 8
+                             <= globals->root.sgotplt->size);
+ 
+ 		outrel.r_addend = 0;
+ 		outrel.r_offset = (globals->root.sgotplt->output_section->vma
+ 				   + globals->root.sgotplt->output_offset
+ 				   + offplt
+ 				   + globals->sgotplt_jump_table_size);
+ 		
+ 		outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_DESC);
+ 		sreloc = globals->root.srelplt;
+ 		loc = sreloc->contents;
+ 		loc += globals->next_tls_desc_index++ * RELOC_SIZE (globals);
+ 		BFD_ASSERT (loc + RELOC_SIZE (globals)
+ 		   	   <= sreloc->contents + sreloc->size);
+ 
+ 		SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
+ 
+ 		/* For globals, the first word in the relocation gets
+ 		   the relocation index and the top bit set, or zero,
+ 		   if we're binding now.  For locals, it gets the
+ 		   symbol's offset in the tls section.  */
+ 	    	bfd_put_32 (output_bfd,
+ 			    !h ? value - elf_hash_table (info)->tls_sec->vma
+ 			    : info->flags & DF_BIND_NOW ? 0
+ 			    : 0x80000000 | ELF32_R_SYM (outrel.r_info),
+ 			    globals->root.sgotplt->contents + offplt +
+ 			    globals->sgotplt_jump_table_size);
+ 		
+ 		/* Second word in the relocation is always zero.  */
+ 	    	bfd_put_32 (output_bfd, 0,
+ 			    globals->root.sgotplt->contents + offplt +
+ 			    globals->sgotplt_jump_table_size + 4);
+ 	      }
  	    if (tls_type & GOT_TLS_GD)
  	      {
  		if (need_relocs)
*************** elf32_arm_final_link_relocate (reloc_how
*** 8084,8093 ****
  		    if (globals->use_rel)
  		      bfd_put_32 (output_bfd, outrel.r_addend,
  				  sgot->contents + cur_off);
  
  		    SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
- 		    srelgot->reloc_count++;
- 		    loc += RELOC_SIZE (globals);
  
  		    if (indx == 0)
  		      bfd_put_32 (output_bfd, value - dtpoff_base (info),
--- 8515,8524 ----
  		    if (globals->use_rel)
  		      bfd_put_32 (output_bfd, outrel.r_addend,
  				  sgot->contents + cur_off);
+ 		    loc = srelgot->contents;
+ 		    loc += srelgot->reloc_count++ * RELOC_SIZE (globals);
  
  		    SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
  
  		    if (indx == 0)
  		      bfd_put_32 (output_bfd, value - dtpoff_base (info),
*************** elf32_arm_final_link_relocate (reloc_how
*** 8103,8112 ****
  			  bfd_put_32 (output_bfd, outrel.r_addend,
  				      sgot->contents + cur_off + 4);
  
  
  			SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
- 			srelgot->reloc_count++;
- 			loc += RELOC_SIZE (globals);
  		      }
  		  }
  		else
--- 8534,8543 ----
  			  bfd_put_32 (output_bfd, outrel.r_addend,
  				      sgot->contents + cur_off + 4);
  
+ 		    	loc = srelgot->contents;
+ 		   	loc += srelgot->reloc_count++ * RELOC_SIZE (globals);
  
  			SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
  		      }
  		  }
  		else
*************** elf32_arm_final_link_relocate (reloc_how
*** 8142,8150 ****
  		      bfd_put_32 (output_bfd, outrel.r_addend,
  				  sgot->contents + cur_off);
  
  		    SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
- 		    srelgot->reloc_count++;
- 		    loc += RELOC_SIZE (globals);
  		  }
  		else
  		  bfd_put_32 (output_bfd, tpoff (info, value),
--- 8573,8582 ----
  		      bfd_put_32 (output_bfd, outrel.r_addend,
  				  sgot->contents + cur_off);
  
+ 		    loc = srelgot->contents;
+ 		    loc += srelgot->reloc_count++ * RELOC_SIZE (globals);
+ 
  		    SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
  		  }
  		else
  		  bfd_put_32 (output_bfd, tpoff (info, value),
*************** elf32_arm_final_link_relocate (reloc_how
*** 8160,8167 ****
  
  	if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32)
  	  off += 8;
! 	value = sgot->output_section->vma + sgot->output_offset + off
! 	  - (input_section->output_section->vma + input_section->output_offset + rel->r_offset);
  
  	return _bfd_final_link_relocate (howto, input_bfd, input_section,
  					 contents, rel->r_offset, value,
--- 8592,8733 ----
  
  	if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32)
  	  off += 8;
! 	else if (tls_type & GOT_TLS_GDESC)
! 	  off = offplt;
! 
! 	if (ELF32_R_TYPE(rel->r_info) == R_ARM_TLS_CALL
! 	    || ELF32_R_TYPE(rel->r_info) == R_ARM_THM_TLS_CALL)
! 	  {
! 	    bfd_signed_vma offset;
! 	    enum elf32_arm_stub_type stub_type
! 	      = arm_type_of_stub (info, input_section, rel, &sym_flags,
! 				  (struct elf32_arm_link_hash_entry *)h,
! 				  globals->tls_trampoline, globals->root.splt,
! 				  input_bfd, sym_name);
! 
! 	    if (stub_type != arm_stub_none)
! 	      {
! 		struct elf32_arm_stub_hash_entry *stub_entry
! 		  = elf32_arm_get_stub_entry
! 		  (input_section, globals->root.splt, 0, rel,
! 		   globals, stub_type);
! 		offset = (stub_entry->stub_offset
! 			  + stub_entry->stub_sec->output_offset
! 			  + stub_entry->stub_sec->output_section->vma);
! 	      }
! 	    else
! 	      offset = (globals->root.splt->output_section->vma
! 			+ globals->root.splt->output_offset
! 			+ globals->tls_trampoline);
! 
! 	    if (ELF32_R_TYPE(rel->r_info) == R_ARM_TLS_CALL)
! 	      {
! 		unsigned long inst;
! 		
! 		offset -= (input_section->output_section->vma +
! 			   input_section->output_offset + rel->r_offset + 8);
! 
! 		inst = offset >> 2;
! 		inst &= 0x00ffffff;
! 		value = inst | (globals->use_blx ? 0xfa000000 : 0xeb000000);
! 	      }
! 	    else
! 	      {
! 		/* Thumb blx encodes the offset in a complicated
! 		   fashion.  */
! 		unsigned upper_insn, lower_insn;
! 		unsigned neg;
! 
! 		offset -= (input_section->output_section->vma + 
! 			   input_section->output_offset
! 			   + rel->r_offset + 4);
! 	    
! 		/* Round up the offset to a word boundary */
! 		offset = (offset + 2) & ~2;
! 		neg = offset < 0;
! 		upper_insn = (0xf000
! 			      | ((offset >> 12) & 0x3ff)
! 			      | (neg << 10));
! 		lower_insn = (0xc000
! 			      | (((!((offset >> 23) & 1)) ^ neg) << 13)
! 			      | (((!((offset >> 22) & 1)) ^ neg) << 11)
! 			      | ((offset >> 1) & 0x7ff));
! 		bfd_put_16 (input_bfd, upper_insn, hit_data);
! 		bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
! 		return bfd_reloc_ok;
! 	      }
! 	  }
! 	/* These relocations needs special care, as besides the fact
! 	   they point somewhere in .gotplt, the addend must be
! 	   adjusted accordingly depending on the type of instruction
! 	   we refer to */
! 	else if ((r_type == R_ARM_TLS_GOTDESC) && (tls_type & GOT_TLS_GDESC))
! 	  {
! 	    unsigned long data, insn;
! 	    unsigned thumb;
! 	    
! 	    data = bfd_get_32 (input_bfd, hit_data);
! 	    thumb = data & 1;
! 	    data &= ~1u;
! 	    
! 	    if (thumb)
! 	      {
! 		insn = bfd_get_16 (input_bfd, contents + rel->r_offset - data);
! 		if ((insn & 0xf000) == 0xf000 || (insn & 0xf800) == 0xe800)
! 		  insn = (insn << 16)
! 		    | bfd_get_16 (input_bfd,
! 				  contents + rel->r_offset - data + 2);
! 		if ((insn & 0xf800c000) == 0xf000c000)
! 		  /* bl/blx */
! 		  value = -6;
! 		else if ((insn & 0xffffff00) == 0x4400)
! 		  /* add */
! 		  value = -5;
! 		else
! 		  {
! 		    (*_bfd_error_handler)
! 		      (_("%B(%A+0x%lx):unexpected Thumb instruction '0x%x' referenced by TLS_GOTDESC"),
! 		       input_bfd, input_section,
! 		       (unsigned long)rel->r_offset, insn);
! 		    return bfd_reloc_notsupported;
! 		  }
! 	      }
! 	    else
! 	      {
! 		insn = bfd_get_32 (input_bfd, contents + rel->r_offset - data);
! 
! 		switch (insn >> 24)
! 		  {
! 		  case 0xeb:  /* bl */
! 		  case 0xfa:  /* blx */
! 		    value = -4;
! 		    break;
! 
! 		  case 0xe0:	/* add */
! 		    value = -8;
! 		    break;
! 		    
! 		  default:
! 		    (*_bfd_error_handler)
! 		      (_("%B(%A+0x%lx):unexpected ARM instruction '0x%x' referenced by TLS_GOTDESC"),
! 		       input_bfd, input_section,
! 		       (unsigned long)rel->r_offset, insn);
! 		    return bfd_reloc_notsupported;
! 		  }
! 	      }
!  
! 	    value += ((globals->root.sgotplt->output_section->vma
! 		       + globals->root.sgotplt->output_offset + off)
! 		      - (input_section->output_section->vma
! 			 + input_section->output_offset
! 			 + rel->r_offset)
! 		      + globals->sgotplt_jump_table_size);
! 	  }
! 	else
! 	  value = ((globals->root.sgot->output_section->vma
! 		    + globals->root.sgot->output_offset + off)
! 		   - (input_section->output_section->vma
! 		      + input_section->output_offset + rel->r_offset));
  
  	return _bfd_final_link_relocate (howto, input_bfd, input_section,
  					 contents, rel->r_offset, value,
*************** arm_add_to_rel (bfd *              abfd,
*** 8789,8795 ****
     || (R_TYPE) == R_ARM_TLS_DTPMOD32	\
     || (R_TYPE) == R_ARM_TLS_TPOFF32	\
     || (R_TYPE) == R_ARM_TLS_LE32	\
!    || (R_TYPE) == R_ARM_TLS_IE32)
  
  /* Relocate an ARM ELF section.  */
  
--- 9355,9370 ----
     || (R_TYPE) == R_ARM_TLS_DTPMOD32	\
     || (R_TYPE) == R_ARM_TLS_TPOFF32	\
     || (R_TYPE) == R_ARM_TLS_LE32	\
!    || (R_TYPE) == R_ARM_TLS_IE32	\
!    || IS_ARM_TLS_GNU_RELOC (R_TYPE))
! 
! /* Specific set of relocations for the gnu tls dialect.  */
! #define IS_ARM_TLS_GNU_RELOC(R_TYPE)	\
!   ((R_TYPE) == R_ARM_TLS_GOTDESC	\
!    || (R_TYPE) == R_ARM_TLS_CALL	\
!    || (R_TYPE) == R_ARM_THM_TLS_CALL	\
!    || (R_TYPE) == R_ARM_TLS_DESCSEQ	\
!    || (R_TYPE) == R_ARM_THM_TLS_DESCSEQ)
  
  /* Relocate an ARM ELF section.  */
  
*************** elf32_arm_relocate_section (bfd *       
*** 9032,9043 ****
  	     name);
  	}
  
!       r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
! 					 input_section, contents, rel,
! 					 relocation, info, sec, name,
! 					 (h ? ELF_ST_TYPE (h->type) :
! 					  ELF_ST_TYPE (sym->st_info)), h,
! 					 &unresolved_reloc, &error_message);
  
        /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
  	 because such sections are not SEC_ALLOC and thus ld.so will
--- 9607,9639 ----
  	     name);
  	}
  
!       /* We call elf32_arm_final_link_relocate unless we're completely
!          done, i.e., the relaxation produced the final output we want,
!          and we won't let anybody mess with it. Also, we have to do
!          addend adjustments in case of a R_ARM_TLS_GOTDESC relocation
!          both in relaxed and non-relaxed cases */
!      if ((elf32_arm_tls_transition (info, r_type, h) != (unsigned)r_type)
! 	 || (IS_ARM_TLS_GNU_RELOC (r_type)
! 	     && !((h ? elf32_arm_hash_entry (h)->tls_type : 
! 		   elf32_arm_local_got_tls_type (input_bfd)[r_symndx])
! 		  & GOT_TLS_GDESC)))
!        {
! 	 r = elf32_arm_tls_relax (globals, input_bfd, input_section,
! 				  contents, rel, h == NULL);
! 	 /* This may have been marked unresolved because it came from
! 	    a shared library.  But we've just dealt with that.  */
! 	 unresolved_reloc = 0;
!        }
!      else
!        r = bfd_reloc_continue;
!      
!      if (r == bfd_reloc_continue)
!        r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
! 					  input_section, contents, rel,
! 					  relocation, info, sec, name,
! 					  (h ? ELF_ST_TYPE (h->type) :
! 					   ELF_ST_TYPE (sym->st_info)), h,
! 					  &unresolved_reloc, &error_message);
  
        /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
  	 because such sections are not SEC_ALLOC and thus ld.so will
*************** elf32_arm_check_relocs (bfd *abfd, struc
*** 10780,10791 ****
--- 11376,11394 ----
  
        eh = (struct elf32_arm_link_hash_entry *) h;
  
+       /* Could be done earlier, if h were already available.  */
+       r_type = elf32_arm_tls_transition (info, r_type, h);
        switch (r_type)
          {
  	  case R_ARM_GOT32:
  	  case R_ARM_GOT_PREL:
  	  case R_ARM_TLS_GD32:
  	  case R_ARM_TLS_IE32:
+ 	  case R_ARM_TLS_GOTDESC:
+ 	  case R_ARM_TLS_DESCSEQ:
+ 	  case R_ARM_THM_TLS_DESCSEQ:
+ 	  case R_ARM_TLS_CALL:
+ 	  case R_ARM_THM_TLS_CALL:
  	    /* This symbol requires a global offset table entry.  */
  	    {
  	      int tls_type, old_tls_type;
*************** elf32_arm_check_relocs (bfd *abfd, struc
*** 10793,10799 ****
--- 11396,11409 ----
  	      switch (r_type)
  		{
  		case R_ARM_TLS_GD32: tls_type = GOT_TLS_GD; break;
+ 		  
  		case R_ARM_TLS_IE32: tls_type = GOT_TLS_IE; break;
+ 		  
+ 		case R_ARM_TLS_GOTDESC:
+ 		case R_ARM_TLS_CALL: case R_ARM_THM_TLS_CALL:
+ 		case R_ARM_TLS_DESCSEQ: case R_ARM_THM_TLS_DESCSEQ:
+ 		  tls_type = GOT_TLS_GDESC; break;
+ 		  
  		default: tls_type = GOT_NORMAL; break;
  		}
  
*************** elf32_arm_check_relocs (bfd *abfd, struc
*** 10813,10839 ****
  		      bfd_size_type size;
  
  		      size = symtab_hdr->sh_info;
! 		      size *= (sizeof (bfd_signed_vma) + sizeof (char));
  		      local_got_refcounts = (bfd_signed_vma *)
                            bfd_zalloc (abfd, size);
  		      if (local_got_refcounts == NULL)
  			return FALSE;
  		      elf_local_got_refcounts (abfd) = local_got_refcounts;
  		      elf32_arm_local_got_tls_type (abfd)
! 			= (char *) (local_got_refcounts + symtab_hdr->sh_info);
  		    }
  		  local_got_refcounts[r_symndx] += 1;
  		  old_tls_type = elf32_arm_local_got_tls_type (abfd) [r_symndx];
  		}
  
! 	      /* We will already have issued an error message if there is a
! 		 TLS / non-TLS mismatch, based on the symbol type.  We don't
! 		 support any linker relaxations.  So just combine any TLS
! 		 types needed.  */
  	      if (old_tls_type != GOT_UNKNOWN && old_tls_type != GOT_NORMAL
  		  && tls_type != GOT_NORMAL)
  		tls_type |= old_tls_type;
  
  	      if (old_tls_type != tls_type)
  		{
  		  if (h != NULL)
--- 11423,11466 ----
  		      bfd_size_type size;
  
  		      size = symtab_hdr->sh_info;
! 		      size *= (sizeof (bfd_signed_vma)
! 			       + sizeof (bfd_vma) + sizeof (char));
  		      local_got_refcounts = (bfd_signed_vma *)
                            bfd_zalloc (abfd, size);
  		      if (local_got_refcounts == NULL)
  			return FALSE;
  		      elf_local_got_refcounts (abfd) = local_got_refcounts;
+ 		      elf32_arm_local_tlsdesc_gotent (abfd)
+ 		        = (bfd_vma *) (local_got_refcounts
+ 				       + symtab_hdr->sh_info);
  		      elf32_arm_local_got_tls_type (abfd)
! 			= (char *) (elf32_arm_local_tlsdesc_gotent (abfd)
! 				    + symtab_hdr->sh_info);
  		    }
  		  local_got_refcounts[r_symndx] += 1;
  		  old_tls_type = elf32_arm_local_got_tls_type (abfd) [r_symndx];
  		}
  
! 	      /* If a variable is accessed with both tls methods, two
! 	         slots may be created.  */
! 	      if (GOT_TLS_GD_ANY_P (old_tls_type)
! 		  && GOT_TLS_GD_ANY_P (tls_type))
! 		tls_type |= old_tls_type;
! 
! 	      /* We will already have issued an error message if there
! 		 is a TLS/non-TLS mismatch, based on the symbol
! 		 type.  So just combine any TLS types needed.  */
  	      if (old_tls_type != GOT_UNKNOWN && old_tls_type != GOT_NORMAL
  		  && tls_type != GOT_NORMAL)
  		tls_type |= old_tls_type;
  
+ 	      /* If the symbol is accessed in both IE and GDESC
+ 	         method, we're able to relax. Turn off the GDESC flag,
+ 	         without messing up with any other kind of tls types
+ 	         that may be involved */
+ 	      if ((tls_type & GOT_TLS_IE) && (tls_type & GOT_TLS_GDESC))
+ 		tls_type &= ~GOT_TLS_GDESC;
+ 
  	      if (old_tls_type != tls_type)
  		{
  		  if (h != NULL)
*************** allocate_dynrelocs (struct elf_link_hash
*** 11454,11465 ****
  	    {
  	      /* We also need to make an entry in the .got.plt section, which
  		 will be placed in the .got section by the linker script.  */
! 	      eh->plt_got_offset = htab->root.sgotplt->size;
  	      htab->root.sgotplt->size += 4;
  	    }
  
  	  /* We also need to make an entry in the .rel(a).plt section.  */
  	  htab->root.srelplt->size += RELOC_SIZE (htab);
  
  	  /* VxWorks executables have a second set of relocations for
  	     each PLT entry.  They go in a separate relocation section,
--- 12081,12094 ----
  	    {
  	      /* We also need to make an entry in the .got.plt section, which
  		 will be placed in the .got section by the linker script.  */
! 	      eh->plt_got_offset = (htab->root.sgotplt->size
! 				    - 8 * htab->num_tls_desc);
  	      htab->root.sgotplt->size += 4;
  	    }
  
  	  /* We also need to make an entry in the .rel(a).plt section.  */
  	  htab->root.srelplt->size += RELOC_SIZE (htab);
+ 	  htab->next_tls_desc_index++;
  
  	  /* VxWorks executables have a second set of relocations for
  	     each PLT entry.  They go in a separate relocation section,
*************** allocate_dynrelocs (struct elf_link_hash
*** 11489,11494 ****
--- 12118,12126 ----
        h->needs_plt = 0;
      }
  
+   eh = (struct elf32_arm_link_hash_entry *) h;
+   eh->tlsdesc_got = (bfd_vma) -1;
+ 
    if (h->got.refcount > 0)
      {
        asection *s;
*************** allocate_dynrelocs (struct elf_link_hash
*** 11518,11526 ****
  	    s->size += 4;
  	  else
  	    {
  	      if (tls_type & GOT_TLS_GD)
! 		/* R_ARM_TLS_GD32 needs 2 consecutive GOT slots.  */
! 		s->size += 8;
  	      if (tls_type & GOT_TLS_IE)
  		/* R_ARM_TLS_IE32 needs one GOT slot.  */
  		s->size += 4;
--- 12150,12177 ----
  	    s->size += 4;
  	  else
  	    {
+               if (tls_type & GOT_TLS_GDESC)
+ 	        {
+ 		  /* R_ARM_TLS_DESC needs 2 GOT slots.  */
+ 	          eh->tlsdesc_got
+ 		    = (htab->root.sgotplt->size
+ 		       - elf32_arm_compute_jump_table_size (htab));
+ 	          htab->root.sgotplt->size += 8;
+ 	          h->got.offset = (bfd_vma) -2;
+ 		  /* plt_got_offset needs to know there's a TLS_DESC
+ 		     reloc in the middle of .got.plt.  */
+                   htab->num_tls_desc++;
+ 	        }
+ 
  	      if (tls_type & GOT_TLS_GD)
! 		{
! 		  /* R_ARM_TLS_GD32 needs 2 consecutive GOT slots.  If
! 		     the symbol is both GD and GDESC, got.offset may
! 		     have been overwritten.  */
! 		  h->got.offset = s->size;
! 		  s->size += 8;
! 		}
! 
  	      if (tls_type & GOT_TLS_IE)
  		/* R_ARM_TLS_IE32 needs one GOT slot.  */
  		s->size += 4;
*************** allocate_dynrelocs (struct elf_link_hash
*** 11545,11552 ****
  	      if (tls_type & GOT_TLS_GD)
  		htab->root.srelgot->size += RELOC_SIZE (htab);
  
! 	      if ((tls_type & GOT_TLS_GD) && indx != 0)
! 		htab->root.srelgot->size += RELOC_SIZE (htab);
  	    }
  	  else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
  		    || h->root.type != bfd_link_hash_undefweak)
--- 12196,12212 ----
  	      if (tls_type & GOT_TLS_GD)
  		htab->root.srelgot->size += RELOC_SIZE (htab);
  
! 	      if (tls_type & GOT_TLS_GDESC) 
! 		{
! 		  htab->root.srelplt->size += RELOC_SIZE (htab); 
! 		  /* GDESC needs a trampoline to jump to.  */
! 		  htab->tls_trampoline = -1;
! 		}
! 
! 	      /* Only GD needs it.  GDESC just emits one relocation per
! 		 2 entries.  */
! 	      if ((tls_type & GOT_TLS_GD) && indx != 0)  
! 		htab->root.srelgot->size += RELOC_SIZE (htab); 
  	    }
  	  else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
  		    || h->root.type != bfd_link_hash_undefweak)
*************** elf32_arm_size_dynamic_sections (bfd * o
*** 11788,11793 ****
--- 12448,12454 ----
        bfd_signed_vma *local_got;
        bfd_signed_vma *end_local_got;
        char *local_tls_type;
+       bfd_vma *local_tlsdesc_gotent;
        bfd_size_type locsymcount;
        Elf_Internal_Shdr *symtab_hdr;
        asection *srel;
*************** elf32_arm_size_dynamic_sections (bfd * o
*** 11836,11858 ****
        locsymcount = symtab_hdr->sh_info;
        end_local_got = local_got + locsymcount;
        local_tls_type = elf32_arm_local_got_tls_type (ibfd);
        s = htab->root.sgot;
        srel = htab->root.srelgot;
!       for (; local_got < end_local_got; ++local_got, ++local_tls_type)
  	{
  	  if (*local_got > 0)
  	    {
  	      *local_got = s->size;
  	      if (*local_tls_type & GOT_TLS_GD)
  		/* TLS_GD relocs need an 8-byte structure in the GOT.  */
  		s->size += 8;
  	      if (*local_tls_type & GOT_TLS_IE)
  		s->size += 4;
- 	      if (*local_tls_type == GOT_NORMAL)
- 		s->size += 4;
  
! 	      if (info->shared || *local_tls_type == GOT_TLS_GD)
  		srel->size += RELOC_SIZE (htab);
  	    }
  	  else
  	    *local_got = (bfd_vma) -1;
--- 12497,12545 ----
        locsymcount = symtab_hdr->sh_info;
        end_local_got = local_got + locsymcount;
        local_tls_type = elf32_arm_local_got_tls_type (ibfd);
+       local_tlsdesc_gotent = elf32_arm_local_tlsdesc_gotent (ibfd);
        s = htab->root.sgot;
        srel = htab->root.srelgot;
!       for (; local_got < end_local_got;
! 	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
  	{
+ 	  *local_tlsdesc_gotent = (bfd_vma) -1;
  	  if (*local_got > 0)
  	    {
  	      *local_got = s->size;
  	      if (*local_tls_type & GOT_TLS_GD)
  		/* TLS_GD relocs need an 8-byte structure in the GOT.  */
  		s->size += 8;
+ 	      if (*local_tls_type & GOT_TLS_GDESC)
+ 		{
+ 		  *local_tlsdesc_gotent = htab->root.sgotplt->size
+ 		    - elf32_arm_compute_jump_table_size (htab);
+ 		  htab->root.sgotplt->size += 8;
+ 		  *local_got = (bfd_vma) -2;
+ 		  /* plt_got_offset needs to know there's a TLS_DESC
+ 		     reloc in the middle of .got.plt.  */
+                   htab->num_tls_desc++;
+ 		}
  	      if (*local_tls_type & GOT_TLS_IE)
  		s->size += 4;
  
! 	      if (*local_tls_type & GOT_NORMAL)
! 		{
! 		  /* If the symbol is both GD and GDESC, *local_got
! 		     may have been overwritten.  */
! 		  *local_got = s->size;
! 		  s->size += 4;
! 		}
! 
! 	      if ((info->shared && !(*local_tls_type & GOT_TLS_GDESC))
! 		  || *local_tls_type & GOT_TLS_GD)
  		srel->size += RELOC_SIZE (htab);
+ 
+ 	      if (info->shared && *local_tls_type & GOT_TLS_GDESC)
+ 		{
+ 		  htab->root.srelplt->size += RELOC_SIZE (htab);
+ 		  htab->tls_trampoline = -1;
+ 		}
  	    }
  	  else
  	    *local_got = (bfd_vma) -1;
*************** elf32_arm_size_dynamic_sections (bfd * o
*** 11894,11899 ****
--- 12581,12614 ----
    /* Allocate space for the glue sections now that we've sized them.  */
    bfd_elf32_arm_allocate_interworking_sections (info);
  
+   /* For every jump slot reserved in the sgotplt, reloc_count is
+      incremented.  However, when we reserve space for TLS descriptors,
+      it's not incremented, so in order to compute the space reserved
+      for them, it suffices to multiply the reloc count by the jump
+      slot size.  */
+   if (htab->root.srelplt)
+     htab->sgotplt_jump_table_size = elf32_arm_compute_jump_table_size(htab);
+ 
+   if (htab->tls_trampoline)
+     {
+       if (htab->root.splt->size == 0)
+ 	htab->root.splt->size += htab->plt_header_size;
+       
+       htab->tls_trampoline = htab->root.splt->size;
+       htab->root.splt->size += htab->plt_entry_size;
+       
+       /* If we're not using lazy TLS relocations, don't generate the
+          PLT and GOT entries they require.  */
+       if (!(info->flags & DF_BIND_NOW))
+ 	{
+ 	  htab->dt_tlsdesc_got = htab->root.sgot->size;
+ 	  htab->root.sgot->size += 4;
+ 
+ 	  htab->dt_tlsdesc_plt = htab->root.splt->size;
+ 	  htab->root.splt->size += 4 * ARRAY_SIZE (dl_tlsdesc_lazy_trampoline);
+ 	}
+     }
+ 
    /* The check_relocs and adjust_dynamic_symbol entry points have
       determined the sizes of the various dynamic sections.  Allocate
       memory for them.  */
*************** elf32_arm_size_dynamic_sections (bfd * o
*** 11984,11989 ****
--- 12699,12709 ----
  				     htab->use_rel ? DT_REL : DT_RELA)
  	      || !add_dynamic_entry (DT_JMPREL, 0))
  	    return FALSE;
+ 
+ 	  if (htab->dt_tlsdesc_plt &&
+ 		(!add_dynamic_entry (DT_TLSDESC_PLT,0) 
+ 		 || !add_dynamic_entry (DT_TLSDESC_GOT,0)))
+ 	    return FALSE; 
  	}
  
        if (relocs)
*************** elf32_arm_size_dynamic_sections (bfd * o
*** 12024,12029 ****
--- 12744,12792 ----
    return TRUE;
  }
  
+ /* Size sections even though they're not dynamic.  We use it to setup
+    _TLS_MODULE_BASE_, if needed.  */
+ 
+ static bfd_boolean
+ elf32_arm_always_size_sections (bfd *output_bfd,
+ 	                        struct bfd_link_info *info)
+ {
+   asection *tls_sec;
+ 
+   if (info->relocatable)
+     return TRUE;
+ 
+   tls_sec = elf_hash_table (info)->tls_sec;
+ 
+   if (tls_sec)
+     {
+       struct elf_link_hash_entry *tlsbase;
+ 
+       tlsbase = elf_link_hash_lookup
+ 	(elf_hash_table (info), "_TLS_MODULE_BASE_", TRUE, TRUE, FALSE);
+ 
+       if (tlsbase)
+         {
+           struct bfd_link_hash_entry *bh = NULL;
+ 	  const struct elf_backend_data *bed
+             = get_elf_backend_data (output_bfd);
+ 
+           if (!(_bfd_generic_link_add_one_symbol
+ 		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+ 		 tls_sec, 0, NULL, FALSE,
+ 		 bed->collect, &bh)))
+ 	    return FALSE;
+ 	  
+       	  tlsbase->type = STT_TLS;
+           tlsbase = (struct elf_link_hash_entry *)bh;
+           tlsbase->def_regular = 1;
+           tlsbase->other = STV_HIDDEN;
+           (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+ 	}
+     }
+   return TRUE;
+ }
+ 
  /* Finish up dynamic symbol handling.  We set the contents of various
     dynamic sections here.  */
  
*************** elf32_arm_finish_dynamic_symbol (bfd * o
*** 12240,12246 ****
      }
  
    if (h->got.offset != (bfd_vma) -1
!       && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_GD) == 0
        && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_IE) == 0)
      {
        asection * sgot;
--- 13003,13009 ----
      }
  
    if (h->got.offset != (bfd_vma) -1
!       && (! GOT_TLS_GD_ANY_P (elf32_arm_hash_entry (h)->tls_type)) 
        && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_IE) == 0)
      {
        asection * sgot;
*************** elf32_arm_finish_dynamic_symbol (bfd * o
*** 12321,12326 ****
--- 13084,13107 ----
    return TRUE;
  }
  
+ static void
+ arm_put_trampoline (struct elf32_arm_link_hash_table *htab, bfd *output_bfd,
+ 		    void *contents,
+ 		    const unsigned long *template, unsigned count)
+ {
+   unsigned ix;
+   
+   for (ix = 0; ix != count; ix++)
+     {
+       unsigned long insn = template[ix];
+ 
+       /* Emit mov pc,rx if bx is not permitted.  */
+       if (htab->fix_v4bx == 1 && (insn & 0x0ffffff0) == 0x012fff10)
+ 	insn = (insn & 0xf000000f) | 0x01a0f000;
+       put_arm_insn (htab, output_bfd, insn, (char *)contents + ix*4);
+     }
+ }
+ 
  /* Finish up the dynamic sections.  */
  
  static bfd_boolean
*************** elf32_arm_finish_dynamic_sections (bfd *
*** 12474,12479 ****
--- 13255,13274 ----
  		}
  	      break;
  
+ 	    case DT_TLSDESC_PLT:
+               s = htab->root.splt;
+ 	      dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
+ 				+ htab->dt_tlsdesc_plt);
+ 	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ 	      break;
+ 
+ 	    case DT_TLSDESC_GOT:
+               s = htab->root.sgot;
+ 	      dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
+ 		      		+ htab->dt_tlsdesc_got);
+ 	      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ 	      break;
+ 
  	      /* Set the bottom bit of DT_INIT/FINI if the
  		 corresponding function is Thumb.  */
  	    case DT_INIT:
*************** elf32_arm_finish_dynamic_sections (bfd *
*** 12563,12568 ****
--- 13358,13398 ----
        if (splt->output_section->owner == output_bfd)
  	elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
  
+       if (htab->dt_tlsdesc_plt)
+ 	{
+ 	  bfd_vma got_address
+ 	    = sgot->output_section->vma + sgot->output_offset;
+ 	  bfd_vma gotplt_address = (htab->root.sgot->output_section->vma
+ 				    + htab->root.sgot->output_offset);
+ 	  bfd_vma plt_address
+ 	    = splt->output_section->vma + splt->output_offset;
+ 
+ 	  arm_put_trampoline (htab, output_bfd, 
+ 			      splt->contents + htab->dt_tlsdesc_plt,
+ 			      dl_tlsdesc_lazy_trampoline, 6);
+ 
+ 	  bfd_put_32 (output_bfd,
+ 		      gotplt_address + htab->dt_tlsdesc_got
+ 		      - (plt_address + htab->dt_tlsdesc_plt)
+ 		      - dl_tlsdesc_lazy_trampoline[6],
+ 		      splt->contents + htab->dt_tlsdesc_plt + 24);
+ 	  bfd_put_32 (output_bfd,
+ 		      got_address - (plt_address + htab->dt_tlsdesc_plt)
+ 		      - dl_tlsdesc_lazy_trampoline[7],
+ 		      splt->contents + htab->dt_tlsdesc_plt + 24 + 4);
+ 	}
+ 
+       if (htab->tls_trampoline)
+ 	{
+ 	  arm_put_trampoline (htab, output_bfd, 
+ 			      splt->contents + htab->tls_trampoline,
+ 			      tls_trampoline, 3);
+ #ifdef FOUR_WORD_PLT
+ 	  bfd_put_32 (output_bfd, 0x00000000,
+ 		      splt->contents + htab->tls_trampoline + 12);
+ #endif 
+ 	}
+ 
        if (htab->vxworks_p && !info->shared && htab->root.splt->size > 0)
  	{
  	  /* Correct the .rel(a).plt.unloaded relocations.  They will have
*************** elf32_arm_output_arch_local_syms (bfd *o
*** 13137,13142 ****
--- 13967,13994 ----
  #endif
      }
  
+   if (htab->dt_tlsdesc_plt != 0)
+     {
+       /* Mapping symbols for the lazy tls trampoline.  */
+       if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, htab->dt_tlsdesc_plt))
+ 	return FALSE;
+        
+       if (!elf32_arm_output_map_sym (&osi, ARM_MAP_DATA,
+ 				     htab->dt_tlsdesc_plt + 24))
+ 	return FALSE;
+     }
+   if (htab->tls_trampoline != 0)
+     {
+       /* Mapping symbols for the tls trampoline.  */
+       if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, htab->tls_trampoline))
+ 	return FALSE;
+ #ifdef FOUR_WORD_PLT
+       if (!elf32_arm_output_map_sym (&osi, ARM_MAP_DATA,
+ 				     htab->tls_trampoline + 12))
+ 	return FALSE;
+ #endif 
+     }
+   
    elf_link_hash_traverse (&htab->root, elf32_arm_output_plt_map, (void *) &osi);
    return TRUE;
  }
*************** const struct elf_size_info elf32_arm_siz
*** 13795,13800 ****
--- 14647,14653 ----
  #define elf_backend_finish_dynamic_symbol	elf32_arm_finish_dynamic_symbol
  #define elf_backend_finish_dynamic_sections	elf32_arm_finish_dynamic_sections
  #define elf_backend_size_dynamic_sections	elf32_arm_size_dynamic_sections
+ #define elf_backend_always_size_sections	elf32_arm_always_size_sections
  #define elf_backend_init_index_section		_bfd_elf_init_2_index_sections
  #define elf_backend_post_process_headers	elf32_arm_post_process_headers
  #define elf_backend_reloc_type_class		elf32_arm_reloc_type_class
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.244
diff -c -3 -p -r1.244 libbfd.h
*** bfd/libbfd.h	17 Dec 2010 04:16:56 -0000	1.244
--- bfd/libbfd.h	5 Jan 2011 11:12:43 -0000
*************** static const char *const bfd_reloc_code_
*** 1377,1382 ****
--- 1377,1388 ----
    "BFD_RELOC_ARM_TLS_TPOFF32",
    "BFD_RELOC_ARM_TLS_IE32",
    "BFD_RELOC_ARM_TLS_LE32",
+   "BFD_RELOC_ARM_TLS_GOTDESC",
+   "BFD_RELOC_ARM_TLS_CALL",
+   "BFD_RELOC_ARM_THM_TLS_CALL",
+   "BFD_RELOC_ARM_TLS_DESCSEQ",
+   "BFD_RELOC_ARM_THM_TLS_DESCSEQ",
+   "BFD_RELOC_ARM_TLS_DESC",
    "BFD_RELOC_ARM_ALU_PC_G0_NC",
    "BFD_RELOC_ARM_ALU_PC_G0",
    "BFD_RELOC_ARM_ALU_PC_G1_NC",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.209
diff -c -3 -p -r1.209 reloc.c
*** bfd/reloc.c	17 Dec 2010 04:16:56 -0000	1.209
--- bfd/reloc.c	5 Jan 2011 11:12:45 -0000
*************** ENUMX
*** 2962,2967 ****
--- 2962,2979 ----
    BFD_RELOC_ARM_TLS_IE32
  ENUMX
    BFD_RELOC_ARM_TLS_LE32
+ ENUMX
+   BFD_RELOC_ARM_TLS_GOTDESC
+ ENUMX
+   BFD_RELOC_ARM_TLS_CALL
+ ENUMX
+   BFD_RELOC_ARM_THM_TLS_CALL
+ ENUMX
+   BFD_RELOC_ARM_TLS_DESCSEQ
+ ENUMX
+   BFD_RELOC_ARM_THM_TLS_DESCSEQ
+ ENUMX
+   BFD_RELOC_ARM_TLS_DESC
  ENUMDOC
    ARM thread-local storage relocations.
  
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.473
diff -c -3 -p -r1.473 tc-arm.c
*** gas/config/tc-arm.c	15 Nov 2010 10:03:04 -0000	1.473
--- gas/config/tc-arm.c	5 Jan 2011 11:12:52 -0000
*************** arm_typed_reg_parse (char **ccp, enum ar
*** 1472,1477 ****
--- 1472,1481 ----
    if (reg == FAIL)
      return FAIL;
  
+   /* Do not allow regname(... to parse as a register.  */
+   if (*str == '(')
+     return FAIL;
+ 
    /* Do not allow a scalar (reg+index) to parse as a register.  */
    if ((atype.defined & NTA_HASINDEX) != 0)
      {
*************** s_arm_eabi_attribute (int ignored ATTRIB
*** 4273,4278 ****
--- 4277,4306 ----
  }
  #endif /* OBJ_ELF */
  
+ /* Emit a tls fix for the symbol.  */
+ 
+ static void
+ s_arm_tls_descseq (int ignored ATTRIBUTE_UNUSED)
+ {
+   char *p;
+   expressionS exp;
+ #ifdef md_flush_pending_output
+   md_flush_pending_output ();
+ #endif
+ 
+ #ifdef md_cons_align
+   md_cons_align (4);
+ #endif
+ 
+   /* Since we're just labelling the code, there's no need to define a
+      mapping symbol.  */
+   expression (&exp);
+   p = obstack_next_free (&frchain_now->frch_obstack);
+   fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
+ 	       thumb_mode ? BFD_RELOC_ARM_THM_TLS_DESCSEQ
+ 	       : BFD_RELOC_ARM_TLS_DESCSEQ);
+ }
+ 
  static void s_arm_arch (int);
  static void s_arm_object_arch (int);
  static void s_arm_cpu (int);
*************** const pseudo_typeS md_pseudo_table[] =
*** 4352,4357 ****
--- 4380,4386 ----
    { "setfp",		s_arm_unwind_setfp,	0 },
    { "unwind_raw",	s_arm_unwind_raw,	0 },
    { "eabi_attribute",	s_arm_eabi_attribute,	0 },
+   { "tlsdescseq",	s_arm_tls_descseq,      0 },
  #else
    { "word",	   cons, 4},
  
*************** encode_branch (int default_reloc)
*** 7281,7289 ****
  {
    if (inst.operands[0].hasreloc)
      {
!       constraint (inst.operands[0].imm != BFD_RELOC_ARM_PLT32,
! 		  _("the only suffix valid here is '(plt)'"));
!       inst.reloc.type  = BFD_RELOC_ARM_PLT32;
      }
    else
      inst.reloc.type = (bfd_reloc_code_real_type) default_reloc;
--- 7310,7321 ----
  {
    if (inst.operands[0].hasreloc)
      {
!       constraint (inst.operands[0].imm != BFD_RELOC_ARM_PLT32
! 		  && inst.operands[0].imm != BFD_RELOC_ARM_TLS_CALL,
! 		  _("the only valid suffixes here are '(plt)' and '(tlscall)'"));
!       inst.reloc.type = inst.operands[0].imm == BFD_RELOC_ARM_PLT32
! 	? BFD_RELOC_ARM_PLT32
! 	: thumb_mode ? BFD_RELOC_ARM_THM_TLS_CALL : BFD_RELOC_ARM_TLS_CALL;
      }
    else
      inst.reloc.type = (bfd_reloc_code_real_type) default_reloc;
*************** do_t_blx (void)
*** 9655,9662 ****
      {
        /* No register.  This must be BLX(1).  */
        inst.instruction = 0xf000e800;
!       inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
!       inst.reloc.pc_rel = 1;
      }
  }
  
--- 9687,9693 ----
      {
        /* No register.  This must be BLX(1).  */
        inst.instruction = 0xf000e800;
!       encode_branch (BFD_RELOC_THUMB_PCREL_BLX);
      }
  }
  
*************** static void
*** 9734,9741 ****
  do_t_branch23 (void)
  {
    set_it_insn_type_last ();
!   inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BRANCH23;
!   inst.reloc.pc_rel = 1;
  
  #if defined(OBJ_COFF)
    /* If the destination of the branch is a defined symbol which does not have
--- 9765,9779 ----
  do_t_branch23 (void)
  {
    set_it_insn_type_last ();
!   encode_branch (BFD_RELOC_THUMB_PCREL_BRANCH23);
!   
!   /* md_apply_fix blows up with 'bl foo(PLT)' where foo is defined in
!      this file.  We used to simply ignore the PLT reloc type here --
!      the branch encoding is now needed to deal with TLSCALL relocs.
!      So if we see a PLT reloc now, put it back to how it used to be to
!      keep the preexisting behaviour.  */
!   if (inst.reloc.type == BFD_RELOC_ARM_PLT32)
!     inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
  
  #if defined(OBJ_COFF)
    /* If the destination of the branch is a defined symbol which does not have
*************** static struct reloc_entry reloc_names[] 
*** 16517,16523 ****
    { "tlsldo",  BFD_RELOC_ARM_TLS_LDO32}, { "TLSLDO",  BFD_RELOC_ARM_TLS_LDO32},
    { "gottpoff",BFD_RELOC_ARM_TLS_IE32},  { "GOTTPOFF",BFD_RELOC_ARM_TLS_IE32},
    { "tpoff",   BFD_RELOC_ARM_TLS_LE32},  { "TPOFF",   BFD_RELOC_ARM_TLS_LE32},
!   { "got_prel", BFD_RELOC_ARM_GOT_PREL}, { "GOT_PREL", BFD_RELOC_ARM_GOT_PREL}
  };
  #endif
  
--- 16555,16567 ----
    { "tlsldo",  BFD_RELOC_ARM_TLS_LDO32}, { "TLSLDO",  BFD_RELOC_ARM_TLS_LDO32},
    { "gottpoff",BFD_RELOC_ARM_TLS_IE32},  { "GOTTPOFF",BFD_RELOC_ARM_TLS_IE32},
    { "tpoff",   BFD_RELOC_ARM_TLS_LE32},  { "TPOFF",   BFD_RELOC_ARM_TLS_LE32},
!   { "got_prel", BFD_RELOC_ARM_GOT_PREL}, { "GOT_PREL", BFD_RELOC_ARM_GOT_PREL},
!   { "tlsdesc", BFD_RELOC_ARM_TLS_GOTDESC},
!   	{ "TLSDESC", BFD_RELOC_ARM_TLS_GOTDESC},
!   { "tlscall", BFD_RELOC_ARM_TLS_CALL},
!   	{ "TLSCALL", BFD_RELOC_ARM_TLS_CALL},
!   { "tlsdescseq", BFD_RELOC_ARM_TLS_DESCSEQ},
!   	{ "TLSDESCSEQ", BFD_RELOC_ARM_TLS_DESCSEQ}
  };
  #endif
  
*************** md_apply_fix (fixS *	fixP,
*** 20835,20840 ****
--- 20879,20892 ----
        break;
  
  #ifdef OBJ_ELF
+     case BFD_RELOC_ARM_TLS_CALL:
+     case BFD_RELOC_ARM_THM_TLS_CALL:
+     case BFD_RELOC_ARM_TLS_DESCSEQ:
+     case BFD_RELOC_ARM_THM_TLS_DESCSEQ:
+       S_SET_THREAD_LOCAL (fixP->fx_addsy);
+       break;
+ 
+     case BFD_RELOC_ARM_TLS_GOTDESC:
      case BFD_RELOC_ARM_TLS_GD32:
      case BFD_RELOC_ARM_TLS_LE32:
      case BFD_RELOC_ARM_TLS_IE32:
*************** tc_gen_reloc (asection *section, fixS *f
*** 21436,21441 ****
--- 21488,21497 ----
        return NULL;
  
  #ifdef OBJ_ELF
+     case BFD_RELOC_ARM_TLS_CALL:
+     case BFD_RELOC_ARM_THM_TLS_CALL:
+     case BFD_RELOC_ARM_TLS_DESCSEQ:
+     case BFD_RELOC_ARM_THM_TLS_DESCSEQ:
      case BFD_RELOC_ARM_GOT32:
      case BFD_RELOC_ARM_GOTOFF:
      case BFD_RELOC_ARM_GOT_PREL:
*************** tc_gen_reloc (asection *section, fixS *f
*** 21481,21486 ****
--- 21537,21543 ----
        code = fixp->fx_r_type;
        break;
  
+     case BFD_RELOC_ARM_TLS_GOTDESC:
      case BFD_RELOC_ARM_TLS_GD32:
      case BFD_RELOC_ARM_TLS_IE32:
      case BFD_RELOC_ARM_TLS_LDM32:
*************** arm_fix_adjustable (fixS * fixP)
*** 21742,21747 ****
--- 21799,21809 ----
        || fixP->fx_r_type == BFD_RELOC_ARM_TLS_IE32
        || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDM32
        || fixP->fx_r_type == BFD_RELOC_ARM_TLS_LDO32
+       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_GOTDESC
+       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_CALL
+       || fixP->fx_r_type == BFD_RELOC_ARM_THM_TLS_CALL
+       || fixP->fx_r_type == BFD_RELOC_ARM_TLS_DESCSEQ
+       || fixP->fx_r_type == BFD_RELOC_ARM_THM_TLS_DESCSEQ
        || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
      return FALSE;
  
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-arm.texi,v
retrieving revision 1.81
diff -c -3 -p -r1.81 c-arm.texi
*** gas/doc/c-arm.texi	23 Sep 2010 15:52:18 -0000	1.81
--- gas/doc/c-arm.texi	5 Jan 2011 11:12:53 -0000
*************** The following relocations are supported:
*** 478,483 ****
--- 478,485 ----
  @code{TLSGD},
  @code{TLSLDM},
  @code{TLSLDO},
+ @code{TLSDESC},
+ @code{TLSCALL},
  @code{GOTTPOFF},
  @code{GOT_PREL}
  and
*************** defined).  This directive also has the a
*** 864,869 ****
--- 866,877 ----
  the aliased symbol as being a thumb function entry point, in the same
  way that the @code{.thumb_func} directive does.
  
+ @cindex @code{.tlsdescseq} directive, ARM
+ @item .tlsdescseq @var{tls-variable}
+ This directive is used to annotate parts of an inlined TLS descriptor
+ trampoline.  Normally the trampoline is provided by the linker, and
+ this directive is not needed.
+ 
  @c UUUUUUUUUUUUUUUUUUUUUUUUUU
  
  @cindex @code{.unreq} directive, ARM
Index: gas/testsuite/gas/arm/tls.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/tls.d,v
retrieving revision 1.5
diff -c -3 -p -r1.5 tls.d
*** gas/testsuite/gas/arm/tls.d	30 Jun 2009 11:57:05 -0000	1.5
--- gas/testsuite/gas/arm/tls.d	5 Jan 2011 11:12:53 -0000
***************
*** 11,25 ****
  
  Disassembly of section .text:
  
! 00+0 <main>:
!    0:	e1a00000 	nop			; \(mov r0, r0\)
!    4:	e1a00000 	nop			; \(mov r0, r0\)
!    8:	e1a0f00e 	mov	pc, lr
!    c:	00000000 	.word	0x00000000
! 			c: R_ARM_TLS_GD32	a
!   10:	00000004 	.word	0x00000004
! 			10: R_ARM_TLS_LDM32	b
!   14:	00000008 	.word	0x00000008
! 			14: R_ARM_TLS_IE32	c
!   18:	00000000 	.word	0x00000000
! 			18: R_ARM_TLS_LE32	d
--- 11,49 ----
  
  Disassembly of section .text:
  
! 0+00 <arm_fn>:
!    0:	e1a00000 	nop			; .*
! 			0: R_ARM_TLS_DESCSEQ	af
!    4:	e59f0014 	ldr	r0, \[pc, #20\]	; 20 .*
!    8:	fa000000 	blx	8 <ae\+.*>
! 			8: R_ARM_TLS_CALL	ae
!    c:	e1a00000 	nop			; .*
! 0+10 <.arm_pool>:
!   10:	00000008 	.word	0x00000008
! 			10: R_ARM_TLS_GD32	aa
!   14:	0000000c 	.word	0x0000000c
! 			14: R_ARM_TLS_LDM32	ab
!   18:	00000010 	.word	0x00000010
! 			18: R_ARM_TLS_IE32	ac
!   1c:	00000000 	.word	0x00000000
! 			1c: R_ARM_TLS_LE32	ad
!   20:	00000018 	.word	0x00000018
! 			20: R_ARM_TLS_GOTDESC	ae
! 0+24 <thumb_fn>:
!   24:	46c0      	nop			; .*
!   26:	46c0      	nop			; .*
! 			26: R_ARM_THM_TLS_DESCSEQ	tf
!   28:	4805      	ldr	r0, \[pc, #20\]	; \(40 .*\)
!   2a:	f000 e800 	blx	4 <te\+0x4>
! 			2a: R_ARM_THM_TLS_CALL	te
!   2e:	46c0      	nop			; .*
!   30:	00000002 	.word	0x00000002
! 			30: R_ARM_TLS_GD32	ta
!   34:	00000006 	.word	0x00000006
! 			34: R_ARM_TLS_LDM32	tb
!   38:	0000000a 	.word	0x0000000a
! 			38: R_ARM_TLS_IE32	tc
!   3c:	00000000 	.word	0x00000000
! 			3c: R_ARM_TLS_LE32	td
!   40:	00000017 	.word	0x00000017
! 			40: R_ARM_TLS_GOTDESC	te
Index: gas/testsuite/gas/arm/tls.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/tls.s,v
retrieving revision 1.2
diff -c -3 -p -r1.2 tls.s
*** gas/testsuite/gas/arm/tls.s	29 Mar 2005 16:54:22 -0000	1.2
--- gas/testsuite/gas/arm/tls.s	5 Jan 2011 11:12:53 -0000
***************
*** 1,14 ****
  	.text
! 	.globl main
! 	.type main, %function
! main:
  	nop
! .L2:
  	nop
- 	mov	pc, lr
  
  .Lpool:
! 	.word	a(tlsgd) + (. - .L2 - 8)
! 	.word	b(tlsldm) + (. - .L2 - 8)
! 	.word	c(gottpoff) + (. - .L2 - 8)
! 	.word	d(tpoff)
--- 1,38 ----
  	.text
! 	.arm
! 	.globl arm_fn
! 	.type arm_fn, %function
! arm_fn:
! 1:
! .tlsdescseq  af
  	nop
! 	ldr	r0, 1f
! 2:	blx	ae(tlscall)
  	nop
  
+ .arm_pool:
+ 	.word	aa(tlsgd) + (. - 1b - 8)
+ 	.word	ab(tlsldm) + (. - 1b- 8)
+ 	.word	ac(gottpoff) + (. - 1b - 8)
+ 	.word	ad(tpoff)
+ 1:	.word	ae(tlsdesc) + (. - 2b)
+ 	
+ 	.thumb
+ 	.globl	thumb_fn
+ 	.type thumb_fn, %function
+ thumb_fn:
+ 	nop
+ 1:	
+ .tlsdescseq tf
+ 	nop
+ 	ldr	r0, 1f
+ 2:	blx	te(tlscall)
+ 	nop
+ 
+ 	.p2align 2
  .Lpool:
! 	.word	ta(tlsgd) + (. - 1b - 8)
! 	.word	tb(tlsldm) + (. - 1b - 8)
! 	.word	tc(gottpoff) + (. - 1b - 8)
! 	.word	td(tpoff)
! 1:	.word	te(tlsdesc) + (. - 2b + 1)
Index: include/elf/arm.h
===================================================================
RCS file: /cvs/src/src/include/elf/arm.h,v
retrieving revision 1.40
diff -c -3 -p -r1.40 arm.h
*** include/elf/arm.h	15 Apr 2010 10:56:36 -0000	1.40
--- include/elf/arm.h	5 Jan 2011 11:12:56 -0000
*************** START_RELOC_NUMBERS (elf_arm_reloc_type)
*** 123,129 ****
    RELOC_NUMBER (R_ARM_THM_CALL,        	 10)
    RELOC_NUMBER (R_ARM_THM_PC8,         	 11)
    RELOC_NUMBER (R_ARM_BREL_ADJ,	       	 12)
!   RELOC_NUMBER (R_ARM_SWI24,           	 13)   /* obsolete */
    RELOC_NUMBER (R_ARM_THM_SWI8,        	 14)   /* obsolete */
    RELOC_NUMBER (R_ARM_XPC25,           	 15)   /* obsolete */
    RELOC_NUMBER (R_ARM_THM_XPC22,       	 16)   /* obsolete */
--- 123,129 ----
    RELOC_NUMBER (R_ARM_THM_CALL,        	 10)
    RELOC_NUMBER (R_ARM_THM_PC8,         	 11)
    RELOC_NUMBER (R_ARM_BREL_ADJ,	       	 12)
!   RELOC_NUMBER (R_ARM_TLS_DESC,          13)
    RELOC_NUMBER (R_ARM_THM_SWI8,        	 14)   /* obsolete */
    RELOC_NUMBER (R_ARM_XPC25,           	 15)   /* obsolete */
    RELOC_NUMBER (R_ARM_THM_XPC22,       	 16)   /* obsolete */
*************** START_RELOC_NUMBERS (elf_arm_reloc_type)
*** 200,206 ****
    RELOC_NUMBER (R_ARM_THM_MOVW_BREL_NC,	 87)
    RELOC_NUMBER (R_ARM_THM_MOVT_BREL,   	 88)
    RELOC_NUMBER (R_ARM_THM_MOVW_BREL,   	 89)
!   /* 90-93 unallocated */
    RELOC_NUMBER (R_ARM_PLT32_ABS,       	 94)
    RELOC_NUMBER (R_ARM_GOT_ABS,	       	 95)
    RELOC_NUMBER (R_ARM_GOT_PREL,	       	 96)
--- 200,209 ----
    RELOC_NUMBER (R_ARM_THM_MOVW_BREL_NC,	 87)
    RELOC_NUMBER (R_ARM_THM_MOVT_BREL,   	 88)
    RELOC_NUMBER (R_ARM_THM_MOVW_BREL,   	 89)
!   RELOC_NUMBER (R_ARM_TLS_GOTDESC,       90)
!   RELOC_NUMBER (R_ARM_TLS_CALL,          91)
!   RELOC_NUMBER (R_ARM_TLS_DESCSEQ,       92)
!   RELOC_NUMBER (R_ARM_THM_TLS_CALL,      93)
    RELOC_NUMBER (R_ARM_PLT32_ABS,       	 94)
    RELOC_NUMBER (R_ARM_GOT_ABS,	       	 95)
    RELOC_NUMBER (R_ARM_GOT_PREL,	       	 96)
*************** START_RELOC_NUMBERS (elf_arm_reloc_type)
*** 221,226 ****
--- 224,230 ----
    RELOC_NUMBER (R_ARM_TLS_IE12GP,     	111)
    /* 112 - 127 private range */
    RELOC_NUMBER (R_ARM_ME_TOO,	        128)   /* obsolete */
+   RELOC_NUMBER (R_ARM_THM_TLS_DESCSEQ  ,129)
  
    /* Extensions?  R=read-only?  */
    RELOC_NUMBER (R_ARM_RXPC25,         	249)
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-arm/arm-elf.exp,v
retrieving revision 1.79
diff -c -3 -p -r1.79 arm-elf.exp
*** ld/testsuite/ld-arm/arm-elf.exp	25 Nov 2010 09:34:43 -0000	1.79
--- ld/testsuite/ld-arm/arm-elf.exp	5 Jan 2011 11:12:57 -0000
*************** set armelftests {
*** 135,140 ****
--- 135,188 ----
      {"TLS dynamic application" "-T arm-dyn.ld tmpdir/tls-lib.so" "" {tls-app.s}
       {{objdump -fdw tls-app.d} {objdump -Rw tls-app.r}}
       "tls-app"}
+     {"TLS gnu shared library" "-shared -T arm-dyn.ld" "" {tls-gdesc.s}
+      {{objdump -fdw tls-gdesc.d} {objdump -Rw tls-gdesc.r}}
+      "tls-lib2.so"}
+     {"TLS gnu shared library got" "-shared -T arm-dyn.ld" "" {tls-gdesc-got.s}
+      {{objdump "-fDR -j .got" tls-gdesc-got.d}}
+      "tls-lib2-got.so"}
+     {"TLS gnu shared library inlined trampoline" "-shared -T arm-dyn.ld" "" {tls-descseq.s}
+      {{objdump -fdw tls-descseq.d} {objdump -Rw tls-descseq.r}}
+      "tls-lib2inline.so"}
+     {"TLS gnu shared library non-lazy" "-z now -shared -T arm-dyn.ld" "" {tls-gdesc.s}
+      {{readelf "-x .got" tls-gdesc-nlazy.g}}
+      "tls-lib2-nlazy.so"}
+     {"TLS shared library gdesc local" "-shared -T arm-dyn.ld" "" {tls-lib-loc.s}
+      {{objdump -fdw tls-lib-loc.d} {objdump -Rw tls-lib-loc.r}}
+      "tls-lib-loc.so"}
+     {"TLS long plt library" "-shared -T arm-dyn.ld --section-start .foo=0x4001000" "" {tls-longplt-lib.s}
+      {{objdump -fdw tls-longplt-lib.d}}
+      "tls-longplt-lib.so"}
+     {"TLS long plt" "-T arm-dyn.ld --section-start .foo=0x4001000 tmpdir/tls-longplt-lib.so" "" {tls-longplt.s}
+      {{objdump -fdw tls-longplt.d}}
+      "tls-longplt"}
+     {"TLS thumb1" "-shared -T arm-dyn.ld --section-start .foo=0x4001000" "" {tls-thumb1.s}
+      {{objdump -fdw tls-thumb1.d}}
+      "tls-thumb1"}
+     {"TLS gnu GD to IE relaxation" "-static -T arm-dyn.ld" "" {tls-gdierelax.s}
+      {{objdump -fdw tls-gdierelax.d}}
+      "tls-app-rel-ie"}
+     {"TLS gnu GD to IE shared relaxation" "-shared -T arm-dyn.ld" "" {tls-gdierelax2.s}
+      {{objdump -fdw tls-gdierelax2.d}}
+      "tls-app-rel-ie2"}
+     {"TLS gnu GD to LE relaxation" "-T arm-dyn.ld" "" {tls-gdlerelax.s}
+      {{objdump -fdw tls-gdlerelax.d}}
+      "tls-app-rel-le"}
+     {"TLS mixed models shared lib" "-shared -T arm-dyn.ld" "" {tls-mixed.s}
+      {{objdump -Rw tls-mixed.r}}
+      "tls-mixed.so"}
+     {"TLS descseq relaxation" "-T arm-dyn.ld" "" {tls-descrelax.s}
+      {{objdump -fdw tls-descrelax.d}}
+      "tls-descrelax"}
+     {"TLS descseq relaxation v7" "-T arm-dyn.ld" "" {tls-descrelax-v7.s}
+      {{objdump -fdw tls-descrelax-v7.d}}
+      "tls-descrelax-v7"}
+     {"TLS descseq relaxation BE8" "-T arm-dyn.ld -EB --be8" "-mbig-endian" {tls-descrelax-be8.s}
+      {{objdump -fdw tls-descrelax-be8.d}}
+      "tls-descrelax-be8"}
+     {"TLS descseq relaxation BE32" "-T arm-dyn.ld -EB" "-mbig-endian" {tls-descrelax-be32.s}
+      {{objdump -fdw tls-descrelax-be32.d}}
+      "tls-descrelax-be32"}
      {"Thumb entry point" "-T arm.ld" "" {thumb-entry.s}
       {{readelf -h thumb-entry.d}}
       "thumb-entry"}
Index: ld/testsuite/ld-arm/tls-descrelax-be32.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descrelax-be32.d
diff -N ld/testsuite/ld-arm/tls-descrelax-be32.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descrelax-be32.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,108 ----
+ .*:     file format elf32-.*
+ architecture: arm, flags 0x[0-9a-f]+:
+ EXEC_P, HAS_SYMS, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .text:
+ 
+ 00008000 <foo>:
+     8000:	e59f0004 	ldr	r0, \[pc, #4\]	; 800c <foo\+0xc>
+     8004:	e79f0000 	ldr	r0, \[pc, r0\]
+     8008:	e1a00000 	nop			; .*
+     800c:	00008138 	.word	0x00008138
+     8010:	e59f0004 	ldr	r0, \[pc, #4\]	; 801c <foo\+0x1c>
+     8014:	e79f0000 	ldr	r0, \[pc, r0\]
+     8018:	e1a00000 	nop			; .*
+     801c:	00008128 	.word	0x00008128
+     8020:	e59f0004 	ldr	r0, \[pc, #4\]	; 802c <foo\+0x2c>
+     8024:	e1a00000 	nop			; .*
+     8028:	e1a00000 	nop			; .*
+     802c:	0000000c 	.word	0x0000000c
+     8030:	e59f0004 	ldr	r0, \[pc, #4\]	; 803c <foo\+0x3c>
+     8034:	e1a00000 	nop			; .*
+     8038:	e1a00000 	nop			; .*
+     803c:	0000000c 	.word	0x0000000c
+     8040:	e59f000c 	ldr	r0, \[pc, #12\]	; 8054 <foo\+0x54>
+     8044:	e08f0000 	add	r0, pc, r0
+     8048:	e5901000 	ldr	r1, \[r0\]
+     804c:	e1a00001 	mov	r0, r1
+     8050:	e1a00000 	nop			; .*
+     8054:	000080f8 	.word	0x000080f8
+     8058:	e59f000c 	ldr	r0, \[pc, #12\]	; 806c <foo\+0x6c>
+     805c:	e08f0000 	add	r0, pc, r0
+     8060:	e5901000 	ldr	r1, \[r0\]
+     8064:	e1a00001 	mov	r0, r1
+     8068:	e1a00000 	nop			; .*
+     806c:	000080e0 	.word	0x000080e0
+     8070:	e59f000c 	ldr	r0, \[pc, #12\]	; 8084 <foo\+0x84>
+     8074:	e1a00000 	nop			; .*
+     8078:	e1a00000 	nop			; .*
+     807c:	e1a00000 	nop			; .*
+     8080:	e1a00000 	nop			; .*
+     8084:	0000000c 	.word	0x0000000c
+     8088:	e59f000c 	ldr	r0, \[pc, #12\]	; 809c <foo\+0x9c>
+     808c:	e1a00000 	nop			; .*
+     8090:	e1a00000 	nop			; .*
+     8094:	e1a00000 	nop			; .*
+     8098:	e1a00000 	nop			; .*
+     809c:	0000000c 	.word	0x0000000c
+ 
+ 000080a0 <bar>:
+     80a0:	4801      	ldr	r0, \[pc, #4\]	; \(80a8 <bar\+0x8>\)
+     80a2:	4478      	add	r0, pc
+     80a4:	6800      	ldr	r0, \[r0, #0\]
+     80a6:	46c0      	nop			; .*
+     80a8:	0000809e 	.word	0x0000809e
+     80ac:	4801      	ldr	r0, \[pc, #4\]	; \(80b4 <bar\+0x14>\)
+     80ae:	4478      	add	r0, pc
+     80b0:	6800      	ldr	r0, \[r0, #0\]
+     80b2:	46c0      	nop			; .*
+     80b4:	00008092 	.word	0x00008092
+     80b8:	4801      	ldr	r0, \[pc, #4\]	; \(80c0 <bar\+0x20>\)
+     80ba:	4478      	add	r0, pc
+     80bc:	6800      	ldr	r0, \[r0, #0\]
+     80be:	46c0      	nop			; .*
+     80c0:	0000808a 	.word	0x0000808a
+     80c4:	4801      	ldr	r0, \[pc, #4\]	; \(80cc <bar\+0x2c>\)
+     80c6:	46c0      	nop			; .*
+     80c8:	46c0      	nop			; .*
+     80ca:	46c0      	nop			; .*
+     80cc:	0000000c 	.word	0x0000000c
+     80d0:	4801      	ldr	r0, \[pc, #4\]	; \(80d8 <bar\+0x38>\)
+     80d2:	bf00      	nop
+     80d4:	bf00      	nop
+     80d6:	46c0      	nop			; .*
+     80d8:	0000000c 	.word	0x0000000c
+     80dc:	4801      	ldr	r0, \[pc, #4\]	; \(80e4 <bar\+0x44>\)
+     80de:	bf00      	nop
+     80e0:	bf00      	nop
+     80e2:	46c0      	nop			; .*
+     80e4:	00000014 	.word	0x00000014
+     80e8:	4802      	ldr	r0, \[pc, #8\]	; \(80f4 <bar\+0x54>\)
+     80ea:	4478      	add	r0, pc
+     80ec:	6801      	ldr	r1, \[r0, #0\]
+     80ee:	1c08      	adds	r0, r1, #0
+     80f0:	46c0      	nop			; .*
+     80f2:	46c0      	nop			; .*
+     80f4:	00008056 	.word	0x00008056
+     80f8:	4802      	ldr	r0, \[pc, #8\]	; \(8104 <bar\+0x64>\)
+     80fa:	4478      	add	r0, pc
+     80fc:	6801      	ldr	r1, \[r0, #0\]
+     80fe:	4608      	mov	r0, r1
+     8100:	46c0      	nop			; .*
+     8102:	46c0      	nop			; .*
+     8104:	00008046 	.word	0x00008046
+     8108:	4802      	ldr	r0, \[pc, #8\]	; \(8114 <bar\+0x74>\)
+     810a:	46c0      	nop			; .*
+     810c:	46c0      	nop			; .*
+     810e:	46c0      	nop			; .*
+     8110:	46c0      	nop			; .*
+     8112:	46c0      	nop			; .*
+     8114:	0000000c 	.word	0x0000000c
+     8118:	4802      	ldr	r0, \[pc, #8\]	; \(8124 <bar\+0x84>\)
+     811a:	46c0      	nop			; .*
+     811c:	46c0      	nop			; .*
+     811e:	46c0      	nop			; .*
+     8120:	46c0      	nop			; .*
+     8122:	46c0      	nop			; .*
+     8124:	0000000c 	.word	0x0000000c
Index: ld/testsuite/ld-arm/tls-descrelax-be32.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descrelax-be32.s
diff -N ld/testsuite/ld-arm/tls-descrelax-be32.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descrelax-be32.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,198 ----
+ @ we can relax local and non-weak globals for non-shared links
+ 
+ 	.arch	armv5te
+ 	.text
+ 	.arm
+ 
+ 	.p2align 2
+ foo:
+ @tlscall global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:	ldr	r0, [pc, r0]
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 8)
+ 	
+ 	.p2align 2
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	gd1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @tlscall local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 
+ 	.p2align 2
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	ld1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @open coded global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:
+ 	add	r0, pc, r0
+ 	ldr	r1, [r0]
+ 	mov	r0, r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 8)
+ 
+ 	.p2align 2
+ @open coded global, should relax to IE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq gd1
+ 	add	r0, pc, r0
+ .tlsdescseq gd1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq gd1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @open coded local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 2:
+ 	nop
+ 	nop
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 	
+ 	.p2align 2
+ @open coded local, should relax to LE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq ld1
+ 	add	r0, pc, r0
+ .tlsdescseq ld1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq ld1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b)
+ 
+ 
+ 	.thumb
+ 	.p2align 1
+ bar:	
+ @tlscall global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:	add	r0, pc, r0
+ 	ldr	r0, [r0]
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 4)
+ 	
+ 	.p2align 1
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	gd1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	r1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	r1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 
+ 	.p2align 1
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	ld1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	r0(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	r0(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @open coded global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:
+ 	add	r0, pc
+ 	ldr	r1, [r0]
+ 	mov	r0, r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 4)
+ 
+ 	.p2align 1
+ @open coded global, should relax to IE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq gd1
+ 	add	r0, pc
+ .tlsdescseq gd1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq gd1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @open coded local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 2:
+ 	nop
+ 	nop
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 	
+ 	.p2align 1
+ @open coded local, should relax to LE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq ld1
+ 	add	r0, pc
+ .tlsdescseq ld1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq ld1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ 	.global	gd1
+ gd1:	.space 4
+ ld1:	.space 4
+ 	.globl r1
+ r1:	.space 4
+ r0:	.space 4
Index: ld/testsuite/ld-arm/tls-descrelax-be8.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descrelax-be8.d
diff -N ld/testsuite/ld-arm/tls-descrelax-be8.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descrelax-be8.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,106 ----
+ .*:     file format elf32-.*
+ architecture: arm, flags 0x[0-9a-f]+:
+ EXEC_P, HAS_SYMS, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .text:
+ 
+ 00008000 <foo>:
+     8000:	e59f0004 	ldr	r0, \[pc, #4\]	; 800c <foo\+0xc>
+     8004:	e79f0000 	ldr	r0, \[pc, r0\]
+     8008:	e320f000 	nop	\{0\}
+     800c:	00008138 	.word	0x00008138
+     8010:	e59f0004 	ldr	r0, \[pc, #4\]	; 801c <foo\+0x1c>
+     8014:	e79f0000 	ldr	r0, \[pc, r0\]
+     8018:	e320f000 	nop	\{0\}
+     801c:	00008128 	.word	0x00008128
+     8020:	e59f0004 	ldr	r0, \[pc, #4\]	; 802c <foo\+0x2c>
+     8024:	e320f000 	nop	\{0\}
+     8028:	e320f000 	nop	\{0\}
+     802c:	0000000c 	.word	0x0000000c
+     8030:	e59f0004 	ldr	r0, \[pc, #4\]	; 803c <foo\+0x3c>
+     8034:	e1a00000 	nop			; .*
+     8038:	e320f000 	nop	\{0\}
+     803c:	0000000c 	.word	0x0000000c
+     8040:	e59f000c 	ldr	r0, \[pc, #12\]	; 8054 <foo\+0x54>
+     8044:	e08f0000 	add	r0, pc, r0
+     8048:	e5901000 	ldr	r1, \[r0\]
+     804c:	e1a00001 	mov	r0, r1
+     8050:	e320f000 	nop	\{0\}
+     8054:	000080f8 	.word	0x000080f8
+     8058:	e59f000c 	ldr	r0, \[pc, #12\]	; 806c <foo\+0x6c>
+     805c:	e08f0000 	add	r0, pc, r0
+     8060:	e5901000 	ldr	r1, \[r0\]
+     8064:	e1a00001 	mov	r0, r1
+     8068:	e320f000 	nop	\{0\}
+     806c:	000080e0 	.word	0x000080e0
+     8070:	e59f000c 	ldr	r0, \[pc, #12\]	; 8084 <foo\+0x84>
+     8074:	e320f000 	nop	\{0\}
+     8078:	e320f000 	nop	\{0\}
+     807c:	e320f000 	nop	\{0\}
+     8080:	e320f000 	nop	\{0\}
+     8084:	0000000c 	.word	0x0000000c
+     8088:	e59f000c 	ldr	r0, \[pc, #12\]	; 809c <foo\+0x9c>
+     808c:	e1a00000 	nop			; .*
+     8090:	e1a00000 	nop			; .*
+     8094:	e1a00000 	nop			; .*
+     8098:	e320f000 	nop	\{0\}
+     809c:	0000000c 	.word	0x0000000c
+ 
+ 000080a0 <bar>:
+     80a0:	4801      	ldr	r0, \[pc, #4\]	; \(80a8 <bar\+0x8>\)
+     80a2:	4478      	add	r0, pc
+     80a4:	6800      	ldr	r0, \[r0, #0\]
+     80a6:	46c0      	nop			; .*
+     80a8:	0000809e 	.word	0x0000809e
+     80ac:	4801      	ldr	r0, \[pc, #4\]	; \(80b4 <bar\+0x14>\)
+     80ae:	4478      	add	r0, pc
+     80b0:	6800      	ldr	r0, \[r0, #0\]
+     80b2:	46c0      	nop			; \(mov r8, r8\)
+     80b4:	00008092 	.word	0x00008092
+     80b8:	4801      	ldr	r0, \[pc, #4\]	; \(80c0 <bar\+0x20>\)
+     80ba:	4478      	add	r0, pc
+     80bc:	6800      	ldr	r0, \[r0, #0\]
+     80be:	46c0      	nop			; \(mov r8, r8\)
+     80c0:	0000808a 	.word	0x0000808a
+     80c4:	4801      	ldr	r0, \[pc, #4\]	; \(80cc <bar\+0x2c>\)
+     80c6:	46c0      	nop			; \(mov r8, r8\)
+     80c8:	46c0      	nop			; \(mov r8, r8\)
+     80ca:	bf00      	nop
+     80cc:	0000000c 	.word	0x0000000c
+     80d0:	4801      	ldr	r0, \[pc, #4\]	; \(80d8 <bar\+0x38>\)
+     80d2:	f3af 8000 	nop.w
+     80d6:	46c0      	nop			; \(mov r8, r8\)
+     80d8:	0000000c 	.word	0x0000000c
+     80dc:	4801      	ldr	r0, \[pc, #4\]	; \(80e4 <bar\+0x44>\)
+     80de:	f3af 8000 	nop.w
+     80e2:	46c0      	nop			; \(mov r8, r8\)
+     80e4:	00000014 	.word	0x00000014
+     80e8:	4802      	ldr	r0, \[pc, #8\]	; \(80f4 <bar\+0x54>\)
+     80ea:	4478      	add	r0, pc
+     80ec:	6801      	ldr	r1, \[r0, #0\]
+     80ee:	1c08      	adds	r0, r1, #0
+     80f0:	46c0      	nop			; \(mov r8, r8\)
+     80f2:	bf00      	nop
+     80f4:	00008056 	.word	0x00008056
+     80f8:	4802      	ldr	r0, \[pc, #8\]	; \(8104 <bar\+0x64>\)
+     80fa:	4478      	add	r0, pc
+     80fc:	6801      	ldr	r1, \[r0, #0\]
+     80fe:	4608      	mov	r0, r1
+     8100:	46c0      	nop			; \(mov r8, r8\)
+     8102:	bf00      	nop
+     8104:	00008046 	.word	0x00008046
+     8108:	4802      	ldr	r0, \[pc, #8\]	; \(8114 <bar\+0x74>\)
+     810a:	46c0      	nop			; \(mov r8, r8\)
+     810c:	46c0      	nop			; \(mov r8, r8\)
+     810e:	46c0      	nop			; \(mov r8, r8\)
+     8110:	46c0      	nop			; \(mov r8, r8\)
+     8112:	bf00      	nop
+     8114:	0000000c 	.word	0x0000000c
+     8118:	4802      	ldr	r0, \[pc, #8\]	; \(8124 <bar\+0x84>\)
+     811a:	46c0      	nop			; \(mov r8, r8\)
+     811c:	46c0      	nop			; \(mov r8, r8\)
+     811e:	46c0      	nop			; \(mov r8, r8\)
+     8120:	46c0      	nop			; \(mov r8, r8\)
+     8122:	bf00      	nop
+     8124:	0000000c 	.word	0x0000000c
Index: ld/testsuite/ld-arm/tls-descrelax-be8.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descrelax-be8.s
diff -N ld/testsuite/ld-arm/tls-descrelax-be8.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descrelax-be8.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,198 ----
+ @ we can relax local and non-weak globals for non-shared links
+ 
+ 	.arch	armv7-a
+ 	.text
+ 	.arm
+ 
+ 	.p2align 2
+ foo:
+ @tlscall global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:	ldr	r0, [pc, r0]
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 8)
+ 	
+ 	.p2align 2
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	gd1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @tlscall local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 
+ 	.p2align 2
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	ld1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @open coded global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:
+ 	add	r0, pc, r0
+ 	ldr	r1, [r0]
+ 	mov	r0, r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 8)
+ 
+ 	.p2align 2
+ @open coded global, should relax to IE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq gd1
+ 	add	r0, pc, r0
+ .tlsdescseq gd1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq gd1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @open coded local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 2:
+ 	nop
+ 	nop
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 	
+ 	.p2align 2
+ @open coded local, should relax to LE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq ld1
+ 	add	r0, pc, r0
+ .tlsdescseq ld1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq ld1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b)
+ 
+ 
+ 	.thumb
+ 	.p2align 1
+ bar:	
+ @tlscall global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:	add	r0, pc, r0
+ 	ldr	r0, [r0]
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 4)
+ 	
+ 	.p2align 1
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	gd1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	r1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	r1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 
+ 	.p2align 1
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	ld1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	r0(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	r0(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @open coded global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:
+ 	add	r0, pc
+ 	ldr	r1, [r0]
+ 	mov	r0, r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 4)
+ 
+ 	.p2align 1
+ @open coded global, should relax to IE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq gd1
+ 	add	r0, pc
+ .tlsdescseq gd1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq gd1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @open coded local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 2:
+ 	nop
+ 	nop
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 	
+ 	.p2align 1
+ @open coded local, should relax to LE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq ld1
+ 	add	r0, pc
+ .tlsdescseq ld1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq ld1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ 	.global	gd1
+ gd1:	.space 4
+ ld1:	.space 4
+ 	.globl r1
+ r1:	.space 4
+ r0:	.space 4
Index: ld/testsuite/ld-arm/tls-descrelax-v7.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descrelax-v7.d
diff -N ld/testsuite/ld-arm/tls-descrelax-v7.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descrelax-v7.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,106 ----
+ .*:     file format elf32-.*
+ architecture: arm, flags 0x[0-9a-f]+:
+ EXEC_P, HAS_SYMS, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .text:
+ 
+ 00008000 <foo>:
+     8000:	e59f0004 	ldr	r0, \[pc, #4\]	; 800c <foo\+0xc>
+     8004:	e79f0000 	ldr	r0, \[pc, r0\]
+     8008:	e320f000 	nop	\{0\}
+     800c:	00008138 	.word	0x00008138
+     8010:	e59f0004 	ldr	r0, \[pc, #4\]	; 801c <foo\+0x1c>
+     8014:	e79f0000 	ldr	r0, \[pc, r0\]
+     8018:	e320f000 	nop	\{0\}
+     801c:	00008128 	.word	0x00008128
+     8020:	e59f0004 	ldr	r0, \[pc, #4\]	; 802c <foo\+0x2c>
+     8024:	e320f000 	nop	\{0\}
+     8028:	e320f000 	nop	\{0\}
+     802c:	0000000c 	.word	0x0000000c
+     8030:	e59f0004 	ldr	r0, \[pc, #4\]	; 803c <foo\+0x3c>
+     8034:	e1a00000 	nop			; .*
+     8038:	e320f000 	nop	\{0\}
+     803c:	0000000c 	.word	0x0000000c
+     8040:	e59f000c 	ldr	r0, \[pc, #12\]	; 8054 <foo\+0x54>
+     8044:	e08f0000 	add	r0, pc, r0
+     8048:	e5901000 	ldr	r1, \[r0\]
+     804c:	e1a00001 	mov	r0, r1
+     8050:	e320f000 	nop	\{0\}
+     8054:	000080f8 	.word	0x000080f8
+     8058:	e59f000c 	ldr	r0, \[pc, #12\]	; 806c <foo\+0x6c>
+     805c:	e08f0000 	add	r0, pc, r0
+     8060:	e5901000 	ldr	r1, \[r0\]
+     8064:	e1a00001 	mov	r0, r1
+     8068:	e320f000 	nop	\{0\}
+     806c:	000080e0 	.word	0x000080e0
+     8070:	e59f000c 	ldr	r0, \[pc, #12\]	; 8084 <foo\+0x84>
+     8074:	e320f000 	nop	\{0\}
+     8078:	e320f000 	nop	\{0\}
+     807c:	e320f000 	nop	\{0\}
+     8080:	e320f000 	nop	\{0\}
+     8084:	0000000c 	.word	0x0000000c
+     8088:	e59f000c 	ldr	r0, \[pc, #12\]	; 809c <foo\+0x9c>
+     808c:	e1a00000 	nop			; .*
+     8090:	e1a00000 	nop			; .*
+     8094:	e1a00000 	nop			; .*
+     8098:	e320f000 	nop	\{0\}
+     809c:	0000000c 	.word	0x0000000c
+ 
+ 000080a0 <bar>:
+     80a0:	4801      	ldr	r0, \[pc, #4\]	; \(80a8 <bar\+0x8>\)
+     80a2:	4478      	add	r0, pc
+     80a4:	6800      	ldr	r0, \[r0, #0\]
+     80a6:	46c0      	nop			; .*
+     80a8:	0000809e 	.word	0x0000809e
+     80ac:	4801      	ldr	r0, \[pc, #4\]	; \(80b4 <bar\+0x14>\)
+     80ae:	4478      	add	r0, pc
+     80b0:	6800      	ldr	r0, \[r0, #0\]
+     80b2:	46c0      	nop			; \(mov r8, r8\)
+     80b4:	00008092 	.word	0x00008092
+     80b8:	4801      	ldr	r0, \[pc, #4\]	; \(80c0 <bar\+0x20>\)
+     80ba:	4478      	add	r0, pc
+     80bc:	6800      	ldr	r0, \[r0, #0\]
+     80be:	46c0      	nop			; \(mov r8, r8\)
+     80c0:	0000808a 	.word	0x0000808a
+     80c4:	4801      	ldr	r0, \[pc, #4\]	; \(80cc <bar\+0x2c>\)
+     80c6:	46c0      	nop			; \(mov r8, r8\)
+     80c8:	46c0      	nop			; \(mov r8, r8\)
+     80ca:	bf00      	nop
+     80cc:	0000000c 	.word	0x0000000c
+     80d0:	4801      	ldr	r0, \[pc, #4\]	; \(80d8 <bar\+0x38>\)
+     80d2:	f3af 8000 	nop.w
+     80d6:	46c0      	nop			; \(mov r8, r8\)
+     80d8:	0000000c 	.word	0x0000000c
+     80dc:	4801      	ldr	r0, \[pc, #4\]	; \(80e4 <bar\+0x44>\)
+     80de:	f3af 8000 	nop.w
+     80e2:	46c0      	nop			; \(mov r8, r8\)
+     80e4:	00000014 	.word	0x00000014
+     80e8:	4802      	ldr	r0, \[pc, #8\]	; \(80f4 <bar\+0x54>\)
+     80ea:	4478      	add	r0, pc
+     80ec:	6801      	ldr	r1, \[r0, #0\]
+     80ee:	1c08      	adds	r0, r1, #0
+     80f0:	46c0      	nop			; \(mov r8, r8\)
+     80f2:	bf00      	nop
+     80f4:	00008056 	.word	0x00008056
+     80f8:	4802      	ldr	r0, \[pc, #8\]	; \(8104 <bar\+0x64>\)
+     80fa:	4478      	add	r0, pc
+     80fc:	6801      	ldr	r1, \[r0, #0\]
+     80fe:	4608      	mov	r0, r1
+     8100:	46c0      	nop			; \(mov r8, r8\)
+     8102:	bf00      	nop
+     8104:	00008046 	.word	0x00008046
+     8108:	4802      	ldr	r0, \[pc, #8\]	; \(8114 <bar\+0x74>\)
+     810a:	46c0      	nop			; \(mov r8, r8\)
+     810c:	46c0      	nop			; \(mov r8, r8\)
+     810e:	46c0      	nop			; \(mov r8, r8\)
+     8110:	46c0      	nop			; \(mov r8, r8\)
+     8112:	bf00      	nop
+     8114:	0000000c 	.word	0x0000000c
+     8118:	4802      	ldr	r0, \[pc, #8\]	; \(8124 <bar\+0x84>\)
+     811a:	46c0      	nop			; \(mov r8, r8\)
+     811c:	46c0      	nop			; \(mov r8, r8\)
+     811e:	46c0      	nop			; \(mov r8, r8\)
+     8120:	46c0      	nop			; \(mov r8, r8\)
+     8122:	bf00      	nop
+     8124:	0000000c 	.word	0x0000000c
Index: ld/testsuite/ld-arm/tls-descrelax-v7.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descrelax-v7.s
diff -N ld/testsuite/ld-arm/tls-descrelax-v7.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descrelax-v7.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,198 ----
+ @ we can relax local and non-weak globals for non-shared links
+ 
+ 	.arch	armv7-a
+ 	.text
+ 	.arm
+ 
+ 	.p2align 2
+ foo:
+ @tlscall global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:	ldr	r0, [pc, r0]
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 8)
+ 	
+ 	.p2align 2
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	gd1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @tlscall local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 
+ 	.p2align 2
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	ld1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @open coded global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:
+ 	add	r0, pc, r0
+ 	ldr	r1, [r0]
+ 	mov	r0, r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 8)
+ 
+ 	.p2align 2
+ @open coded global, should relax to IE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq gd1
+ 	add	r0, pc, r0
+ .tlsdescseq gd1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq gd1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @open coded local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 2:
+ 	nop
+ 	nop
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 	
+ 	.p2align 2
+ @open coded local, should relax to LE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq ld1
+ 	add	r0, pc, r0
+ .tlsdescseq ld1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq ld1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b)
+ 
+ 
+ 	.thumb
+ 	.p2align 1
+ bar:	
+ @tlscall global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:	add	r0, pc, r0
+ 	ldr	r0, [r0]
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 4)
+ 	
+ 	.p2align 1
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	gd1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	r1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	r1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 
+ 	.p2align 1
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	ld1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	r0(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	r0(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @open coded global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:
+ 	add	r0, pc
+ 	ldr	r1, [r0]
+ 	mov	r0, r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 4)
+ 
+ 	.p2align 1
+ @open coded global, should relax to IE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq gd1
+ 	add	r0, pc
+ .tlsdescseq gd1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq gd1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @open coded local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 2:
+ 	nop
+ 	nop
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 	
+ 	.p2align 1
+ @open coded local, should relax to LE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq ld1
+ 	add	r0, pc
+ .tlsdescseq ld1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq ld1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ 	.global	gd1
+ gd1:	.space 4
+ ld1:	.space 4
+ 	.globl r1
+ r1:	.space 4
+ r0:	.space 4
Index: ld/testsuite/ld-arm/tls-descrelax.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descrelax.d
diff -N ld/testsuite/ld-arm/tls-descrelax.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descrelax.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,108 ----
+ .*:     file format elf32-.*
+ architecture: arm, flags 0x[0-9a-f]+:
+ EXEC_P, HAS_SYMS, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .text:
+ 
+ 00008000 <foo>:
+     8000:	e59f0004 	ldr	r0, \[pc, #4\]	; 800c <foo\+0xc>
+     8004:	e79f0000 	ldr	r0, \[pc, r0\]
+     8008:	e1a00000 	nop			; \(mov r0, r0\)
+     800c:	00008138 	.word	0x00008138
+     8010:	e59f0004 	ldr	r0, \[pc, #4\]	; 801c <foo\+0x1c>
+     8014:	e79f0000 	ldr	r0, \[pc, r0\]
+     8018:	e1a00000 	nop			; \(mov r0, r0\)
+     801c:	00008128 	.word	0x00008128
+     8020:	e59f0004 	ldr	r0, \[pc, #4\]	; 802c <foo\+0x2c>
+     8024:	e1a00000 	nop			; \(mov r0, r0\)
+     8028:	e1a00000 	nop			; \(mov r0, r0\)
+     802c:	0000000c 	.word	0x0000000c
+     8030:	e59f0004 	ldr	r0, \[pc, #4\]	; 803c <foo\+0x3c>
+     8034:	e1a00000 	nop			; \(mov r0, r0\)
+     8038:	e1a00000 	nop			; \(mov r0, r0\)
+     803c:	0000000c 	.word	0x0000000c
+     8040:	e59f000c 	ldr	r0, \[pc, #12\]	; 8054 <foo\+0x54>
+     8044:	e08f0000 	add	r0, pc, r0
+     8048:	e5901000 	ldr	r1, \[r0\]
+     804c:	e1a00001 	mov	r0, r1
+     8050:	e1a00000 	nop			; \(mov r0, r0\)
+     8054:	000080f8 	.word	0x000080f8
+     8058:	e59f000c 	ldr	r0, \[pc, #12\]	; 806c <foo\+0x6c>
+     805c:	e08f0000 	add	r0, pc, r0
+     8060:	e5901000 	ldr	r1, \[r0\]
+     8064:	e1a00001 	mov	r0, r1
+     8068:	e1a00000 	nop			; \(mov r0, r0\)
+     806c:	000080e0 	.word	0x000080e0
+     8070:	e59f000c 	ldr	r0, \[pc, #12\]	; 8084 <foo\+0x84>
+     8074:	e1a00000 	nop			; \(mov r0, r0\)
+     8078:	e1a00000 	nop			; \(mov r0, r0\)
+     807c:	e1a00000 	nop			; \(mov r0, r0\)
+     8080:	e1a00000 	nop			; \(mov r0, r0\)
+     8084:	0000000c 	.word	0x0000000c
+     8088:	e59f000c 	ldr	r0, \[pc, #12\]	; 809c <foo\+0x9c>
+     808c:	e1a00000 	nop			; \(mov r0, r0\)
+     8090:	e1a00000 	nop			; \(mov r0, r0\)
+     8094:	e1a00000 	nop			; \(mov r0, r0\)
+     8098:	e1a00000 	nop			; \(mov r0, r0\)
+     809c:	0000000c 	.word	0x0000000c
+ 
+ 000080a0 <bar>:
+     80a0:	4801      	ldr	r0, \[pc, #4\]	; \(80a8 <bar\+0x8>\)
+     80a2:	4478      	add	r0, pc
+     80a4:	6800      	ldr	r0, \[r0, #0\]
+     80a6:	46c0      	nop			; \(mov r8, r8\)
+     80a8:	0000809e 	.word	0x0000809e
+     80ac:	4801      	ldr	r0, \[pc, #4\]	; \(80b4 <bar\+0x14>\)
+     80ae:	4478      	add	r0, pc
+     80b0:	6800      	ldr	r0, \[r0, #0\]
+     80b2:	46c0      	nop			; \(mov r8, r8\)
+     80b4:	00008092 	.word	0x00008092
+     80b8:	4801      	ldr	r0, \[pc, #4\]	; \(80c0 <bar\+0x20>\)
+     80ba:	4478      	add	r0, pc
+     80bc:	6800      	ldr	r0, \[r0, #0\]
+     80be:	46c0      	nop			; \(mov r8, r8\)
+     80c0:	0000808a 	.word	0x0000808a
+     80c4:	4801      	ldr	r0, \[pc, #4\]	; \(80cc <bar\+0x2c>\)
+     80c6:	46c0      	nop			; \(mov r8, r8\)
+     80c8:	46c0      	nop			; \(mov r8, r8\)
+     80ca:	46c0      	nop			; \(mov r8, r8\)
+     80cc:	0000000c 	.word	0x0000000c
+     80d0:	4801      	ldr	r0, \[pc, #4\]	; \(80d8 <bar\+0x38>\)
+     80d2:	bf00      	nop
+     80d4:	bf00      	nop
+     80d6:	46c0      	nop			; \(mov r8, r8\)
+     80d8:	0000000c 	.word	0x0000000c
+     80dc:	4801      	ldr	r0, \[pc, #4\]	; \(80e4 <bar\+0x44>\)
+     80de:	bf00      	nop
+     80e0:	bf00      	nop
+     80e2:	46c0      	nop			; \(mov r8, r8\)
+     80e4:	00000014 	.word	0x00000014
+     80e8:	4802      	ldr	r0, \[pc, #8\]	; \(80f4 <bar\+0x54>\)
+     80ea:	4478      	add	r0, pc
+     80ec:	6801      	ldr	r1, \[r0, #0\]
+     80ee:	1c08      	adds	r0, r1, #0
+     80f0:	46c0      	nop			; \(mov r8, r8\)
+     80f2:	46c0      	nop			; \(mov r8, r8\)
+     80f4:	00008056 	.word	0x00008056
+     80f8:	4802      	ldr	r0, \[pc, #8\]	; \(8104 <bar\+0x64>\)
+     80fa:	4478      	add	r0, pc
+     80fc:	6801      	ldr	r1, \[r0, #0\]
+     80fe:	4608      	mov	r0, r1
+     8100:	46c0      	nop			; \(mov r8, r8\)
+     8102:	46c0      	nop			; \(mov r8, r8\)
+     8104:	00008046 	.word	0x00008046
+     8108:	4802      	ldr	r0, \[pc, #8\]	; \(8114 <bar\+0x74>\)
+     810a:	46c0      	nop			; \(mov r8, r8\)
+     810c:	46c0      	nop			; \(mov r8, r8\)
+     810e:	46c0      	nop			; \(mov r8, r8\)
+     8110:	46c0      	nop			; \(mov r8, r8\)
+     8112:	46c0      	nop			; \(mov r8, r8\)
+     8114:	0000000c 	.word	0x0000000c
+     8118:	4802      	ldr	r0, \[pc, #8\]	; \(8124 <bar\+0x84>\)
+     811a:	46c0      	nop			; \(mov r8, r8\)
+     811c:	46c0      	nop			; \(mov r8, r8\)
+     811e:	46c0      	nop			; \(mov r8, r8\)
+     8120:	46c0      	nop			; \(mov r8, r8\)
+     8122:	46c0      	nop			; \(mov r8, r8\)
+     8124:	0000000c 	.word	0x0000000c
Index: ld/testsuite/ld-arm/tls-descrelax.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descrelax.s
diff -N ld/testsuite/ld-arm/tls-descrelax.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descrelax.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,197 ----
+ @ we can relax local and non-weak globals for non-shared links
+ 
+ 	.text
+ 	.arm
+ 
+ 	.p2align 2
+ foo:
+ @tlscall global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:	ldr	r0, [pc, r0]
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 8)
+ 	
+ 	.p2align 2
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	gd1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @tlscall local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 
+ 	.p2align 2
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	ld1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @open coded global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:
+ 	add	r0, pc, r0
+ 	ldr	r1, [r0]
+ 	mov	r0, r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 8)
+ 
+ 	.p2align 2
+ @open coded global, should relax to IE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq gd1
+ 	add	r0, pc, r0
+ .tlsdescseq gd1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq gd1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b)
+ 
+ 	.p2align 2
+ @open coded local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 2:
+ 	nop
+ 	nop
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 	
+ 	.p2align 2
+ @open coded local, should relax to LE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq ld1
+ 	add	r0, pc, r0
+ .tlsdescseq ld1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq ld1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b)
+ 
+ 
+ 	.thumb
+ 	.p2align 1
+ bar:	
+ @tlscall global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:	add	r0, pc, r0
+ 	ldr	r0, [r0]
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 4)
+ 	
+ 	.p2align 1
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	gd1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall global, should relax to IE
+ 	ldr	r0, 1f
+ 2:	blx	r1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	r1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 
+ 	.p2align 1
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	ld1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @tlscall local, should relax to LE
+ 	ldr	r0, 1f
+ 2:	blx	r0(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	r0(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @open coded global, manually relaxed to IE
+ 	ldr	r0, 1f
+ 2:
+ 	add	r0, pc
+ 	ldr	r1, [r0]
+ 	mov	r0, r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(gottpoff) + (. - 2b - 4)
+ 
+ 	.p2align 1
+ @open coded global, should relax to IE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq gd1
+ 	add	r0, pc
+ .tlsdescseq gd1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq gd1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	gd1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.p2align 1
+ @open coded local, manually relaxed to LE
+ 	ldr	r0, 1f
+ 2:
+ 	nop
+ 	nop
+ 	nop
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tpoff)
+ 	
+ 	.p2align 1
+ @open coded local, should relax to LE
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq ld1
+ 	add	r0, pc
+ .tlsdescseq ld1
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq ld1
+ 	blx	r1
+ 	nop
+ 	.p2align 2
+ 1:	.word	ld1(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ 	.global	gd1
+ gd1:	.space 4
+ ld1:	.space 4
+ 	.globl r1
+ r1:	.space 4
+ r0:	.space 4
Index: ld/testsuite/ld-arm/tls-descseq.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descseq.d
diff -N ld/testsuite/ld-arm/tls-descseq.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descseq.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,44 ----
+ 
+ tmpdir/tls-lib2inline.so:     file format elf32-.*arm
+ architecture: arm, flags 0x[0-9a-f]+:
+ HAS_SYMS, DYNAMIC, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .plt:
+ 
+ [0-9a-f]+ <.plt>:
+     [0-9a-f]+:	e52de004 	push	{lr}		; .*
+     [0-9a-f]+:	e59fe004 	ldr	lr, \[pc, #4\]	; .*
+     [0-9a-f]+:	e08fe00e 	add	lr, pc, lr
+     [0-9a-f]+:	e5bef008 	ldr	pc, \[lr, #8\]!
+     [0-9a-f]+:	000080e4 	.word	0x000080e4
+     [0-9a-f]+:	e08e0000 	add	r0, lr, r0
+     [0-9a-f]+:	e5901004 	ldr	r1, \[r0, #4\]
+     [0-9a-f]+:	e12fff11 	bx	r1
+     [0-9a-f]+:	e52d2004 	push	{r2}		; .*
+     [0-9a-f]+:	e59f200c 	ldr	r2, \[pc, #12\]	; .*
+     [0-9a-f]+:	e59f100c 	ldr	r1, \[pc, #12\]	; .*
+     [0-9a-f]+:	e79f2002 	ldr	r2, \[pc, r2\]
+     [0-9a-f]+:	e081100f 	add	r1, r1, pc
+     [0-9a-f]+:	e12fff12 	bx	r2
+     [0-9a-f]+:	000080d4 	.word	0x000080d4
+     [0-9a-f]+:	000080bc 	.word	0x000080bc
+ 
+ Disassembly of section .text:
+ 
+ [0-9a-f]+ <foo>:
+     [0-9a-f]+:	e59f000c 	ldr	r0, \[pc, #12\]	; .*
+     [0-9a-f]+:	e08f0000 	add	r0, pc, r0
+     [0-9a-f]+:	e5901004 	ldr	r1, \[r0, #4\]
+     [0-9a-f]+:	e12fff31 	blx	r1
+     [0-9a-f]+:	e1a00000 	nop			; .*
+     [0-9a-f]+:	000080b4 	.word	0x000080b4
+ 
+ [0-9a-f]+ <bar>:
+     [0-9a-f]+:	4802      	ldr	r0, \[pc, #8\]	; .*
+     [0-9a-f]+:	4478      	add	r0, pc
+     [0-9a-f]+:	6841      	ldr	r1, \[r0, #4\]
+     [0-9a-f]+:	4788      	blx	r1
+     [0-9a-f]+:	46c0      	nop			; .*
+     [0-9a-f]+:	46c0      	nop			; .*
+     [0-9a-f]+:	000080a2 	.word	0x000080a2
Index: ld/testsuite/ld-arm/tls-descseq.r
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descseq.r
diff -N ld/testsuite/ld-arm/tls-descseq.r
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descseq.r	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,6 ----
+ 
+ .*:     file format elf32-.*arm
+ 
+ DYNAMIC RELOCATION RECORDS
+ OFFSET   TYPE              VALUE 
+ [0-9a-f]+ R_ARM_TLS_DESC    lib_gd2
Index: ld/testsuite/ld-arm/tls-descseq.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-descseq.s
diff -N ld/testsuite/ld-arm/tls-descseq.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-descseq.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,41 ----
+ 	.text
+ 	.arm
+ 	.globl foo
+ 	.type foo, %function
+ foo:
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq lib_gd2
+ 	add	r0, pc, r0
+ .tlsdescseq lib_gd2
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq lib_gd2
+ 	blx	r1
+ 	nop
+ 
+ 1:
+ 	.word	lib_gd2(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	.globl bar
+ 	.type bar, %function
+ bar:
+ 	ldr	r0, 1f
+ 2:
+ .tlsdescseq lib_gd2
+ 	add	r0, pc
+ .tlsdescseq lib_gd2
+ 	ldr	r1, [r0,#4]
+ .tlsdescseq lib_gd2
+ 	blx	r1
+ 	nop
+ 
+ 	.p2align 2
+ 1:
+ 	.word	lib_gd2(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ 	.global lib_gd2
+ lib_gd2:
+ 	.space	4
+ 
Index: ld/testsuite/ld-arm/tls-gdesc-got.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdesc-got.d
diff -N ld/testsuite/ld-arm/tls-gdesc-got.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdesc-got.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,30 ----
+ 
+ .*/tls-lib2-got.so:     file format elf32-.*arm
+ architecture: arm, flags 0x00000150:
+ HAS_SYMS, DYNAMIC, D_PAGED
+ start address 0x00008210
+ 
+ 
+ Disassembly of section .got:
+ 
+ 00010310 <.*>:
+    10310:	00010288 	.*
+ 	...
+    1031c:	00000008 	.*
+ 			1031c: R_ARM_TLS_DESC	\*ABS\*
+    10320:	00000000 	.*
+    10324:	0000000c 	.*
+ 			10324: R_ARM_TLS_DESC	\*ABS\*
+    10328:	00000000 	.*
+    1032c:	80000004 	.*
+ 			1032c: R_ARM_TLS_DESC	glob1
+    10330:	00000000 	.*
+    10334:	80000006 	.*
+ 			10334: R_ARM_TLS_DESC	ext2
+    10338:	00000000 	.*
+    1033c:	80000007 	.*
+ 			1033c: R_ARM_TLS_DESC	ext1
+    10340:	00000000 	.*
+    10344:	80000009 	.*
+ 			10344: R_ARM_TLS_DESC	glob2
+ 	...
Index: ld/testsuite/ld-arm/tls-gdesc-got.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdesc-got.s
diff -N ld/testsuite/ld-arm/tls-gdesc-got.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdesc-got.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,45 ----
+ 
+ 	.arm
+ foo:
+ 	ldr	r0,1f
+ 2:	bl	loc1(tlscall)
+ 	nop
+ 1:	.word	loc1(tlsdesc) + (. - 2b)
+ 
+ 	ldr	r0,1f
+ 2:	bl	loc2(tlscall)
+ 	nop
+ 1:	.word	loc2(tlsdesc) + (. - 2b)
+ 
+ 	ldr	r0,1f
+ 2:	bl	glob1(tlscall)
+ 	nop
+ 1:	.word	glob1(tlsdesc) + (. - 2b)
+ 
+ 	ldr	r0,1f
+ 2:	bl	glob2(tlscall)
+ 	nop
+ 1:	.word	glob2(tlsdesc) + (. - 2b)
+ 
+ 	ldr	r0,1f
+ 2:	bl	ext1(tlscall)
+ 	nop
+ 1:	.word	ext1(tlsdesc) + (. - 2b)
+ 
+ 	ldr	r0,1f
+ 2:	bl	ext2(tlscall)
+ 	nop
+ 1:	.word	ext2(tlsdesc) + (. - 2b)
+ 
+ 	.section	.tdata,"awT",%progbits
+ 	.space	8
+ 	.type	loc1, %object
+ loc1:	.space	4
+ 	.type	loc2, %object
+ loc2:	.space	4
+ 	.globl	glob1
+ 	.type	glob1, %object
+ glob1:	.space	4
+ 	.globl	glob2
+ 	.type	glob2, %object
+ glob2:	.space	4
Index: ld/testsuite/ld-arm/tls-gdesc-nlazy.g
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdesc-nlazy.g
diff -N ld/testsuite/ld-arm/tls-gdesc-nlazy.g
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdesc-nlazy.g	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,4 ----
+ 
+ Hex dump of section '.got':
+   0x[0-9a-f]+ [0-9a-f]+ 00000000 00000000 00000000 ................
+   0x[0-9a-f]+ 00000000 00000000 00000000          ............
Index: ld/testsuite/ld-arm/tls-gdesc-nlazy.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdesc-nlazy.s
diff -N ld/testsuite/ld-arm/tls-gdesc-nlazy.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdesc-nlazy.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,17 ----
+ 	.text
+ 	.globl foo
+ 	.type foo, %function
+ foo:
+ 	nop
+ .L2:
+ 	blx	lib_gd2(tlscall) 
+ 	mov	pc, lr
+ 
+ .Lpool:
+ 	.word	lib_gd2(tlsdesc) + (. - .L2)
+ 
+ 	.section .tdata,"awT"
+ 	.global lib_gd2
+ lib_gd2:
+ 	.space	4
+ 
Index: ld/testsuite/ld-arm/tls-gdesc.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdesc.d
diff -N ld/testsuite/ld-arm/tls-gdesc.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdesc.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,42 ----
+ 
+ tmpdir/tls-lib2.so:     file format elf32-.*arm
+ architecture: arm, flags 0x[0-9a-f]+:
+ HAS_SYMS, DYNAMIC, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .plt:
+ 
+ [0-9a-f]+ <.plt>:
+     [0-9a-f]+:	e52de004 	push	{lr}		; .*
+     [0-9a-f]+:	e59fe004 	ldr	lr, \[pc, #4\]	; .*
+     [0-9a-f]+:	e08fe00e 	add	lr, pc, lr
+     [0-9a-f]+:	e5bef008 	ldr	pc, \[lr, #8\]!
+     [0-9a-f]+:	000080e8 	.word	0x000080e8
+     [0-9a-f]+:	e08e0000 	add	r0, lr, r0
+     [0-9a-f]+:	e5901004 	ldr	r1, \[r0, #4\]
+     [0-9a-f]+:	e12fff11 	bx	r1
+     [0-9a-f]+:	e52d2004 	push	{r2}		; .*
+     [0-9a-f]+:	e59f200c 	ldr	r2, \[pc, #12\]	; .*
+     [0-9a-f]+:	e59f100c 	ldr	r1, \[pc, #12\]	; .*
+     [0-9a-f]+:	e79f2002 	ldr	r2, \[pc, r2\]
+     [0-9a-f]+:	e081100f 	add	r1, r1, pc
+     [0-9a-f]+:	e12fff12 	bx	r2
+     [0-9a-f]+:	000080e0 	.word	0x000080e0
+     [0-9a-f]+:	000080c0 	.word	0x000080c0
+ Disassembly of section .text:
+ 
+ [0-9a-f]+ <foo>:
+     [0-9a-f]+:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+     [0-9a-f]+:	fafffff2 	blx	[0-9a-f]+ .*
+     [0-9a-f]+:	e1a00000 	nop			; .*
+     [0-9a-f]+:	000080c4 	.word	0x000080c4
+ 
+ [0-9a-f]+ <bar>:
+     [0-9a-f]+:	4801      	ldr	r0, \[pc, #4\]	; .*
+     [0-9a-f]+:	f7ff efe0 	blx	[0-9a-f]+ .*
+     [0-9a-f]+:	46c0      	nop			; .*
+     [0-9a-f]+:	000080b5 	.word	0x000080b5
+     [0-9a-f]+:	4801      	ldr	r0, \[pc, #4\]	; .*
+     [0-9a-f]+:	f7ff efda 	blx	[0-9a-f]+ .*
+     [0-9a-f]+:	46c0      	nop			; .*
+     [0-9a-f]+:	000080a1 	.word	0x000080a1
Index: ld/testsuite/ld-arm/tls-gdesc.r
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdesc.r
diff -N ld/testsuite/ld-arm/tls-gdesc.r
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdesc.r	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,7 ----
+ 
+ .*:     file format elf32-.*arm
+ 
+ DYNAMIC RELOCATION RECORDS
+ OFFSET   TYPE              VALUE 
+ [0-9a-f]+ R_ARM_TLS_DESC    lib_gd2
+ [0-9a-f]+ R_ARM_TLS_DESC    r0
Index: ld/testsuite/ld-arm/tls-gdesc.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdesc.s
diff -N ld/testsuite/ld-arm/tls-gdesc.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdesc.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,41 ----
+ 	.text
+ 	.arm
+ 	.globl foo
+ 	.type foo, %function
+ foo:
+ 	ldr	r0,1f
+ 2:
+ 	blx	lib_gd2(tlscall) 
+ 	nop
+ 
+ 1:
+ 	.word	lib_gd2(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	.globl bar
+ 	.type bar, %function
+ bar:
+ 	ldr	r0,1f
+ 2:
+ 	blx	lib_gd2(tlscall) 
+ 	nop
+ 
+ 	.p2align 2
+ 1:
+ 	.word	lib_gd2(tlsdesc) + (. - 2b + 1)
+ 
+ 	ldr	r0,1f
+ 2:
+ 	blx	r0(tlscall) 
+ 	nop
+ 
+ 	.p2align 2
+ 1:
+ 	.word	r0(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ 	.global lib_gd2
+ lib_gd2:
+ 	.space	4
+ 	.globl r0
+ r0:	.space 4
Index: ld/testsuite/ld-arm/tls-gdierelax.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdierelax.d
diff -N ld/testsuite/ld-arm/tls-gdierelax.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdierelax.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,20 ----
+ 
+ tmpdir/tls-app-rel-ie:     file format elf32-.*arm
+ architecture: arm, flags 0x[0-9a-f]+:
+ EXEC_P, HAS_SYMS, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .text:
+ 
+ [0-9a-f]+ <foo>:
+     [0-9a-f]+:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+     [0-9a-f]+:	e79f0000 	ldr	r0, \[pc, r0\]
+     [0-9a-f]+:	e1a00000 	nop			; .*
+     [0-9a-f]+:	00008020 	.word	0x00008020
+ 
+ [0-9a-f]+ <bar>:
+     [0-9a-f]+:	4801      	ldr	r0, \[pc, #4\]	; .*
+     [0-9a-f]+:	4478      	add	r0, pc
+     [0-9a-f]+:	6800      	ldr	r0, \[r0, #0\]
+     [0-9a-f]+:	46c0      	nop			; .*
+     [0-9a-f]+:	00008016 	.word	0x00008016
Index: ld/testsuite/ld-arm/tls-gdierelax.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdierelax.s
diff -N ld/testsuite/ld-arm/tls-gdierelax.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdierelax.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,34 ----
+ 	.text
+ 	.arm
+ 	.globl foo
+ 	.type foo, %function
+ foo:
+ 	ldr	r0, 1f
+ 2:
+ 	blx	lib_gd2(tlscall) 
+ 	nop
+ 
+ 1:
+ 	.word	lib_gd2(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	.globl bar
+ 	.type bar, %function
+ bar:
+ 	ldr	r0,1f
+ 2:
+ 	blx	lib_gd2(tlscall) 
+ 	nop
+ 
+ 	.p2align 2
+ 1:
+ 	.word	lib_gd2(tlsdesc) + (. - 2b + 1)
+ 
+ 	.globl _start
+ _start:
+ 	
+ 	.section .tdata,"awT"
+ 	.global lib_gd2
+ lib_gd2:
+ 	.space	4
+ 
Index: ld/testsuite/ld-arm/tls-gdierelax2.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdierelax2.d
diff -N ld/testsuite/ld-arm/tls-gdierelax2.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdierelax2.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,23 ----
+ 
+ tmpdir/tls-app-rel-ie2:     file format elf32-.*arm
+ architecture: arm, flags 0x[0-9a-f]+:
+ HAS_SYMS, DYNAMIC, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .text:
+ 
+ [0-9a-f]+ <foo>:
+     [0-9a-f]+:	e1a00000 	nop			; .*
+     [0-9a-f]+:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+     [0-9a-f]+:	e79f0000 	ldr	r0, \[pc, r0\]
+     [0-9a-f]+:	e1a00000 	nop			; .*
+     [0-9a-f]+:	00008098 	.word	0x00008098
+     [0-9a-f]+:	0000809c 	.word	0x0000809c
+ 
+ [0-9a-f]+ <bar>:
+     [0-9a-f]+:	4801      	ldr	r0, \[pc, #4\]	; .*
+     [0-9a-f]+:	4478      	add	r0, pc
+     [0-9a-f]+:	6800      	ldr	r0, \[r0, #0\]
+     [0-9a-f]+:	46c0      	nop			; .*
+     [0-9a-f]+:	0000808a 	.word	0x0000808a
+     [0-9a-f]+:	0000808c 	.word	0x0000808c
Index: ld/testsuite/ld-arm/tls-gdierelax2.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdierelax2.s
diff -N ld/testsuite/ld-arm/tls-gdierelax2.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdierelax2.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,35 ----
+ 	.text
+ 	.arm
+ 	.globl foo
+ 	.type foo, %function
+ foo:
+ 	nop
+ 3:	ldr	r0,1f
+ 2:	bl	lib_gd2(tlscall) 
+ 	nop
+ 
+ 1:
+ 	.word	lib_gd2(tlsdesc) + (. - 2b)
+ 	.word	lib_gd2(gottpoff) + (. - 3b - 8)
+ 
+ 	.thumb
+ 	.globl bar
+ 	.type bar, %function
+ bar:
+ 3:	ldr	r0,1f
+ 2:	blx	lib_gd2(tlscall) 
+ 	nop
+ 
+ 	.p2align 2
+ 1:
+ 	.word	lib_gd2(tlsdesc) + (. - 2b + 1)
+ 	.word	lib_gd2(gottpoff) + (. - 3b - 4)
+ 
+ 	.globl _start
+ _start:
+ 
+ 	.section .tdata,"awT"
+ 	.global lib_gd2
+ lib_gd2:
+ 	.space	4
+ 
Index: ld/testsuite/ld-arm/tls-gdlerelax.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdlerelax.d
diff -N ld/testsuite/ld-arm/tls-gdlerelax.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdlerelax.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,13 ----
+ 
+ tmpdir/tls-app-rel-le:     file format elf32-.*arm
+ architecture: arm, flags 0x[0-9a-f]+:
+ EXEC_P, HAS_SYMS, D_PAGED
+ start address 0x[0-9a-f]+
+ 
+ Disassembly of section .text:
+ 
+ [0-9a-f]+ <foo>:
+     [0-9a-f]+:	e1a00000 	nop			; .*
+     [0-9a-f]+:	e1a00000 	nop			; .*
+     [0-9a-f]+:	e1a0f00e 	mov	pc, lr
+     [0-9a-f]+:	00000008 	.word	0x00000008
Index: ld/testsuite/ld-arm/tls-gdlerelax.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-gdlerelax.s
diff -N ld/testsuite/ld-arm/tls-gdlerelax.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-gdlerelax.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,16 ----
+ 	.text
+ 	.globl foo
+ 	.type foo, %function
+ foo:
+ 	nop
+ .L2:
+ 	blx	lib_gd2(tlscall) 
+ 	mov	pc, lr
+ 
+ .Lpool:
+ 	.word	lib_gd2(tlsdesc) + (. - .L2)
+ 
+ 	.section .tdata,"awT"
+ lib_gd2:
+ 	.space	4
+ 
Index: ld/testsuite/ld-arm/tls-lib-loc.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-lib-loc.d
diff -N ld/testsuite/ld-arm/tls-lib-loc.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-lib-loc.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,33 ----
+ 
+ .*:     file format elf32-.*arm
+ architecture: arm, flags 0x00000150:
+ HAS_SYMS, DYNAMIC, D_PAGED
+ start address 0x.*
+ 
+ Disassembly of section .plt:
+ 
+ [0-9a-f]+ <.plt>:
+     [0-9a-f]+:	e52de004 	push	{lr}		; .*
+     [0-9a-f]+:	e59fe004 	ldr	lr, \[pc, #4\]	; 8150 .*
+     [0-9a-f]+:	e08fe00e 	add	lr, pc, lr
+     [0-9a-f]+:	e5bef008 	ldr	pc, \[lr, #8\]!
+     8150:	000080cc 	.word	0x000080cc
+     8154:	e08e0000 	add	r0, lr, r0
+     [0-9a-f]+:	e5901004 	ldr	r1, \[r0, #4\]
+     [0-9a-f]+:	e12fff11 	bx	r1
+     [0-9a-f]+:	e52d2004 	push	{r2}		; .*
+     8164:	e59f200c 	ldr	r2, \[pc, #12\]	; 8178 .*
+     [0-9a-f]+:	e59f100c 	ldr	r1, \[pc, #12\]	; 817c .*
+     [0-9a-f]+:	e79f2002 	ldr	r2, \[pc, r2\]
+     [0-9a-f]+:	e081100f 	add	r1, r1, pc
+     [0-9a-f]+:	e12fff12 	bx	r2
+     8178:	000080bc 	.word	0x000080bc
+     817c:	000080a4 	.word	0x000080a4
+ 
+ Disassembly of section .text:
+ 
+ [0-9a-f]+ <foo>:
+     [0-9a-f]+:	e59f0004 	ldr	r0, \[pc, #4\]	; 818c .*
+     [0-9a-f]+:	fafffff2 	blx	8154 <.*\+0x8154>
+     [0-9a-f]+:	e1a00000 	nop			; .*
+     818c:	000080a0 	.word	0x000080a0
Index: ld/testsuite/ld-arm/tls-lib-loc.r
===================================================================
RCS file: ld/testsuite/ld-arm/tls-lib-loc.r
diff -N ld/testsuite/ld-arm/tls-lib-loc.r
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-lib-loc.r	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,6 ----
+ 
+ .*:     file format elf32-.*arm
+ 
+ DYNAMIC RELOCATION RECORDS
+ OFFSET   TYPE              VALUE 
+ .* R_ARM_TLS_DESC    \*ABS\*
Index: ld/testsuite/ld-arm/tls-lib-loc.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-lib-loc.s
diff -N ld/testsuite/ld-arm/tls-lib-loc.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-lib-loc.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,14 ----
+ 	.text
+ 	.arm
+ 
+ foo:
+ 	ldr	r0,1f
+ 2:	blx	loc(tlscall)
+ 	nop
+ 
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b)
+ 
+ 	.section .tdata,"awT"
+ loc:
+ 	.space	4
Index: ld/testsuite/ld-arm/tls-longplt-lib.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-longplt-lib.d
diff -N ld/testsuite/ld-arm/tls-longplt-lib.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-longplt-lib.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,59 ----
+ .*:     file format elf32-.*arm
+ architecture: arm, flags 0x00000150:
+ HAS_SYMS, DYNAMIC, D_PAGED
+ start address 0x.*
+ 
+ Disassembly of section .plt:
+ 
+ 00008198 <.plt>:
+     8198:	e52de004 	push	{lr}		; .*
+     819c:	e59fe004 	ldr	lr, \[pc, #4\]	; .*
+     81a0:	e08fe00e 	add	lr, pc, lr
+     81a4:	e5bef008 	ldr	pc, \[lr, #8\]!
+     81a8:	000080e0 	.word	0x000080e0
+     81ac:	e08e0000 	add	r0, lr, r0
+     81b0:	e5901004 	ldr	r1, \[r0, #4\]
+     81b4:	e12fff11 	bx	r1
+     81b8:	e52d2004 	push	{r2}		; .*
+     81bc:	e59f200c 	ldr	r2, \[pc, #12\]	; .*
+     81c0:	e59f100c 	ldr	r1, \[pc, #12\]	; .*
+     81c4:	e79f2002 	ldr	r2, \[pc, r2\]
+     81c8:	e081100f 	add	r1, r1, pc
+     81cc:	e12fff12 	bx	r2
+     81d0:	000080d8 	.word	0x000080d8
+     81d4:	000080b8 	.word	0x000080b8
+ 
+ Disassembly of section .text:
+ 
+ 000081d8 <text>:
+     81d8:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+     81dc:	fafffff2 	blx	81ac .*
+     81e0:	e1a00000 	nop			; .*
+     81e4:	000080b4 	.word	0x000080b4
+     81e8:	4801      	ldr	r0, \[pc, #4\]	; .*
+     81ea:	f7ff efe0 	blx	81ac <.*>
+     81ee:	46c0      	nop			; .*
+     81f0:	000080a5 	.word	0x000080a5
+ 
+ Disassembly of section .foo:
+ 
+ 04001000 <foo>:
+  4001000:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+  4001004:	fa000009 	blx	4001030 .*
+  4001008:	e1a00000 	nop			; .*
+  400100c:	fc00f28c 	.word	0xfc00f28c
+  4001010:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+  4001014:	fa000005 	blx	4001030 .*
+  4001018:	e1a00000 	nop			; .*
+  400101c:	fc00f284 	.word	0xfc00f284
+  4001020:	4801      	ldr	r0, \[pc, #4\]	; .*
+  4001022:	f000 e806 	blx	4001030 .*
+  4001026:	46c0      	nop			; .*
+  4001028:	fc00f26d 	.word	0xfc00f26d
+  400102c:	00000000 	.word	0x00000000
+ 
+ 04001030 <__unnamed_veneer>:
+  4001030:	e59f1000 	ldr	r1, \[pc, #0\]	; .*
+  4001034:	e08ff001 	add	pc, pc, r1
+  4001038:	fc007170 	.word	0xfc007170
+  400103c:	00000000 	.word	0x00000000
Index: ld/testsuite/ld-arm/tls-longplt-lib.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-longplt-lib.s
diff -N ld/testsuite/ld-arm/tls-longplt-lib.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-longplt-lib.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,51 ----
+ 	.syntax unified
+ 	.text
+ text:
+ 	.arm
+ 	ldr	r0,1f
+ 2:	blx	loc(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	ldr	r0,1f
+ 2:	blx	loc(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section ".foo","ax"
+ foo:
+ 	.arm
+ 	ldr	r0,1f
+ 2:	blx	loc(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b)
+ 
+ 	.arm
+ 	ldr	r0,1f
+ 2:	blx	glob(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	glob(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	ldr	r0,1f
+ 2:	blx	loc(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ 	.type	loc, %object
+ loc:	.space	4
+ 
+ 	@ glob1 and glob2 used by tls-longplt
+ 	.type	glob1, %object
+ 	.globl	glob1
+ glob1:	.space	4
+ 	.type	glob2, %object
+ 	.globl	glob2
+ glob2:	.space	4
Index: ld/testsuite/ld-arm/tls-longplt.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-longplt.d
diff -N ld/testsuite/ld-arm/tls-longplt.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-longplt.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,64 ----
+ .*:     file format elf32-.*arm
+ architecture: arm, flags 0x00000112:
+ EXEC_P, HAS_SYMS, D_PAGED
+ start address 0x.*
+ 
+ Disassembly of section .plt:
+ 
+ 0000819c <.plt>:
+     819c:	e52de004 	push	{lr}		; .*
+     81a0:	e59fe004 	ldr	lr, \[pc, #4\]	; .*
+     81a4:	e08fe00e 	add	lr, pc, lr
+     81a8:	e5bef008 	ldr	pc, \[lr, #8\]!
+     81ac:	00008100 	.word	0x00008100
+     81b0:	e08e0000 	add	r0, lr, r0
+     81b4:	e5901004 	ldr	r1, \[r0, #4]
+     81b8:	e12fff11 	bx	r1
+     81bc:	e52d2004 	push	{r2}		; .*
+     81c0:	e59f200c 	ldr	r2, \[pc, #12\]	; .*
+     81c4:	e59f100c 	ldr	r1, \[pc, #12\]	; .*
+     81c8:	e79f2002 	ldr	r2, \[pc, r2\]
+     81cc:	e081100f 	add	r1, r1, pc
+     81d0:	e12fff12 	bx	r2
+     81d4:	000080f4 	.word	0x000080f4
+     81d8:	000080d8 	.word	0x000080d8
+ 
+ Disassembly of section .text:
+ 
+ 000081dc <text>:
+     81dc:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+     81e0:	fafffff2 	blx	81b0 .*
+     81e4:	e1a00000 	nop			; .*
+     81e8:	000080d4 	.word	0x000080d4
+     81ec:	4801      	ldr	r0, \[pc, #4\]	; .*
+     81ee:	f7ff efe0 	blx	81b0 .*
+     81f2:	46c0      	nop			; .*
+     81f4:	000080c5 	.word	0x000080c5
+ 
+ Disassembly of section .foo:
+ 
+ 04001000 <foo>:
+  4001000:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+  4001004:	e79f0000 	ldr	r0, \[pc, r0\]
+  4001008:	e1a00000 	nop			; .*
+  400100c:	fc00f2b4 	.word	0xfc00f2b4
+  4001010:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+  4001014:	fa000005 	blx	4001030 .*
+  4001018:	e1a00000 	nop			; .*
+  400101c:	fc00f2a0 	.word	0xfc00f2a0
+  4001020:	4801      	ldr	r0, \[pc, #4\]	; .*
+  4001022:	f000 e80a 	blx	4001038 .*
+  4001026:	46c0      	nop			; .*
+  4001028:	fc00f291 	.word	0xfc00f291
+  400102c:	00000000 	.word	0x00000000
+ 
+ 04001030 <__unnamed_veneer>:
+  4001030:	e51ff004 	ldr	pc, \[pc, #-4\]	; .*
+  4001034:	000081b0 	.word	0x000081b0
+ 
+ 04001038 <__unnamed_veneer>:
+  4001038:	4778      	bx	pc
+  400103a:	46c0      	nop			; .*
+  400103c:	e51ff004 	ldr	pc, \[pc, #-4\]	; .*
+  4001040:	000081b0 	.word	0x000081b0
+  4001044:	00000000 	.word	0x00000000
Index: ld/testsuite/ld-arm/tls-longplt.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-longplt.s
diff -N ld/testsuite/ld-arm/tls-longplt.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-longplt.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,47 ----
+ 	.syntax unified
+ 	.text
+ text:
+ 	.arm
+ 	ldr	r0,1f
+ 2:	blx	udefw(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	udefw(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	ldr	r0,1f
+ 2:	blx	udefw(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	udefw(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section ".foo","ax"
+ foo:
+ 	.arm
+ 	ldr	r0,1f
+ 2:	blx	glob1(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	glob1(tlsdesc) + (. - 2b)
+ 
+ 	.arm
+ 	ldr	r0,1f
+ 2:	blx	udefw(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	udefw(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	ldr	r0,1f
+ 2:	blx	udefw(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	udefw(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ 	@ glob used by tls-longplt-lib
+ 	.type	glob, %object
+ 	.globl	glob
+ glob:	.space	4
+ 	.globl  udefw
+ 	.weak	udefw
Index: ld/testsuite/ld-arm/tls-mixed.r
===================================================================
RCS file: ld/testsuite/ld-arm/tls-mixed.r
diff -N ld/testsuite/ld-arm/tls-mixed.r
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-mixed.r	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,10 ----
+ 
+ .*:     file format elf32-.*arm
+ 
+ DYNAMIC RELOCATION RECORDS
+ OFFSET   TYPE              VALUE 
+ [0-9a-f]+ R_ARM_TLS_DTPMOD32  lib_gd2
+ [0-9a-f]+ R_ARM_TLS_DTPOFF32  lib_gd2
+ [0-9a-f]+ R_ARM_TLS_DTPMOD32  lib_gd
+ [0-9a-f]+ R_ARM_TLS_DTPOFF32  lib_gd
+ [0-9a-f]+ R_ARM_TLS_DESC    lib_gd2
Index: ld/testsuite/ld-arm/tls-mixed.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-mixed.s
diff -N ld/testsuite/ld-arm/tls-mixed.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-mixed.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,25 ----
+ 	.text
+ 	.globl foo
+ 	.type foo, %function
+ foo:
+ 	nop
+ .L1:
+ 	nop	
+ .L2:
+ 	bl	lib_gd2(tlscall) 
+ 	mov	pc, lr
+ 
+ .Lpool:
+ 	.word	lib_gd(tlsgd)	+  (. - .L1 - 8)
+ .Lpool2:
+ 	.word	lib_gd2(tlsdesc) + (. - .L2)
+ 	.word	lib_gd2(tlsgd)	+  (. - .L2 - 8)
+ 
+ 	.section .tdata,"awT"
+ 	.global lib_gd
+ lib_gd:
+ 	.space	4 
+ 	.global lib_gd2
+ lib_gd2:
+ 	.space	4
+ 
Index: ld/testsuite/ld-arm/tls-thumb1.d
===================================================================
RCS file: ld/testsuite/ld-arm/tls-thumb1.d
diff -N ld/testsuite/ld-arm/tls-thumb1.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-thumb1.d	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,74 ----
+ .*:     file format elf32-.*arm
+ architecture: arm, flags 0x00000150:
+ HAS_SYMS, DYNAMIC, D_PAGED
+ start address 0x.*
+ 
+ Disassembly of section .plt:
+ 
+ 00008164 <.plt>:
+     8164:	e52de004 	push	{lr}		; .*
+     8168:	e59fe004 	ldr	lr, \[pc, #4\]	; .*
+     816c:	e08fe00e 	add	lr, pc, lr
+     8170:	e5bef008 	ldr	pc, \[lr, #8\]!
+     8174:	000080f0 	.word	0x000080f0
+     8178:	e08e0000 	add	r0, lr, r0
+     817c:	e5901004 	ldr	r1, \[r0, #4\]
+     8180:	e12fff11 	bx	r1
+     8184:	e52d2004 	push	{r2}		; .*
+     8188:	e59f200c 	ldr	r2, \[pc, #12\]	; .*
+     818c:	e59f100c 	ldr	r1, \[pc, #12\]	; .*
+     8190:	e79f2002 	ldr	r2, \[pc, r2\]
+     8194:	e081100f 	add	r1, r1, pc
+     8198:	e12fff12 	bx	r2
+     819c:	000080e8 	.word	0x000080e8
+     81a0:	000080c8 	.word	0x000080c8
+ 
+ Disassembly of section .text:
+ 
+ 000081a8 <text>:
+     81a8:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+     81ac:	ebfffff1 	bl	8178 .*
+     81b0:	e1a00000 	nop			; .*
+     81b4:	000080c0 	.word	0x000080c0
+     81b8:	4801      	ldr	r0, \[pc, #4\]	; .*
+     81ba:	f000 e806 	blx	81c8 .*
+     81be:	46c0      	nop			; .*
+     81c0:	000080b1 	.word	0x000080b1
+     81c4:	00000000 	.word	0x00000000
+ 
+ 000081c8 <__unnamed_veneer>:
+     81c8:	4778      	bx	pc
+     81ca:	46c0      	nop			; .*
+     81cc:	e59f1000 	ldr	r1, \[pc, #0\]	; .*
+     81d0:	e081f00f 	add	pc, r1, pc
+     81d4:	ffffffa0 	.word	0xffffffa0
+ 
+ Disassembly of section .foo:
+ 
+ 04001000 <foo>:
+  4001000:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+  4001004:	eb000009 	bl	4001030 .*
+  4001008:	e1a00000 	nop			; .*
+  400100c:	fc00f268 	.word	0xfc00f268
+  4001010:	e59f0004 	ldr	r0, \[pc, #4\]	; .*
+  4001014:	eb000005 	bl	4001030 .*
+  4001018:	e1a00000 	nop			; .*
+  400101c:	fc00f260 	.word	0xfc00f260
+  4001020:	4801      	ldr	r0, \[pc, #4\]	; .*
+  4001022:	f000 e80c 	blx	400103c .*
+  4001026:	46c0      	nop			; .*
+  4001028:	fc00f249 	.word	0xfc00f249
+  400102c:	00000000 	.word	0x00000000
+ 
+ 04001030 <__unnamed_veneer>:
+  4001030:	e59f1000 	ldr	r1, \[pc, #0\]	; .*
+  4001034:	e08ff001 	add	pc, pc, r1
+  4001038:	fc00713c 	.word	0xfc00713c
+ 
+ 0400103c <__unnamed_veneer>:
+  400103c:	4778      	bx	pc
+  400103e:	46c0      	nop			; .*
+  4001040:	e59f1000 	ldr	r1, \[pc, #0\]	; .*
+  4001044:	e081f00f 	add	pc, r1, pc
+  4001048:	fc00712c 	.word	0xfc00712c
+  400104c:	00000000 	.word	0x00000000
Index: ld/testsuite/ld-arm/tls-thumb1.s
===================================================================
RCS file: ld/testsuite/ld-arm/tls-thumb1.s
diff -N ld/testsuite/ld-arm/tls-thumb1.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-arm/tls-thumb1.s	5 Jan 2011 11:12:57 -0000
***************
*** 0 ****
--- 1,43 ----
+ 	.arch armv4t
+ 	.syntax unified
+ 	.text
+ text:
+ 	.arm
+ 	ldr	r0,1f
+ 2:	bl	+loc(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	ldr	r0,1f
+ 2:	bl	+loc(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section ".foo","ax"
+ foo:
+ 	.arm
+ 	ldr	r0,1f
+ 2:	bl	+loc(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b)
+ 
+ 	.arm
+ 	ldr	r0,1f
+ 2:	bl	+glob(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	glob(tlsdesc) + (. - 2b)
+ 
+ 	.thumb
+ 	ldr	r0,1f
+ 2:	bl	+loc(tlscall)
+ 	nop
+ 	.p2align 2
+ 1:	.word	loc(tlsdesc) + (. - 2b + 1)
+ 
+ 	.section .tdata,"awT"
+ loc:	.space	4

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