This is the mail archive of the binutils@sources.redhat.com 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]

Fix SH TLS support


Hi,

SH uses R_SH_TLS_TPOFF32 relocation as a kind of copy relocation
for TLS and sh_elf_check_relocation set a flag to show whether
it's required or not. It should be recorded per entry of dyn_relocs
but currently done per symbol.
The attached testcase causes an abort of the current SH linker in
sh_elf_relocate_section for this reason. This testcase reveals also
an another bug that a bad symbol index is set for R_SH_TLS_TPOFF32.
I'd like to commit the following patch to fix them. It affects TLS
relocation only.

Regards,
	kaz
--
2003-02-10  Kaz kojima  <kkojima@rr.iij4u.or.jp>
[bfd]
	* elf32-sh.c (elf_sh_dyn_relocs): Add tls_tpoff32 field.
	(elf_sh_link_hash_entry): Remove tls_tpoff32 field.
	(sh_elf_link_hash_newfunc): Remove the initialization of
	tls_tpoff32 field.
	(allocate_dynrelocs): Keep dyn_relocs if it includes the entry
	for which tls_tpoff32 flag is set.
	(sh_elf_relocate_section): Covert to LE only if the dyn_relocs
	of the symbol includes the entry matched with the input_section
	and having tls_tpoff32 flag on.
	When linking statically, set symbol index of R_SH_TLS_TPOFF32
	relocation to zero if the symbol is defined in this executable.
	(sh_elf_check_relocs): Set tls_tpoff32 flag appropriately.

[ld/testsuite]
	* ld-sh/tlstpoff-1.d: New.
	* ld-sh/tlstpoff-2.d: New.
	* ld-sh/tlstpoff1.s: New.
	* ld-sh/tlstpoff2.s: New.

diff -u3prN ORIG/src/bfd/elf32-sh.c LOCAL/src/bfd/elf32-sh.c
--- ORIG/src/bfd/elf32-sh.c	Fri Jan 24 08:38:56 2003
+++ LOCAL/src/bfd/elf32-sh.c	Mon Feb 10 11:27:45 2003
@@ -3500,6 +3500,9 @@ struct elf_sh_dyn_relocs
 
   /* Number of pc-relative relocs copied for the input section.  */
   bfd_size_type pc_count;
+
+  /* If TRUE, R_SH_TLS_TPOFF32 relocation is generated.  */
+  bfd_boolean tls_tpoff32;
 };
 
 /* sh ELF linker hash entry.  */
@@ -3524,9 +3527,6 @@ struct elf_sh_link_hash_entry
   enum {
     GOT_UNKNOWN = 0, GOT_NORMAL, GOT_TLS_GD, GOT_TLS_IE
   } tls_type;
-
-  /* If TRUE, R_SH_TLS_TPOFF32 relocation is generated.  */
-  bfd_boolean tls_tpoff32;
 };
 
 #define sh_elf_hash_entry(ent) ((struct elf_sh_link_hash_entry *)(ent))
@@ -3630,7 +3630,6 @@ sh_elf_link_hash_newfunc (entry, table, 
       ret->datalabel_got.refcount = ret->root.got.refcount;
 #endif
       ret->tls_type = GOT_UNKNOWN;
-      ret->tls_tpoff32 = FALSE;
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -4207,8 +4206,9 @@ allocate_dynrelocs (h, inf)
     }
   else
     {
-      if (sh_elf_hash_entry (h)->tls_tpoff32)
-	goto keep;
+      for (p = eh->dyn_relocs; p; p = p->next)
+	if (p->tls_tpoff32)
+	  goto keep;
 
       /* For the non-shared case, discard space for relocs against
 	 symbols which turn out to need copy relocs or are not
@@ -5256,10 +5256,18 @@ sh_elf_relocate_section (output_bfd, inf
 	      tls_type = sh_elf_hash_entry (h)->tls_type;
 	      if (! info->shared
 		  && (h->dynindx == -1
-		      || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
-		  && (tls_type == GOT_TLS_IE
-		      || sh_elf_hash_entry (h)->tls_tpoff32))
-		r_type = R_SH_TLS_LE_32;
+		      || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+		{
+		  struct elf_sh_dyn_relocs *p;
+
+		  /* If TPOFF32 relocation can be created, convert it.  */
+		  for (p = sh_elf_hash_entry (h)->dyn_relocs; p; p = p->next)
+		    if (p->sec == input_section && p->tls_tpoff32)
+		      {
+			r_type = R_SH_TLS_LE_32;
+			break;
+		      }
+		}
 	    }
 
 	  if (r_type == R_SH_TLS_GD_32 && tls_type == GOT_TLS_IE)
@@ -5368,7 +5376,13 @@ sh_elf_relocate_section (output_bfd, inf
 		  BFD_ASSERT (sreloc != NULL);
 		}
 
