Implement dl_iterate_phdr function.

Convert boolean flags in internal Obj_Entry structure into bitfields.
Properly check for loaded segment alignment in map_object.
This commit is contained in:
Alexander Kabaev 2007-04-03 18:31:20 +00:00
parent fb6395da91
commit 49f90ad282
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=168312
3 changed files with 80 additions and 21 deletions

View File

@ -61,7 +61,6 @@ map_object(int fd, const char *path, const struct stat *sb)
Elf_Phdr **segs;
int nsegs;
Elf_Phdr *phdyn;
Elf_Phdr *phphdr;
Elf_Phdr *phinterp;
Elf_Phdr *phtls;
caddr_t mapbase;
@ -79,7 +78,8 @@ map_object(int fd, const char *path, const struct stat *sb)
Elf_Addr clear_vaddr;
caddr_t clear_addr;
caddr_t clear_page;
size_t nclear;
Elf_Addr phdr_vaddr;
size_t nclear, phsize;
Elf_Addr bss_vaddr;
Elf_Addr bss_vlimit;
caddr_t bss_addr;
@ -95,9 +95,11 @@ map_object(int fd, const char *path, const struct stat *sb)
* in that order.
*/
phdr = (Elf_Phdr *) ((char *)hdr + hdr->e_phoff);
phsize = hdr->e_phnum * sizeof (phdr[0]);
phlimit = phdr + hdr->e_phnum;
nsegs = -1;
phdyn = phphdr = phinterp = phtls = NULL;
phdyn = phinterp = phtls = NULL;
phdr_vaddr = 0;
segs = alloca(sizeof(segs[0]) * hdr->e_phnum);
while (phdr < phlimit) {
switch (phdr->p_type) {
@ -108,7 +110,7 @@ map_object(int fd, const char *path, const struct stat *sb)
case PT_LOAD:
segs[++nsegs] = phdr;
if (segs[nsegs]->p_align < PAGE_SIZE) {
if ((segs[nsegs]->p_align & (PAGE_SIZE - 1)) != 0) {
_rtld_error("%s: PT_LOAD segment %d not page-aligned",
path, nsegs);
return NULL;
@ -116,7 +118,8 @@ map_object(int fd, const char *path, const struct stat *sb)
break;
case PT_PHDR:
phphdr = phdr;
phdr_vaddr = phdr->p_vaddr;
phsize = phdr->p_memsz;
break;
case PT_DYNAMIC:
@ -211,6 +214,11 @@ map_object(int fd, const char *path, const struct stat *sb)
return NULL;
}
}
if (phdr_vaddr == 0 && data_offset <= hdr->e_phoff &&
(data_vlimit - data_vaddr + data_offset) >=
(hdr->e_phoff + hdr->e_phnum * sizeof (Elf_Phdr))) {
phdr_vaddr = data_vaddr + hdr->e_phoff - data_offset;
}
}
obj = obj_new();
@ -227,10 +235,19 @@ map_object(int fd, const char *path, const struct stat *sb)
obj->dynamic = (const Elf_Dyn *) (obj->relocbase + phdyn->p_vaddr);
if (hdr->e_entry != 0)
obj->entry = (caddr_t) (obj->relocbase + hdr->e_entry);
if (phphdr != NULL) {
obj->phdr = (const Elf_Phdr *) (obj->relocbase + phphdr->p_vaddr);
obj->phsize = phphdr->p_memsz;
if (phdr_vaddr != 0) {
obj->phdr = (const Elf_Phdr *) (obj->relocbase + phdr_vaddr);
} else {
obj->phdr = malloc(phsize);
if (obj->phdr == NULL) {
obj_free(obj);
_rtld_error("%s: cannot allocate program header", path);
return NULL;
}
memcpy((char *)obj->phdr, (char *)hdr + hdr->e_phoff, phsize);
obj->phdr_alloc = true;
}
obj->phsize = phsize;
if (phinterp != NULL)
obj->interp = (const char *) (obj->relocbase + phinterp->p_vaddr);
if (phtls != NULL) {
@ -307,7 +324,6 @@ obj_free(Obj_Entry *obj)
if (obj->tls_done)
free_tls_offset(obj);
free(obj->path);
while (obj->needed != NULL) {
Needed_Entry *needed = obj->needed;
obj->needed = needed->next;
@ -328,9 +344,16 @@ obj_free(Obj_Entry *obj)
STAILQ_REMOVE_HEAD(&obj->dagmembers, link);
free(elm);
}
free(obj->vertab);
free(obj->origin_path);
free(obj->priv);
if (obj->vertab)
free(obj->vertab);
if (obj->origin_path)
free(obj->origin_path);
if (obj->priv)
free(obj->priv);
if (obj->path)
free(obj->path);
if (obj->phdr_alloc)
free((void *)obj->phdr);
free(obj);
}

View File

@ -164,6 +164,7 @@ static Obj_Entry **obj_tail; /* Link field of last object in list */
static Obj_Entry *obj_main; /* The main program shared object */
static Obj_Entry obj_rtld; /* The dynamic linker shared object */
static unsigned int obj_count; /* Number of objects in obj_list */
static unsigned int obj_loads; /* Number of objects in obj_list */
static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */
STAILQ_HEAD_INITIALIZER(list_global);
@ -204,6 +205,7 @@ static func_ptr_type exports[] = {
(func_ptr_type) &__tls_get_addr,
(func_ptr_type) &_rtld_allocate_tls,
(func_ptr_type) &_rtld_free_tls,
(func_ptr_type) &dl_iterate_phdr,
NULL
};
@ -423,6 +425,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
*obj_tail = obj_main;
obj_tail = &obj_main->next;
obj_count++;
obj_loads++;
/* Make sure we don't call the main program's init and fini functions. */
obj_main->init = obj_main->fini = (Elf_Addr)NULL;
@ -1387,6 +1390,7 @@ do_load_object(int fd, const char *name, char *path, struct stat *sbp)
*obj_tail = obj;
obj_tail = &obj->next;
obj_count++;
obj_loads++;
linkmap_add(obj); /* for GDB & dlinfo() */
dbg(" %p .. %p: %s", obj->mapbase,
@ -2079,6 +2083,37 @@ dlinfo(void *handle, int request, void *p)
return (error);
}
int
dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param)
{
struct dl_phdr_info phdr_info;
const Obj_Entry *obj;
int error, lockstate;
lockstate = rlock_acquire(rtld_bind_lock);
error = 0;
for (obj = obj_list; obj != NULL; obj = obj->next) {
phdr_info.dlpi_addr = (Elf_Addr)obj->relocbase;
phdr_info.dlpi_name = STAILQ_FIRST(&obj->names) ?
STAILQ_FIRST(&obj->names)->name : obj->path;
phdr_info.dlpi_phdr = obj->phdr;
phdr_info.dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
phdr_info.dlpi_tls_modid = obj->tlsindex;
phdr_info.dlpi_tls_data = obj->tlsinit;
phdr_info.dlpi_adds = obj_loads;
phdr_info.dlpi_subs = obj_loads - obj_count;
if ((error = callback(&phdr_info, sizeof phdr_info, param)) != 0)
break;
}
rlock_release(rtld_bind_lock, lockstate);
return (error);
}
struct fill_search_info_args {
int request;
unsigned int flags;

View File

@ -201,15 +201,16 @@ typedef struct Struct_Obj_Entry {
Elf_Addr init; /* Initialization function to call */
Elf_Addr fini; /* Termination function to call */
bool mainprog; /* True if this is the main program */
bool rtld; /* True if this is the dynamic linker */
bool textrel; /* True if there are relocations to text seg */
bool symbolic; /* True if generated with "-Bsymbolic" */
bool bind_now; /* True if all relocations should be made first */
bool traced; /* Already printed in ldd trace output */
bool jmpslots_done; /* Already have relocated the jump slots */
bool init_done; /* Already have added object to init list */
bool tls_done; /* Already allocated offset for static TLS */
bool mainprog : 1; /* True if this is the main program */
bool rtld : 1; /* True if this is the dynamic linker */
bool textrel : 1; /* True if there are relocations to text seg */
bool symbolic : 1; /* True if generated with "-Bsymbolic" */
bool bind_now : 1; /* True if all relocations should be made first */
bool traced : 1; /* Already printed in ldd trace output */
bool jmpslots_done : 1; /* Already have relocated the jump slots */
bool init_done : 1; /* Already have added object to init list */
bool tls_done : 1; /* Already allocated offset for static TLS */
bool phdr_alloc : 1; /* Phdr is allocated and needs to be freed. */
struct link_map linkmap; /* for GDB and dlinfo() */
Objlist dldags; /* Object belongs to these dlopened DAGs (%) */