diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1120111a8b1ced59be39f5e59b7c5b55fbca8d62..32a21bee7af5098fef5789ec63ed5fab6e2c76c7 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,19 @@
+2009-06-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* elf32-i386.c (elf_i386_tls_transition): Add a parameter,
+	r_symndx.  Report local symbol name on error.
+	(elf_i386_check_relocs): Updated.  Report local symbol name on
+	error.
+	(elf_i386_gc_sweep_hook): Updated.
+	(elf_i386_relocate_section): Likewise.
+
+	* elf64-x86-64.c (elf64_x86_64_tls_transition): Add a parameter,
+	r_symndx.  Report local symbol name on error.
+	(elf64_x86_64_check_relocs): Updated.  Report local symbol name
+	on error.
+	(elf64_x86_64_gc_sweep_hook): Updated.
+	(elf64_x86_64_relocate_section): Likewise.
+
 2009-06-19  Tristan Gingold  <gingold@adacore.com>
 
 	* mach-o.c (bfd_mach_o_print_private_header): Fix format character.
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 36672fe7904ac10e3e2c1956c018bcaf86af8c4d..bac80e327ebc92c2f52719e631beb04dec039613 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1149,7 +1149,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 			 unsigned int *r_type, int tls_type,
 			 const Elf_Internal_Rela *rel,
 			 const Elf_Internal_Rela *relend,
-			 struct elf_link_hash_entry *h)
+			 struct elf_link_hash_entry *h,
+			 unsigned long r_symndx)
 {
   unsigned int from_type = *r_type;
   unsigned int to_type = from_type;
@@ -1224,15 +1225,27 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
 					  from_type, rel, relend))
     {
       reloc_howto_type *from, *to;
+      const char *name;
 
       from = elf_i386_rtype_to_howto (abfd, from_type);
       to = elf_i386_rtype_to_howto (abfd, to_type);
 
+      if (h)
+	name = h->root.root.string;
+      else
+	{
+	  Elf_Internal_Sym *isym;
+	  struct elf_i386_link_hash_table *htab;
+	  htab = elf_i386_hash_table (info);
+	  isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+					abfd, r_symndx);
+	  name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
+	}
+
       (*_bfd_error_handler)
 	(_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
 	   "in section `%A' failed"),
-	 abfd, sec, from->name, to->name,
-	 h ? h->root.root.string : "a local symbol",
+	 abfd, sec, from->name, to->name, name,
 	 (unsigned long) rel->r_offset);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
@@ -1276,6 +1289,8 @@ elf_i386_check_relocs (bfd *abfd,
       unsigned int r_type;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
+      Elf_Internal_Sym *isym;
+      const char *name;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -1291,8 +1306,6 @@ elf_i386_check_relocs (bfd *abfd,
       if (r_symndx < symtab_hdr->sh_info)
 	{
 	  /* A local symbol.  */
-	  Elf_Internal_Sym *isym;
-
 	  isym = bfd_sym_from_r_symndx (&htab->sym_cache,
 					abfd, r_symndx);
 	  if (isym == NULL)
@@ -1318,6 +1331,7 @@ elf_i386_check_relocs (bfd *abfd,
 	}
       else
 	{
+	  isym = NULL;
 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 	  while (h->root.type == bfd_link_hash_indirect
 		 || h->root.type == bfd_link_hash_warning)
@@ -1363,13 +1377,16 @@ elf_i386_check_relocs (bfd *abfd,
 	      switch (r_type)
 		{
 		default:
+		  if (h->root.root.string)
+		    name = h->root.root.string;
+		  else
+		    name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
+					     NULL);
 		  (*_bfd_error_handler)
 		    (_("%B: relocation %s against STT_GNU_IFUNC "
 		       "symbol `%s' isn't handled by %s"), abfd,
 		     elf_howto_table[r_type].name,
-		     (h->root.root.string
-		      ? h->root.root.string : "a local symbol"),
-		     __FUNCTION__);
+		     name, __FUNCTION__);
 		  bfd_set_error (bfd_error_bad_value);
 		  return FALSE;
 
@@ -1413,7 +1430,7 @@ elf_i386_check_relocs (bfd *abfd,
       if (! elf_i386_tls_transition (info, abfd, sec, NULL,
 				     symtab_hdr, sym_hashes,
 				     &r_type, GOT_UNKNOWN,
-				     rel, rel_end, h)) 
+				     rel, rel_end, h, r_symndx)) 
 	return FALSE;
 
       switch (r_type)
@@ -1521,11 +1538,15 @@ elf_i386_check_relocs (bfd *abfd,
 		  tls_type |= old_tls_type;
 		else
 		  {
+		    if (h->root.root.string)
+		      name = h->root.root.string;
+		    else
+		      name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
+					     NULL);
 		    (*_bfd_error_handler)
 		      (_("%B: `%s' accessed both as normal and "
 			 "thread local symbol"),
-		       abfd,
-		       h ? h->root.root.string : "<local>");
+		       abfd, name);
 		    return FALSE;
 		  }
 	      }
@@ -1781,7 +1802,7 @@ elf_i386_gc_sweep_hook (bfd *abfd,
       if (! elf_i386_tls_transition (info, abfd, sec, NULL,
 				     symtab_hdr, sym_hashes,
 				     &r_type, GOT_UNKNOWN,
-				     rel, relend, h)) 
+				     rel, relend, h, r_symndx)) 
 	return FALSE;
 
       switch (r_type)
