Beispiel #1
0
int old_atexit(aefuncp func)
#endif
{
    /*
     * glibc casts aefuncp to cxaefuncp.
     * This seems dodgy, but I guess callling a function with more
     * parameters than it needs will work everywhere?
     */
#ifdef ARCH_HAS_MMU
    return __cxa_atexit((cxaefuncp)func, NULL,
                        &__dso_handle == NULL ? NULL : __dso_handle);
#else
    return __cxa_atexit((cxaefuncp)func, NULL, NULL);
#endif
}
/* is called by crt0 immediately before calling __main() */
void
crt0_construction(void)
{
  static_construction();
  __cxa_atexit((void (*)(void*))&static_destruction, 0,
      &__dso_handle == 0 ? 0 : __dso_handle);
}
Beispiel #3
0
int
atexit (void (*fn) (void))
{
  extern int __cxa_atexit(void (*)(void*), void*, void*);
  extern void *__dso_handle;
  extern void *__ImageBase;

  void *fixed_dso_handle = &__dso_handle;
  /* Check for being called from inside the executable.  If so, use NULL
     as __dso_handle.  This allows to link executables with GCC versions
     not providing __dso_handle in crtbegin{S}.o.  In this case our own
     __dso_handle defined in lib/dso_handle.c is used.  However, our
     __dso_handle always points to &__ImageBase, while the __dso_handle
     for executables provided by crtbegin.o usually points to NULL.
     That's what we remodel here. */
  if (&__ImageBase == (void **) GetModuleHandleW (NULL))
    fixed_dso_handle = NULL;
  /* With recent Cygwin versions starting with API version 0.280 we call
     __cxa_atexit (which is actually the cygwin__cxa_atexit wrapper in
     dcrt0.cc) with the address of __dso_handle since that's how g++ generates
     calls to __cxa_atexit as well.  However, when running an application
     built with this atexit under an older Cygwin version, the __cxa_atexit
     entry point is the one from newlib, which expects the *value* of
     __dso_handle.  So, check for the Cygwin version we're running under.
     Older version prior to 0.280 don't know CW_FIXED_ATEXIT and return -1.
     0.280 and later return 0. */
  else if (cygwin_internal (CW_FIXED_ATEXIT) != 0)
    fixed_dso_handle = __dso_handle;

  return __cxa_atexit ((void (*)(void*))fn, NULL, fixed_dso_handle);
}
__noreturn void __libc_init(void* raw_args,
                            void (*onexit)(void),
                            int (*slingshot)(int, char**, char**),
                            structors_array_t const * const structors) {
  KernelArgumentBlock args(raw_args);
  __libc_init_tls(args);
  __libc_init_common(args);

  apply_gnu_relro();

  // Several Linux ABIs don't pass the onexit pointer, and the ones that
  // do never use it.  Therefore, we ignore it.

  call_array(structors->preinit_array);
  call_array(structors->init_array);

  // The executable may have its own destructors listed in its .fini_array
  // so we need to ensure that these are called when the program exits
  // normally.
  if (structors->fini_array != NULL) {
    __cxa_atexit(__libc_fini,structors->fini_array,NULL);
  }

  exit(slingshot(args.argc, args.argv, args.envp));
}
Beispiel #5
0
void
bar (void *p)
{
  extern void *__dso_handle;
  printf ("This is %s\n", __FUNCTION__);
  __cxa_atexit (fluffy, p, __dso_handle);
}
Beispiel #6
0
// address: 8049e90
void proc2() {
    __size32 eax; 		// r24

    if (eax != 0) {
    }
    __cxa_atexit();
    return;
}
Beispiel #7
0
int
main(int argc, char *argv[])
{

	exiting_state = 5;

	ASSERT(0 == atexit(normal_handler_0));
	ASSERT(0 == atexit(normal_handler_1));
	ASSERT(0 == __cxa_atexit(cxa_handler_4, &arg_1, &dso_handle_1));
	ASSERT(0 == __cxa_atexit(cxa_handler_5, &arg_1, &dso_handle_1));
	ASSERT(0 == __cxa_atexit(cxa_handler_3, &arg_2, &dso_handle_2));
	ASSERT(0 == __cxa_atexit(cxa_handler_2, &arg_3, &dso_handle_3));

	__cxa_finalize(&dso_handle_1);
	__cxa_finalize(&dso_handle_2);
	exit(0);
}
Beispiel #8
0
// address: 8048904
void atexit() {
    __size32 edx; 		// r26

    if (edx != 0) {
    }
    __cxa_atexit();
    return;
}
int
__libc_start_main (void)
{
  /* Store the lowest stack address.  */
  __libc_stack_end = __libc_start_data.stack;

  /* Used by setenv */
  __environ = __libc_start_data.envp;

#ifndef SHARED
  /* Clear errno. */
    errno = 0;

  /* Some security at this point.  Prevent starting a SUID binary where
     the standard file descriptors are not opened.  We have to do this
     only for statically linked applications since otherwise the dynamic
     loader did the work already.  */
  if (__builtin_expect (__libc_enable_secure, 0))
    __libc_check_standard_fds ();

#endif

  /* Register the destructor of the dynamic linker if there is any.  */
  if (__builtin_expect (__libc_start_data.rtld_fini != NULL, 1))
    __cxa_atexit ((void (*) (void *)) __libc_start_data.rtld_fini, NULL, NULL);

  /* Call the initializer of the libc.  This is only needed here if we
     are compiling for the static library in which case we haven't
     run the constructors in `_dl_start_user'.  */
#ifndef SHARED
  __libc_init_first (__libc_start_data.argc, __libc_start_data.argv,
		     __libc_start_data.envp);
#endif

  /* Register the destructor of the program, if any.  */
  if (__libc_start_data.fini)
    __cxa_atexit ((void (*) (void *)) __libc_start_data.fini, NULL, NULL);

  /* Call the initializer of the program, if any.  */
  if (__libc_start_data.init)
    (*__libc_start_data.init) ();

  exit ((*__libc_start_data.main) (__libc_start_data.argc,
				   __libc_start_data.argv,
				   __libc_start_data.envp));
}
Beispiel #10
0
/* Register FUNC to be executed by `exit'.  */
int
#ifndef atexit
attribute_hidden
#endif
atexit (void (*func) (void))
{
  return __cxa_atexit ((void (*) (void *)) func, NULL,
		       &__dso_handle == NULL ? NULL : __dso_handle);
}
Beispiel #11
0
int main()
{
	std::ios::sync_with_stdio(false);
	extern void* __dso_handle __attribute__ ((__weak__));
	__cxa_atexit((void (*) (void *)) __libc_freeres, NULL,
			&__dso_handle ? __dso_handle : NULL);
	do_something();

	return 0;
}
/* This function is called from the executable's _start entry point
 * (see arch-$ARCH/bionic/crtbegin_dynamic.S), which is itself
 * called by the dynamic linker after it has loaded all shared
 * libraries the executable depends on.
 *
 * Note that the dynamic linker has also run all constructors in the
 * executable at this point.
 */
