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/*
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * libc_init_static.c
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
31b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * The program startup function __libc_init() defined here is
32b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * used for static executables only (i.e. those that don't depend
33b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * on shared libraries). It is called from arch-$ARCH/bionic/crtbegin_static.S
34b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * which is directly invoked by the kernel when the program is launched.
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
36b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * The 'structors' parameter contains pointers to various initializer
37b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner * arrays that must be run before the program's 'main' routine is launched.
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stddef.h>
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdint.h>
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <elf.h>
453a654b1e04d4275ae315cfe1b196998acf10052cDavid 'Digit' Turner#include "pthread_internal.h"
463a654b1e04d4275ae315cfe1b196998acf10052cDavid 'Digit' Turner#include "atexit.h"
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "libc_init_common.h"
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
493a654b1e04d4275ae315cfe1b196998acf10052cDavid 'Digit' Turner#include <bionic_tls.h>
503a654b1e04d4275ae315cfe1b196998acf10052cDavid 'Digit' Turner#include <errno.h>
513a654b1e04d4275ae315cfe1b196998acf10052cDavid 'Digit' Turner
52b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turnerstatic void call_array(void(**list)())
53b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner{
54b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    // First element is -1, list is null-terminated
55b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    while (*++list) {
56b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner        (*list)();
57b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    }
58b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner}
59b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__noreturn void __libc_init(uintptr_t *elfdata,
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                       void (*onexit)(void),
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                       int (*slingshot)(int, char**, char**),
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                       structors_array_t const * const structors)
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
65b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    int  argc;
66b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    char **argv, **envp;
67b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner
681a78fbb5c8228e4aea2a516818828b76044310f2Evgeniy Stepanov    __libc_init_tls(NULL);
691a78fbb5c8228e4aea2a516818828b76044310f2Evgeniy Stepanov
70b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    /* Initialize the C runtime environment */
71b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    __libc_init_common(elfdata);
72b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner
73b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    /* Several Linux ABIs don't pass the onexit pointer, and the ones that
74b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner     * do never use it.  Therefore, we ignore it.
75b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner     */
76b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner
77b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    /* pre-init array. */
78b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    call_array(structors->preinit_array);
79b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner
80b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    // call static constructors
81b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    call_array(structors->init_array);
82b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner
83b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    argc = (int) *elfdata;
84b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    argv = (char**)(elfdata + 1);
85b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    envp = argv + argc + 1;
86b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner
871df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner    /* The executable may have its own destructors listed in its .fini_array
881df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner     * so we need to ensure that these are called when the program exits
891df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner     * normally.
901df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner     */
911df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner    if (structors->fini_array)
921df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner        __cxa_atexit(__libc_fini,structors->fini_array,NULL);
931df986c21ee52c6756846b4a5e45cb316f772112David 'Digit' Turner
94b56b5659b3996e98c2060f168d1cff1474e77d2aDavid 'Digit' Turner    exit(slingshot(argc, argv, envp));
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
96