@@ -2914,6 +2935,7 @@ elf_i386_relocate_section (bfd *output_bfd,
 	{
 	  asection *plt, *gotplt, *base_got;
 	  bfd_vma plt_index;
+	  const char *name;
 
 	  if ((input_section->flags & SEC_ALLOC) == 0
 	      || h->plt.offset == (bfd_vma) -1)
@@ -2937,13 +2959,16 @@ elf_i386_relocate_section (bfd *output_bfd,
 	  switch (r_type)
 	    {
 	    default:
+	      if (h->root.root.string)
+		name = h->root.root.string;
+	      else
+		name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+					 NULL);
 	      (*_bfd_error_handler)
 		(_("%B: relocation %s against STT_GNU_IFUNC "
 		   "symbol `%s' isn't handled by %s"), input_bfd,
 		 elf_howto_table[r_type].name,
-		 (h->root.root.string
-		  ? h->root.root.string : "a local symbol"),
-		 __FUNCTION__);
+		 name, __FUNCTION__);
 	      bfd_set_error (bfd_error_bad_value);
 	      return FALSE;
 
@@ -3375,7 +3400,7 @@ elf_i386_relocate_section (bfd *output_bfd,
 					 input_section, contents,
 					 symtab_hdr, sym_hashes,
 					 &r_type, tls_type, rel,
-					 relend, h))
+					 relend, h, r_symndx))
 	    return FALSE;
 
 	  if (r_type == R_386_TLS_LE_32)
@@ -3844,7 +3869,7 @@ elf_i386_relocate_section (bfd *output_bfd,
 					 input_section, contents,
 					 symtab_hdr, sym_hashes,
 					 &r_type, GOT_UNKNOWN, rel,
-					 relend, h))
+					 relend, h, r_symndx))
 	    return FALSE;
 
 	  if (r_type != R_386_TLS_LDM)
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 061f785641a9a01042653960f7afb52a05c16c51..44149c5bf7de2ebf3101359a2f4ef252ea22eca5 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -937,7 +937,8 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
 			     unsigned int *r_type, int tls_type,
 			     const Elf_Internal_Rela *rel,
 			     const Elf_Internal_Rela *relend,
-			     struct elf_link_hash_entry *h)
+			     struct elf_link_hash_entry *h,
+			     unsigned long r_symndx)
 {
   unsigned int from_type = *r_type;
   unsigned int to_type = from_type;
@@ -1007,15 +1008,27 @@ elf64_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
 					      from_type, rel, relend))
     {
       reloc_howto_type *from, *to;
+      const char *name;
 
       from = elf64_x86_64_rtype_to_howto (abfd, from_type);
       to = elf64_x86_64_rtype_to_howto (abfd, to_type);
 
+      if (h)
+	name = h->root.root.string;
+      else
+	{
+	  Elf_Internal_Sym *isym;
+	  struct elf64_x86_64_link_hash_table *htab;
+	  htab = elf64_x86_64_hash_table (info);
+	  isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+					abfd, r_symndx);
+	  name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
+	}
+
       (*_bfd_error_handler)
 	(_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
 	   "in section `%A' failed"),
-	 abfd, sec, from->name, to->name,
-	 h ? h->root.root.string : "a local symbol",
+	 abfd, sec, from->name, to->name, name,
 	 (unsigned long) rel->r_offset);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
@@ -1058,6 +1071,8 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       unsigned int r_type;
       unsigned long r_symndx;
       struct elf_link_hash_entry *h;
+      Elf_Internal_Sym *isym;
+      const char *name;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
       r_type = ELF64_R_TYPE (rel->r_info);
