@@ -27,6 +27,7 @@ routines = \
dladdr1 \
dlclose \
dlrelocate \
+ dlset_object_base \
dlerror \
dlinfo \
dlmopen \
@@ -30,6 +30,7 @@ libc {
}
GLIBC_2.38 {
dlrelocate;
+ dlset_object_base;
}
GLIBC_PRIVATE {
__libc_dlerror_result;
@@ -71,6 +71,10 @@ extern void *dlmopen (Lmid_t __nsid, const char *__file, int __mode) __THROWNL;
/* Relocate a shared object opened by `dlopen' with `RTLD_NORELOCATE'. */
extern int dlrelocate (void *__handle) __THROWNL __nonnull ((1));
+/* Set a new base address of a shared object opened by `dlopen' with
+ `RTLD_NORELOCATE' and then moved by user. */
+extern int dlset_object_base (void *handle, void *base);
+
/* Find the run-time address in the shared object HANDLE refers to
of the symbol called NAME with VERSION. */
extern void *dlvsym (void *__restrict __handle,
new file mode 100644
@@ -0,0 +1,124 @@
+/* Set the new base address for shared object loaded by `dlopen' with
+ `RTLD_NORELOCATE' and moved by the user.
+ Copyright (C) 1995-2023 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
+ 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <ldsodefs.h>
+#include <shlib-compat.h>
+#include <stddef.h>
+#include <array_length.h>
+
+static void
+adjust_dyn_info (ElfW(Dyn) **info, ptrdiff_t delta)
+{
+# define ADJUST_DYN_INFO(tag) \
+ do \
+ { \
+ if (info[tag] != NULL) \
+ info[tag]->d_un.d_ptr += delta; \
+ } \
+ while (0)
+
+ ADJUST_DYN_INFO (DT_HASH);
+ ADJUST_DYN_INFO (DT_PLTGOT);
+ ADJUST_DYN_INFO (DT_STRTAB);
+ ADJUST_DYN_INFO (DT_SYMTAB);
+ ADJUST_DYN_INFO (DT_RELR);
+ ADJUST_DYN_INFO (DT_JMPREL);
+ ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
+ ADJUST_DYN_INFO (ADDRIDX (DT_GNU_HASH));
+# undef ADJUST_DYN_INFO
+
+ /* DT_RELA/DT_REL are mandatory. But they may have zero value if
+ there is DT_RELR. Don't relocate them if they are zero. */
+# define ADJUST_DYN_INFO(tag) \
+ do \
+ if (info[tag] != NULL && info[tag]->d_un.d_ptr != 0) \
+ info[tag]->d_un.d_ptr += delta; \
+ while (0)
+
+ ADJUST_DYN_INFO (DT_RELA);
+ ADJUST_DYN_INFO (DT_REL);
+# undef ADJUST_DYN_INFO
+}
+
+static int
+dlset_object_base_implementation (void *handle, void *base)
+{
+ struct link_map *l = handle;
+ int result = 0;
+
+ /* Protect against concurrent loads and unloads. */
+ __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+ if (l->l_relocated)
+ result = -1;
+ else
+ {
+ ptrdiff_t delta = (uintptr_t) base - l->l_map_start;
+ if (delta)
+ {
+ int i;
+
+ l->l_map_start += delta;
+ l->l_map_end += delta;
+ l->l_addr += delta;
+ l->l_text_end += delta;
+ l->l_entry += delta;
+ if (!l->l_phdr_allocated)
+ l->l_phdr = (__typeof (l->l_phdr)) (((uintptr_t) l->l_phdr)
+ + delta);
+ l->l_ld = (__typeof (l->l_ld)) (((uintptr_t) l->l_ld) + delta);
+ for (i = 0; i < array_length (l->l_info); i++)
+ if (l->l_info[i])
+ l->l_info[i] = (__typeof (l->l_info[i])) (((uintptr_t)
+ l->l_info[i])
+ + delta);
+ l->l_versyms = (__typeof (l->l_versyms)) (((uintptr_t) l->l_versyms)
+ + delta);
+ l->l_gnu_bitmask = (__typeof (l->l_gnu_bitmask))
+ (((uintptr_t) l->l_gnu_bitmask)
+ + delta);
+ l->l_chain = (__typeof (l->l_chain)) (((uintptr_t) l->l_chain)
+ + delta);
+ l->l_buckets = (__typeof (l->l_buckets)) (((uintptr_t) l->l_buckets)
+ + delta);
+ adjust_dyn_info (l->l_info, delta);
+ }
+ }
+
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+ return result;
+}
+
+int
+__dlset_object_base (void *handle, void *base)
+{
+#ifdef SHARED
+ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlset_object_base (handle, base);
+#endif
+ return dlset_object_base_implementation (handle, base);
+}
+#ifdef SHARED
+versioned_symbol (libc, __dlset_object_base, dlset_object_base, GLIBC_2_38);
+#else /* !SHARED */
+/* Also used with _dlfcn_hook. */
+weak_alias (__dlset_object_base, dlset_object_base)
+#endif /* !SHARED */
@@ -22,10 +22,37 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/mman.h>
#include <support/check.h>
int ctor_called;
+static void move_object (void *handle)
+{
+ int ret;
+ Dl_mapinfo mapinfo;
+ void *new_addr;
+
+ ret = dlinfo (handle, RTLD_DI_MAPINFO, &mapinfo);
+ TEST_COMPARE (ret, 0);
+ TEST_COMPARE (mapinfo.relocated, 0);
+ if (mapinfo.map_align != getpagesize ())
+ error (EXIT_FAILURE, 0, "unsupported map alignment");
+#ifndef MAP_32BIT
+#define MAP_32BIT 0
+#endif
+ new_addr = mmap (NULL, mapinfo.map_length, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
+ if (new_addr == MAP_FAILED)
+ error (EXIT_FAILURE, 0, "cannot mmap buffer");
+ memcpy (new_addr, mapinfo.map_start, mapinfo.map_length);
+ ret = dlset_object_base (handle, new_addr);
+ TEST_COMPARE (ret, 0);
+ munmap (mapinfo.map_start, mapinfo.map_length);
+}
+
static int
do_test (void)
{
@@ -64,10 +91,27 @@ do_test (void)
error (EXIT_FAILURE, 0, "dlsym failed");
TEST_COMPARE (ctor_called, 1);
+ dlclose (handle);
+ ctor_called = 0;
+ handle = dlopen ("ctorlib1.so", RTLD_NOW | RTLD_NORELOCATE);
+ if (handle == NULL)
+ error (EXIT_FAILURE, 0, "cannot load: ctorlib1.so");
+
+ move_object (handle);
+
+ TEST_COMPARE (ctor_called, 0);
+ sym = dlsym (handle, "ref1");
+ if (sym == NULL)
+ error (EXIT_FAILURE, 0, "dlsym failed");
+ TEST_COMPARE (ctor_called, 1);
+
memset (&info, 0, sizeof (info));
ret = dladdr (sym, &info);
if (ret == 0)
error (EXIT_FAILURE, 0, "dladdr failed");
+#if MAP_32BIT != 0
+ TEST_VERIFY ((uintptr_t) info.dli_fbase < 0x100000000);
+#endif
printf ("ret = %d\n", ret);
printf ("info.dli_fname = %p (\"%s\")\n", info.dli_fname, info.dli_fname);
@@ -59,6 +59,8 @@ extern int __libc_dlclose (void *__map)
attribute_hidden;
extern int __libc_dlrelocate (void *__map)
attribute_hidden;
+extern int __libc_dlset_object_base (void *__map, void *base)
+ attribute_hidden;
/* Locate shared object containing the given address. */
#ifdef ElfW
@@ -107,6 +109,7 @@ struct dlfcn_hook
void *(*dlopen) (const char *file, int mode, void *dl_caller);
int (*dlclose) (void *handle);
int (*dlrelocate) (void *handle);
+ int (*dlset_object_base) (void *handle, void *base);
void *(*dlsym) (void *handle, const char *name, void *dl_caller);
void *(*dlvsym) (void *handle, const char *name, const char *version,
void *dl_caller);
@@ -133,6 +136,7 @@ extern void *__dlmopen (Lmid_t nsid, const char *file, int mode,
void *dl_caller);
extern int __dlclose (void *handle);
extern int __dlrelocate (void *handle);
+extern int __dlset_object_base (void *handle, void *base);
extern void *__dlsym (void *handle, const char *name, void *dl_caller);
extern void *__dlvsym (void *handle, const char *name, const char *version,
void *dl_caller);
@@ -2327,6 +2327,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2666,3 +2666,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2775,6 +2775,7 @@ GLIBC_2.38 __nldbl___isoc23_vswscanf F
GLIBC_2.38 __nldbl___isoc23_vwscanf F
GLIBC_2.38 __nldbl___isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
GLIBC_2.4 _IO_sprintf F
@@ -2427,3 +2427,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -547,6 +547,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
@@ -544,6 +544,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
@@ -2703,3 +2703,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2652,6 +2652,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2836,6 +2836,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2601,6 +2601,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2187,3 +2187,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -548,6 +548,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0x98
GLIBC_2.4 _IO_2_1_stdin_ D 0x98
@@ -2779,6 +2779,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2752,3 +2752,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2749,3 +2749,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2744,6 +2744,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2742,6 +2742,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2750,6 +2750,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2652,6 +2652,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2791,3 +2791,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2173,3 +2173,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2818,6 +2818,7 @@ GLIBC_2.38 __nldbl___isoc23_vswscanf F
GLIBC_2.38 __nldbl___isoc23_vwscanf F
GLIBC_2.38 __nldbl___isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
GLIBC_2.4 _IO_sprintf F
@@ -2851,6 +2851,7 @@ GLIBC_2.38 __nldbl___isoc23_vswscanf F
GLIBC_2.38 __nldbl___isoc23_vwscanf F
GLIBC_2.38 __nldbl___isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
GLIBC_2.4 _IO_sprintf F
@@ -2572,6 +2572,7 @@ GLIBC_2.38 __nldbl___isoc23_vswscanf F
GLIBC_2.38 __nldbl___isoc23_vwscanf F
GLIBC_2.38 __nldbl___isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
GLIBC_2.4 _IO_sprintf F
@@ -2886,3 +2886,4 @@ GLIBC_2.38 __nldbl___isoc23_vswscanf F
GLIBC_2.38 __nldbl___isoc23_vwscanf F
GLIBC_2.38 __nldbl___isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2429,3 +2429,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2629,3 +2629,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
@@ -2816,6 +2816,7 @@ GLIBC_2.38 __nldbl___isoc23_vswscanf F
GLIBC_2.38 __nldbl___isoc23_vwscanf F
GLIBC_2.38 __nldbl___isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
GLIBC_2.4 _IO_sprintf F
@@ -2609,6 +2609,7 @@ GLIBC_2.38 __nldbl___isoc23_vswscanf F
GLIBC_2.38 __nldbl___isoc23_vwscanf F
GLIBC_2.38 __nldbl___isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
GLIBC_2.4 _IO_sprintf F
@@ -2659,6 +2659,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2656,6 +2656,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2811,6 +2811,7 @@ GLIBC_2.38 __nldbl___isoc23_vswscanf F
GLIBC_2.38 __nldbl___isoc23_vwscanf F
GLIBC_2.38 __nldbl___isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 _IO_fprintf F
GLIBC_2.4 _IO_printf F
GLIBC_2.4 _IO_sprintf F
@@ -2624,6 +2624,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2575,6 +2575,7 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F
GLIBC_2.4 __confstr_chk F
GLIBC_2.4 __fgets_chk F
GLIBC_2.4 __fgets_unlocked_chk F
@@ -2681,3 +2681,4 @@ GLIBC_2.38 __isoc23_wcstoull_l F
GLIBC_2.38 __isoc23_wcstoumax F
GLIBC_2.38 __isoc23_wscanf F
GLIBC_2.38 dlrelocate F
+GLIBC_2.38 dlset_object_base F