-	      indx = (h && h->dynindx != -1) ? h->dynindx : 0;
+	      if (h == NULL
+		  || h->dynindx == -1
+		  || (! info->shared
+		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+		indx = 0;
+	      else
+		indx = h->dynindx;
 	      outrel.r_offset = (input_section->output_section->vma
 				 + input_section->output_offset
 				 + rel->r_offset);
@@ -5415,7 +5429,13 @@ sh_elf_relocate_section (output_bfd, inf
 	      outrel.r_offset = (sgot->output_section->vma
 				 + sgot->output_offset + off);
 
-	      indx = (h && h->dynindx != -1) ? h->dynindx : 0;
+	      if (h == NULL
+		  || h->dynindx == -1
+		  || (! info->shared
+		      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+		indx = 0;
+	      else
+		indx = h->dynindx;
 	      dr_type = (r_type == R_SH_TLS_GD_32 ? R_SH_TLS_DTPMOD32 :
 			 R_SH_TLS_TPOFF32);
 	      if (dr_type == R_SH_TLS_TPOFF32 && indx == 0)
@@ -6596,6 +6616,7 @@ sh_elf_check_relocs (abfd, info, sec, re
 		  p->sec = sec;
 		  p->count = 0;
 		  p->pc_count = 0;
+		  p->tls_tpoff32 = FALSE;
 		}
 
 	      p->count += 1;
@@ -6693,11 +6714,11 @@ sh_elf_check_relocs (abfd, info, sec, re
 		  p->sec = sec;
 		  p->count = 0;
 		  p->pc_count = 0;
+		  p->tls_tpoff32 = FALSE;
 		}
 
 	      p->count += 1;
-	      if (h)
-		sh_elf_hash_entry (h)->tls_tpoff32 = TRUE;
+	      p->tls_tpoff32 = TRUE;
 	    }
 	  break;
 
diff -u3prN ORIG/src/ld/testsuite/ld-sh/tlstpoff-1.d LOCAL/src/ld/testsuite/ld-sh/tlstpoff-1.d
--- ORIG/src/ld/testsuite/ld-sh/tlstpoff-1.d	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlstpoff-1.d	Mon Feb 10 11:18:28 2003
@@ -0,0 +1,31 @@
+#source: tlstpoff1.s
+#source: tlstpoff2.s
+#as: -little
+#ld: -EL -e foo
+#objdump: -drj.text
+#target: sh*-*-linux* sh*-*-netbsd*
+
+.*: +file format elf32-sh.*
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo>:
+  [0-9a-f]+:	c6 2f       	mov.l	r12,@-r15
+  [0-9a-f]+:	07 c7       	mova	[0-9a-f]+ <foo\+0x20>,r0
+  [0-9a-f]+:	06 dc       	mov.l	[0-9a-f]+ <foo\+0x20>,r12	! 0x[0-9a-f]+
+  [0-9a-f]+:	0c 3c       	add	r0,r12
+  [0-9a-f]+:	02 d0       	mov.l	[0-9a-f]+ <foo\+0x14>,r0	! 0xc
+  [0-9a-f]+:	12 01       	stc	gbr,r1
+  [0-9a-f]+:	ce 00       	mov.l	@\(r0,r12\),r0
+  [0-9a-f]+:	03 a0       	bra	[0-9a-f]+ <foo\+0x18>
+  [0-9a-f]+:	0c 31       	add	r0,r1
+  [0-9a-f]+:	09 00       	nop	
+  [0-9a-f]+:	0c 00       	.*[	]*.*
+  [0-9a-f]+:	00 00       	.*[	]*.*
+  [0-9a-f]+:	12 60       	mov.l	@r1,r0
+  [0-9a-f]+:	0b 00       	rts	
+  [0-9a-f]+:	f6 6c       	mov.l	@r15\+,r12
+  [0-9a-f]+:	09 00       	nop	
+  [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[	]*.*
+  [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[	]*.*
+#pass
diff -u3prN ORIG/src/ld/testsuite/ld-sh/tlstpoff-2.d LOCAL/src/ld/testsuite/ld-sh/tlstpoff-2.d
--- ORIG/src/ld/testsuite/ld-sh/tlstpoff-2.d	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlstpoff-2.d	Mon Feb 10 11:29:26 2003
@@ -0,0 +1,12 @@
+#source: tlstpoff1.s
+#source: tlstpoff2.s
+#as: -little
+#ld: -EL -e foo
+#readelf: -r
+#target: sh*-*-linux* sh*-*-netbsd*
+
+Relocation section '\.rela\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+ Offset +Info +Type +Sym\.Value +Sym\. Name \+ Addend
+0+[0-9a-f]+  00000097 R_SH_TLS_TPOFF32 +0+04
+0+[0-9a-f]+  00000097 R_SH_TLS_TPOFF32 +0+04
+
diff -u3prN ORIG/src/ld/testsuite/ld-sh/tlstpoff1.s LOCAL/src/ld/testsuite/ld-sh/tlstpoff1.s
--- ORIG/src/ld/testsuite/ld-sh/tlstpoff1.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlstpoff1.s	Mon Feb 10 08:56:12 2003
@@ -0,0 +1,23 @@
+	.text
+	.align 5
+	.global	foo
+	.type	foo, @function
+foo:
+	mov.l	r12,@-r15
+	mova	.L1,r0
+	mov.l	.L1,r12
+	add	r0,r12
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	 add	r0,r1
+	.align 2
+1:	.long	x@GOTTPOFF
+2:	
+	mov.l	@r1,r0
+	rts	
+	mov.l	@r15+,r12
+
+	.align 2
+.L1:	.long	_GLOBAL_OFFSET_TABLE_
diff -u3prN ORIG/src/ld/testsuite/ld-sh/tlstpoff2.s LOCAL/src/ld/testsuite/ld-sh/tlstpoff2.s
--- ORIG/src/ld/testsuite/ld-sh/tlstpoff2.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlstpoff2.s	Mon Feb 10 11:12:03 2003
@@ -0,0 +1,26 @@
+	.section .tbss,"awT",@nobits
+	.global	x
+y:	.space	4
+x:	.space	4
+
+	.section barfn,"ax",@progbits
+	.align	1
+	.type	bar, @function
+bar:	
+	mova	.L1,r0
+	mov.l	.L1,r12
+	add	r0,r12
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	x@GOTTPOFF
+2:
+	mov.l	@r1,r0
+	rts	
+	mov.l	@r15+,r12
+
+	.align 2
+.L1:	.long	_GLOBAL_OFFSET_TABLE_


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