OSDN Git Service

Fix by Martin Schlemmer:
authorMike Frysinger <vapier@gentoo.org>
Thu, 8 Sep 2005 02:29:37 +0000 (02:29 -0000)
committerMike Frysinger <vapier@gentoo.org>
Thu, 8 Sep 2005 02:29:37 +0000 (02:29 -0000)
If _DL_FINI_CRT_COMPAT is defined, _dl_fini is setup to run at exit via
atexit(), but this makes it run _before_ the fini (__app_fini()) of the
app, causing stuff like sandbox that frees structs, etc via its fini to
segfault.
http://bugs.gentoo.org/98187

ldso/ldso/ldso.c
libc/misc/internals/__uClibc_main.c
libc/stdlib/atexit.c

index db250f0..f6ac509 100644 (file)
@@ -766,11 +766,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 #ifdef _DL_FINI_CRT_COMPAT
        /* arches that have moved their ldso FINI handling should skip this part */
        {
-               int (*_dl_atexit) (void *) = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit",
+               void (*__set__dl_fini) (void *) = (void (*)(void *)) (intptr_t) _dl_find_hash("_set__dl_fini",
                                _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT);
 
-               if (_dl_atexit)
-                       (*_dl_atexit) (_dl_fini);
+               if (__set__dl_fini)
+                       (*__set__dl_fini)(_dl_fini);
+               else
+                       _dl_if_debug_dprint("_set__dl_fini not found\n");
        }
 #endif
 
index 6f74e39..53bb028 100644 (file)
@@ -161,6 +161,16 @@ void attribute_hidden (*__app_fini)(void) = NULL;
 
 void attribute_hidden (*__rtld_fini)(void) = NULL;
 
+#ifdef _DL_FINI_CRT_COMPAT
+void attribute_hidden (*__dl_fini)(void) = NULL;
+
+void _set__dl_fini(void *fini_func)
+{
+       if (fini_func != NULL)
+               __dl_fini = fini_func;
+}
+#endif
+
 /* __uClibc_start_main is the new main stub for uClibc. This function is
  * called from crt0 (version 0.9.16 or newer), after ALL shared libraries
  * are initialized, just before we call the application's main function.
index 280f42c..c703181 100644 (file)
@@ -223,6 +223,11 @@ extern void (*__app_fini)(void);
 #endif
 
 extern void (*__rtld_fini)(void);
+
+#ifdef _DL_FINI_CRT_COMPAT
+extern void (*__dl_fini)(void);
+#endif
+
 /*
  * Normal program termination
  */
@@ -242,6 +247,9 @@ void exit(int rv)
 #ifndef _DL_FINI_CRT_COMPAT
        if (__rtld_fini != NULL)
                (__rtld_fini)();
+#else
+       if (__dl_fini != NULL)
+               (__dl_fini)();
 #endif
 
     /* If we are using stdio, try to shut it down.  At the very least,