diff options
Diffstat (limited to 'libexec/rtld-elf/rtld.c')
-rw-r--r-- | libexec/rtld-elf/rtld.c | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 24e56b7..f96b8e7 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -97,6 +97,7 @@ static void *fill_search_info(const char *, size_t, void *); static char *find_library(const char *, const Obj_Entry *); static const char *gethints(bool); static void init_dag(Obj_Entry *); +static void init_pagesizes(Elf_Auxinfo **aux_info); 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 *); @@ -205,7 +206,8 @@ extern Elf_Dyn _DYNAMIC; #define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) #endif -int osreldate, pagesize; +int npagesizes, osreldate; +size_t *pagesizes; long __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -1822,8 +1824,9 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info) /* 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; + /* The page size is required by the dynamic memory allocator. */ + init_pagesizes(aux_info); + if (aux_info[AT_OSRELDATE] != NULL) osreldate = aux_info[AT_OSRELDATE]->a_un.a_val; @@ -1837,6 +1840,50 @@ init_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info) } /* + * Retrieve the array of supported page sizes. The kernel provides the page + * sizes in increasing order. + */ +static void +init_pagesizes(Elf_Auxinfo **aux_info) +{ + static size_t psa[MAXPAGESIZES]; + int mib[2]; + size_t len, size; + + if (aux_info[AT_PAGESIZES] != NULL && aux_info[AT_PAGESIZESLEN] != + NULL) { + size = aux_info[AT_PAGESIZESLEN]->a_un.a_val; + pagesizes = aux_info[AT_PAGESIZES]->a_un.a_ptr; + } else { + len = 2; + if (sysctlnametomib("hw.pagesizes", mib, &len) == 0) + size = sizeof(psa); + else { + /* As a fallback, retrieve the base page size. */ + size = sizeof(psa[0]); + if (aux_info[AT_PAGESZ] != NULL) { + psa[0] = aux_info[AT_PAGESZ]->a_un.a_val; + goto psa_filled; + } else { + mib[0] = CTL_HW; + mib[1] = HW_PAGESIZE; + len = 2; + } + } + if (sysctl(mib, len, psa, &size, NULL, 0) == -1) { + _rtld_error("sysctl for hw.pagesize(s) failed"); + die(); + } +psa_filled: + pagesizes = psa; + } + npagesizes = size / sizeof(pagesizes[0]); + /* Discard any invalid entries at the end of the array. */ + while (npagesizes > 0 && pagesizes[npagesizes - 1] == 0) + npagesizes--; +} + +/* * Add the init functions from a needed object list (and its recursive * needed objects) to "list". This is not used directly; it is a helper * function for initlist_add_objects(). The write lock must be held |