From 6a51defa034a1c033ed01f7de444c0a4fc615249 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Fri, 27 Aug 2010 08:19:19 -0700 Subject: Fix __get_tls() in static C library to use kernel helpers. This is needed to fix gdbserver's handling of threaded programs, among other things. Change-Id: I823387c602cef9891532da946a01db14be780ab0 --- libc/Android.mk | 38 ++++++++++++++++++++++++++++++++------ libc/docs/CHANGES.TXT | 7 +++++++ libc/private/bionic_tls.h | 44 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/libc/Android.mk b/libc/Android.mk index 510864f..f700ca0 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -64,7 +64,6 @@ libc_common_src_files := \ unistd/sleep.c \ unistd/statfs.c \ unistd/strsignal.c \ - unistd/sysconf.c \ unistd/syslog.c \ unistd/system.c \ unistd/tcgetpgrp.c \ @@ -245,7 +244,6 @@ libc_common_src_files := \ tzcode/localtime.c \ tzcode/strftime.c \ tzcode/strptime.c \ - bionic/__errno.c \ bionic/__set_errno.c \ bionic/_rand48.c \ bionic/cpuacct.c \ @@ -314,6 +312,23 @@ libc_common_src_files := \ regex/regexec.c \ regex/regfree.c \ +# The following files are common, but must be compiled +# with different C flags when building a static C library. +# +# The reason for this is the implementation of __get_tls() +# that will differ between the shared and static versions +# of the library. +# +# See comments in private/bionic_tls.h for more details. +# +# NOTE: bionic/pthread.c is added later to this list +# because it needs special handling on ARM, see +# below. +# +libc_static_common_src_files := \ + unistd/sysconf.c \ + bionic/__errno.c \ + # Architecture specific source files go here # ========================================================= ifeq ($(TARGET_ARCH),arm) @@ -348,11 +363,13 @@ libc_common_src_files += \ # can set breakpoints in them without messing # up any thumb code. libc_common_src_files += \ - bionic/pthread.c.arm \ bionic/pthread-rwlocks.c.arm \ bionic/pthread-timers.c.arm \ bionic/ptrace.c.arm +libc_static_common_src_files += \ + bionic/pthread.c.arm \ + # these are used by the static and dynamic versions of the libc # respectively libc_arch_static_src_files := \ @@ -383,11 +400,13 @@ libc_common_src_files += \ arch-x86/string/strcmp_wrapper.S \ arch-x86/string/strncmp_wrapper.S \ arch-x86/string/strlen.S \ - bionic/pthread.c \ bionic/pthread-rwlocks.c \ bionic/pthread-timers.c \ bionic/ptrace.c +libc_static_common_src_files += \ + bionic/pthread.c \ + # this is needed for static versions of libc libc_arch_static_src_files := \ arch-x86/bionic/dl_iterate_phdr_static.c @@ -420,11 +439,14 @@ libc_common_src_files += \ string/strncmp.c \ string/memcmp.c \ string/strlen.c \ - bionic/pthread.c \ bionic/pthread-rwlocks.c \ bionic/pthread-timers.c \ bionic/ptrace.c \ unistd/socketcalls.c + +libc_static_common_src_files += \ + bionic/pthread.c \ + endif # sh endif # !x86 @@ -584,10 +606,12 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ $(libc_arch_static_src_files) \ + $(libc_static_common_src_files) \ bionic/libc_init_static.c LOCAL_C_INCLUDES := $(libc_common_c_includes) -LOCAL_CFLAGS := $(libc_common_cflags) +LOCAL_CFLAGS := $(libc_common_cflags) \ + -DLIBC_STATIC LOCAL_MODULE := libc_nomalloc LOCAL_WHOLE_STATIC_LIBRARIES := libc_common @@ -603,6 +627,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ $(libc_arch_static_src_files) \ + $(libc_static_common_src_files) \ bionic/dlmalloc.c \ bionic/malloc_debug_common.c \ bionic/libc_init_static.c @@ -627,6 +652,7 @@ LOCAL_C_INCLUDES := $(libc_common_c_includes) LOCAL_SRC_FILES := \ $(libc_arch_dynamic_src_files) \ + $(libc_static_common_src_files) \ bionic/dlmalloc.c \ bionic/malloc_debug_common.c \ bionic/libc_init_dynamic.c diff --git a/libc/docs/CHANGES.TXT b/libc/docs/CHANGES.TXT index d1d82de..4d094d0 100644 --- a/libc/docs/CHANGES.TXT +++ b/libc/docs/CHANGES.TXT @@ -73,6 +73,13 @@ Differences between current and Android 2.2: - : fixed dlopen() implementation to support dlopen(NULL, ...). This allows one to look at the dynamic symbols exported by an executable. +- : use kernel helper functions for static versions + of the C library. This is necessary because we don't know where the corresponding + machine code is going to run, and the optimization for __get_tls() might + not match the features of the target device where we run a static executable + linked to the C library. This fixes one of the bug that explains why gdbserver + didn't work well with threads. + ------------------------------------------------------------------------------- Differences between Android 2.2. and Android 2.1: diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h index 2412577..008fd2f 100644 --- a/libc/private/bionic_tls.h +++ b/libc/private/bionic_tls.h @@ -88,22 +88,48 @@ extern int __set_tls(void *ptr); /* get the TLS */ #ifdef __arm__ -/* Linux kernel helpers for its TLS implementation */ -/* For performance reasons, avoid calling the kernel helper +/* The standard way to get the TLS is to call a kernel helper + * function (i.e. a function provided at a fixed address in a + * "magic page" mapped in all user-space address spaces ), which + * contains the most appropriate code path for the target device. + * + * However, for performance reasons, we're going to use our own + * machine code for the system's C shared library. + * + * We cannot use this optimization in the static version of the + * C library, because we don't know where the corresponding code + * is going to run. + */ +# ifdef LIBC_STATIC + +/* Use the kernel helper in static C library. */ + typedef volatile void* (__kernel_get_tls_t)(void); +# define __get_tls() (*(__kernel_get_tls_t *)0xffff0fe0)() + +# else /* !LIBC_STATIC */ +/* Use optimized code path. * Note that HAVE_ARM_TLS_REGISTER is build-specific * (it must match your kernel configuration) */ -# ifdef HAVE_ARM_TLS_REGISTER -# define __get_tls() \ +# ifdef HAVE_ARM_TLS_REGISTER + /* We can read the address directly from a coprocessor + * register, which avoids touching the data cache + * completely. + */ +# define __get_tls() \ ({ register unsigned int __val asm("r0"); \ asm ("mrc p15, 0, r0, c13, c0, 3" : "=r"(__val) ); \ (volatile void*)__val; }) -# else /* !HAVE_ARM_TLS_REGISTER */ -# define __get_tls() ( *((volatile void **) 0xffff0ff0) ) -# endif -#else +# else /* !HAVE_ARM_TLS_REGISTER */ + /* The kernel provides the address of the TLS at a fixed + * address of the magic page too. + */ +# define __get_tls() ( *((volatile void **) 0xffff0ff0) ) +# endif +# endif /* !LIBC_STATIC */ +#else /* !ARM */ extern void* __get_tls( void ); -#endif +#endif /* !ARM */ /* return the stack base and size, used by our malloc debugger */ extern void* __get_stack_base(int *p_stack_size); -- cgit v1.1