11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved. 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions of source code must retain the above copyright 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions in binary form must reproduce the above copyright 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the documentation and/or other materials provided with the 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * distribution. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 29b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * libc_init_dynamic.c 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 31b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * This source files provides two important functions for dynamic 32b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * executables: 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 34b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * - a C runtime initializer (__libc_preinit), which is called by 35b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * the dynamic linker when libc.so is loaded. This happens before 36b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * any other initializer (e.g. static C++ constructors in other 37b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * shared libraries the program depends on). 38b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * 39b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * - a program launch function (__libc_init), which is called after 40b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * all dynamic linking has been performed. Technically, it is called 41b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * from arch-$ARCH/bionic/crtbegin_dynamic.S which is itself called 42b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * by the dynamic linker after all libraries have been loaded and 43b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * initialized. 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stddef.h> 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h> 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h> 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdint.h> 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <elf.h> 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "atexit.h" 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "libc_init_common.h" 53b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner#include <bionic_tls.h> 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 55b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner/* We flag the __libc_preinit function as a constructor to ensure 56b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * that its address is listed in libc.so's .init_array section. 57b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * This ensures that the function is called by the dynamic linker 58b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * as soon as the shared library is loaded. 59b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner */ 601df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turnervoid __attribute__((constructor)) __libc_preinit(void); 61b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner 621df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turnervoid __libc_preinit(void) 63b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner{ 642bf607d599b703604cb1caf5beeb2e70c44682fbChris Peterson /* Read the ELF data pointer from a special slot of the 65b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * TLS area, then call __libc_init_common with it. 66b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * 67b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * Note that: 68b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * - we clear the slot so no other initializer sees its value. 69b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * - __libc_init_common() will change the TLS area so the old one 70b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * won't be accessible anyway. 71b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner */ 72b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner void** tls_area = (void**)__get_tls(); 73b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner unsigned* elfdata = tls_area[TLS_SLOT_BIONIC_PREINIT]; 74b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner 75b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL; 76b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner 77b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner __libc_init_common(elfdata); 7839f3745cf30efe38482ffead1c32f4e62f6fe32eAndy McFadden 797c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian /* Setup pthread routines accordingly to the environment. 807c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian * Requires system properties 817c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian */ 827c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian extern void pthread_debug_init(void); 837c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian pthread_debug_init(); 847c0c3793722aea293c45921ef50e4adcdf9645ceMathias Agopian 85b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine /* Setup malloc routines accordingly to the environment. 86b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine * Requires system properties 87b74ceb25aae555570df64fa4d4076272733a9a20Vladimir Chtchetkine */ 8839f3745cf30efe38482ffead1c32f4e62f6fe32eAndy McFadden extern void malloc_debug_init(void); 8939f3745cf30efe38482ffead1c32f4e62f6fe32eAndy McFadden malloc_debug_init(); 90b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner} 91b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner 92e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchevvoid __libc_postfini(void) 93e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev{ 94e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev extern void malloc_debug_fini(void); 95e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev malloc_debug_fini(); 96e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev} 97e1dd3c287ba836281de0197670018bd9bbfbd62bIliyan Malchev 981df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner/* This function is called from the executable's _start entry point 991df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner * (see arch-$ARCH/bionic/crtbegin_dynamic.S), which is itself 1001df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner * called by the dynamic linker after it has loaded all shared 1011df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner * libraries the executable depends on. 1021df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner * 1031df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner * Note that the dynamic linker has also run all constructors in the 1041df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner * executable at this point. 1051df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner */ 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__noreturn void __libc_init(uintptr_t *elfdata, 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project void (*onexit)(void), 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int (*slingshot)(int, char**, char**), 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project structors_array_t const * const structors) 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 111b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner int argc = (int)*elfdata; 112b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner char** argv = (char**)(elfdata + 1); 113b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner char** envp = argv + argc + 1; 114b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner 115b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner /* Several Linux ABIs don't pass the onexit pointer, and the ones that 116b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * do never use it. Therefore, we ignore it. 117b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner */ 118b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner 1191df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner /* The executable may have its own destructors listed in its .fini_array 1201df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner * so we need to ensure that these are called when the program exits 1211df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner * normally. 1221df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner */ 1231df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner if (structors->fini_array) 1241df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner __cxa_atexit(__libc_fini,structors->fini_array,NULL); 1251df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner 126b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner exit(slingshot(argc, argv, envp)); 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 128