blob: e3277770bcacb11aeee6e3b7002193e93910f7af [file] [log] [blame]
/*
* Copyright (C) 2008 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 <compiler.h>
#include <stddef.h>
#include <trusty_std.h>
#include "libc_fatal.h"
#include "libc_init.h"
#include "atexit.h"
static void call_array(void(**list)(void)) {
// First element is -1, list is null-terminated
while (*++list) {
(*list)();
}
}
__NO_RETURN void __libc_init(void *args,
int (*slingshot)(int, char**, char**),
structors_array_t const * const structors)
{
int ret;
call_array(structors->preinit_array);
call_array(structors->init_array);
if (structors->fini_array != NULL) {
ret = __cxa_atexit(__libc_fini, structors->fini_array);
if (ret)
__libc_fatal("__cxa_atexit failed\n");
}
exit(slingshot(0, NULL, NULL));
}
/* This function will be called during normal program termination
* to run the destructors that are listed in the .fini_array section
* of the executable, if any.
*
* 'fini_array' points to a list of function addresses. The first
* entry in the list has value -1, the last one has value 0.
*/
void __libc_fini(void* array) {
void** fini_array = (void **)array;
const size_t minus1 = ~(size_t)0; /* ensure proper sign extension */
/* Sanity check - first entry must be -1 */
if (array == NULL || (size_t)fini_array[0] != minus1) {
return;
}
/* skip over it */
fini_array += 1;
/* Count the number of destructors. */
int count = 0;
while (fini_array[count] != NULL) {
++count;
}
/* Now call each destructor in reverse order. */
while (count > 0) {
void (*func)(void) = (void (*)(void)) fini_array[--count];
/* Sanity check, any -1 in the list is ignored */
if ((size_t)func == minus1) {
continue;
}
func();
}
}