@@ -1072,8 +1087,6 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       if (r_symndx < symtab_hdr->sh_info)
 	{
 	  /* A local symbol.  */
-	  Elf_Internal_Sym *isym;
-
 	  isym = bfd_sym_from_r_symndx (&htab->sym_cache,
 					abfd, r_symndx);
 	  if (isym == NULL)
@@ -1099,6 +1112,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	}
       else
 	{
+	  isym = NULL;
 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 	  while (h->root.type == bfd_link_hash_indirect
 		 || h->root.type == bfd_link_hash_warning)
@@ -1147,13 +1161,16 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	      switch (r_type)
 		{
 		default:
+		  if (h->root.root.string)
+		    name = h->root.root.string;
+		  else
+		    name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
+					     NULL);
 		  (*_bfd_error_handler)
 		    (_("%B: relocation %s against STT_GNU_IFUNC "
 		       "symbol `%s' isn't handled by %s"), abfd,
 		     x86_64_elf_howto_table[r_type].name,
-		     (h->root.root.string
-		      ? h->root.root.string : "a local symbol"),
-		     __FUNCTION__);
+		     name, __FUNCTION__);
 		  bfd_set_error (bfd_error_bad_value);
 		  return FALSE;
 
@@ -1203,7 +1220,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
       if (! elf64_x86_64_tls_transition (info, abfd, sec, NULL,
 					 symtab_hdr, sym_hashes,
 					 &r_type, GOT_UNKNOWN,
-					 rel, rel_end, h))
+					 rel, rel_end, h, r_symndx))
 	return FALSE;
 
       switch (r_type)
@@ -1215,11 +1232,15 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	case R_X86_64_TPOFF32:
 	  if (info->shared)
 	    {
+	      if (h->root.root.string)
+		name = h->root.root.string;
+	      else
+		name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
+					 NULL);
 	      (*_bfd_error_handler)
 		(_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
 		 abfd,
-		 x86_64_elf_howto_table[r_type].name,
-		 (h) ? h->root.root.string : "a local symbol");
+		 x86_64_elf_howto_table[r_type].name, name);
 	      bfd_set_error (bfd_error_bad_value);
 	      return FALSE;
 	    }
@@ -1306,9 +1327,14 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 		  tls_type |= old_tls_type;
 		else
 		  {
+		    if (h->root.root.string)
+		      name = h->root.root.string;
+		    else
+		      name = bfd_elf_sym_name (abfd, symtab_hdr,
+					       isym, NULL);
 		    (*_bfd_error_handler)
 		      (_("%B: '%s' accessed both as normal and thread local symbol"),
-		       abfd, h ? h->root.root.string : "<local>");
+		       abfd, name);
 		    return FALSE;
 		  }
 	      }
@@ -1376,11 +1402,13 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	      && (sec->flags & SEC_ALLOC) != 0
 	      && (sec->flags & SEC_READONLY) != 0)
 	    {
+	      if (h->root.root.string)
+		name = h->root.root.string;
+	      else
+		name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
 	      (*_bfd_error_handler)
 		(_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
-		 abfd,
-		 x86_64_elf_howto_table[r_type].name,
-		 (h) ? h->root.root.string : "a local symbol");
+		 abfd, x86_64_elf_howto_table[r_type].name, name);
 	      bfd_set_error (bfd_error_bad_value);
 	      return FALSE;
 	    }
@@ -1612,7 +1640,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
       if (! elf64_x86_64_tls_transition (info, abfd, sec, NULL,
 					 symtab_hdr, sym_hashes,
 					 &r_type, GOT_UNKNOWN,
-					 rel, relend, h))
+					 rel, relend, h, r_symndx))
 	return FALSE;
 
       switch (r_type)
@@ -2627,6 +2655,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	{
 	  asection *plt;
 	  bfd_vma plt_index;
+	  const char *name;
 
 	  if ((input_section->flags & SEC_ALLOC) == 0
 	      || h->plt.offset == (bfd_vma) -1)
@@ -2640,13 +2669,16 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  switch (r_type)
 	    {
 	    default:
+	      if (h->root.root.string)
+		name = h->root.root.string;
+	      else
+		name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+					 NULL);
 	      (*_bfd_error_handler)
 		(_("%B: relocation %s against STT_GNU_IFUNC "
 		   "symbol `%s' isn't handled by %s"), input_bfd,
 		 x86_64_elf_howto_table[r_type].name,
-		 (h->root.root.string
-		  ? h->root.root.string : "a local symbol"),
-		 __FUNCTION__);
+		 name, __FUNCTION__);
 	      bfd_set_error (bfd_error_bad_value);
 	      return FALSE;
 
