diff --git a/libc/Android.mk b/libc/Android.mk index 32bf9322e..8b54f3e6c 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 \ @@ -247,7 +246,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 \ @@ -316,6 +314,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) @@ -350,12 +365,14 @@ 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-atfork.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 := \ @@ -386,12 +403,14 @@ 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-atfork.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 @@ -424,12 +443,15 @@ libc_common_src_files += \ string/strncmp.c \ string/memcmp.c \ string/strlen.c \ - bionic/pthread.c \ bionic/pthread-atfork.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 @@ -593,10 +615,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 @@ -612,6 +636,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 @@ -636,6 +661,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 e1eee4f4f..0eab8791c 100644 --- a/libc/docs/CHANGES.TXT +++ b/libc/docs/CHANGES.TXT @@ -75,6 +75,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 241257768..008fd2ff7 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);