__noreturn void __libc_init(uintptr_t *elfdata,
                       void (*onexit)(void),
                       int (*slingshot)(int, char**, char**),
                       structors_array_t const * const structors)
{
    int     argc = (int)*elfdata;
    char**  argv = (char**)(elfdata + 1);
    char**  envp = argv + argc + 1;

    /* Several Linux ABIs don't pass the onexit pointer, and the ones that
     * do never use it.  Therefore, we ignore it.
     */

    /* The executable may have its own destructors listed in its .fini_array
     * so we need to ensure that these are called when the program exits
     * normally.
     */
    if (structors->fini_array)
        __cxa_atexit(__libc_fini,structors->fini_array,NULL);

    exit(slingshot(argc, argv, envp));
}
__noreturn void __libc_init(uintptr_t *elfdata,
                       void (*onexit)(void),
                       int (*slingshot)(int, char**, char**),
                       structors_array_t const * const structors)
{
    int  argc;
    char **argv, **envp;

    __libc_init_tls(NULL);

    /* Initialize the C runtime environment */
    __libc_init_common(elfdata);

    /* Several Linux ABIs don't pass the onexit pointer, and the ones that
     * do never use it.  Therefore, we ignore it.
     */

    /* pre-init array. */
    call_array(structors->preinit_array);

    // call static constructors
    call_array(structors->init_array);

    argc = (int) *elfdata;
    argv = (char**)(elfdata + 1);
    envp = argv + argc + 1;

    /* The executable may have its own destructors listed in its .fini_array
     * so we need to ensure that these are called when the program exits
     * normally.
     */
    if (structors->fini_array)
        __cxa_atexit(__libc_fini,structors->fini_array,NULL);

    apply_gnu_relro();
    exit(slingshot(argc, argv, envp));
}
Beispiel #14
0
int
atexit (void (*func) ())
{
  return __cxa_atexit ((void (*)(void*))func, 0, 0);
}
Beispiel #15
0
int
__aeabi_atexit (void *arg, void (*func) (void *), void *d)
{
    //printf("__aeabi_atexit(%X, %X, %X)\n", arg, func, d);
    return __cxa_atexit (func, arg, d);
}
Beispiel #16
0
/*
 * Copy of atexit() used by libc and anything staticly linked into the
 * executable.  This passes NULL for the dso, so the callbacks are only
 * invoked by exit() and not dlclose()
 */
