Module Name: src Committed By: matt Date: Wed Aug 15 03:46:07 UTC 2012
Modified Files: src/libexec/ld.elf_so: headers.c rtld.c rtld.h symbol.c src/libexec/ld.elf_so/arch/arm: Makefile.inc Log Message: Add .init_array/.fini_array support (conditionalized on HAVE_INITFINI_ARRAY). To generate a diff of this commit: cvs rdiff -u -r1.42 -r1.43 src/libexec/ld.elf_so/headers.c cvs rdiff -u -r1.157 -r1.158 src/libexec/ld.elf_so/rtld.c cvs rdiff -u -r1.109 -r1.110 src/libexec/ld.elf_so/rtld.h cvs rdiff -u -r1.60 -r1.61 src/libexec/ld.elf_so/symbol.c cvs rdiff -u -r1.11 -r1.12 src/libexec/ld.elf_so/arch/arm/Makefile.inc Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/libexec/ld.elf_so/headers.c diff -u src/libexec/ld.elf_so/headers.c:1.42 src/libexec/ld.elf_so/headers.c:1.43 --- src/libexec/ld.elf_so/headers.c:1.42 Sun Jul 22 09:16:35 2012 +++ src/libexec/ld.elf_so/headers.c Wed Aug 15 03:46:06 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: headers.c,v 1.42 2012/07/22 09:16:35 martin Exp $ */ +/* $NetBSD: headers.c,v 1.43 2012/08/15 03:46:06 matt Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -40,7 +40,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: headers.c,v 1.42 2012/07/22 09:16:35 martin Exp $"); +__RCSID("$NetBSD: headers.c,v 1.43 2012/08/15 03:46:06 matt Exp $"); #endif /* not lint */ #include <err.h> @@ -227,10 +227,32 @@ _rtld_digest_dynamic(const char *execnam init = dynp->d_un.d_ptr; break; +#ifdef HAVE_INITFINI_ARRAY + case DT_INIT_ARRAY: + obj->init_array = + (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_INIT_ARRAYSZ: + obj->init_arraysz = dynp->d_un.d_val / sizeof(fptr_t); + break; +#endif + case DT_FINI: fini = dynp->d_un.d_ptr; break; +#ifdef HAVE_INITFINI_ARRAY + case DT_FINI_ARRAY: + obj->fini_array = + (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr); + break; + + case DT_FINI_ARRAYSZ: + obj->fini_arraysz = dynp->d_un.d_val / sizeof(fptr_t); + break; +#endif + /* * Don't process DT_DEBUG on MIPS as the dynamic section * is mapped read-only. DT_MIPS_RLD_MAP is used instead. Index: src/libexec/ld.elf_so/rtld.c diff -u src/libexec/ld.elf_so/rtld.c:1.157 src/libexec/ld.elf_so/rtld.c:1.158 --- src/libexec/ld.elf_so/rtld.c:1.157 Tue Mar 13 21:00:31 2012 +++ src/libexec/ld.elf_so/rtld.c Wed Aug 15 03:46:06 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.c,v 1.157 2012/03/13 21:00:31 joerg Exp $ */ +/* $NetBSD: rtld.c,v 1.158 2012/08/15 03:46:06 matt Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -40,7 +40,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: rtld.c,v 1.157 2012/03/13 21:00:31 joerg Exp $"); +__RCSID("$NetBSD: rtld.c,v 1.158 2012/08/15 03:46:06 matt Exp $"); #endif /* not lint */ #include <sys/param.h> @@ -135,13 +135,50 @@ static void _rtld_unload_object(sigset_t static void _rtld_unref_dag(Obj_Entry *); static Obj_Entry *_rtld_obj_from_addr(const void *); +static inline void +_rtld_call_initfini_function(fptr_t func, sigset_t *mask) +{ + _rtld_exclusive_exit(mask); + (*func)(); + _rtld_exclusive_enter(mask); +} + +static void +_rtld_call_fini_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen) +{ + if (obj->fini_arraysz == 0 && (obj->fini == NULL || obj->fini_called)) { + return; + } + if (obj->fini != NULL && !obj->fini_called) { + dbg (("calling fini function %s at %p%s", obj->path, + (void *)obj->fini, + obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); + obj->fini_called = 1; + _rtld_call_initfini_function(obj->fini, mask); + } +#ifdef HAVE_INITFINI_ARRAY + /* + * Now process the fini_array if it exists. Simply go from + * start to end. We need to make restartable so just advance + * the array pointer and decrement the size each time through + * the loop. + */ + while (obj->fini_arraysz > 0 && _rtld_objgen == cur_objgen) { + fptr_t fini = *obj->fini_array++; + obj->fini_arraysz--; + dbg (("calling fini array function %s at %p%s", obj->path, + (void *)fini, + obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); + _rtld_call_initfini_function(fini, mask); + } +#endif /* HAVE_INITFINI_ARRAY */ +} + static void _rtld_call_fini_functions(sigset_t *mask, int force) { Objlist_Entry *elm; Objlist finilist; - Obj_Entry *obj; - void (*fini)(void); u_int cur_objgen; dbg(("_rtld_call_fini_functions(%d)", force)); @@ -153,49 +190,33 @@ restart: /* First pass: objects _not_ marked with DF_1_INITFIRST. */ SIMPLEQ_FOREACH(elm, &finilist, link) { - obj = elm->obj; - if (obj->refcount > 0 && !force) { - continue; - } - if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) { - continue; + Obj_Entry * const obj = elm->obj; + if (!obj->z_initfirst) { + if (obj->refcount > 0 && !force) { + continue; + } + /* + * XXX This can race against a concurrent dlclose(). + * XXX In that case, the object could be unmapped before + * XXX the fini() call or the fini_array has completed. + */ + _rtld_call_fini_function(obj, mask, cur_objgen); + if (_rtld_objgen != cur_objgen) { + dbg(("restarting fini iteration")); + _rtld_objlist_clear(&finilist); + goto restart; } - dbg (("calling fini function %s at %p", obj->path, - (void *)obj->fini)); - obj->fini_called = 1; - /* - * XXX This can race against a concurrent dlclose(). - * XXX In that case, the object could be unmapped before - * XXX the fini() call is done. - */ - fini = obj->fini; - _rtld_exclusive_exit(mask); - (*fini)(); - _rtld_exclusive_enter(mask); - if (_rtld_objgen != cur_objgen) { - dbg(("restarting fini iteration")); - _rtld_objlist_clear(&finilist); - goto restart; } } /* Second pass: objects marked with DF_1_INITFIRST. */ SIMPLEQ_FOREACH(elm, &finilist, link) { - obj = elm->obj; + Obj_Entry * const obj = elm->obj; if (obj->refcount > 0 && !force) { continue; } - if (obj->fini == NULL || obj->fini_called) { - continue; - } - dbg (("calling fini function %s at %p (DF_1_INITFIRST)", - obj->path, (void *)obj->fini)); - obj->fini_called = 1; /* XXX See above for the race condition here */ - fini = obj->fini; - _rtld_exclusive_exit(mask); - (*fini)(); - _rtld_exclusive_enter(mask); + _rtld_call_fini_function(obj, mask, cur_objgen); if (_rtld_objgen != cur_objgen) { dbg(("restarting fini iteration")); _rtld_objlist_clear(&finilist); @@ -207,12 +228,42 @@ restart: } static void +_rtld_call_init_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen) +{ + if (obj->init_arraysz == 0 && (obj->init_called || obj->init == NULL)) { + return; + } + if (!obj->init_called && obj->init != NULL) { + dbg (("calling init function %s at %p%s", + obj->path, (void *)obj->init, + obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); + obj->init_called = 1; + _rtld_call_initfini_function(obj->init, mask); + } + +#ifdef HAVE_INITFINI_ARRAY + /* + * Now process the init_array if it exists. Simply go from + * start to end. We need to make restartable so just advance + * the array pointer and decrement the size each time through + * the loop. + */ + while (obj->init_arraysz > 0 && _rtld_objgen == cur_objgen) { + fptr_t init = *obj->init_array++; + obj->init_arraysz--; + dbg (("calling init_array function %s at %p%s", + obj->path, (void *)init, + obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); + _rtld_call_initfini_function(init, mask); + } +#endif /* HAVE_INITFINI_ARRAY */ +} + +static void _rtld_call_init_functions(sigset_t *mask) { Objlist_Entry *elm; Objlist initlist; - Obj_Entry *obj; - void (*init)(void); u_int cur_objgen; dbg(("_rtld_call_init_functions()")); @@ -224,37 +275,20 @@ restart: /* First pass: objects marked with DF_1_INITFIRST. */ SIMPLEQ_FOREACH(elm, &initlist, link) { - obj = elm->obj; - if (obj->init == NULL || obj->init_called || !obj->z_initfirst) { - continue; - } - dbg (("calling init function %s at %p (DF_1_INITFIRST)", - obj->path, (void *)obj->init)); - obj->init_called = 1; - init = obj->init; - _rtld_exclusive_exit(mask); - (*init)(); - _rtld_exclusive_enter(mask); - if (_rtld_objgen != cur_objgen) { - dbg(("restarting init iteration")); - _rtld_objlist_clear(&initlist); - goto restart; + Obj_Entry * const obj = elm->obj; + if (obj->z_initfirst) { + _rtld_call_init_function(obj, mask, cur_objgen); + if (_rtld_objgen != cur_objgen) { + dbg(("restarting init iteration")); + _rtld_objlist_clear(&initlist); + goto restart; + } } } /* Second pass: all other objects. */ SIMPLEQ_FOREACH(elm, &initlist, link) { - obj = elm->obj; - if (obj->init == NULL || obj->init_called) { - continue; - } - dbg (("calling init function %s at %p", obj->path, - (void *)obj->init)); - obj->init_called = 1; - init = obj->init; - _rtld_exclusive_exit(mask); - (*init)(); - _rtld_exclusive_enter(mask); + _rtld_call_init_function(elm->obj, mask, cur_objgen); if (_rtld_objgen != cur_objgen) { dbg(("restarting init iteration")); _rtld_objlist_clear(&initlist); Index: src/libexec/ld.elf_so/rtld.h diff -u src/libexec/ld.elf_so/rtld.h:1.109 src/libexec/ld.elf_so/rtld.h:1.110 --- src/libexec/ld.elf_so/rtld.h:1.109 Tue Mar 13 21:00:32 2012 +++ src/libexec/ld.elf_so/rtld.h Wed Aug 15 03:46:06 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.h,v 1.109 2012/03/13 21:00:32 joerg Exp $ */ +/* $NetBSD: rtld.h,v 1.110 2012/08/15 03:46:06 matt Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -114,7 +114,6 @@ typedef struct Struct_Ver_Entry { /* Ver_Entry.flags */ #define VER_INFO_HIDDEN 0x01 - #define RTLD_MAX_ENTRY 10 #define RTLD_MAX_LIBRARY 4 #define RTLD_MAX_CTL 2 @@ -141,6 +140,8 @@ typedef struct _rtld_library_xform_t { #define RTLD_MAGIC 0xd550b87a #define RTLD_VERSION 1 +typedef void (*fptr_t)(void); + typedef struct Struct_Obj_Entry { Elf32_Word magic; /* Magic number (sanity check) */ Elf32_Word version; /* Version number of struct format */ @@ -188,8 +189,8 @@ typedef struct Struct_Obj_Entry { Search_Path *rpaths; /* Search path specified in object */ Needed_Entry *needed; /* Shared objects needed by this (%) */ - void (*init)(void); /* Initialization function to call */ - void (*fini)(void); /* Termination function to call */ + fptr_t init; /* Initialization function to call */ + fptr_t fini; /* Termination function to call */ /* * BACKWARDS COMPAT Entry points for dlopen() and friends. @@ -277,6 +278,12 @@ typedef struct Struct_Obj_Entry { Ver_Entry *vertab; /* Versions required/defined by this * object */ int vertabnum; /* Number of entries in vertab */ + + /* init_array/fini_array */ + fptr_t *init_array; /* start of init array */ + size_t init_arraysz; /* # of entries in it */ + fptr_t *fini_array; /* start of fini array */ + size_t fini_arraysz; /* # of entries in it */ } Obj_Entry; typedef struct Struct_DoneList { Index: src/libexec/ld.elf_so/symbol.c diff -u src/libexec/ld.elf_so/symbol.c:1.60 src/libexec/ld.elf_so/symbol.c:1.61 --- src/libexec/ld.elf_so/symbol.c:1.60 Thu Feb 16 23:00:39 2012 +++ src/libexec/ld.elf_so/symbol.c Wed Aug 15 03:46:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: symbol.c,v 1.60 2012/02/16 23:00:39 joerg Exp $ */ +/* $NetBSD: symbol.c,v 1.61 2012/08/15 03:46:07 matt Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -40,7 +40,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: symbol.c,v 1.60 2012/02/16 23:00:39 joerg Exp $"); +__RCSID("$NetBSD: symbol.c,v 1.61 2012/08/15 03:46:07 matt Exp $"); #endif /* not lint */ #include <err.h> @@ -59,8 +59,6 @@ __RCSID("$NetBSD: symbol.c,v 1.60 2012/0 #include "debug.h" #include "rtld.h" -typedef void (*fptr_t)(void); - /* * If the given object is already in the donelist, return true. Otherwise * add the object to the list and return false. Index: src/libexec/ld.elf_so/arch/arm/Makefile.inc diff -u src/libexec/ld.elf_so/arch/arm/Makefile.inc:1.11 src/libexec/ld.elf_so/arch/arm/Makefile.inc:1.12 --- src/libexec/ld.elf_so/arch/arm/Makefile.inc:1.11 Sat Jun 4 16:17:17 2005 +++ src/libexec/ld.elf_so/arch/arm/Makefile.inc Wed Aug 15 03:46:07 2012 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.11 2005/06/04 16:17:17 lukem Exp $ +# $NetBSD: Makefile.inc,v 1.12 2012/08/15 03:46:07 matt Exp $ SRCS+= rtld_start.S mdreloc.c @@ -6,5 +6,8 @@ SRCS+= rtld_start.S mdreloc.c CPPFLAGS+= -fpic CPPFLAGS+= -DELFSIZE=32 +.if ${MACHINE_ARCH} == "earm" || ${MACHINE_ARCH} == "earmeb" +CPPFLAGS+= -DHAVE_INITFINI_ARRAY +.endif LDFLAGS+= -Wl,-e,_rtld_start