From f3cfcd869ded41d25c1f4f4e48e7c374a64f9583 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 21 Aug 2012 14:13:50 +0200 Subject: [PATCH] ARM: make CRT_LEGACY_WORKAROUND work as intended To properly support legacy ARM shared libraries, libc.so needs to export the symbols __dso_handle and atexit, even though these are now supplied by the crt startup code. This patch reshuffles the existing CRT_LEGACY_WORKAROUND conditionally compiled code slightly so it works as the original author likely intended. Change-Id: Id6c0e94dc65b7928324a5f0bad7eba6eb2f464b9 Signed-off-by: Ard Biesheuvel --- libc/Android.mk | 18 ++++++----- libc/arch-arm/bionic/atexit.h | 18 ----------- libc/arch-arm/bionic/atexit_legacy.c | 46 ++++++++++++++++++++++++++++ libc/arch-arm/bionic/crtbegin_so.c | 21 +++++++++++-- libc/arch-arm/bionic/eabi.c | 16 ---------- libc/private/__dso_handle_so.c | 2 +- libc/stdlib/atexit.c | 11 ------- 7 files changed, 76 insertions(+), 56 deletions(-) create mode 100644 libc/arch-arm/bionic/atexit_legacy.c diff --git a/libc/Android.mk b/libc/Android.mk index 04301ef39..f20e67165 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -584,10 +584,6 @@ libc_crt_target_cflags += \ -I$(LOCAL_PATH)/include \ -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) -ifeq ($(TARGET_ARCH),arm) - libc_crt_target_cflags += -DCRT_LEGACY_WORKAROUND -endif - # Define some common includes # ======================================================== libc_common_c_includes := \ @@ -762,9 +758,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(libc_common_src_files) LOCAL_CFLAGS := $(libc_common_cflags) -ifeq ($(TARGET_ARCH),arm) - LOCAL_CFLAGS += -DCRT_LEGACY_WORKAROUND -endif LOCAL_C_INCLUDES := $(libc_common_c_includes) LOCAL_MODULE := libc_common LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk @@ -848,6 +841,17 @@ LOCAL_SRC_FILES := \ bionic/pthread_debug.c \ bionic/libc_init_dynamic.c +ifeq ($(TARGET_ARCH),arm) + LOCAL_NO_CRT := true + LOCAL_CFLAGS += -DCRT_LEGACY_WORKAROUND + + LOCAL_SRC_FILES := \ + arch-arm/bionic/crtbegin_so.c \ + arch-arm/bionic/atexit_legacy.c \ + $(LOCAL_SRC_FILES) \ + arch-arm/bionic/crtend_so.S +endif + LOCAL_MODULE:= libc LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk diff --git a/libc/arch-arm/bionic/atexit.h b/libc/arch-arm/bionic/atexit.h index d567bfc2c..bc776a8b4 100644 --- a/libc/arch-arm/bionic/atexit.h +++ b/libc/arch-arm/bionic/atexit.h @@ -26,23 +26,6 @@ * SUCH DAMAGE. */ -/* CRT_LEGACY_WORKAROUND should only be defined when building - * this file as part of the platform's C library. - * - * The C library already defines a function named 'atexit()' - * for backwards compatibility with older NDK-generated binaries. - * - * For newer ones, 'atexit' is actually embedded in the C - * runtime objects that are linked into the final ELF - * binary (shared library or executable), and will call - * __cxa_atexit() in order to un-register any atexit() - * handler when a library is unloaded. - * - * This function must be global *and* hidden. Only the - * code inside the same ELF binary should be able to access it. - */ - -#ifndef CRT_LEGACY_WORKAROUND extern void *__dso_handle; __attribute__ ((visibility ("hidden"))) @@ -50,4 +33,3 @@ int atexit(void (*func)(void)) { return (__cxa_atexit((void (*)(void *))func, (void *)0, &__dso_handle)); } -#endif diff --git a/libc/arch-arm/bionic/atexit_legacy.c b/libc/arch-arm/bionic/atexit_legacy.c new file mode 100644 index 000000000..09da17cbc --- /dev/null +++ b/libc/arch-arm/bionic/atexit_legacy.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012 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. + */ + +#include + +/* + * This source file should only be included by libc.so, its purpose is + * to support legacy ARM binaries by exporting a publicly visible + * implementation of atexit(). + */ + +extern int __cxa_atexit(void (*func)(void *), void *arg, void *dso); + +/* + * Register a function to be performed at exit. + */ +int +atexit(void (*func)(void)) +{ + return (__cxa_atexit((void (*)(void *))func, NULL, NULL)); +} diff --git a/libc/arch-arm/bionic/crtbegin_so.c b/libc/arch-arm/bionic/crtbegin_so.c index 57d19bf30..36e4b9cff 100644 --- a/libc/arch-arm/bionic/crtbegin_so.c +++ b/libc/arch-arm/bionic/crtbegin_so.c @@ -34,10 +34,25 @@ void __on_dlclose() { __cxa_finalize(&__dso_handle); } +/* CRT_LEGACY_WORKAROUND should only be defined when building + * this file as part of the platform's C library. + * + * The C library already defines a function named 'atexit()' + * for backwards compatibility with older NDK-generated binaries. + * + * For newer ones, 'atexit' is actually embedded in the C + * runtime objects that are linked into the final ELF + * binary (shared library or executable), and will call + * __cxa_atexit() in order to un-register any atexit() + * handler when a library is unloaded. + * + * This function must be global *and* hidden. Only the + * code inside the same ELF binary should be able to access it. + */ + #ifdef CRT_LEGACY_WORKAROUND #include "__dso_handle.h" #else -#include "__dso_handle_so.h" -#endif - +#include "__dso_handle_so.c" #include "atexit.h" +#endif diff --git a/libc/arch-arm/bionic/eabi.c b/libc/arch-arm/bionic/eabi.c index 3f26f2b45..51a5b9752 100644 --- a/libc/arch-arm/bionic/eabi.c +++ b/libc/arch-arm/bionic/eabi.c @@ -30,22 +30,6 @@ extern int __cxa_atexit(void (*)(void*), void*, void* ); -/* Temporary hack: this variable should not be part of the C library - * itself, but placed in the .bss section of each executable or - * shared library instead. - * - * We keep it here temporarily until the build system has been - * modified properly to use crtbegin_so.S and crtend_so.S when - * generating shared libraries. - * - * It must be a 'weak' symbol to avoid conflicts with the definitions - * that have been moved to crtbegin_static.S and crtbegin_dynamic.S - * - * For the record, it is used for static C++ object construction - * and destruction. See http://www.codesourcery.com/public/cxx-abi/abi.html#dso-dtor - */ -void* __attribute__((weak)) __dso_handle; - /* The "C++ ABI for ARM" document states that static C++ constructors, * which are called from the .init_array, should manually call * __aeabi_atexit() to register static destructors explicitely. diff --git a/libc/private/__dso_handle_so.c b/libc/private/__dso_handle_so.c index 198e64b92..732799bf3 100644 --- a/libc/private/__dso_handle_so.c +++ b/libc/private/__dso_handle_so.c @@ -29,4 +29,4 @@ __attribute__ ((visibility ("hidden"))) __attribute__ ((section (".data"))) -void *__dso_handle; +void *__dso_handle = &__dso_handle; diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c index 55b7132e6..23a2636dc 100644 --- a/libc/stdlib/atexit.c +++ b/libc/stdlib/atexit.c @@ -104,17 +104,6 @@ unlock: return (ret); } -#ifdef CRT_LEGACY_WORKAROUND -/* - * Register a function to be performed at exit. - */ -int -atexit(void (*func)(void)) -{ - return (__cxa_atexit((void (*)(void *))func, NULL, NULL)); -} -#endif - /* * Call all handlers registered with __cxa_atexit() for the shared * object owning 'dso'.