summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2010-08-27 08:19:19 -0700
committerDavid 'Digit' Turner <digit@google.com>2010-08-27 08:19:19 -0700
commit6a51defa034a1c033ed01f7de444c0a4fc615249 (patch)
tree87b93dbfe8ab9c61d80d4a6036c66b0982b72c73
parent22f1e3d4fae7d45cc439da94690d786ed44756fb (diff)
downloadbionic-6a51defa034a1c033ed01f7de444c0a4fc615249.zip
bionic-6a51defa034a1c033ed01f7de444c0a4fc615249.tar.gz
bionic-6a51defa034a1c033ed01f7de444c0a4fc615249.tar.bz2
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
-rw-r--r--libc/Android.mk38
-rw-r--r--libc/docs/CHANGES.TXT7
-rw-r--r--libc/private/bionic_tls.h44
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:
- <dlfcn.h>: fixed dlopen() implementation to support dlopen(NULL, ...).
This allows one to look at the dynamic symbols exported by an executable.
+- <private/bionic_tls.h>: 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);