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