* 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.
This commit is contained in:
Ulrich Drepper 2007-06-19 22:59:48 +00:00
parent ae1ad3aebb
commit 9be09e060f
9 changed files with 93 additions and 41 deletions

View file

@ -1,3 +1,25 @@
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>

View file

@ -1,5 +1,5 @@
/* 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
@ -56,9 +56,8 @@ dlinfo_doit (void *argsblock)
/* 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)

View file

@ -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;
}

View file

@ -1,5 +1,5 @@
/* 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.
@ -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;
}

View file

@ -1,5 +1,5 @@
/* 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
@ -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])
{

View file

@ -201,10 +201,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;
@ -662,3 +662,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

View file

@ -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;
}

View file

@ -187,6 +187,9 @@ struct link_map
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;

View file

@ -439,18 +439,18 @@ struct rtld_global
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
{
@ -534,15 +534,15 @@ struct rtld_global_ro
#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;
@ -571,9 +571,6 @@ struct rtld_global_ro
/* 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;
@ -657,6 +654,9 @@ struct rtld_global_ro
/* 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
@ -1061,6 +1061,8 @@ extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid);
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