diff options
author | kib <kib@FreeBSD.org> | 2010-08-17 09:05:39 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2010-08-17 09:05:39 +0000 |
commit | 3c2c3f33ee230b5a0169bd5dd2d57e42fdb22d05 (patch) | |
tree | 2a4b7d1ddfeee3c1c0711a89f2cac3b60b2c3d0f /libexec | |
parent | d9f088a03e65b9a9a1109213406f79fc4a1b33ae (diff) | |
download | FreeBSD-src-3c2c3f33ee230b5a0169bd5dd2d57e42fdb22d05.zip FreeBSD-src-3c2c3f33ee230b5a0169bd5dd2d57e42fdb22d05.tar.gz |
Use the newly provided aux vectors to get pagesize and osreldate information.
Use local version of getpagesize(), rtld_getpagesize() in private allocator.
Override the __getosreldate() previously fetched from libc_pic.a with
local version that uses aux value if present. Note that __getosreldate()
is used by rtld indirectly, by mmap(2) libc wrapper.
To be able to utilize aux, split digest_dynamic() for use by init_rtld()
into two parts, where the first one does not call malloc(), and the
second part uses it. init_rtld() is able to initialize global variables
before digest_dynamic2() calls. In particular, pagesize and osreldate are
set up from the aux values.
Now, rtld avoids (two) sysctl calls in startup.
Tested by: marius (sparc64)
MFC after: 1 month
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/rtld-elf/malloc.c | 23 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.c | 71 |
2 files changed, 84 insertions, 10 deletions
diff --git a/libexec/rtld-elf/malloc.c b/libexec/rtld-elf/malloc.c index 3da5bee..38ae89a 100644 --- a/libexec/rtld-elf/malloc.c +++ b/libexec/rtld-elf/malloc.c @@ -48,6 +48,7 @@ static char *rcsid = "$FreeBSD$"; */ #include <sys/types.h> +#include <sys/sysctl.h> #include <err.h> #include <paths.h> #include <stdarg.h> @@ -152,6 +153,26 @@ botch(s) static void xprintf(const char *, ...); #define TRACE() xprintf("TRACE %s:%d\n", __FILE__, __LINE__) +extern int pagesize; + +static int +rtld_getpagesize(void) +{ + int mib[2]; + size_t size; + + if (pagesize != 0) + return (pagesize); + + mib[0] = CTL_HW; + mib[1] = HW_PAGESIZE; + size = sizeof(pagesize); + if (sysctl(mib, 2, &pagesize, &size, NULL, 0) == -1) + return (-1); + return (pagesize); + +} + void * malloc(nbytes) size_t nbytes; @@ -166,7 +187,7 @@ malloc(nbytes) * align break pointer so all data will be page aligned. */ if (pagesz == 0) { - pagesz = n = getpagesize(); + pagesz = n = rtld_getpagesize(); if (morepages(NPOOLPAGES) == 0) return NULL; op = (union overhead *)(pagepool_start); diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 8082656..a7bf914 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -40,6 +40,7 @@ #include <sys/mount.h> #include <sys/mman.h> #include <sys/stat.h> +#include <sys/sysctl.h> #include <sys/uio.h> #include <sys/utsname.h> #include <sys/ktrace.h> @@ -84,6 +85,9 @@ typedef struct Struct_DoneList { */ static const char *basename(const char *); 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 *); @@ -97,7 +101,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 *); @@ -188,6 +192,8 @@ extern Elf_Dyn _DYNAMIC; #define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) #endif +int osreldate, pagesize; + /* * These are the functions the dynamic linker exports to application * programs. They are the only symbols the dynamic linker is willing @@ -350,7 +356,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); __progname = obj_rtld.path; argv0 = argv[0] != NULL ? argv[0] : "(null)"; @@ -737,14 +743,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) { @@ -868,11 +876,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: @@ -961,6 +969,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); @@ -978,6 +992,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 @@ -1304,9 +1328,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. @@ -1323,7 +1349,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); #if !defined(__mips__) /* MIPS and SH{3,5} have a bogus DT_TEXTREL. */ @@ -1344,6 +1370,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)); + if (aux_info[AT_PAGESZ] != NULL) + pagesize = aux_info[AT_PAGESZ]->a_un.a_val; + if (aux_info[AT_OSRELDATE] != NULL) + osreldate = aux_info[AT_OSRELDATE]->a_un.a_val; + + digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname); + /* Replace the path with a dynamically allocated copy. */ obj_rtld.path = xstrdup(PATH_RTLD); @@ -3630,3 +3663,23 @@ fetch_ventry(const Obj_Entry *obj, unsigned long symnum) } return NULL; } + +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); +} |