From b566341b03125971f3394e8c877fba725175ce1f Mon Sep 17 00:00:00 2001 From: John Marino Date: Sat, 21 Jan 2012 14:13:17 +0100 Subject: [PATCH] rtld: Set foundation to use aux vectors to get osreldate __getosreldate isn't used by rtld currently. The FreeBSD dynamic linker does use it indirectly in libc's mmap wrapper. The capability is included here both to ease the task to synchronizing with FreeBSD, and to quickly obtain the capability in the future if necessary. It's currently disabled with the undefined ENABLE_OSRELDATE macro. The splitting of digest_dynamic required to use aux vectors also has the benefit of avoiding the use of malloc at startup. --- libexec/rtld-elf/rtld.c | 88 ++++++++++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 15 deletions(-) diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 6f62700228..c41e684506 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,9 @@ typedef struct Struct_DoneList { */ static const char *_getenv_ld(const char *id); static void die(void) __dead2; +static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, + const Elf_Dyn **); +static void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *); static void digest_dynamic(Obj_Entry *, int); static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); static Obj_Entry *dlcheck(void *); @@ -98,7 +102,7 @@ static char *find_library(const char *, const Obj_Entry *); static const char *gethints(void); static void init_dag(Obj_Entry *); static void init_dag1(Obj_Entry *, Obj_Entry *, DoneList *); -static void init_rtld(caddr_t); +static void init_rtld(caddr_t, Elf_Auxinfo **); static void initlist_add_neededs(Needed_Entry *, Objlist *); static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *); static bool is_exported(const Elf_Sym *); @@ -165,13 +169,13 @@ static const char *ld_library_path; /* Environment variable for search path */ static char *ld_preload; /* Environment variable for libraries to load first */ static const char *ld_elf_hints_path; /* Environment variable for alternative hints path */ -static const char *ld_tracing; /* Called from ldd(1) to print libs */ - /* Optional function call tracing hook */ +static const char *ld_tracing; /* Called from ldd to print libs */ static const char *ld_utrace; /* Use utrace() to log events. */ -static int (*rtld_functrace)(const char *caller_obj, - const char *callee_obj, - const char *callee_func, - void *stack); +static int (*rtld_functrace)( /* Optional function call tracing hook */ + const char *caller_obj, + const char *callee_obj, + const char *callee_func, + void *stack); static Obj_Entry *rtld_functrace_obj; /* Object thereof */ static Obj_Entry *obj_list; /* Head of linked list of shared objects */ static Obj_Entry **obj_tail; /* Link field of last object in list */ @@ -203,6 +207,10 @@ extern Elf_Dyn _DYNAMIC; #define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) #endif +#ifdef ENABLE_OSRELDATE +int osreldate; +#endif + /* * These are the functions the dynamic linker exports to application * programs. They are the only symbols the dynamic linker is willing @@ -380,7 +388,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) /* Initialize and relocate ourselves. */ assert(aux_info[AT_BASE] != NULL); - init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr); + init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info); } ld_index = 0; /* don't use old env cache in case we are resident */ @@ -623,6 +631,7 @@ resident_skip2: dbg("initializing key program variables"); set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); set_program_var("environ", env); + set_program_var("__elf_aux_vector", aux); if (_getenv_ld("LD_RESIDENT_REGISTER_NOW")) { extern void resident_start(void); @@ -862,14 +871,16 @@ die(void) * information in its Obj_Entry structure. */ static void -digest_dynamic(Obj_Entry *obj, int early) +digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, + const Elf_Dyn **dyn_soname) { const Elf_Dyn *dynp; Needed_Entry **needed_tail = &obj->needed; - const Elf_Dyn *dyn_rpath = NULL; - const Elf_Dyn *dyn_soname = NULL; int plttype = DT_REL; + *dyn_rpath = NULL; + *dyn_soname = NULL; + obj->bind_now = false; for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { switch (dynp->d_tag) { @@ -993,11 +1004,11 @@ digest_dynamic(Obj_Entry *obj, int early) * We have to wait until later to process this, because we * might not have gotten the address of the string table yet. */ - dyn_rpath = dynp; + *dyn_rpath = dynp; break; case DT_SONAME: - dyn_soname = dynp; + *dyn_soname = dynp; break; case DT_INIT: @@ -1058,6 +1069,12 @@ digest_dynamic(Obj_Entry *obj, int early) obj->pltrelasize = obj->pltrelsize; obj->pltrelsize = 0; } +} + +static void +digest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath, + const Elf_Dyn *dyn_soname) +{ if (obj->z_origin && obj->origin_path == NULL) { obj->origin_path = xmalloc(PATH_MAX); @@ -1075,6 +1092,16 @@ digest_dynamic(Obj_Entry *obj, int early) object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val); } +static void +digest_dynamic(Obj_Entry *obj, int early) +{ + const Elf_Dyn *dyn_rpath; + const Elf_Dyn *dyn_soname; + + digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname); + digest_dynamic2(obj, dyn_rpath, dyn_soname); +} + /* * Process a shared object's program header. This is used only for the * main program, when the kernel has already loaded the main program @@ -1410,9 +1437,11 @@ init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp) * this function is to relocate the dynamic linker. */ static void -init_rtld(caddr_t mapbase) +init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info) { Obj_Entry objtmp; /* Temporary rtld object */ + const Elf_Dyn *dyn_rpath; + const Elf_Dyn *dyn_soname; /* * Conjure up an Obj_Entry structure for the dynamic linker. @@ -1429,7 +1458,7 @@ init_rtld(caddr_t mapbase) #endif if (RTLD_IS_DYNAMIC()) { objtmp.dynamic = rtld_dynamic(&objtmp); - digest_dynamic(&objtmp, 1); + digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname); assert(objtmp.needed == NULL); assert(!objtmp.textrel); @@ -1447,6 +1476,13 @@ init_rtld(caddr_t mapbase) /* Now that non-local variables can be accesses, copy out obj_rtld. */ memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld)); +#ifdef ENABLE_OSRELDATE + if (aux_info[AT_OSRELDATE] != NULL) + osreldate = aux_info[AT_OSRELDATE]->a_un.a_val; +#endif + + digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname); + /* Replace the path with a dynamically allocated copy. */ obj_rtld.path = xstrdup(PATH_RTLD); @@ -3741,6 +3777,28 @@ fetch_ventry(const Obj_Entry *obj, unsigned long symnum) return NULL; } +#ifdef ENABLE_OSRELDATE +int +__getosreldate(void) +{ + size_t len; + int oid[2]; + int error, osrel; + + if (osreldate != 0) + return (osreldate); + + oid[0] = CTL_KERN; + oid[1] = KERN_OSRELDATE; + osrel = 0; + len = sizeof(osrel); + error = sysctl(oid, 2, &osrel, &len, NULL, 0); + if (error == 0 && osrel > 0 && len == sizeof(osrel)) + osreldate = osrel; + return (osreldate); +} +#endif + /* * No unresolved symbols for rtld. */ -- 2.41.0