diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-07-07 17:31:45 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2007-07-07 17:31:45 +0000 |
commit | a1ce84f35f28616163778cd63878e12e65ddb97b (patch) | |
tree | 5d20132d84a9af620f21126320f44126b4d4c742 /elf | |
parent | 5daa0615659c5651d48e39ba7c17db769bbe10d4 (diff) | |
download | glibc-a1ce84f35f28616163778cd63878e12e65ddb97b.tar.gz |
* sysdeps/generic/ldsodefs.h (rtld_global): Reorder some elements
to fill in holes
(rtld_global_ro): Likewise.
* elf/dl-addr.c (_dl_addr): Skip PT_LOAD checking if l_contiguous.
Move PT_LOAD checking to...
(_dl_addr_inside_object): ... here, new function.
* elf/dl-sym.c (do_sym): If not l_contiguous,
call _dl_addr_inside_object.
* elf/dl-iteratephdr.c (__dl_iterate_phdr): Likewise.
* dlfcn/dlinfo.c (dlinfo_doit): Likewise.
* elf/dl-open.c (dl_open_worker): Likewise.
(_dl_addr_inside_object): New function if IS_IN_rtld.
* elf/dl-load.c (_dl_map_object_from_fd): Set l_contiguous if no
holes are present or are PROT_NONE protected.
* include/link.h (struct link_map): Add l_contiguous field.
* sysdeps/generic/ldsodefs.h (_dl_addr_inside_object): New prototype.
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-addr.c | 36 | ||||
-rw-r--r-- | elf/dl-iteratephdr.c | 6 | ||||
-rw-r--r-- | elf/dl-load.c | 3 | ||||
-rw-r--r-- | elf/dl-open.c | 24 | ||||
-rw-r--r-- | elf/dl-sym.c | 5 |
5 files changed, 50 insertions, 24 deletions
diff --git a/elf/dl-addr.c b/elf/dl-addr.c index e13105572e..17745b55b0 100644 --- a/elf/dl-addr.c +++ b/elf/dl-addr.c @@ -134,22 +134,12 @@ _dl_addr (const void *address, Dl_info *info, /* Find the highest-addressed object that ADDRESS is not below. */ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next) - if (addr >= l->l_map_start && addr < l->l_map_end) + if (addr >= l->l_map_start && addr < l->l_map_end + && (l->l_contiguous || _dl_addr_inside_object (l, addr))) { - /* Make sure it lies within one of L's segments. */ - int n = l->l_phnum; - const ElfW(Addr) reladdr = addr - l->l_addr; - while (--n >= 0) - if (l->l_phdr[n].p_type == PT_LOAD) - { - if (reladdr - l->l_phdr[n].p_vaddr >= 0 - && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz) - { - determine_info (addr, l, info, mapp, symbolp); - result = 1; - goto out; - } - } + determine_info (addr, l, info, mapp, symbolp); + result = 1; + goto out; } out: @@ -158,3 +148,19 @@ _dl_addr (const void *address, Dl_info *info, return result; } libc_hidden_def (_dl_addr) + +/* Return non-zero if ADDR lies within one of L's segments. */ +int +internal_function +_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr) +{ + int n = l->l_phnum; + const ElfW(Addr) reladdr = addr - l->l_addr; + + while (--n >= 0) + if (l->l_phdr[n].p_type == PT_LOAD + && reladdr - l->l_phdr[n].p_vaddr >= 0 + && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz) + return 1; + return 0; +} diff --git a/elf/dl-iteratephdr.c b/elf/dl-iteratephdr.c index d03d8b6daf..1b743bd3e9 100644 --- a/elf/dl-iteratephdr.c +++ b/elf/dl-iteratephdr.c @@ -54,9 +54,9 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, nloaded += GL(dl_ns)[cnt]._ns_nloaded; if (caller >= (const void *) l->l_map_start - && caller < (const void *) l->l_map_end) - /* There must be exactly one DSO for the range of the virtual - memory. Otherwise something is really broken. */ + && caller < (const void *) l->l_map_end + && (l->l_contiguous + || _dl_addr_inside_object (l, (ElfW(Addr)) caller))) ns = cnt; } diff --git a/elf/dl-load.c b/elf/dl-load.c index 1650ef953a..0301b425a9 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1223,6 +1223,8 @@ cannot allocate TLS data structures for initial thread"); loadcmds[nloadcmds - 1].mapstart - c->mapend, PROT_NONE); + l->l_contiguous = 1; + goto postmap; } @@ -1242,6 +1244,7 @@ cannot allocate TLS data structures for initial thread"); /* Remember which part of the address space this object uses. */ l->l_map_start = c->mapstart + l->l_addr; l->l_map_end = l->l_map_start + maplength; + l->l_contiguous = !has_holes; while (c < &loadcmds[nloadcmds]) { diff --git a/elf/dl-open.c b/elf/dl-open.c index c61caa4790..fda3219ae2 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -235,10 +235,10 @@ dl_open_worker (void *a) for (Lmid_t ns = 0; ns < DL_NNS; ++ns) for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) if (caller_dlopen >= (const void *) l->l_map_start - && caller_dlopen < (const void *) l->l_map_end) + && caller_dlopen < (const void *) l->l_map_end + && (l->l_contiguous + || _dl_addr_inside_object (l, (ElfW(Addr)) caller_dlopen))) { - /* There must be exactly one DSO for the range of the virtual - memory. Otherwise something is really broken. */ assert (ns == l->l_ns); call_map = l; goto found_caller; @@ -689,3 +689,21 @@ show_scope (struct link_map *new) } } #endif + +#ifdef IS_IN_rtld +/* Return non-zero if ADDR lies within one of L's segments. */ +int +internal_function +_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr) +{ + int n = l->l_phnum; + const ElfW(Addr) reladdr = addr - l->l_addr; + + while (--n >= 0) + if (l->l_phdr[n].p_type == PT_LOAD + && reladdr - l->l_phdr[n].p_vaddr >= 0 + && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz) + return 1; + return 0; +} +#endif diff --git a/elf/dl-sym.c b/elf/dl-sym.c index be0e7a64b4..b12ff375fe 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -98,10 +98,9 @@ do_sym (void *handle, const char *name, void *who, for (Lmid_t ns = 0; ns < DL_NNS; ++ns) for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) - if (caller >= l->l_map_start && caller < l->l_map_end) + if (caller >= l->l_map_start && caller < l->l_map_end + && (l->l_contiguous || _dl_addr_inside_object (l, caller))) { - /* There must be exactly one DSO for the range of the virtual - memory. Otherwise something is really broken. */ match = l; break; } |