From c4eee3765bf9dd81ff055e70ff7daa83a3926d2a Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Wed, 8 Jul 2009 14:22:41 +0200 Subject: Prevent a crash in the memory leak checker (which happened in chk_free()) Simplify the code a little, removing un-necessary mutex locks/unlocks. Provide slightly better diagnostic message in case of corruption. Use snprintf/strlcat instead of sprintf/strcat --- libc/bionic/logd_write.c | 8 +-- libc/bionic/malloc_leak.c | 140 +++++++++++++++++++++++++++------------------- libc/private/logd.h | 3 + 3 files changed, 88 insertions(+), 63 deletions(-) diff --git a/libc/bionic/logd_write.c b/libc/bionic/logd_write.c index 7c3608b..211b527 100644 --- a/libc/bionic/logd_write.c +++ b/libc/bionic/logd_write.c @@ -126,10 +126,10 @@ static int __android_log_write(int prio, const char *tag, const char *msg) } -static int __android_log_vprint(int prio, const char *tag, const char *fmt, - va_list ap) +int __libc_android_log_vprint(int prio, const char *tag, const char *fmt, + va_list ap) { - char buf[LOG_BUF_SIZE]; + char buf[LOG_BUF_SIZE]; vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); @@ -139,7 +139,7 @@ static int __android_log_vprint(int prio, const char *tag, const char *fmt, int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...) { va_list ap; - char buf[LOG_BUF_SIZE]; + char buf[LOG_BUF_SIZE]; va_start(ap, fmt); vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); diff --git a/libc/bionic/malloc_leak.c b/libc/bionic/malloc_leak.c index a0aa2ae..df09424 100644 --- a/libc/bionic/malloc_leak.c +++ b/libc/bionic/malloc_leak.c @@ -515,8 +515,8 @@ static void dump_stack_trace() tmp[0] = 0; // Need to initialize tmp[0] for the first strcat for (i=0 ; i=0 ; i--) { if (buf[i] != CHK_SENTINEL_VALUE) { - gMallocDispatch = &gMallocEngineTable[INDEX_NORMAL]; - __libc_android_log_print(ANDROID_LOG_ERROR, "libc", - "*** MALLOC CHECK: buffer %p, size=%lu, " - "corrupted %d bytes after allocation", - buffer, size, i+1); - dump_stack_trace(); - if (gTrapOnError) { - __builtin_trap(); - } - gMallocDispatch = &gMallocEngineTable[INDEX_MALLOC_CHECK]; + assert_log_message( + "*** %s CHECK: buffer %p, size=%lu, " + "corrupted %d bytes after allocation", + func, buffer, bytes, i+1); + return -1; } } + + *allocated = bytes; + return 0; } + void* chk_malloc(size_t bytes) { char* buffer = (char*)dlmalloc(bytes + CHK_OVERHEAD_SIZE); if (buffer) { - pthread_mutex_lock(&gAllocationsMutex); - memset(buffer, CHK_SENTINEL_VALUE, bytes + CHK_OVERHEAD_SIZE); - size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t); - *(size_t *)(buffer + offset) = bytes; - buffer += CHK_SENTINEL_HEAD_SIZE; - pthread_mutex_unlock(&gAllocationsMutex); + memset(buffer, CHK_SENTINEL_VALUE, bytes + CHK_OVERHEAD_SIZE); + size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t); + *(size_t *)(buffer + offset) = bytes; + buffer += CHK_SENTINEL_HEAD_SIZE; } return buffer; } @@ -597,14 +618,14 @@ void chk_free(void* mem) { assert_valid_malloc_pointer(mem); if (mem) { - pthread_mutex_lock(&gAllocationsMutex); - char* buffer = (char*)mem - CHK_SENTINEL_HEAD_SIZE; - size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t); - size_t bytes = *(size_t *)(buffer + offset); - chk_out_of_bounds_check__locked(mem, bytes); - pthread_mutex_unlock(&gAllocationsMutex); - memset(buffer, CHK_FILL_FREE, bytes); - dlfree(buffer); + size_t size; + char* buffer; + + if (chk_mem_check(mem, &size, "FREE") == 0) { + buffer = (char*)mem - CHK_SENTINEL_HEAD_SIZE; + memset(buffer, CHK_FILL_FREE, size + CHK_OVERHEAD_SIZE); + dlfree(buffer); + } } } @@ -628,19 +649,20 @@ void* chk_calloc(size_t n_elements, size_t elem_size) void* chk_realloc(void* mem, size_t bytes) { + char* buffer; + int ret; + size_t old_bytes = 0; + assert_valid_malloc_pointer(mem); + + if (mem != NULL && chk_mem_check(mem, &old_bytes, "REALLOC") < 0) + return NULL; + char* new_buffer = chk_malloc(bytes); if (mem == NULL) { return new_buffer; } - pthread_mutex_lock(&gAllocationsMutex); - char* buffer = (char*)mem - CHK_SENTINEL_HEAD_SIZE; - size_t offset = dlmalloc_usable_size(buffer) - sizeof(size_t); - size_t old_bytes = *(size_t *)(buffer + offset); - chk_out_of_bounds_check__locked(mem, old_bytes); - pthread_mutex_unlock(&gAllocationsMutex); - if (new_buffer) { size_t size = (bytes < old_bytes)?(bytes):(old_bytes); memcpy(new_buffer, mem, size); diff --git a/libc/private/logd.h b/libc/private/logd.h index 671cb48..43fa742 100644 --- a/libc/private/logd.h +++ b/libc/private/logd.h @@ -28,6 +28,8 @@ #ifndef _ANDROID_BIONIC_LOGD_H #define _ANDROID_BIONIC_LOGD_H +#include + enum { ANDROID_LOG_UNKNOWN = 0, ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ @@ -43,5 +45,6 @@ enum { }; int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...); +int __libc_android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap); #endif /* _ANDROID_BIONIC_LOGD_H */ -- cgit v1.1 From db4616b2d3234a1916cafb48e65c50cf302afcde Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Fri, 10 Jul 2009 00:59:56 +0200 Subject: Add to C library kernel headers --- libc/kernel/common/linux/uinput.h | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 libc/kernel/common/linux/uinput.h diff --git a/libc/kernel/common/linux/uinput.h b/libc/kernel/common/linux/uinput.h new file mode 100644 index 0000000..b7a6add --- /dev/null +++ b/libc/kernel/common/linux/uinput.h @@ -0,0 +1,67 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was automatically generated from a Linux kernel header + *** of the same name, to make information necessary for userspace to + *** call into the kernel available to libc. It contains only constants, + *** structures, and macros generated from the original header, and thus, + *** contains no copyrightable information. + *** + **************************************************************************** + ****************************************************************************/ +#ifndef __UINPUT_H_ +#define __UINPUT_H_ + +#include + +#define UINPUT_VERSION 3 + +struct uinput_ff_upload { + int request_id; + int retval; + struct ff_effect effect; + struct ff_effect old; +}; + +struct uinput_ff_erase { + int request_id; + int retval; + int effect_id; +}; + +#define UINPUT_IOCTL_BASE 'U' +#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1) +#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2) + +#define UI_SET_EVBIT _IOW(UINPUT_IOCTL_BASE, 100, int) +#define UI_SET_KEYBIT _IOW(UINPUT_IOCTL_BASE, 101, int) +#define UI_SET_RELBIT _IOW(UINPUT_IOCTL_BASE, 102, int) +#define UI_SET_ABSBIT _IOW(UINPUT_IOCTL_BASE, 103, int) +#define UI_SET_MSCBIT _IOW(UINPUT_IOCTL_BASE, 104, int) +#define UI_SET_LEDBIT _IOW(UINPUT_IOCTL_BASE, 105, int) +#define UI_SET_SNDBIT _IOW(UINPUT_IOCTL_BASE, 106, int) +#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int) +#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*) +#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int) + +#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload) +#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload) +#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase) +#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase) + +#define EV_UINPUT 0x0101 +#define UI_FF_UPLOAD 1 +#define UI_FF_ERASE 2 + +#define UINPUT_MAX_NAME_SIZE 80 +struct uinput_user_dev { + char name[UINPUT_MAX_NAME_SIZE]; + struct input_id id; + int ff_effects_max; + int absmax[ABS_MAX + 1]; + int absmin[ABS_MAX + 1]; + int absfuzz[ABS_MAX + 1]; + int absflat[ABS_MAX + 1]; +}; +#endif + -- cgit v1.1 From 348065586a2e6154d6cff36afa6e00af6bbc5918 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Fri, 10 Jul 2009 12:23:09 +0200 Subject: Add new C++ headers and Also add std::malloc/realloc/calloc/free to Rename to --- libstdc++/include/cerrno | 40 +++++++++++++++++++++++++++++++ libstdc++/include/cfloat | 39 ++++++++++++++++++++++++++++++ libstdc++/include/cstdlib | 5 ++++ libstdc++/include/cwchar | 31 ++++++++++++++++++++++++ libstdc++/include/cwchar_is_not_supported | 31 ------------------------ 5 files changed, 115 insertions(+), 31 deletions(-) create mode 100644 libstdc++/include/cerrno create mode 100644 libstdc++/include/cfloat create mode 100644 libstdc++/include/cwchar delete mode 100644 libstdc++/include/cwchar_is_not_supported diff --git a/libstdc++/include/cerrno b/libstdc++/include/cerrno new file mode 100644 index 0000000..e53ca25 --- /dev/null +++ b/libstdc++/include/cerrno @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CERRNO__ +#define BIONIC_LIBSTDCPP_INCLUDE_CERRNO__ + +/* + * Standard C++ Library wrapper around the C errno.h header file. + */ +#include + +// errno is a macro, so we can't define std::errno + +#endif // BIONIC_LIBSTDCPP_INCLUDE_CERRNO__ diff --git a/libstdc++/include/cfloat b/libstdc++/include/cfloat new file mode 100644 index 0000000..21c01d9 --- /dev/null +++ b/libstdc++/include/cfloat @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef BIONIC_LIBSTDCPP_INCLUDE_CFLOAT__ +#define BIONIC_LIBSTDCPP_INCLUDE_CFLOAT__ + +/* + * Standard C++ Library wrapper around the C float.h header file. + */ +#include +#include + +#endif // BIONIC_LIBSTDCPP_INCLUDE_CFLOAT__ diff --git a/libstdc++/include/cstdlib b/libstdc++/include/cstdlib index 9e8a7ce..5e6a0b3 100644 --- a/libstdc++/include/cstdlib +++ b/libstdc++/include/cstdlib @@ -85,6 +85,11 @@ using ::srand; using ::random; using ::srandom; +using ::malloc; +using ::free; +using ::calloc; +using ::realloc; + using ::unlockpt; using ::ptsname; using ::ptsname_r; diff --git a/libstdc++/include/cwchar b/libstdc++/include/cwchar new file mode 100644 index 0000000..a4f9f42 --- /dev/null +++ b/libstdc++/include/cwchar @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* IMPORTANT: cwchar and cwctype are not supported. See comment in + * bionic/libc/include/wchar.h */ diff --git a/libstdc++/include/cwchar_is_not_supported b/libstdc++/include/cwchar_is_not_supported deleted file mode 100644 index a4f9f42..0000000 --- a/libstdc++/include/cwchar_is_not_supported +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright (C) 2009 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* IMPORTANT: cwchar and cwctype are not supported. See comment in - * bionic/libc/include/wchar.h */ -- cgit v1.1 From ef0bd1857041ffde069cf52138aaf22c1af7130e Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Fri, 17 Jul 2009 17:55:01 +0200 Subject: Pass the elfdata pointer in a slot of the temporary TLS area. This is needed to properly initialize the C runtime when libc.so is loaded by the dynamic linker. Move the temporary TLS setup before the first system call, just in case something really horrible happens, we won't crash when trying to write an error code in 'errno' Remove the broken TLS_SLOT_THREAD_ID setup. First, this slot should normally receive the address of a pthread_internal_t, not a kernel thread identifier. Second, it is never used by the linker anyway. Also remove an obsolete comment. --- libc/private/bionic_tls.h | 7 +++++++ linker/linker.c | 21 ++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h index da34344..82c8cd9 100644 --- a/libc/private/bionic_tls.h +++ b/libc/private/bionic_tls.h @@ -60,6 +60,13 @@ __BEGIN_DECLS #define TLS_SLOT_OPENGL_API 3 #define TLS_SLOT_OPENGL 4 +/* this slot is only used to pass information from the dynamic linker to + * libc.so when the C library is loaded in to memory. The C runtime init + * function will then clear it. Since its use is extremely temporary, + * we reuse an existing location. + */ +#define TLS_SLOT_BIONIC_PREINIT (TLS_SLOT_ERRNO+1) + /* small technical note: it is not possible to call pthread_setspecific * on keys that are <= TLS_SLOT_MAX_WELL_KNOWN, which is why it is set to * TLS_SLOT_ERRNO. diff --git a/linker/linker.c b/linker/linker.c index 77f995e..e235498 100644 --- a/linker/linker.c +++ b/linker/linker.c @@ -76,11 +76,6 @@ * headers provide versions that are negative... * - allocate space for soinfo structs dynamically instead of * having a hard limit (64) - * - * features to add someday: - * - * - dlopen() and friends - * */ @@ -1744,6 +1739,11 @@ unsigned __linker_init(unsigned **elfdata) struct link_map * map; char *ldpath_env = NULL; + /* Setup a temporary TLS area that is used to get a working + * errno for system calls. + */ + __set_tls(__tls_area); + pid = getpid(); #if TIMING @@ -1751,8 +1751,15 @@ unsigned __linker_init(unsigned **elfdata) gettimeofday(&t0, 0); #endif - __set_tls(__tls_area); - ((unsigned *)__get_tls())[TLS_SLOT_THREAD_ID] = gettid(); + /* NOTE: we store the elfdata pointer on a special location + * of the temporary TLS area in order to pass it to + * the C Library's runtime initializer. + * + * The initializer must clear the slot and reset the TLS + * to point to a different location to ensure that no other + * shared library constructor can access it. + */ + __tls_area[TLS_SLOT_BIONIC_PREINIT] = elfdata; debugger_init(); -- cgit v1.1 From b56b5659b3996e98c2060f168d1cff1474e77d2a Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Sat, 18 Jul 2009 01:11:10 +0200 Subject: Fix the C library runtime initialization order. This allows libc.so to run the C runtime initializer as soon as the dynamic linker loads the shared library, i.e. before any other initializers (e.g. static C++ constructors in other shared libraries the executable depends on). This also removes the bug where the initializers from the executable itself were run twice: once by the dynamic linker, and another time by __libc_init as defined by libc_init_dynamic.c --- libc/bionic/libc_init_common.c | 77 +++++++++++++---------------------------- libc/bionic/libc_init_common.h | 6 +--- libc/bionic/libc_init_dynamic.c | 69 ++++++++++++++++++++++++++---------- libc/bionic/libc_init_static.c | 63 ++++++++++++++++++++------------- 4 files changed, 115 insertions(+), 100 deletions(-) diff --git a/libc/bionic/libc_init_common.c b/libc/bionic/libc_init_common.c index de4919d..c77c162 100644 --- a/libc/bionic/libc_init_common.c +++ b/libc/bionic/libc_init_common.c @@ -39,23 +39,6 @@ #include #include -extern void _init(void); -extern void _fini(void); - -static void call_array(void(**list)()) -{ - // First element is -1, list is null-terminated - while (*++list) { - (*list)(); - } -} - -static void __bionic_do_global_dtors(structors_array_t const * const p) -{ - call_array(p->fini_array); - //_fini(); -} - extern unsigned __get_sp(void); extern pid_t gettid(void); @@ -69,23 +52,23 @@ unsigned int __page_shift = PAGE_SHIFT; int __system_properties_init(void); -void __libc_init_common(uintptr_t *elfdata, - void (*onexit)(void), - int (*slingshot)(int, char**, char**), - structors_array_t const * const structors, - void (*pre_ctor_hook)()) +#ifdef MALLOCK_LEAK_CHECK +void malloc_debug_init(void); +#endif + +void __libc_init_common(uintptr_t *elfdata) { - pthread_internal_t thread; - pthread_attr_t thread_attr; - void *tls_area[BIONIC_TLS_SLOTS]; - int argc; - char **argv, **envp, **envend; - struct auxentry *auxentry; - unsigned int page_size = 0, page_shift = 0; - - /* The main thread's stack has empirically shown to be 84k */ + int argc = *elfdata; + char** argv = (char**)(elfdata + 1); + char** envp = argv + argc + 1; + + pthread_attr_t thread_attr; + static pthread_internal_t thread; + static void* tls_area[BIONIC_TLS_SLOTS]; + + /* setup pthread runtime and maint thread descriptor */ unsigned stacktop = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE; - unsigned stacksize = 128 * 1024; //84 * 1024; + unsigned stacksize = 128 * 1024; unsigned stackbottom = stacktop - stacksize; pthread_attr_init(&thread_attr); @@ -93,30 +76,20 @@ void __libc_init_common(uintptr_t *elfdata, _init_thread(&thread, gettid(), &thread_attr, (void*)stackbottom); __init_tls(tls_area, &thread); - argc = (int) *elfdata++; - argv = (char**) elfdata; - envp = argv+(argc+1); - environ = envp; + /* clear errno - requires TLS area */ + errno = 0; + /* set program name */ __progname = argv[0] ? argv[0] : ""; - errno = 0; + /* setup environment pointer */ + environ = envp; + /* setup system properties - requires environment */ __system_properties_init(); - if (pre_ctor_hook) pre_ctor_hook(); - - // XXX: we should execute the .fini_array upon exit - - // pre-init array. - // XXX: I'm not sure what's the different with the init array. - call_array(structors->preinit_array); - - // for compatibility with non-eabi binary, call the .ctors section - call_array(structors->ctors_array); - - // call static constructors - call_array(structors->init_array); - - exit(slingshot(argc, argv, envp)); + /* setup malloc leak checker, requires system properties */ +#if MALLOC_LEAK_CHECK + malloc_debug_init(); +#endif } diff --git a/libc/bionic/libc_init_common.h b/libc/bionic/libc_init_common.h index bbc82e4..8663c61 100644 --- a/libc/bionic/libc_init_common.h +++ b/libc/bionic/libc_init_common.h @@ -38,10 +38,6 @@ typedef struct void (**ctors_array)(void); } structors_array_t; -extern __noreturn void __libc_init_common(uintptr_t *elfdata, - void (*onexit)(void), - int (*slingshot)(int, char**, char**), - structors_array_t const * const structors, - void (*pre_ctor_hook)()); +extern void __libc_init_common(uintptr_t *elfdata); #endif diff --git a/libc/bionic/libc_init_dynamic.c b/libc/bionic/libc_init_dynamic.c index 8cf24b4..b8e1078 100644 --- a/libc/bionic/libc_init_dynamic.c +++ b/libc/bionic/libc_init_dynamic.c @@ -26,41 +26,74 @@ * SUCH DAMAGE. */ /* - * libc_init_static.c + * libc_init_dynamic.c * - * This function takes the raw data block set up by the ELF loader - * in the kernel and parses it. It is invoked by crt0.S which makes - * any necessary adjustments and passes calls this function using - * the standard C calling convention. + * This source files provides two important functions for dynamic + * executables: * - * The arguments are: - * uintptr_t *elfdata -- The ELF loader data block; usually from the stack. - * Basically a pointer to argc. - * void (*onexit)(void) -- Function to install into onexit - */ - -/* - * Several Linux ABIs don't pass the onexit pointer, and the ones that - * do never use it. Therefore, unless USE_ONEXIT is defined, we just - * ignore the onexit pointer. + * - a C runtime initializer (__libc_preinit), which is called by + * the dynamic linker when libc.so is loaded. This happens before + * any other initializer (e.g. static C++ constructors in other + * shared libraries the program depends on). + * + * - a program launch function (__libc_init), which is called after + * all dynamic linking has been performed. Technically, it is called + * from arch-$ARCH/bionic/crtbegin_dynamic.S which is itself called + * by the dynamic linker after all libraries have been loaded and + * initialized. */ -/* #define USE_ONEXIT */ #include #include #include #include #include -#include "pthread_internal.h" #include "atexit.h" #include "libc_init_common.h" +#include extern void malloc_debug_init(); +/* We flag the __libc_preinit function as a constructor to ensure + * that its address is listed in libc.so's .init_array section. + * This ensures that the function is called by the dynamic linker + * as soon as the shared library is loaded. + */ +void __attribute__((constructor)) __libc_prenit(void); + +void __libc_prenit(void) +{ + /* Read the ELF data pointer form a special slot of the + * TLS area, then call __libc_init_common with it. + * + * Note that: + * - we clear the slot so no other initializer sees its value. + * - __libc_init_common() will change the TLS area so the old one + * won't be accessible anyway. + */ + void** tls_area = (void**)__get_tls(); + unsigned* elfdata = tls_area[TLS_SLOT_BIONIC_PREINIT]; + + tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL; + + __libc_init_common(elfdata); +} + __noreturn void __libc_init(uintptr_t *elfdata, void (*onexit)(void), int (*slingshot)(int, char**, char**), structors_array_t const * const structors) { - __libc_init_common(elfdata, onexit, slingshot, structors, malloc_debug_init); + /* When we reach this point, all initializers have been already + * run by the dynamic linker, so ignore 'structors'. + */ + int argc = (int)*elfdata; + char** argv = (char**)(elfdata + 1); + char** envp = argv + argc + 1; + + /* Several Linux ABIs don't pass the onexit pointer, and the ones that + * do never use it. Therefore, we ignore it. + */ + + exit(slingshot(argc, argv, envp)); } diff --git a/libc/bionic/libc_init_static.c b/libc/bionic/libc_init_static.c index ec463f7..d097b6b 100644 --- a/libc/bionic/libc_init_static.c +++ b/libc/bionic/libc_init_static.c @@ -28,24 +28,15 @@ /* * libc_init_static.c * - * This function takes the raw data block set up by the ELF loader - * in the kernel and parses it. It is invoked by crt0.S which makes - * any necessary adjustments and passes calls this function using - * the standard C calling convention. + * The program startup function __libc_init() defined here is + * used for static executables only (i.e. those that don't depend + * on shared libraries). It is called from arch-$ARCH/bionic/crtbegin_static.S + * which is directly invoked by the kernel when the program is launched. * - * The arguments are: - * uintptr_t *elfdata -- The ELF loader data block; usually from the stack. - * Basically a pointer to argc. - * void (*onexit)(void) -- Function to install into onexit + * The 'structors' parameter contains pointers to various initializer + * arrays that must be run before the program's 'main' routine is launched. */ -/* - * Several Linux ABIs don't pass the onexit pointer, and the ones that - * do never use it. Therefore, unless USE_ONEXIT is defined, we just - * ignore the onexit pointer. - */ -/* #define USE_ONEXIT */ - #include #include #include @@ -58,19 +49,41 @@ #include #include +static void call_array(void(**list)()) +{ + // First element is -1, list is null-terminated + while (*++list) { + (*list)(); + } +} + __noreturn void __libc_init(uintptr_t *elfdata, void (*onexit)(void), int (*slingshot)(int, char**, char**), structors_array_t const * const structors) { -/* - * To enable malloc checks for statically linked programs, add - * "WITH_MALLOC_CHECK_LIBC_A := true" in device/buildspec.mk - */ -#ifdef MALLOC_LEAK_CHECK - extern void malloc_debug_init(); - __libc_init_common(elfdata, onexit, slingshot, structors, malloc_debug_init); -#else - __libc_init_common(elfdata, onexit, slingshot, structors, NULL); -#endif + int argc; + char **argv, **envp; + + /* Initialize the C runtime environment */ + __libc_init_common(elfdata); + + /* Several Linux ABIs don't pass the onexit pointer, and the ones that + * do never use it. Therefore, we ignore it. + */ + + /* pre-init array. */ + call_array(structors->preinit_array); + + /* .ctors section initializers, for non-arm-eabi ABIs */ + call_array(structors->ctors_array); + + // call static constructors + call_array(structors->init_array); + + argc = (int) *elfdata; + argv = (char**)(elfdata + 1); + envp = argv + argc + 1; + + exit(slingshot(argc, argv, envp)); } -- cgit v1.1 From 39f3745cf30efe38482ffead1c32f4e62f6fe32e Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Tue, 21 Jul 2009 15:25:23 -0700 Subject: Restore malloc debug. Some libc changes were preventing the initialization call from being made. The basic problem appears to be that libc_init_common.c is only built once, and it's only built for the non-debug libc. --- libc/bionic/libc_init_common.c | 9 --------- libc/bionic/libc_init_dynamic.c | 7 +++++++ libc/bionic/libc_init_static.c | 6 ++++++ libc/bionic/malloc_leak.c | 15 ++++++++------- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/libc/bionic/libc_init_common.c b/libc/bionic/libc_init_common.c index c77c162..d78d673 100644 --- a/libc/bionic/libc_init_common.c +++ b/libc/bionic/libc_init_common.c @@ -52,10 +52,6 @@ unsigned int __page_shift = PAGE_SHIFT; int __system_properties_init(void); -#ifdef MALLOCK_LEAK_CHECK -void malloc_debug_init(void); -#endif - void __libc_init_common(uintptr_t *elfdata) { int argc = *elfdata; @@ -87,9 +83,4 @@ void __libc_init_common(uintptr_t *elfdata) /* setup system properties - requires environment */ __system_properties_init(); - - /* setup malloc leak checker, requires system properties */ -#if MALLOC_LEAK_CHECK - malloc_debug_init(); -#endif } diff --git a/libc/bionic/libc_init_dynamic.c b/libc/bionic/libc_init_dynamic.c index b8e1078..b479b27 100644 --- a/libc/bionic/libc_init_dynamic.c +++ b/libc/bionic/libc_init_dynamic.c @@ -77,6 +77,13 @@ void __libc_prenit(void) tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL; __libc_init_common(elfdata); + +#ifdef MALLOC_LEAK_CHECK + /* setup malloc leak checker, requires system properties */ + extern void malloc_debug_init(void); + malloc_debug_init(); +#endif + } __noreturn void __libc_init(uintptr_t *elfdata, diff --git a/libc/bionic/libc_init_static.c b/libc/bionic/libc_init_static.c index d097b6b..e6264bb 100644 --- a/libc/bionic/libc_init_static.c +++ b/libc/bionic/libc_init_static.c @@ -68,6 +68,12 @@ __noreturn void __libc_init(uintptr_t *elfdata, /* Initialize the C runtime environment */ __libc_init_common(elfdata); +#ifdef MALLOC_LEAK_CHECK + /* setup malloc leak checker, requires system properties */ + extern void malloc_debug_init(void); + malloc_debug_init(); +#endif + /* Several Linux ABIs don't pass the onexit pointer, and the ones that * do never use it. Therefore, we ignore it. */ diff --git a/libc/bionic/malloc_leak.c b/libc/bionic/malloc_leak.c index df09424..305f954 100644 --- a/libc/bionic/malloc_leak.c +++ b/libc/bionic/malloc_leak.c @@ -91,7 +91,14 @@ static pthread_mutex_t gAllocationsMutex = PTHREAD_MUTEX_INITIALIZER; static HashTable gHashTable; // ============================================================================= -// output fucntions +// log functions +// ============================================================================= + +#define debug_log(format, ...) \ + __libc_android_log_print(ANDROID_LOG_DEBUG, "malloc_leak", (format), ##__VA_ARGS__ ) + +// ============================================================================= +// output functions // ============================================================================= static int hash_entry_compare(const void* arg1, const void* arg2) @@ -257,12 +264,6 @@ struct AllocationEntry { uint32_t guard; }; -// ============================================================================= -// log funtions -// ============================================================================= - -#define debug_log(format, ...) \ - __libc_android_log_print(ANDROID_LOG_DEBUG, "malloc_leak", (format), ##__VA_ARGS__ ) // ============================================================================= // Hash Table functions -- cgit v1.1 From d00d23a9d4598108d7f498291b35c7730e48cf5c Mon Sep 17 00:00:00 2001 From: Erik Gilling Date: Wed, 22 Jul 2009 17:06:11 -0700 Subject: linker: remove newlines from DL_ERR so that dlerror works correctly Signed-off-by: Erik Gilling --- linker/linker.c | 68 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/linker/linker.c b/linker/linker.c index e235498..0c1af9d 100644 --- a/linker/linker.c +++ b/linker/linker.c @@ -123,7 +123,7 @@ static char __linker_dl_err_buf[768]; do { \ snprintf(__linker_dl_err_buf, sizeof(__linker_dl_err_buf), \ "%s[%d]: " fmt, __func__, __LINE__, ##x); \ - ERROR(fmt, ##x); \ + ERROR(fmt "\n", ##x); \ } while(0) const char *linker_get_error(void) @@ -234,7 +234,7 @@ static soinfo *alloc_info(const char *name) soinfo *si; if(strlen(name) >= SOINFO_NAME_LEN) { - DL_ERR("%5d library name %s too long\n", pid, name); + DL_ERR("%5d library name %s too long", pid, name); return 0; } @@ -243,7 +243,7 @@ static soinfo *alloc_info(const char *name) */ if (!freelist) { if(socount == SO_MAX) { - DL_ERR("%5d too many libraries when loading %s\n", pid, name); + DL_ERR("%5d too many libraries when loading %s", pid, name); return NULL; } freelist = sopool + socount++; @@ -279,7 +279,7 @@ static void free_info(soinfo *si) } if (trav == NULL) { /* si was not ni solist */ - DL_ERR("%5d name %s is not in solist!\n", pid, si->name); + DL_ERR("%5d name %s is not in solist!", pid, si->name); return; } @@ -560,7 +560,7 @@ is_prelinked(int fd, const char *name) sz = lseek(fd, -sizeof(prelink_info_t), SEEK_END); if (sz < 0) { - DL_ERR("lseek() failed!\n"); + DL_ERR("lseek() failed!"); return 0; } @@ -636,7 +636,7 @@ get_lib_extents(int fd, const char *name, void *__hdr, unsigned *total_sz) TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name); if (verify_elf_object(_hdr, name) < 0) { - DL_ERR("%5d - %s is not a valid ELF object\n", pid, name); + DL_ERR("%5d - %s is not a valid ELF object", pid, name); return (unsigned)-1; } @@ -664,7 +664,7 @@ get_lib_extents(int fd, const char *name, void *__hdr, unsigned *total_sz) } if ((min_vaddr == 0xffffffff) && (max_vaddr == 0)) { - DL_ERR("%5d - No loadable segments found in %s.\n", pid, name); + DL_ERR("%5d - No loadable segments found in %s.", pid, name); return (unsigned)-1; } @@ -701,13 +701,13 @@ static int reserve_mem_region(soinfo *si) MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (base == MAP_FAILED) { DL_ERR("%5d can NOT map (%sprelinked) library '%s' at 0x%08x " - "as requested, will try general pool: %d (%s)\n", + "as requested, will try general pool: %d (%s)", pid, (si->base ? "" : "non-"), si->name, si->base, errno, strerror(errno)); return -1; } else if (base != (void *)si->base) { DL_ERR("OOPS: %5d %sprelinked library '%s' mapped at 0x%08x, " - "not at 0x%08x\n", pid, (si->base ? "" : "non-"), + "not at 0x%08x", pid, (si->base ? "" : "non-"), si->name, (unsigned)base, si->base); munmap(base, si->size); return -1; @@ -744,7 +744,7 @@ alloc_mem_region(soinfo *si) } err: - DL_ERR("OOPS: %5d cannot map library '%s'. no vspace available.\n", + DL_ERR("OOPS: %5d cannot map library '%s'. no vspace available.", pid, si->name); return -1; } @@ -804,7 +804,7 @@ load_segments(int fd, void *header, soinfo *si) phdr->p_offset & (~PAGE_MASK)); if (pbase == MAP_FAILED) { DL_ERR("%d failed to map segment from '%s' @ 0x%08x (0x%08x). " - "p_vaddr=0x%08x p_offset=0x%08x\n", pid, si->name, + "p_vaddr=0x%08x p_offset=0x%08x", pid, si->name, (unsigned)tmp, len, phdr->p_vaddr, phdr->p_offset); goto fail; } @@ -860,7 +860,7 @@ load_segments(int fd, void *header, soinfo *si) -1, 0); if (extra_base == MAP_FAILED) { DL_ERR("[ %5d - failed to extend segment from '%s' @ 0x%08x" - " (0x%08x) ]\n", pid, si->name, (unsigned)tmp, + " (0x%08x) ]", pid, si->name, (unsigned)tmp, extra_len); goto fail; } @@ -913,7 +913,7 @@ load_segments(int fd, void *header, soinfo *si) /* Sanity check */ if (total_sz > si->size) { DL_ERR("%5d - Total length (0x%08x) of mapped segments from '%s' is " - "greater than what was allocated (0x%08x). THIS IS BAD!\n", + "greater than what was allocated (0x%08x). THIS IS BAD!", pid, total_sz, si->name, si->size); goto fail; } @@ -980,19 +980,19 @@ load_library(const char *name) Elf32_Ehdr *hdr; if(fd == -1) { - DL_ERR("Library '%s' not found\n", name); + DL_ERR("Library '%s' not found", name); return NULL; } /* We have to read the ELF header to figure out what to do with this image */ if (lseek(fd, 0, SEEK_SET) < 0) { - DL_ERR("lseek() failed!\n"); + DL_ERR("lseek() failed!"); goto fail; } if ((cnt = read(fd, &__header[0], PAGE_SIZE)) < 0) { - DL_ERR("read() failed!\n"); + DL_ERR("read() failed!"); goto fail; } @@ -1083,7 +1083,7 @@ soinfo *find_library(const char *name) if(!strcmp(name, si->name)) { if(si->flags & FLAG_ERROR) return 0; if(si->flags & FLAG_LINKED) return si; - DL_ERR("OOPS: %5d recursive link to '%s'\n", pid, si->name); + DL_ERR("OOPS: %5d recursive link to '%s'", pid, si->name); return NULL; } } @@ -1115,7 +1115,7 @@ unsigned unload_library(soinfo *si) if(lsi) unload_library(lsi); else - DL_ERR("%5d could not unload '%s'\n", + DL_ERR("%5d could not unload '%s'", pid, si->strtab + d[1]); } } @@ -1165,20 +1165,20 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) sym_name = (char *)(strtab + symtab[sym].st_name); s = _do_lookup(si, sym_name, &base); if(s == 0) { - DL_ERR("%5d cannot locate '%s'...\n", pid, sym_name); + DL_ERR("%5d cannot locate '%s'...", pid, sym_name); return -1; } #if 0 if((base == 0) && (si->base != 0)){ /* linking from libraries to main image is bad */ - DL_ERR("%5d cannot locate '%s'...\n", + DL_ERR("%5d cannot locate '%s'...", pid, strtab + symtab[sym].st_name); return -1; } #endif if ((s->st_shndx == SHN_UNDEF) && (s->st_value != 0)) { DL_ERR("%5d In '%s', shndx=%d && value=0x%08x. We do not " - "handle this yet\n", pid, si->name, s->st_shndx, + "handle this yet", pid, si->name, s->st_shndx, s->st_value); return -1; } @@ -1239,7 +1239,7 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) COUNT_RELOC(RELOC_RELATIVE); MARK(rel->r_offset); if(sym){ - DL_ERR("%5d odd RELATIVE form...\n", pid); + DL_ERR("%5d odd RELATIVE form...", pid); return -1; } TRACE_TYPE(RELO, "%5d RELO RELATIVE %08x <- +%08x\n", pid, @@ -1280,7 +1280,7 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) #endif /* ANDROID_ARM_LINKER */ default: - DL_ERR("%5d unknown reloc type %d @ %p (%d)\n", + DL_ERR("%5d unknown reloc type %d @ %p (%d)", pid, type, rel, (int) (rel - start)); return -1; } @@ -1338,7 +1338,7 @@ static void call_constructors(soinfo *si) } else { if (si->preinit_array) { DL_ERR("%5d Shared library '%s' has a preinit_array table @ 0x%08x." - " This is INVALID.\n", pid, si->name, + " This is INVALID.", pid, si->name, (unsigned)si->preinit_array); } } @@ -1385,7 +1385,7 @@ static int nullify_closed_stdio (void) dev_null = open("/dev/null", O_RDWR); if (dev_null < 0) { - DL_ERR("Cannot open /dev/null.\n"); + DL_ERR("Cannot open /dev/null."); return -1; } TRACE("[ %5d Opened /dev/null file-descriptor=%d]\n", pid, dev_null); @@ -1411,7 +1411,7 @@ static int nullify_closed_stdio (void) /* The only error we allow is that the file descriptor does not exist, in which case we dup /dev/null to it. */ if (errno != EBADF) { - DL_ERR("nullify_stdio: unhandled error %s\n", strerror(errno)); + DL_ERR("nullify_stdio: unhandled error %s", strerror(errno)); return_value = -1; continue; } @@ -1424,7 +1424,7 @@ static int nullify_closed_stdio (void) } while (status < 0 && errno == EINTR); if (status < 0) { - DL_ERR("nullify_stdio: dup2 error %s\n", strerror(errno)); + DL_ERR("nullify_stdio: dup2 error %s", strerror(errno)); return_value = -1; continue; } @@ -1438,7 +1438,7 @@ static int nullify_closed_stdio (void) } while (status < 0 && errno == EINTR); if (status < 0) { - DL_ERR("nullify_stdio: close error %s\n", strerror(errno)); + DL_ERR("nullify_stdio: close error %s", strerror(errno)); return_value = -1; } } @@ -1507,7 +1507,7 @@ static int link_image(soinfo *si, unsigned wr_offset) } else if (phdr->p_type == PT_DYNAMIC) { if (si->dynamic != (unsigned *)-1) { DL_ERR("%5d multiple PT_DYNAMIC segments found in '%s'. " - "Segment at 0x%08x, previously one found at 0x%08x\n", + "Segment at 0x%08x, previously one found at 0x%08x", pid, si->name, si->base + phdr->p_vaddr, (unsigned)si->dynamic); goto fail; @@ -1519,7 +1519,7 @@ static int link_image(soinfo *si, unsigned wr_offset) } if (si->dynamic == (unsigned *)-1) { - DL_ERR("%5d missing PT_DYNAMIC?!\n", pid); + DL_ERR("%5d missing PT_DYNAMIC?!", pid); goto fail; } @@ -1543,7 +1543,7 @@ static int link_image(soinfo *si, unsigned wr_offset) break; case DT_PLTREL: if(*d != DT_REL) { - DL_ERR("DT_RELA not supported\n"); + DL_ERR("DT_RELA not supported"); goto fail; } break; @@ -1568,7 +1568,7 @@ static int link_image(soinfo *si, unsigned wr_offset) *d = (int) &_r_debug; break; case DT_RELA: - DL_ERR("%5d DT_RELA not supported\n", pid); + DL_ERR("%5d DT_RELA not supported", pid); goto fail; case DT_INIT: si->init_func = (void (*)(void))(si->base + *d); @@ -1620,7 +1620,7 @@ static int link_image(soinfo *si, unsigned wr_offset) pid, si->base, si->strtab, si->symtab); if((si->strtab == 0) || (si->symtab == 0)) { - DL_ERR("%5d missing essential tables\n", pid); + DL_ERR("%5d missing essential tables", pid); goto fail; } @@ -1630,7 +1630,7 @@ static int link_image(soinfo *si, unsigned wr_offset) soinfo *lsi = find_library(si->strtab + d[1]); if(lsi == 0) { strlcpy(tmp_err_buf, linker_get_error(), sizeof(tmp_err_buf)); - DL_ERR("%5d could not load needed library '%s' for '%s' (%s)\n", + DL_ERR("%5d could not load needed library '%s' for '%s' (%s)", pid, si->strtab + d[1], si->name, tmp_err_buf); goto fail; } -- cgit v1.1 From 3773d35eb98e22b5edab4d82fb72bdf86ff80494 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Mon, 27 Jul 2009 19:19:29 +0200 Subject: Make the DNS resolver accept domain names with an underscore. More precisely, this accepts domain labels with an underscore in the middle (i.e. not at the start or the end of the label). This is needed to perform complex CNAME chain resolution in certain VPN networks. --- libc/netbsd/resolv/res_comp.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libc/netbsd/resolv/res_comp.c b/libc/netbsd/resolv/res_comp.c index 6991e8b..77b81b4 100644 --- a/libc/netbsd/resolv/res_comp.c +++ b/libc/netbsd/resolv/res_comp.c @@ -147,6 +147,12 @@ dn_skipname(const u_char *ptr, const u_char *eom) { * tell us anything about network-format data. The rest of the BIND system * is not careful about this, but for some reason, we're doing it right here. */ + +/* BIONIC: We also accept underscores in the middle of labels. + * This extension is needed to make resolution on some VPN networks + * work properly. + */ + #define PERIOD 0x2e #define hyphenchar(c) ((c) == 0x2d) #define bslashchar(c) ((c) == 0x5c) @@ -155,9 +161,10 @@ dn_skipname(const u_char *ptr, const u_char *eom) { #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ || ((c) >= 0x61 && (c) <= 0x7a)) #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) +#define underscorechar(c) ((c) == 0x5f) #define borderchar(c) (alphachar(c) || digitchar(c)) -#define middlechar(c) (borderchar(c) || hyphenchar(c)) +#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c)) #define domainchar(c) ((c) > 0x20 && (c) < 0x7f) int -- cgit v1.1 From fde8642fc43bdd224e43e5ee9583a49a758fb03c Mon Sep 17 00:00:00 2001 From: Erik Gilling Date: Tue, 28 Jul 2009 20:28:19 -0700 Subject: bionic/linker: keep track of opened libraries by basename Prior to this change, the dynamic loader kept track of opened libraries either by their base name (i.e., libfoo.so instead of /system/lib/libfoo.so) when the shared library was loaded through the DT_NEEDED tag in an ELF header, or by whatever name was passed to dlopen(). This created a number of problems, among which: 1. dlopen("libfoo.so") and dlopen("/path/to/libfoo.so") would open the same library twice; 2. dlopen("/path/to/libfoo.so") and then dlopen("libbar.so"), where libbar.so depends on libfoo.so, would open libfoo.so twice. This patch makes the dynamic loader keep track of each loaded library by basename, which resolves the above ambiguity. The patch also enforces library lookup by base name, which means that it will refuse to load another library that has the same name. Thanks for the inspiration Iliyan. Signed-off-by: Erik Gilling Cc: Iliyan Malchev --- linker/linker.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/linker/linker.c b/linker/linker.c index 0c1af9d..789a828 100644 --- a/linker/linker.c +++ b/linker/linker.c @@ -976,6 +976,7 @@ load_library(const char *name) int cnt; unsigned ext_sz; unsigned req_base; + const char *bname; soinfo *si = NULL; Elf32_Ehdr *hdr; @@ -1009,7 +1010,8 @@ load_library(const char *name) * same thing would happen if we failed during linking. Configuring the * soinfo struct here is a lot more convenient. */ - si = alloc_info(name); + bname = strrchr(name, '/'); + si = alloc_info(bname ? bname + 1 : name); if (si == NULL) goto fail; @@ -1078,9 +1080,11 @@ init_library(soinfo *si) soinfo *find_library(const char *name) { soinfo *si; + const char *bname = strrchr(name, '/'); + bname = bname ? bname + 1 : name; for(si = solist; si != 0; si = si->next){ - if(!strcmp(name, si->name)) { + if(!strcmp(bname, si->name)) { if(si->flags & FLAG_ERROR) return 0; if(si->flags & FLAG_LINKED) return si; DL_ERR("OOPS: %5d recursive link to '%s'", pid, si->name); -- cgit v1.1