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
This commit is contained in:
David 'Digit' Turner 2010-08-27 08:19:19 -07:00
parent 22f1e3d4fa
commit 6a51defa03
3 changed files with 74 additions and 15 deletions

View file

@ -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

View file

@ -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:

View file

@ -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);