aboutsummaryrefslogtreecommitdiff
path: root/elf/rtld.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c110
1 files changed, 63 insertions, 47 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index 87a86be..943901f 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -95,14 +95,6 @@ struct rtld_global _rtld_global =
/* Get architecture specific initializer. */
#include <dl-procinfo.c>
._dl_debug_fd = STDERR_FILENO,
-#ifdef NEED_DL_SYSINFO
- ._dl_sysinfo = DL_SYSINFO_DEFAULT,
-#endif
- ._dl_lazy = 1,
- ._dl_use_load_bias = -2,
- ._dl_fpu_control = _FPU_DEFAULT,
- ._dl_correct_cache_id = _DL_CACHE_DEFAULT_ID,
- ._dl_hwcap_mask = HWCAP_IMPORTANT,
/* Default presumption without further information is executable stack. */
._dl_stack_flags = PF_R|PF_W|PF_X,
#ifdef _LIBC_REENTRANT
@@ -116,6 +108,28 @@ struct rtld_global _rtld_global =
extern struct rtld_global _rtld_local
__attribute__ ((alias ("_rtld_global"), visibility ("hidden")));
+
+/* This variable is similar to _rtld_local, but all values are
+ read-only after relocation. */
+struct rtld_global_ro _rtld_global_ro attribute_relro =
+ {
+#ifdef NEED_DL_SYSINFO
+ ._dl_sysinfo = DL_SYSINFO_DEFAULT,
+#endif
+ ._dl_use_load_bias = -2,
+ ._dl_correct_cache_id = _DL_CACHE_DEFAULT_ID,
+ ._dl_hwcap_mask = HWCAP_IMPORTANT,
+ ._dl_lazy = 1,
+ ._dl_fpu_control = _FPU_DEFAULT,
+ };
+/* If we would use strong_alias here the compiler would see a
+ non-hidden definition. This would undo the effect of the previous
+ declaration. So spell out was strong_alias does plus add the
+ visibility attribute. */
+extern struct rtld_global_ro _rtld_local_ro
+ __attribute__ ((alias ("_rtld_global_ro"), visibility ("hidden")));
+
+
static void dl_main (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry);
@@ -280,7 +294,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
}
#endif
- if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
+ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0))
{
#ifndef HP_TIMING_NONAVAIL
print_statistics (&rtld_total_time);
@@ -712,7 +726,7 @@ dl_main (const ElfW(Phdr) *phdr,
if (! strcmp (INTUSE(_dl_argv)[1], "--list"))
{
mode = list;
- GL(dl_lazy) = -1; /* This means do no dependency analysis. */
+ GLRO(dl_lazy) = -1; /* This means do no dependency analysis. */
++_dl_skip_args;
--_dl_argc;
@@ -738,7 +752,7 @@ dl_main (const ElfW(Phdr) *phdr,
else if (! strcmp (INTUSE(_dl_argv)[1], "--inhibit-rpath")
&& _dl_argc > 2)
{
- GL(dl_inhibit_rpath) = INTUSE(_dl_argv)[2];
+ GLRO(dl_inhibit_rpath) = INTUSE(_dl_argv)[2];
_dl_skip_args += 2;
_dl_argc -= 2;
@@ -1035,8 +1049,8 @@ of this helper program; chances are you did not intend to run this program.\n\
/* If LD_USE_LOAD_BIAS env variable has not been seen, default
to not using bias for non-prelinked PIEs and libraries
and using it for executables or prelinked PIEs or libraries. */
- if (GL(dl_use_load_bias) == (ElfW(Addr)) -2)
- GL(dl_use_load_bias) = (GL(dl_loaded)->l_addr == 0) ? -1 : 0;
+ if (GLRO(dl_use_load_bias) == (ElfW(Addr)) -2)
+ GLRO(dl_use_load_bias) = (GL(dl_loaded)->l_addr == 0) ? -1 : 0;
/* Set up the program header information for the dynamic linker
itself. It is needed in the dl_iterate_phdr() callbacks. */
@@ -1212,7 +1226,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
#ifdef NEED_DL_SYSINFO
struct link_map *sysinfo_map = NULL;
- if (GL(dl_sysinfo_dso) != NULL)
+ if (GLRO(dl_sysinfo_dso) != NULL)
{
/* 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
@@ -1224,9 +1238,9 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
{
static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT];
- l->l_phdr = ((const void *) GL(dl_sysinfo_dso)
- + GL(dl_sysinfo_dso)->e_phoff);
- l->l_phnum = GL(dl_sysinfo_dso)->e_phnum;
+ 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];
@@ -1243,7 +1257,7 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
l->l_map_end = ph->p_vaddr + ph->p_memsz;
}
}
- l->l_map_start = (ElfW(Addr)) GL(dl_sysinfo_dso);
+ 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_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr);
@@ -1269,8 +1283,8 @@ ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
}
/* We have a prelinked DSO preloaded by the system. */
- if (GL(dl_sysinfo) == DL_SYSINFO_DEFAULT)
- GL(dl_sysinfo) = GL(dl_sysinfo_dso)->e_entry + l->l_addr;
+ if (GLRO(dl_sysinfo) == DL_SYSINFO_DEFAULT)
+ GLRO(dl_sysinfo) = GLRO(dl_sysinfo_dso)->e_entry + l->l_addr;
sysinfo_map = l;
}
}
@@ -1437,7 +1451,7 @@ cannot allocate TLS data structures for initial thread");
after relocation. */
struct link_map *l;
- if (GL(dl_debug_mask) & DL_DEBUG_PRELINK)
+ if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
{
struct r_scope_elem *scope = &GL(dl_loaded)->l_searchlist;
@@ -1449,8 +1463,8 @@ cannot allocate TLS data structures for initial thread");
_dl_printf ("\t%s => not found\n", l->l_libname->name);
continue;
}
- if (_dl_name_match_p (GL(dl_trace_prelink), l))
- GL(dl_trace_prelink_map) = l;
+ if (_dl_name_match_p (GLRO(dl_trace_prelink), l))
+ GLRO(dl_trace_prelink_map) = l;
_dl_printf ("\t%s => %s (0x%0*Zx, 0x%0*Zx)",
l->l_libname->name[0] ? l->l_libname->name
: rtld_progname ?: "<main program>",
@@ -1507,13 +1521,13 @@ cannot allocate TLS data structures for initial thread");
else
{
/* If LD_WARN is set warn about undefined symbols. */
- if (GL(dl_lazy) >= 0 && GL(dl_verbose))
+ if (GLRO(dl_lazy) >= 0 && GLRO(dl_verbose))
{
/* We have to do symbol dependency testing. */
struct relocate_args args;
struct link_map *l;
- args.lazy = GL(dl_lazy);
+ args.lazy = GLRO(dl_lazy);
l = GL(dl_loaded);
while (l->l_next)
@@ -1529,7 +1543,7 @@ cannot allocate TLS data structures for initial thread");
l = l->l_prev;
} while (l);
- if ((GL(dl_debug_mask) & DL_DEBUG_PRELINK)
+ if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
&& GL(dl_rtld_map).l_opencount > 1)
INTUSE(_dl_relocate_object) (&GL(dl_rtld_map),
GL(dl_loaded)->l_scope, 0, 0);
@@ -1612,7 +1626,7 @@ cannot allocate TLS data structures for initial thread");
}
if (GL(dl_loaded)->l_info [ADDRIDX (DT_GNU_LIBLIST)]
- && ! __builtin_expect (GL(dl_profile) != NULL, 0))
+ && ! __builtin_expect (GLRO(dl_profile) != NULL, 0))
{
ElfW(Lib) *liblist, *liblistend;
struct link_map **r_list, **r_listend, *l;
@@ -1660,7 +1674,7 @@ cannot allocate TLS data structures for initial thread");
if (r_list == r_listend && liblist == liblistend)
prelinked = true;
- if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
_dl_printf ("\nprelink checking: %s\n", prelinked ? "ok" : "failed");
}
@@ -1740,7 +1754,7 @@ cannot allocate TLS data structures for initial thread");
know that because it is self-contained). */
struct link_map *l;
- int consider_profiling = GL(dl_profile) != NULL;
+ int consider_profiling = GLRO(dl_profile) != NULL;
#ifndef HP_TIMING_NONAVAIL
hp_timing_t start;
hp_timing_t stop;
@@ -1748,7 +1762,7 @@ cannot allocate TLS data structures for initial thread");
#endif
/* If we are profiling we also must do lazy reloaction. */
- GL(dl_lazy) |= consider_profiling;
+ GLRO(dl_lazy) |= consider_profiling;
l = GL(dl_loaded);
while (l->l_next)
@@ -1769,7 +1783,7 @@ cannot allocate TLS data structures for initial thread");
}
if (l != &GL(dl_rtld_map))
- INTUSE(_dl_relocate_object) (l, l->l_scope, GL(dl_lazy),
+ INTUSE(_dl_relocate_object) (l, l->l_scope, GLRO(dl_lazy),
consider_profiling);
l = l->l_prev;
@@ -1792,7 +1806,8 @@ cannot allocate TLS data structures for initial thread");
needs to have _dl_profile_map set up by the relocator. */
if (__builtin_expect (GL(dl_profile_map) != NULL, 0))
/* We must prepare the profiling. */
- INTUSE(_dl_start_profile) (GL(dl_profile_map), GL(dl_profile_output));
+ INTUSE(_dl_start_profile) (GL(dl_profile_map),
+ GLRO(dl_profile_output));
if (GL(dl_rtld_map).l_opencount > 1)
{
@@ -1928,7 +1943,7 @@ process_dl_debug (const char *dl_debug)
if (debopts[cnt].len == len
&& memcmp (dl_debug, debopts[cnt].name, len) == 0)
{
- GL(dl_debug_mask) |= debopts[cnt].mask;
+ GLRO(dl_debug_mask) |= debopts[cnt].mask;
any_debug = 1;
break;
}
@@ -1949,7 +1964,7 @@ warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy);
++dl_debug;
}
- if (GL(dl_debug_mask) & DL_DEBUG_HELP)
+ if (GLRO(dl_debug_mask) & DL_DEBUG_HELP)
{
size_t cnt;
@@ -1983,7 +1998,7 @@ process_envvars (enum mode *modep)
char *debug_output = NULL;
/* This is the default place for profiling data file. */
- GL(dl_profile_output)
+ GLRO(dl_profile_output)
= &"/var/tmp\0/var/profile"[INTUSE(__libc_enable_secure) ? 9 : 0];
while ((envline = _dl_next_ld_env_entry (&runp)) != NULL)
@@ -2004,7 +2019,7 @@ process_envvars (enum mode *modep)
case 4:
/* Warning level, verbose or not. */
if (memcmp (envline, "WARN", 4) == 0)
- GL(dl_verbose) = envline[5] != '\0';
+ GLRO(dl_verbose) = envline[5] != '\0';
break;
case 5:
@@ -2030,18 +2045,18 @@ process_envvars (enum mode *modep)
/* Which shared object shall be profiled. */
if (memcmp (envline, "PROFILE", 7) == 0 && envline[8] != '\0')
- GL(dl_profile) = &envline[8];
+ GLRO(dl_profile) = &envline[8];
break;
case 8:
/* Do we bind early? */
if (memcmp (envline, "BIND_NOW", 8) == 0)
{
- GL(dl_lazy) = envline[9] == '\0';
+ GLRO(dl_lazy) = envline[9] == '\0';
break;
}
if (memcmp (envline, "BIND_NOT", 8) == 0)
- GL(dl_bind_not) = envline[9] != '\0';
+ GLRO(dl_bind_not) = envline[9] != '\0';
break;
case 9:
@@ -2054,14 +2069,15 @@ process_envvars (enum mode *modep)
case 10:
/* Mask for the important hardware capabilities. */
if (memcmp (envline, "HWCAP_MASK", 10) == 0)
- GL(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL, 0, 0);
+ GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL,
+ 0, 0);
break;
case 11:
/* Path where the binary is found. */
if (!INTUSE(__libc_enable_secure)
&& memcmp (envline, "ORIGIN_PATH", 11) == 0)
- GL(dl_origin_path) = &envline[12];
+ GLRO(dl_origin_path) = &envline[12];
break;
case 12:
@@ -2080,7 +2096,7 @@ process_envvars (enum mode *modep)
}
if (memcmp (envline, "DYNAMIC_WEAK", 12) == 0)
- GL(dl_dynamic_weak) = 1;
+ GLRO(dl_dynamic_weak) = 1;
break;
case 13:
@@ -2091,7 +2107,7 @@ process_envvars (enum mode *modep)
#endif
if (!INTUSE(__libc_enable_secure)
&& memcmp (envline, "USE_LOAD_BIAS", 13) == 0)
- GL(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
+ GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
break;
case 14:
@@ -2099,7 +2115,7 @@ process_envvars (enum mode *modep)
if (!INTUSE(__libc_enable_secure)
&& memcmp (envline, "PROFILE_OUTPUT", 14) == 0
&& envline[15] != '\0')
- GL(dl_profile_output) = &envline[15];
+ GLRO(dl_profile_output) = &envline[15];
break;
case 16:
@@ -2107,9 +2123,9 @@ process_envvars (enum mode *modep)
if (memcmp (envline, "TRACE_PRELINKING", 16) == 0)
{
mode = trace;
- GL(dl_verbose) = 1;
- GL(dl_debug_mask) |= DL_DEBUG_PRELINK;
- GL(dl_trace_prelink) = &envline[17];
+ GLRO(dl_verbose) = 1;
+ GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
+ GLRO(dl_trace_prelink) = &envline[17];
}
break;