* The symbols __preinit_array_start, __init_array_start, __init_array_end,
* __fini_array_start, __fini_array_end are defined by the linker script.
* _init() and _fini() come from crti.o/crtn.o (GCC CRT files).
+ *
+ * In a shared-library build these linker-generated symbols may remain
+ * SHN_UNDEF (value 0) when the library has no .init_array / .fini_array
+ * sections. We guard against that by checking the GOT entries for NULL.
*/
#include <stddef.h>
typedef void (*init_func)(void);
-extern init_func __preinit_array_start[];
-extern init_func __preinit_array_end[];
-extern init_func __init_array_start[];
-extern init_func __init_array_end[];
-extern init_func __fini_array_start[];
-extern init_func __fini_array_end[];
+/* These are resolved via the GOT in PIC mode; their values come from
+ * GLOB_DAT relocations. When the linker doesn't define them they
+ * resolve to 0. We read them through a volatile pointer so the
+ * compiler cannot assume they are non-null. */
+extern init_func *volatile __preinit_array_start[];
+extern init_func *volatile __preinit_array_end[];
+extern init_func *volatile __init_array_start[];
+extern init_func *volatile __init_array_end[];
+extern init_func *volatile __fini_array_start[];
+extern init_func *volatile __fini_array_end[];
extern void _init(void);
extern void _fini(void);
+/* Read _init/_fini through volatile to allow null check.
+ * In PIC shared libs, these resolve via GOT and may be 0. */
+static volatile init_func _init_ptr = _init;
+static volatile init_func _fini_ptr = _fini;
+
void __libc_init_array(void) {
size_t count, i;
+ init_func *s, *e;
- count = (size_t)(__preinit_array_end - __preinit_array_start);
- for (i = 0; i < count; i++)
- __preinit_array_start[i]();
+ s = (init_func*)__preinit_array_start;
+ e = (init_func*)__preinit_array_end;
+ if (s && e) {
+ count = (size_t)(e - s);
+ for (i = 0; i < count; i++)
+ s[i]();
+ }
- _init();
+ {
+ init_func fn = _init_ptr;
+ if (fn) fn();
+ }
- count = (size_t)(__init_array_end - __init_array_start);
- for (i = 0; i < count; i++)
- __init_array_start[i]();
+ s = (init_func*)__init_array_start;
+ e = (init_func*)__init_array_end;
+ if (s && e) {
+ count = (size_t)(e - s);
+ for (i = 0; i < count; i++)
+ s[i]();
+ }
}
void __libc_fini_array(void) {
size_t count;
+ init_func *s, *e;
- count = (size_t)(__fini_array_end - __fini_array_start);
- while (count-- > 0)
- __fini_array_start[count]();
+ s = (init_func*)__fini_array_start;
+ e = (init_func*)__fini_array_end;
+ if (s && e) {
+ count = (size_t)(e - s);
+ while (count-- > 0)
+ s[count]();
+ }
- _fini();
+ {
+ init_func fn = _fini_ptr;
+ if (fn) fn();
+ }
}