@@ -2658,13 +2690,16 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	    case R_X86_64_64: 
 	      if (rel->r_addend != 0)
 		{
+		  if (h->root.root.string)
+		    name = h->root.root.string;
+		  else
+		    name = bfd_elf_sym_name (input_bfd, symtab_hdr,
+					     sym, NULL);
 		  (*_bfd_error_handler)
 		    (_("%B: relocation %s against STT_GNU_IFUNC "
 		       "symbol `%s' has non-zero addend: %d"),
 		     input_bfd, x86_64_elf_howto_table[r_type].name,
-		     (h->root.root.string
-		      ? h->root.root.string : "a local symbol"),
-		     rel->r_addend);
+		     name, rel->r_addend);
 		  bfd_set_error (bfd_error_bad_value);
 		  return FALSE;
 		}
@@ -3209,7 +3244,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 					     input_section, contents,
 					     symtab_hdr, sym_hashes,
 					     &r_type, tls_type, rel,
-					     relend, h))
+					     relend, h, r_symndx))
 	    return FALSE;
 
 	  if (r_type == R_X86_64_TPOFF32)
@@ -3543,7 +3578,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 					     input_section, contents,
 					     symtab_hdr, sym_hashes,
 					     &r_type, GOT_UNKNOWN,
-					     rel, relend, h))
+					     rel, relend, h, r_symndx))
 	    return FALSE;
 
 	  if (r_type != R_X86_64_TLSLD)
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index fbd1ff4fe9be2486baf5a8f8f41f2e82d295dc20..c7f7adb8db8b95f23ab515ed3a67f527246e4137 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2009-06-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* ld-i386/i386.exp: Run tlsgd2.
+
+	* ld-i386/tlsgd2.d: New.
+	* ld-i386/tlsgd2.s: Likewise.
+
+	* ld-x86-64/tlsgd3.d: Updated.
+
 2009-06-18  Dave Korn  <dave.korn.cygwin@gmail.com>
 
 	* ld-pe/pe-run.exp (proc test_direct_link_dll):  Always pass
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 6f75f3ae375313d143ff8baaef73839c6954bf5f..18e8d808bddf9948768ad784a741467e6e7bab25 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -128,6 +128,7 @@ run_dump_test "pcrel16"
 run_dump_test "pcrel16abs"
 run_dump_test "alloc"
 run_dump_test "warn1"
+run_dump_test "tlsgd2"
 run_dump_test "tlsie2"
 run_dump_test "tlsie3"
 run_dump_test "tlsie4"
diff --git a/ld/testsuite/ld-i386/tlsgd2.d b/ld/testsuite/ld-i386/tlsgd2.d
new file mode 100644
index 0000000000000000000000000000000000000000..136a8fa8650afbfb2d9a87ce512aa338cad99c5f
--- /dev/null
+++ b/ld/testsuite/ld-i386/tlsgd2.d
@@ -0,0 +1,4 @@
+#name: TLS GD->LE transition check
+#as: --32
+#ld: -melf_i386
+#error: .*TLS transition from R_386_TLS_GD to R_386_TLS_LE_32 against `foo'.*failed.*
diff --git a/ld/testsuite/ld-i386/tlsgd2.s b/ld/testsuite/ld-i386/tlsgd2.s
new file mode 100644
index 0000000000000000000000000000000000000000..29d933932ab66955cf98ff1da0ff97bd406396c4
--- /dev/null
+++ b/ld/testsuite/ld-i386/tlsgd2.s
@@ -0,0 +1,11 @@
+	.text
+	.globl _start
+_start:
+	leal	foo@TLSGD(%ebx), %eax
+	call	___tls_get_addr
+	.section	.tdata,"awT",@progbits
+	.align 4
+	.type	foo, @object
+	.size	foo, 4
+foo:
+	.long	100
diff --git a/ld/testsuite/ld-x86-64/tlsgd3.d b/ld/testsuite/ld-x86-64/tlsgd3.d
index 40f8e3d2277c77acc199e3fe3d6156aa2589096a..a8830e979117e94ddf44ace9d22943392ac36738 100644
--- a/ld/testsuite/ld-x86-64/tlsgd3.d
+++ b/ld/testsuite/ld-x86-64/tlsgd3.d
@@ -1,4 +1,4 @@
 #name: TLS GD->LE transition check
 #as: --64
 #ld: -melf_x86_64
-#error: .*TLS transition from R_X86_64_TLSGD to R_X86_64_TPOFF32 against `a local symbol'.*failed.*
+#error: .*TLS transition from R_X86_64_TLSGD to R_X86_64_TPOFF32 against `foo'.*failed.*