This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Fix SH TLS support
- From: kaz Kojima <kkojima at rr dot iij4u dot or dot jp>
- To: binutils at sources dot redhat dot com
- Date: Mon, 10 Feb 2003 20:16:00 +0900
- Subject: 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_