From 4e432c780261495504daabc746306f377ec15254 Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Tue, 11 Apr 2006 12:14:01 +0000 Subject: [PATCH] Merge bug fix from binutils main line: When a thread local symbol is accessed both from PIC and non-PIC code, ld incorrectly merged both entries in the main program, ignoring the different relocation offsets. This occured originally in dbus-0.61 and showed itself in segfaults within rtld. MFC after 3 days --- gnu/usr.bin/binutils215/libbfd/Makefile | 4 +- gnu/usr.bin/binutils215/libbfd/Makefile.i386 | 3 +- .../libbfd/patches/elf32-i386.c.patch | 78 +++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 gnu/usr.bin/binutils215/libbfd/patches/elf32-i386.c.patch diff --git a/gnu/usr.bin/binutils215/libbfd/Makefile b/gnu/usr.bin/binutils215/libbfd/Makefile index 27dfafaa39..35186471a3 100644 --- a/gnu/usr.bin/binutils215/libbfd/Makefile +++ b/gnu/usr.bin/binutils215/libbfd/Makefile @@ -1,9 +1,11 @@ -# $DragonFly: src/gnu/usr.bin/binutils215/libbfd/Attic/Makefile,v 1.2 2005/10/01 12:40:32 corecode Exp $ +# $DragonFly: src/gnu/usr.bin/binutils215/libbfd/Attic/Makefile,v 1.3 2006/04/11 12:14:00 joerg Exp $ .include "../Makefile.inc0" .PATH: ${SRCDIR}/bfd ${SRCDIR}/opcodes +CONTRIBDIR= ${SRCDIR}/bfd + LIB= bfd SRCS+= archive.c archive64.c archures.c bfd.c bfdio.c binary.c cache.c \ coffgen.c corefile.c elf.c elf-eh-frame.c elf-strtab.c format.c \ diff --git a/gnu/usr.bin/binutils215/libbfd/Makefile.i386 b/gnu/usr.bin/binutils215/libbfd/Makefile.i386 index 3e42b0a991..309aa884a2 100644 --- a/gnu/usr.bin/binutils215/libbfd/Makefile.i386 +++ b/gnu/usr.bin/binutils215/libbfd/Makefile.i386 @@ -1,4 +1,4 @@ -# $DragonFly: src/gnu/usr.bin/binutils215/libbfd/Attic/Makefile.i386,v 1.3 2005/10/01 12:40:32 corecode Exp $ +# $DragonFly: src/gnu/usr.bin/binutils215/libbfd/Attic/Makefile.i386,v 1.4 2006/04/11 12:14:00 joerg Exp $ BFD_ARCH_SIZE?=32 BFD_DEFAULT_TARGET_SIZE?=32 @@ -6,6 +6,7 @@ BFD_DEFAULT_TARGET_SIZE?=32 # see main Makefile SRCS+= cpu-i386.c SRCS+= elf32-i386.c elf32-target.h elf32.c elflink.c +SRCS+= patches/elf32-i386.c.patch VECS+= bfd_elf32_i386_vec DEFAULT_VECTOR?= bfd_elf32_i386_vec diff --git a/gnu/usr.bin/binutils215/libbfd/patches/elf32-i386.c.patch b/gnu/usr.bin/binutils215/libbfd/patches/elf32-i386.c.patch new file mode 100644 index 0000000000..59f4be5d5f --- /dev/null +++ b/gnu/usr.bin/binutils215/libbfd/patches/elf32-i386.c.patch @@ -0,0 +1,78 @@ +$DragonFly: src/gnu/usr.bin/binutils215/libbfd/patches/Attic/elf32-i386.c.patch,v 1.1 2006/04/11 12:14:01 joerg Exp $ +From binutils PR ld/2513. + +Index: elf32-i386.c +=================================================================== +RCS file: /cvs/src/contrib/binutils-2.15/bfd/elf32-i386.c,v +retrieving revision 1.1 +diff -u -r1.1 elf32-i386.c +--- elf32-i386.c 18 Dec 2004 20:21:20 -0000 1.1 ++++ elf32-i386.c 11 Apr 2006 11:37:15 -0000 +@@ -552,6 +552,10 @@ + #define GOT_TLS_IE_POS 5 + #define GOT_TLS_IE_NEG 6 + #define GOT_TLS_IE_BOTH 7 ++#define GOT_TLS_MASK 0x0f ++#define GOT_TLS_IE_IE 0x10 ++#define GOT_TLS_IE_GD 0x20 ++#define GOT_TLS_IE_MASK 0x30 + unsigned char tls_type; + }; + +@@ -918,12 +922,25 @@ + case R_386_TLS_IE_32: + if (ELF32_R_TYPE (rel->r_info) == r_type) + tls_type = GOT_TLS_IE_NEG; ++ else if (h ++ && ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) ++ /* If this is a GD->IE transition, we may use either ++ of R_386_TLS_TPOFF and R_386_TLS_TPOFF32. But if ++ we may have both R_386_TLS_IE and R_386_TLS_GD, ++ we can't share the same R_386_TLS_TPOFF since ++ they require different offsets. So we remember ++ it comes from R_386_TLS_GD. */ ++ tls_type = GOT_TLS_IE | GOT_TLS_IE_GD; + else +- /* If this is a GD->IE transition, we may use either of +- R_386_TLS_TPOFF and R_386_TLS_TPOFF32. */ + tls_type = GOT_TLS_IE; + break; + case R_386_TLS_IE: ++ if (h) ++ { ++ /* We remember it comes from R_386_TLS_IE. */ ++ tls_type = GOT_TLS_IE_POS | GOT_TLS_IE_IE; ++ break; ++ } + case R_386_TLS_GOTIE: + tls_type = GOT_TLS_IE_POS; break; + } +@@ -1551,6 +1568,14 @@ + asection *s; + bfd_boolean dyn; + int tls_type = elf_i386_hash_entry(h)->tls_type; ++ ++ /* If we have both R_386_TLS_IE and R_386_TLS_GD, GOT_TLS_IE_BOTH ++ should be used. */ ++ if ((tls_type & GOT_TLS_IE_MASK) ++ == (GOT_TLS_IE_IE | GOT_TLS_IE_GD)) ++ tls_type = GOT_TLS_IE_BOTH; ++ else ++ tls_type &= GOT_TLS_MASK; + + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ +@@ -2419,6 +2444,13 @@ + else if (h != NULL) + { + tls_type = elf_i386_hash_entry(h)->tls_type; ++ /* If we have both R_386_TLS_IE and R_386_TLS_GD, ++ GOT_TLS_IE_BOTH should be used. */ ++ if ((tls_type & GOT_TLS_IE_MASK) ++ == (GOT_TLS_IE_IE | GOT_TLS_IE_GD)) ++ tls_type = GOT_TLS_IE_BOTH; ++ else ++ tls_type &= GOT_TLS_MASK; + if (!info->shared && h->dynindx == -1 && (tls_type & GOT_TLS_IE)) + r_type = R_386_TLS_LE_32; + } -- 2.41.0