int
atexit(void (*fn)(void))
{
	return (__cxa_atexit((void (*)(void *))fn, NULL, NULL));
}
Beispiel #17
0
// Initializes memory allocation framework once per process.
static void malloc_init_impl(libc_globals* globals) {
  char value[PROP_VALUE_MAX];

  // If DEBUG_MALLOC_ENV_OPTIONS is set then it overrides the system properties.
  const char* options = getenv(DEBUG_MALLOC_ENV_OPTIONS);
  if (options == nullptr || options[0] == '\0') {
    if (__system_property_get(DEBUG_MALLOC_PROPERTY_OPTIONS, value) == 0 || value[0] == '\0') {
      return;
    }
    options = value;

    // Check to see if only a specific program should have debug malloc enabled.
    char program[PROP_VALUE_MAX];
    if (__system_property_get(DEBUG_MALLOC_PROPERTY_PROGRAM, program) != 0 &&
        strstr(getprogname(), program) == nullptr) {
      return;
    }
  }

  // Load the debug malloc shared library.
  void* malloc_impl_handle = dlopen(DEBUG_SHARED_LIB, RTLD_NOW | RTLD_LOCAL);
  if (malloc_impl_handle == nullptr) {
    error_log("%s: Unable to open debug malloc shared library %s: %s",
              getprogname(), DEBUG_SHARED_LIB, dlerror());
    return;
  }

  // Initialize malloc debugging in the loaded module.
  auto init_func = reinterpret_cast<bool (*)(const MallocDispatch*, int*, const char*)>(
      dlsym(malloc_impl_handle, "debug_initialize"));
  if (init_func == nullptr) {
    error_log("%s: debug_initialize routine not found in %s", getprogname(), DEBUG_SHARED_LIB);
    dlclose(malloc_impl_handle);
    return;
  }

  // Get the syms for the external functions.
  void* finalize_sym = dlsym(malloc_impl_handle, "debug_finalize");
  if (finalize_sym == nullptr) {
    error_log("%s: debug_finalize routine not found in %s", getprogname(), DEBUG_SHARED_LIB);
    dlclose(malloc_impl_handle);
    return;
  }

  void* get_leak_info_sym = dlsym(malloc_impl_handle, "debug_get_malloc_leak_info");
  if (get_leak_info_sym == nullptr) {
    error_log("%s: debug_get_malloc_leak_info routine not found in %s", getprogname(),
              DEBUG_SHARED_LIB);
    dlclose(malloc_impl_handle);
    return;
  }

  void* free_leak_info_sym = dlsym(malloc_impl_handle, "debug_free_malloc_leak_info");
  if (free_leak_info_sym == nullptr) {
    error_log("%s: debug_free_malloc_leak_info routine not found in %s", getprogname(),
              DEBUG_SHARED_LIB);
    dlclose(malloc_impl_handle);
    return;
  }

  void* malloc_backtrace_sym = dlsym(malloc_impl_handle, "debug_malloc_backtrace");
  if (malloc_backtrace_sym == nullptr) {
    error_log("%s: debug_malloc_backtrace routine not found in %s", getprogname(),
              DEBUG_SHARED_LIB);
    dlclose(malloc_impl_handle);
    return;
  }

  if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) {
    dlclose(malloc_impl_handle);
    return;
  }

  MallocDispatch malloc_dispatch_table;
  if (!InitMalloc(malloc_impl_handle, &malloc_dispatch_table, "debug")) {
    auto finalize_func = reinterpret_cast<void (*)()>(finalize_sym);
    finalize_func();
    dlclose(malloc_impl_handle);
    return;
  }

  g_debug_finalize_func = reinterpret_cast<void (*)()>(finalize_sym);
  g_debug_get_malloc_leak_info_func = reinterpret_cast<void (*)(
      uint8_t**, size_t*, size_t*, size_t*, size_t*)>(get_leak_info_sym);
  g_debug_free_malloc_leak_info_func = reinterpret_cast<void (*)(uint8_t*)>(free_leak_info_sym);
  g_debug_malloc_backtrace_func = reinterpret_cast<ssize_t (*)(
      void*, uintptr_t*, size_t)>(malloc_backtrace_sym);

  globals->malloc_dispatch = malloc_dispatch_table;
  libc_malloc_impl_handle = malloc_impl_handle;

  info_log("%s: malloc debug enabled", getprogname());

  // Use atexit to trigger the cleanup function. This avoids a problem
  // where another atexit function is used to cleanup allocated memory,
  // but the finalize function was already called. This particular error
  // seems to be triggered by a zygote spawned process calling exit.
  int ret_value = __cxa_atexit(malloc_fini_impl, nullptr, nullptr);
  if (ret_value != 0) {
    error_log("failed to set atexit cleanup function: %d", ret_value);
  }
}
Beispiel #18
0
int
__aeabi_atexit(void *object, void (*func)(void*), void *dso)
{
	return __cxa_atexit(func, object, dso);
}
Beispiel #19
0
static void pthread_initialize(void)
{
  struct sigaction sa;
  sigset_t mask;

  /* If already done (e.g. by a constructor called earlier!), bail out */
  if (__pthread_initial_thread_bos != NULL) return;
#ifdef TEST_FOR_COMPARE_AND_SWAP
  /* Test if compare-and-swap is available */
  __pthread_has_cas = compare_and_swap_is_available();
#endif
#ifdef FLOATING_STACKS
  /* We don't need to know the bottom of the stack.  Give the pointer some
     value to signal that initialization happened.  */
  __pthread_initial_thread_bos = (void *) -1l;
#else
  /* Determine stack size limits .  */
  __pthread_init_max_stacksize ();
# ifdef _STACK_GROWS_UP
  /* The initial thread already has all the stack it needs */
  __pthread_initial_thread_bos = (char *)
    ((long)CURRENT_STACK_FRAME &~ (STACK_SIZE - 1));
# else
  /* For the initial stack, reserve at least STACK_SIZE bytes of stack
     below the current stack address, and align that on a
     STACK_SIZE boundary. */
  __pthread_initial_thread_bos =
    (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
# endif
#endif
  /* Update the descriptor for the initial thread. */
  __pthread_initial_thread.p_pid = __getpid();
  /* Likewise for the resolver state _res.  */
  __pthread_initial_thread.p_resp = &_res;
#ifdef __SIGRTMIN
  /* Initialize real-time signals. */
  init_rtsigs ();
#endif
  /* Setup signal handlers for the initial thread.
     Since signal handlers are shared between threads, these settings
     will be inherited by all other threads. */
  sa.sa_handler = pthread_handle_sigrestart;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  __libc_sigaction(__pthread_sig_restart, &sa, NULL);
  sa.sa_handler = pthread_handle_sigcancel;
  // sa.sa_flags = 0;
  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
  if (__pthread_sig_debug > 0) {
    sa.sa_handler = pthread_handle_sigdebug;
    sigemptyset(&sa.sa_mask);
    // sa.sa_flags = 0;
    __libc_sigaction(__pthread_sig_debug, &sa, NULL);
  }
  /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
  sigemptyset(&mask);
  sigaddset(&mask, __pthread_sig_restart);
  sigprocmask(SIG_BLOCK, &mask, NULL);
  /* Register an exit function to kill all other threads. */
  /* Do it early so that user-registered atexit functions are called
     before pthread_*exit_process. */
#ifndef HAVE_Z_NODELETE
  if (__builtin_expect (&__dso_handle != NULL, 1))
    __cxa_atexit ((void (*) (void *)) pthread_atexit_process, NULL,
		  __dso_handle);
  else
#endif
    on_exit (pthread_onexit_process, NULL);
  /* How many processors.  */
  __pthread_smp_kernel = is_smp_system ();
}
Beispiel #20
0
/* Register FUNC to be executed by `exit'.  */
int
atexit (void (*func) (void))
{
  int __cxa_atexit (void (*func) (void *), void *arg, void *d);
  return __cxa_atexit ((void (*) (void *)) func, 0, 0);
}
Beispiel #21
0
int atexit(void (*func)(void))
{
	return __cxa_atexit(call, (void *)(uintptr_t)func, 0);
}
Beispiel #22
0
int
atexit(void (*fn)(void))
{
    return (__cxa_atexit((void (*)(void *))fn, NULL, &__dso_handle));
}
Beispiel #23
0
__attribute__((weak)) int atexit(void (*func)(void)) { return __cxa_atexit(caller, func, NULL); }
Beispiel #24
0
int __pthread_initialize_manager(void)
{
  int manager_pipe[2];
  int pid;
  struct pthread_request request;

#ifndef HAVE_Z_NODELETE
  if (__builtin_expect (&__dso_handle != NULL, 1))
    __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL,
		  __dso_handle);
#endif

  if (__pthread_max_stacksize == 0)
    __pthread_init_max_stacksize ();
  /* If basic initialization not done yet (e.g. we're called from a
     constructor run before our constructor), do it now */
  if (__pthread_initial_thread_bos == NULL) pthread_initialize();
  /* Setup stack for thread manager */
  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
  if (__pthread_manager_thread_bos == NULL) return -1;
  __pthread_manager_thread_tos =
    __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
  /* Setup pipe to communicate with thread manager */
  if (__libc_pipe(manager_pipe) == -1) {
    free(__pthread_manager_thread_bos);
    return -1;
  }
  /* Start the thread manager */
  pid = 0;
  if (__builtin_expect (__pthread_initial_thread.p_report_events, 0))
    {
      /* It's a bit more complicated.  We have to report the creation of
	 the manager thread.  */
      int idx = __td_eventword (TD_CREATE);
      uint32_t mask = __td_eventmask (TD_CREATE);

      if ((mask & (__pthread_threads_events.event_bits[idx]
		   | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
	  != 0)
	{
	  __pthread_lock(__pthread_manager_thread.p_lock, NULL);

#ifdef NEED_SEPARATE_REGISTER_STACK
	  pid = __clone2(__pthread_manager_event,
			 (void **) __pthread_manager_thread_bos,
			 THREAD_MANAGER_STACK_SIZE,
			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			 (void *)(long)manager_pipe[0]);
#elif _STACK_GROWS_UP
	  pid = __clone(__pthread_manager_event,
			(void **) __pthread_manager_thread_bos,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			(void *)(long)manager_pipe[0]);
#else
	  pid = __clone(__pthread_manager_event,
			(void **) __pthread_manager_thread_tos,
			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
			(void *)(long)manager_pipe[0]);
#endif

	  if (pid != -1)
	    {
	      /* Now fill in the information about the new thread in
	         the newly created thread's data structure.  We cannot let
	         the new thread do this since we don't know whether it was
	         already scheduled when we send the event.  */
	      __pthread_manager_thread.p_eventbuf.eventdata =
		&__pthread_manager_thread;
	      __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
	      __pthread_last_event = &__pthread_manager_thread;
	      __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
	      __pthread_manager_thread.p_pid = pid;

	      /* Now call the function which signals the event.  */
	      __linuxthreads_create_event ();
	    }

	  /* Now restart the thread.  */
	  __pthread_unlock(__pthread_manager_thread.p_lock);
	}
    }

  if (__builtin_expect (pid, 0) == 0)
    {
#ifdef NEED_SEPARATE_REGISTER_STACK
      pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos,
		     THREAD_MANAGER_STACK_SIZE,
		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		     (void *)(long)manager_pipe[0]);
#elif _STACK_GROWS_UP
      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		    (void *)(long)manager_pipe[0]);
#else
      pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
		    (void *)(long)manager_pipe[0]);
#endif
    }
  if (__builtin_expect (pid, 0) == -1) {
    free(__pthread_manager_thread_bos);
    __libc_close(manager_pipe[0]);
    __libc_close(manager_pipe[1]);
    return -1;
  }
  __pthread_manager_request = manager_pipe[1]; /* writing end */
  __pthread_manager_reader = manager_pipe[0]; /* reading end */
  __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
  __pthread_manager_thread.p_pid = pid;
  /* Make gdb aware of new thread manager */
  if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0)
    {
      raise(__pthread_sig_debug);
      /* We suspend ourself and gdb will wake us up when it is
	 ready to handle us. */
      __pthread_wait_for_restart_signal(thread_self());
    }
  /* Synchronize debugging of the thread manager */
  request.req_kind = REQ_DEBUG;
  TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
				  (char *) &request, sizeof(request)));
  return 0;
}
Beispiel #25
0
int
atexit(void (*func)(void))
{
  return __cxa_atexit((void (*)(void *))func, NULL, NULL);
}
Beispiel #26
0
int __aeabi_atexit (void *obj, void (*func) (void *), void *d)
{
    return __cxa_atexit (func, obj, d);
}
/* Register a function to be called by exit or when a shared library
   is unloaded.  This routine is like __cxa_atexit, but uses the
   calling sequence required by the ARM EABI.  */
int
__aeabi_atexit (void *arg, void (*func) (void *), void *d)
{
  return __cxa_atexit (func, arg, d);
}
Beispiel #28
0
int
atexit(
    _In_ void (*Function)(void))
{
    return __cxa_atexit((void (*)(void*))Function, NULL, __dso_handle);
}