+2007-06-19 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/generic/ldsodefs.h (rtld_global): Reorder some elements
+ to fill in holes
+ (rtld_global_ro): Likewise.
+
+2007-06-18 Jakub Jelinek <jakub@redhat.com>
+
+ * 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.
+
2007-06-18 Jakub Jelinek <jakub@redhat.com>
Tomas Janousek <tjanouse@redhat.com>
Ulrich Drepper <drepper@redhat.com>
/* dlinfo -- Get information from the dynamic linker.
- Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
/* Find the highest-addressed object that CALLER is not below. */
for (nsid = 0; nsid < DL_NNS; ++nsid)
for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
- if (caller >= l->l_map_start && caller < l->l_map_end)
- /* There must be exactly one DSO for the range of the virtual
- memory. Otherwise something is really broken. */
+ if (caller >= l->l_map_start && caller < l->l_map_end
+ && (l->l_contiguous || _dl_addr_inside_object (l, caller)))
break;
if (l == NULL)
/* 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:
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;
+}
/* Get loaded objects program headers.
- Copyright (C) 2001,2002,2003,2004,2006 Free Software Foundation, Inc.
+ Copyright (C) 2001,2002,2003,2004,2006,2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
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;
}
/* Map in a shared object's segments from the file.
- Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1995-2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
loadcmds[nloadcmds - 1].mapstart - c->mapend,
PROT_NONE);
+ l->l_contiguous = 1;
+
goto postmap;
}
/* 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])
{
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;
}
}
#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
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;
}
is interested in the PLT interception.*/
unsigned int l_removed:1; /* Nozero if the object cannot be used anymore
since it is removed. */
+ unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are
+ mprotected or if no holes are present at
+ all. */
/* Collected information about own RPATH directories. */
struct r_search_path_struct l_rpath_dirs;
EXTERN void (*_dl_rtld_unlock_recursive) (void *);
#endif
- /* Prevailing state of the stack, PF_X indicating it's executable. */
- EXTERN ElfW(Word) _dl_stack_flags;
-
/* If loading a shared object requires that we make the stack executable
when it was not, we do it by calling this function.
It returns an errno code or zero on success. */
EXTERN int (*_dl_make_stack_executable_hook) (void **) internal_function;
- /* Highest dtv index currently needed. */
- EXTERN size_t _dl_tls_max_dtv_idx;
+ /* Prevailing state of the stack, PF_X indicating it's executable. */
+ EXTERN ElfW(Word) _dl_stack_flags;
+
/* Flag signalling whether there are gaps in the module ID allocation. */
EXTERN bool _dl_tls_dtv_gaps;
+ /* Highest dtv index currently needed. */
+ EXTERN size_t _dl_tls_max_dtv_idx;
/* Information about the dtv slots. */
EXTERN struct dtv_slotinfo_list
{
#define DL_DEBUG_HELP (1 << 9)
#define DL_DEBUG_PRELINK (1 << 10)
- /* Cached value of `getpagesize ()'. */
- EXTERN size_t _dl_pagesize;
-
/* OS version. */
EXTERN unsigned int _dl_osversion;
/* Platform name. */
EXTERN const char *_dl_platform;
EXTERN size_t _dl_platformlen;
+ /* Cached value of `getpagesize ()'. */
+ EXTERN size_t _dl_pagesize;
+
/* Copy of the content of `_dl_main_searchlist' at startup time. */
EXTERN struct r_scope_elem _dl_initial_searchlist;
/* Expected cache ID. */
EXTERN int _dl_correct_cache_id;
- /* 0 if internal pointer values should not be guarded, 1 if they should. */
- EXTERN int _dl_pointer_guard;
-
/* Mask for hardware capabilities that are available. */
EXTERN uint64_t _dl_hwcap;
/* List of auditing interfaces. */
struct audit_ifaces *_dl_audit;
unsigned int _dl_naudit;
+
+ /* 0 if internal pointer values should not be guarded, 1 if they should. */
+ EXTERN int _dl_pointer_guard;
};
# define __rtld_global_attribute__
# ifdef IS_IN_rtld
but never touch anything. Return null if it's not allocated yet. */
extern void *_dl_tls_get_addr_soft (struct link_map *l) internal_function;
+extern int _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
+ internal_function attribute_hidden;
__END_DECLS