Commit ed428356 authored by Jakub Jirutka's avatar Jakub Jirutka Committed by Natanael Copa

main/musl: backport patch fixing TLS layout

This issue affects e.g. Rust on aarch64.
parent 7503de19
......@@ -2,7 +2,7 @@
# Maintainer: Timo Teräs <timo.teras@iki.fi>
pkgname=musl
pkgver=1.1.19
pkgrel=9
pkgrel=10
pkgdesc="the musl c library (libc) implementation"
url="http://www.musl-libc.org/"
arch="all"
......@@ -24,6 +24,8 @@ source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz
2000-pthread-internals-increase-DEFAULT_GUARD_SIZE-to-2-p.patch
handle-aux-at_base.patch
fix-TLS-layout-of-TLS-variant-I-when-there-is-gap-above-TP.patch
ldconfig
__stack_chk_fail_local.c
getconf.c
......@@ -155,6 +157,7 @@ b0bcfc837f888f2b1c2d65c06dcc0a2fa12da78986ba9c7c86a64123ce44c21a63c13c1cc2e93fdf
023fc05d653f4a3be4d16a2e223bddc26be7bc31c4decf3f5b9bed78cbe7bc8687ff8c164b94541f6fda66d6c3864dd42cb10920d066f97d2891e31a366c3e8d 0006-powerpc-update-hwcap.h-for-linux-v4.15.patch
2c8e1dde1834238097b2ee8a7bfb53471a0d9cff4a5e38b55f048b567deff1cdd47c170d0578a67b1a039f95a6c5fbb8cff369c75b6a3e4d7ed171e8e86ebb8c 2000-pthread-internals-increase-DEFAULT_GUARD_SIZE-to-2-p.patch
6a7ff16d95b5d1be77e0a0fbb245491817db192176496a57b22ab037637d97a185ea0b0d19da687da66c2a2f5578e4343d230f399d49fe377d8f008410974238 handle-aux-at_base.patch
898507a75af05d960ac25343ac1ff026923a62f5095400fa3dcc650baf25b83cdff740da8a87fa6e40856227a44dcc469b78af6905e2f0e4f027abef5d3fad57 fix-TLS-layout-of-TLS-variant-I-when-there-is-gap-above-TP.patch
8d3a2d5315fc56fee7da9abb8b89bb38c6046c33d154c10d168fb35bfde6b0cf9f13042a3bceee34daf091bc409d699223735dcf19f382eeee1f6be34154f26f ldconfig
062bb49fa54839010acd4af113e20f7263dde1c8a2ca359b5fb2661ef9ed9d84a0f7c3bc10c25dcfa10bb3c5a4874588dff636ac43d5dbb3d748d75400756d0b __stack_chk_fail_local.c
0d80f37b34a35e3d14b012257c50862dfeb9d2c81139ea2dfa101d981d093b009b9fa450ba27a708ac59377a48626971dfc58e20a3799084a65777a0c32cbc7d getconf.c
......
From 610c5a8524c3d6cd3ac5a5f1231422e7648a3791 Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <nsz@port70.net>
Date: Sat, 2 Jun 2018 01:52:01 +0200
Subject: fix TLS layout of TLS variant I when there is a gap above TP
In TLS variant I the TLS is above TP (or above a fixed offset from TP)
but on some targets there is a reserved gap above TP before TLS starts.
This matters for the local-exec tls access model when the offsets of
TLS variables from the TP are hard coded by the linker into the
executable, so the libc must compute these offsets the same way as the
linker. The tls offset of the main module has to be
alignup(GAP_ABOVE_TP, main_tls_align).
If there is no TLS in the main module then the gap can be ignored
since musl does not use it and the tls access models of shared
libraries are not affected.
The previous setup only worked if (tls_align & -GAP_ABOVE_TP) == 0
(i.e. TLS did not require large alignment) because the gap was
treated as a fixed offset from TP. Now the TP points at the end
of the pthread struct (which is aligned) and there is a gap above
it (which may also need alignment).
The fix required changing TP_ADJ and __pthread_self on affected
targets (aarch64, arm and sh) and in the tlsdesc asm the offset to
access the dtv changed too.
Patch-Source: https://git.musl-libc.org/cgit/musl/commit/?id=610c5a8524c3d6cd3ac5a5f1231422e7648a3791
See-Also: https://github.com/rust-lang/rust/issues/48967
---
arch/aarch64/pthread_arch.h | 5 +++--
arch/aarch64/reloc.h | 2 +-
arch/arm/pthread_arch.h | 7 ++++---
arch/arm/reloc.h | 2 +-
arch/mips/pthread_arch.h | 1 +
arch/mips64/pthread_arch.h | 1 +
arch/mipsn32/pthread_arch.h | 1 +
arch/or1k/pthread_arch.h | 1 +
arch/powerpc/pthread_arch.h | 1 +
arch/powerpc64/pthread_arch.h | 1 +
arch/sh/pthread_arch.h | 5 +++--
arch/sh/reloc.h | 2 +-
ldso/dynlink.c | 5 +++--
src/env/__init_tls.c | 10 ++++++++--
src/ldso/aarch64/tlsdesc.s | 5 ++---
15 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/arch/aarch64/pthread_arch.h b/arch/aarch64/pthread_arch.h
index b2e2d8f..e8499d8 100644
--- a/arch/aarch64/pthread_arch.h
+++ b/arch/aarch64/pthread_arch.h
@@ -2,10 +2,11 @@ static inline struct pthread *__pthread_self()
{
char *self;
__asm__ __volatile__ ("mrs %0,tpidr_el0" : "=r"(self));
- return (void*)(self + 16 - sizeof(struct pthread));
+ return (void*)(self - sizeof(struct pthread));
}
#define TLS_ABOVE_TP
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 16)
+#define GAP_ABOVE_TP 16
+#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
#define MC_PC pc
diff --git a/arch/aarch64/reloc.h b/arch/aarch64/reloc.h
index 51b66e2..40cf0b2 100644
--- a/arch/aarch64/reloc.h
+++ b/arch/aarch64/reloc.h
@@ -10,7 +10,7 @@
#define NO_LEGACY_INITFINI
-#define TPOFF_K 16
+#define TPOFF_K 0
#define REL_SYMBOLIC R_AARCH64_ABS64
#define REL_GOT R_AARCH64_GLOB_DAT
diff --git a/arch/arm/pthread_arch.h b/arch/arm/pthread_arch.h
index 6657e19..8f2ae8f 100644
--- a/arch/arm/pthread_arch.h
+++ b/arch/arm/pthread_arch.h
@@ -5,7 +5,7 @@ static inline pthread_t __pthread_self()
{
char *p;
__asm__ __volatile__ ( "mrc p15,0,%0,c13,c0,3" : "=r"(p) );
- return (void *)(p+8-sizeof(struct pthread));
+ return (void *)(p-sizeof(struct pthread));
}
#else
@@ -21,12 +21,13 @@ static inline pthread_t __pthread_self()
extern uintptr_t __attribute__((__visibility__("hidden"))) __a_gettp_ptr;
register uintptr_t p __asm__("r0");
__asm__ __volatile__ ( BLX " %1" : "=r"(p) : "r"(__a_gettp_ptr) : "cc", "lr" );
- return (void *)(p+8-sizeof(struct pthread));
+ return (void *)(p-sizeof(struct pthread));
}
#endif
#define TLS_ABOVE_TP
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8)
+#define GAP_ABOVE_TP 8
+#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
#define MC_PC arm_pc
diff --git a/arch/arm/reloc.h b/arch/arm/reloc.h
index b175711..4b00bf6 100644
--- a/arch/arm/reloc.h
+++ b/arch/arm/reloc.h
@@ -16,7 +16,7 @@
#define NO_LEGACY_INITFINI
-#define TPOFF_K 8
+#define TPOFF_K 0
#define REL_SYMBOLIC R_ARM_ABS32
#define REL_GOT R_ARM_GLOB_DAT
diff --git a/arch/mips/pthread_arch.h b/arch/mips/pthread_arch.h
index e581265..5fea15a 100644
--- a/arch/mips/pthread_arch.h
+++ b/arch/mips/pthread_arch.h
@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self()
}
#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
#define DTP_OFFSET 0x8000
diff --git a/arch/mips64/pthread_arch.h b/arch/mips64/pthread_arch.h
index e581265..5fea15a 100644
--- a/arch/mips64/pthread_arch.h
+++ b/arch/mips64/pthread_arch.h
@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self()
}
#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
#define DTP_OFFSET 0x8000
diff --git a/arch/mipsn32/pthread_arch.h b/arch/mipsn32/pthread_arch.h
index e581265..5fea15a 100644
--- a/arch/mipsn32/pthread_arch.h
+++ b/arch/mipsn32/pthread_arch.h
@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self()
}
#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
#define DTP_OFFSET 0x8000
diff --git a/arch/or1k/pthread_arch.h b/arch/or1k/pthread_arch.h
index 7decd76..521b9c5 100644
--- a/arch/or1k/pthread_arch.h
+++ b/arch/or1k/pthread_arch.h
@@ -12,6 +12,7 @@ static inline struct pthread *__pthread_self()
}
#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
#define MC_PC regs.pc
diff --git a/arch/powerpc/pthread_arch.h b/arch/powerpc/pthread_arch.h
index 7c5c4fa..79e5a09 100644
--- a/arch/powerpc/pthread_arch.h
+++ b/arch/powerpc/pthread_arch.h
@@ -11,6 +11,7 @@ static inline struct pthread *__pthread_self()
}
#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
#define DTP_OFFSET 0x8000
diff --git a/arch/powerpc64/pthread_arch.h b/arch/powerpc64/pthread_arch.h
index 2f976fe..37b75e2 100644
--- a/arch/powerpc64/pthread_arch.h
+++ b/arch/powerpc64/pthread_arch.h
@@ -6,6 +6,7 @@ static inline struct pthread *__pthread_self()
}
#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) + 0x7000)
#define DTP_OFFSET 0x8000
diff --git a/arch/sh/pthread_arch.h b/arch/sh/pthread_arch.h
index 2756e7e..41fefac 100644
--- a/arch/sh/pthread_arch.h
+++ b/arch/sh/pthread_arch.h
@@ -2,10 +2,11 @@ static inline struct pthread *__pthread_self()
{
char *self;
__asm__ __volatile__ ("stc gbr,%0" : "=r" (self) );
- return (struct pthread *) (self + 8 - sizeof(struct pthread));
+ return (struct pthread *) (self - sizeof(struct pthread));
}
#define TLS_ABOVE_TP
-#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8)
+#define GAP_ABOVE_TP 8
+#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
#define MC_PC sc_pc
diff --git a/arch/sh/reloc.h b/arch/sh/reloc.h
index 0238ce0..a1f16cb 100644
--- a/arch/sh/reloc.h
+++ b/arch/sh/reloc.h
@@ -20,7 +20,7 @@
#define LDSO_ARCH "sh" ENDIAN_SUFFIX FP_SUFFIX ABI_SUFFIX
-#define TPOFF_K 8
+#define TPOFF_K 0
#define REL_SYMBOLIC R_SH_DIR32
#define REL_OFFSET R_SH_REL32
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index cea5f45..c6216b7 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -1594,8 +1594,9 @@ _Noreturn void __dls3(size_t *sp)
libc.tls_head = tls_tail = &app.tls;
app.tls_id = tls_cnt = 1;
#ifdef TLS_ABOVE_TP
- app.tls.offset = 0;
- tls_offset = app.tls.size
+ app.tls.offset = GAP_ABOVE_TP;
+ app.tls.offset += -GAP_ABOVE_TP & (app.tls.align-1);
+ tls_offset = app.tls.offset + app.tls.size
+ ( -((uintptr_t)app.tls.image + app.tls.size)
& (app.tls.align-1) );
#else
diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
index 1c5d98a..31d324a 100644
--- a/src/env/__init_tls.c
+++ b/src/env/__init_tls.c
@@ -104,13 +104,19 @@ static void static_init_tls(size_t *aux)
main_tls.size += (-main_tls.size - (uintptr_t)main_tls.image)
& (main_tls.align-1);
- if (main_tls.align < MIN_TLS_ALIGN) main_tls.align = MIN_TLS_ALIGN;
-#ifndef TLS_ABOVE_TP
+#ifdef TLS_ABOVE_TP
+ main_tls.offset = GAP_ABOVE_TP;
+ main_tls.offset += -GAP_ABOVE_TP & (main_tls.align-1);
+#else
main_tls.offset = main_tls.size;
#endif
+ if (main_tls.align < MIN_TLS_ALIGN) main_tls.align = MIN_TLS_ALIGN;
libc.tls_align = main_tls.align;
libc.tls_size = 2*sizeof(void *) + sizeof(struct pthread)
+#ifdef TLS_ABOVE_TP
+ + main_tls.offset
+#endif
+ main_tls.size + main_tls.align
+ MIN_TLS_ALIGN-1 & -MIN_TLS_ALIGN;
diff --git a/src/ldso/aarch64/tlsdesc.s b/src/ldso/aarch64/tlsdesc.s
index 8ed5c26..8e4004d 100644
--- a/src/ldso/aarch64/tlsdesc.s
+++ b/src/ldso/aarch64/tlsdesc.s
@@ -14,7 +14,7 @@ __tlsdesc_static:
// size_t __tlsdesc_dynamic(size_t *a)
// {
// struct {size_t modidx,off;} *p = (void*)a[1];
-// size_t *dtv = *(size_t**)(tp + 16 - 8);
+// size_t *dtv = *(size_t**)(tp - 8);
// if (p->modidx <= dtv[0])
// return dtv[p->modidx] + p->off - tp;
// return __tls_get_new(p) - tp;
@@ -28,8 +28,7 @@ __tlsdesc_dynamic:
mrs x1,tpidr_el0 // tp
ldr x0,[x0,#8] // p
ldr x2,[x0] // p->modidx
- add x3,x1,#8
- ldr x3,[x3] // dtv
+ ldr x3,[x1,#-8] // dtv
ldr x4,[x3] // dtv[0]
cmp x2,x4
b.hi 1f
--
cgit v0.11.2
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment