NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-sparc/54093 (Recent test regressions on sparc)



Hello,

I found that the cause of this probrem is that TLS data area is not
properly aligned.  jemalloc uses TLS, so the problem has become
apparent.

netbsd-8% readelf -l /lib/libc.so | egrep 'TLS|Align'
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  TLS            0x140000 0x00140000 0x00140000 0x00000 0x00004 R   0x4

netbsd-9% readelf -l /lib/libc.so | egrep 'TLS|Align'
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  TLS            0x1d2000 0x001e2000 0x001e2000 0x00b10 0x00b14 R   0x8

When I upgraded to netbsd-9, statically linked binaries and some
pkg binaries compiled with netbsd-8 now cause bus errors.  So I
take a look in details and found the cause by referring to the
following document.

  https://docs.oracle.com/cd/E19683-01/817-3677/6mj8mbtcb/index.html

The attached patch fixes the problem (and also fixes PR/54074).
lib/libc/tls/tls.c is a fix for statically linked binaries and
libexec/ld.elf_so/tls.c is a fix for dynamically linked binaries.

I think there is a similar problem in the case of __HAVE_TLS_VARIANT_I,
but I couldn't confirm it because I don't have such a machine.

-- Takeshi Nakayama


Index: lib/libc/tls/tls.c
===================================================================
RCS file: /cvsroot/src/lib/libc/tls/tls.c,v
retrieving revision 1.9
diff -u -d -r1.9 tls.c
--- lib/libc/tls/tls.c	13 Jul 2018 19:50:21 -0000	1.9
+++ lib/libc/tls/tls.c	1 Nov 2019 13:01:25 -0000
@@ -57,6 +57,9 @@
 static const void *tls_initaddr;
 static size_t tls_initsize;
 static size_t tls_size;
+#ifdef __HAVE_TLS_VARIANT_II
+static size_t tls_align;
+#endif
 static size_t tls_allocation;
 static void *initial_thread_tcb;
 
@@ -85,7 +88,7 @@
 
 	if (initial_thread_tcb == NULL) {
 #ifdef __HAVE_TLS_VARIANT_II
-		tls_size = roundup2(tls_size, sizeof(void *));
+		tls_size = roundup2(tls_size, tls_align);
 #endif
 		tls_allocation = tls_size + sizeof(*tcb);
 
@@ -149,6 +152,9 @@
 		tls_initaddr = (void *)(phdr->p_vaddr + data->dlpi_addr);
 		tls_initsize = phdr->p_filesz;
 		tls_size = phdr->p_memsz;
+#ifdef __HAVE_TLS_VARIANT_II
+		tls_align = phdr->p_align;
+#endif
 	}
 	return 0;
 }
Index: libexec/ld.elf_so/tls.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/tls.c,v
retrieving revision 1.12
diff -u -d -r1.12 tls.c
--- libexec/ld.elf_so/tls.c	13 Apr 2019 00:23:32 -0000	1.12
+++ libexec/ld.elf_so/tls.c	1 Nov 2019 13:01:25 -0000
@@ -48,6 +48,9 @@
 
 static size_t _rtld_tls_static_space;	/* Static TLS space allocated */
 static size_t _rtld_tls_static_offset;	/* Next offset for static TLS to use */
+#ifndef __HAVE_TLS_VARIANT_I
+static size_t _rtld_tls_static_align;	/* Static TLS space alignment */
+#endif
 size_t _rtld_tls_dtv_generation = 1;
 size_t _rtld_tls_max_index = 1;
 
@@ -99,7 +102,7 @@
 
 #ifndef __HAVE_TLS_VARIANT_I
 	_rtld_tls_static_space = roundup2(_rtld_tls_static_space,
-	    sizeof(void *));
+	    _rtld_tls_static_align);
 #endif
 	dbg(("_rtld_tls_static_space %zu", _rtld_tls_static_space));
 
@@ -118,11 +121,13 @@
 	struct tls_tcb *tcb;
 	uint8_t *p, *q;
 
-	p = xcalloc(_rtld_tls_static_space + sizeof(struct tls_tcb));
 #ifdef __HAVE_TLS_VARIANT_I
+	p = xcalloc(_rtld_tls_static_space + sizeof(struct tls_tcb));
 	tcb = (struct tls_tcb *)p;
 	p += sizeof(struct tls_tcb);
 #else
+	p = xcalloc(roundup2(_rtld_tls_static_space + sizeof(struct tls_tcb),
+	    _rtld_tls_static_align));
 	p += _rtld_tls_static_space;
 	tcb = (struct tls_tcb *)p;
 	tcb->tcb_self = tcb;
@@ -207,7 +212,11 @@
 		_rtld_die();
 	}
 
+#ifdef __HAVE_TLS_VARIANT_I
 	p = xmalloc(obj->tlssize);
+#else
+	p = xmalloc(roundup2(obj->tlssize, obj->tlsalign));
+#endif
 	memcpy(p, obj->tlsinit, obj->tlsinitsize);
 	memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize);
 
@@ -260,6 +269,10 @@
 	}
 	obj->tlsoffset = offset;
 	_rtld_tls_static_offset = next_offset;
+#ifndef __HAVE_TLS_VARIANT_I
+	if (_rtld_tls_static_align < obj->tlsalign)
+		_rtld_tls_static_align = obj->tlsalign;
+#endif
 	obj->tls_done = 1;
 
 	return 0;


Home | Main Index | Thread Index | Old Index