1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
/* Copyright (C) 2011-2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
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
<http://www.gnu.org/licenses/>. */
/* Like x86_64, we pass the index of the relocation and not its offset.
In _dl_profile_fixup and _dl_call_pltexit we also use the index.
Therefore it is wasteful to compute the offset in the trampoline
just to reverse the operation immediately afterwards. */
#define reloc_offset reloc_arg * sizeof (PLTREL)
#define reloc_index reloc_arg
#include <elf/dl-runtime.c>
#include <sys/mman.h>
#include <arch/sim.h>
#include <dl-unmap-segments.h>
/* Like realpath(), but simplified: no dynamic memory use, no lstat(),
no set_errno(), no valid "rpath" on error, etc. This handles some
simple cases where the simulator might not have a valid entry for
a loaded Elf object, in particular dlopen() with a relative path.
For this relatively rare case, one could also imagine using
link_map.l_origin to avoid the getcwd() here, but the simpler code
here seems like a better solution. */
static char *
dl_realpath (const char *name, char *rpath)
{
char *dest;
const char *start, *end;
if (name[0] != '/')
{
if (!__getcwd (rpath, PATH_MAX))
return NULL;
dest = __rawmemchr (rpath, '\0');
}
else
{
rpath[0] = '/';
dest = rpath + 1;
}
for (start = end = name; *start; start = end)
{
/* Skip sequence of multiple path-separators. */
while (*start == '/')
++start;
/* Find end of path component. */
for (end = start; *end && *end != '/'; ++end)
/* Nothing. */;
if (end - start == 0)
break;
else if (end - start == 1 && start[0] == '.')
/* nothing */;
else if (end - start == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
if (dest > rpath + 1)
while ((--dest)[-1] != '/');
}
else
{
if (dest[-1] != '/')
*dest++ = '/';
if (dest + (end - start) >= rpath + PATH_MAX)
return NULL;
dest = __mempcpy (dest, start, end - start);
*dest = '\0';
}
}
if (dest > rpath + 1 && dest[-1] == '/')
--dest;
*dest = '\0';
return rpath;
}
/* Support notifying the simulator about new objects. */
void internal_function
_dl_after_load (struct link_map *l)
{
int shift;
char pathbuf[PATH_MAX];
char *path;
/* Don't bother if not in the simulator. */
if (__insn_mfspr (SPR_SIM_CONTROL) == 0)
return;
#define DLPUTC(c) __insn_mtspr (SPR_SIM_CONTROL, \
(SIM_CONTROL_DLOPEN \
| ((c) << _SIM_CONTROL_OPERATOR_BITS)))
/* Write the library address in hex. */
DLPUTC ('0');
DLPUTC ('x');
for (shift = (int) sizeof (unsigned long) * 8 - 4; shift >= 0; shift -= 4)
DLPUTC ("0123456789abcdef"[(l->l_map_start >> shift) & 0xF]);
DLPUTC (':');
/* Write the library path, including the terminating '\0'. */
path = dl_realpath (l->l_name, pathbuf) ?: l->l_name;
for (size_t i = 0;; i++)
{
DLPUTC (path[i]);
if (path[i] == '\0')
break;
}
#undef DLPUTC
}
/* Support notifying the simulator about removed objects prior to munmap(). */
static void
sim_dlclose (ElfW(Addr) map_start)
{
int shift;
/* Don't bother if not in the simulator. */
if (__insn_mfspr (SPR_SIM_CONTROL) == 0)
return;
#define DLPUTC(c) __insn_mtspr (SPR_SIM_CONTROL, \
(SIM_CONTROL_DLCLOSE \
| ((c) << _SIM_CONTROL_OPERATOR_BITS)))
/* Write the library address in hex. */
DLPUTC ('0');
DLPUTC ('x');
for (shift = (int) sizeof (unsigned long) * 8 - 4; shift >= 0; shift -= 4)
DLPUTC ("0123456789abcdef"[(map_start >> shift) & 0xF]);
DLPUTC ('\0');
#undef DLPUTC
}
void internal_function
_dl_unmap (struct link_map *map)
{
sim_dlclose (map->l_map_start);
_dl_unmap_segments (map);
}
|