Move Bionic slots to the end of pthread_internal_t

With ELF TLS, the static linker assumes that an executable's TLS segment
is at a known offset from the thread pointer (i.e. __get_tls()). The
segment can be located prior to the TP (variant 2, x86[_64], sparc) or
after it (variant 1, arm{32,64}, ppc, mips, ia64, riscv).

We can't make our pthread_internal_t exactly follow the ordinary arm64
ABI (at least) because TP[5] is used for clang's -fstack-protector on
Android. Instead, reserve extra space after the TP (up to 16 words), which
will be followed by the executable's TLS segment.

Bug: http://b/78026329
Test: boot device, bionic unit tests
Change-Id: I0f3b270b793f9872ba0effeac03f4dec364438d6
Merged-In: I0f3b270b793f9872ba0effeac03f4dec364438d6
(cherry picked from commit f397317e96)
This commit is contained in:
Ryan Prichard 2018-10-19 20:35:23 -07:00
parent a2af8bea8c
commit 29d6dbc906
1 changed files with 6 additions and 4 deletions

View File

@ -112,10 +112,6 @@ class pthread_internal_t {
thread_local_dtor* thread_local_dtors;
void* tls[BIONIC_TLS_SLOTS];
pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];
/*
* The dynamic linker implements dlerror(3), which makes it hard for us to implement this
* per-thread buffer by simply using malloc(3) and free(3).
@ -124,6 +120,12 @@ class pthread_internal_t {
char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
bionic_tls* bionic_tls;
pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];
// The thread pointer (__get_tls()) points at this field. This field must come last so that
// an executable's TLS segment can be allocated at a fixed offset after the thread pointer.
void* tls[BIONIC_TLS_SLOTS];
};
__LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);