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:
parent
fb6395da91
commit
49f90ad282
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=168312
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 (%) */
|
||||
|
Loading…
Reference in New Issue
Block a user