2012-10-05 17:20:39 +00:00
|
|
|
/* Set up the data structures for the system-supplied DSO.
|
2019-01-01 00:11:28 +00:00
|
|
|
Copyright (C) 2012-2019 Free Software Foundation, Inc.
|
2012-10-05 17:20:39 +00:00
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with the GNU C Library; if not, see
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 05:40:42 +00:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
2012-10-05 17:20:39 +00:00
|
|
|
|
|
|
|
static inline void __attribute__ ((always_inline))
|
|
|
|
setup_vdso (struct link_map *main_map __attribute__ ((unused)),
|
|
|
|
struct link_map ***first_preload __attribute__ ((unused)))
|
|
|
|
{
|
2013-03-01 22:44:44 +00:00
|
|
|
#ifdef NEED_DL_SYSINFO_DSO
|
2012-10-05 17:20:39 +00:00
|
|
|
if (GLRO(dl_sysinfo_dso) == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Do an abridged version of the work _dl_map_object_from_fd would do
|
|
|
|
to map in the object. It's already mapped and prelinked (and
|
|
|
|
better be, since it's read-only and so we couldn't relocate it).
|
|
|
|
We just want our data structures to describe it as if we had just
|
|
|
|
mapped and relocated it normally. */
|
|
|
|
struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
|
|
|
|
0, LM_ID_BASE);
|
2014-02-10 13:45:42 +00:00
|
|
|
if (__glibc_likely (l != NULL))
|
2012-10-05 17:20:39 +00:00
|
|
|
{
|
|
|
|
static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro;
|
|
|
|
|
|
|
|
l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
|
|
|
|
+ GLRO(dl_sysinfo_dso)->e_phoff);
|
|
|
|
l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum;
|
|
|
|
for (uint_fast16_t i = 0; i < l->l_phnum; ++i)
|
|
|
|
{
|
|
|
|
const ElfW(Phdr) *const ph = &l->l_phdr[i];
|
|
|
|
if (ph->p_type == PT_DYNAMIC)
|
|
|
|
{
|
|
|
|
l->l_ld = (void *) ph->p_vaddr;
|
|
|
|
l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
|
|
|
|
}
|
|
|
|
else if (ph->p_type == PT_LOAD)
|
|
|
|
{
|
|
|
|
if (! l->l_addr)
|
|
|
|
l->l_addr = ph->p_vaddr;
|
|
|
|
if (ph->p_vaddr + ph->p_memsz >= l->l_map_end)
|
|
|
|
l->l_map_end = ph->p_vaddr + ph->p_memsz;
|
|
|
|
if ((ph->p_flags & PF_X)
|
|
|
|
&& ph->p_vaddr + ph->p_memsz >= l->l_text_end)
|
|
|
|
l->l_text_end = ph->p_vaddr + ph->p_memsz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* There must be no TLS segment. */
|
|
|
|
assert (ph->p_type != PT_TLS);
|
|
|
|
}
|
|
|
|
l->l_map_start = (ElfW(Addr)) GLRO(dl_sysinfo_dso);
|
|
|
|
l->l_addr = l->l_map_start - l->l_addr;
|
|
|
|
l->l_map_end += l->l_addr;
|
|
|
|
l->l_text_end += l->l_addr;
|
|
|
|
l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr);
|
|
|
|
elf_get_dynamic_info (l, dyn_temp);
|
|
|
|
_dl_setup_hash (l);
|
|
|
|
l->l_relocated = 1;
|
|
|
|
|
|
|
|
/* The vDSO is always used. */
|
|
|
|
l->l_used = 1;
|
|
|
|
|
|
|
|
/* Initialize l_local_scope to contain just this map. This allows
|
|
|
|
the use of dl_lookup_symbol_x to resolve symbols within the vdso.
|
|
|
|
So we create a single entry list pointing to l_real as its only
|
|
|
|
element */
|
|
|
|
l->l_local_scope[0]->r_nlist = 1;
|
|
|
|
l->l_local_scope[0]->r_list = &l->l_real;
|
|
|
|
|
|
|
|
/* Now that we have the info handy, use the DSO image's soname
|
|
|
|
so this object can be looked up by name. Note that we do not
|
|
|
|
set l_name here. That field gives the file name of the DSO,
|
|
|
|
and this DSO is not associated with any file. */
|
|
|
|
if (l->l_info[DT_SONAME] != NULL)
|
|
|
|
{
|
|
|
|
/* Work around a kernel problem. The kernel cannot handle
|
|
|
|
addresses in the vsyscall DSO pages in writev() calls. */
|
|
|
|
const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
|
|
|
|
+ l->l_info[DT_SONAME]->d_un.d_val);
|
2013-08-20 12:03:04 +00:00
|
|
|
size_t len = strlen (dsoname) + 1;
|
2012-10-05 17:20:39 +00:00
|
|
|
char *copy = malloc (len);
|
|
|
|
if (copy == NULL)
|
|
|
|
_dl_fatal_printf ("out of memory\n");
|
|
|
|
l->l_libname->name = l->l_name = memcpy (copy, dsoname, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add the vDSO to the object list. */
|
|
|
|
_dl_add_to_namespace_list (l, LM_ID_BASE);
|
|
|
|
|
2014-11-20 15:39:43 +00:00
|
|
|
# if IS_IN (rtld)
|
2012-10-05 17:20:39 +00:00
|
|
|
/* Rearrange the list so this DSO appears after rtld_map. */
|
|
|
|
assert (l->l_next == NULL);
|
|
|
|
assert (l->l_prev == main_map);
|
|
|
|
GL(dl_rtld_map).l_next = l;
|
|
|
|
l->l_prev = &GL(dl_rtld_map);
|
|
|
|
*first_preload = &l->l_next;
|
2012-10-05 17:22:14 +00:00
|
|
|
# else
|
|
|
|
GL(dl_nns) = 1;
|
2012-10-05 17:20:39 +00:00
|
|
|
# endif
|
|
|
|
|
|
|
|
/* We have a prelinked DSO preloaded by the system. */
|
|
|
|
GLRO(dl_sysinfo_map) = l;
|
|
|
|
# ifdef NEED_DL_SYSINFO
|
|
|
|
if (GLRO(dl_sysinfo) == DL_SYSINFO_DEFAULT)
|
|
|
|
GLRO(dl_sysinfo) = GLRO(dl_sysinfo_dso)->e_entry + l->l_addr;
|
|
|
|
# endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|