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