public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007]
@ 2023-05-18  8:28 Stas Sergeev
  2023-05-18  8:28 ` [PATCH 01/14] elf: switch _dl_map_segment() to anonymous mapping Stas Sergeev
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

RTLD_NORELOCATE api is a proposal that adds a fine-grained control
over the solib dynamic-load process. It allows the user to load the
solib to the particular address he needs, using the mapping type he
needs. The basic idea is that after loading the solib with RTLD_NORELOCATE
flag, the user can move an unrelocated object before relocating it.

The API consist of the following elements:

`RTLD_NORELOCATE' - new dlopen() flag.
It defers the relocation of an object, allowing to perform the
relocation later. Ctors are delayed, and are called immediately
after the relocation is done.
Relocation is performed upon the first dlsym() or dlrelocate()
call with the obtained handle. This flag doesn't delay the
load of an object deps, but their relocation and ctors are
delayed. This flag doesn't delay the LA_ACT_CONSISTENT audit event.


`int dlrelocate(void *handle)' - new function to perform the
object relocation if the RTLD_NORELOCATE flag was used. The object
itself and all of its dependencies are relocated.
Returns EINVAL if already relocated. This function may be omitted
even if RTLD_NORELOCATE was used, in which case the relocation will
be performed upon the first dlsym() call with the obtained handle,
but using dlrelocate() function allows to handle relocation errors
and run ctors before using the object's handle. If the function
returned success then ctors of an object and all of its deps were
called by it.
If it returned error other than EINVAL (EINVAL means object
already relocated), then relocation error happened and the
handle should be closed with dlclose().


`RTLD_DI_MAPINFO' - new dlinfo() request that fills in this structure:
typedef struct
{
  void *map_start;		/* Beginning of mapping containing address.  */
  size_t map_length;		/* Length of mapping.  */
  size_t map_align;		/* Alignment of mapping.  */
  int relocated;		/* Indicates whether an object was relocated. */
} Dl_mapinfo;

The user have to check the `relocated` member, and if it is 0
then the object can be moved to the new location. The new location
must be aligned according to the `map_aligned' member, which is
usually equal to a page size. One way to move a solib image is to
use mmap() for allocating a new memory mapping, then use memcpy()
to copy an image, and finally use munmap() to unmap the memory space
at an old location.
This request may fail if the used handle was not obtained from dlopen().


`int dlset_object_base(void *handle, void *addr)' - new function to
set the new base address of an unrelocated object, after it was moved.
Returns error if the object is already relocated. The base address
set by this function, will be used when relocation is performed.


`RTLD_DI_DEPLIST' is a new dlinfo() request that fills in this structure:
typedef struct
{
  void **deps;			/* Array of handles for the deps.  */
  unsigned int ndeps;		/* Number of entries in the list.  */
} Dl_deplist;

It is needed if the user wants to move also the dependencies of the
loaded solib. In this case he needs to traverse the `deps' array,
make RTLD_DI_MAPINFO dlinfo() request per each handle from an array,
find the object he needs by inspecting the filled-in Dl_mapinfo structure,
make sure this object is not relocated yet, and move it, calling
dlset_object_base() at the end.


Use-case.

Suppose you have a VM that runs a 32bit code. Suppose you wrote a
compatibility layer that allows to compile the old 32bit non-unix code
under linux, into the native 64bit shared libraries. But compiling is
not enough and some calls should still go to a VM. VM's memory is available
in a 4Gb window somewhere in a 64bit space. In order for the code under
VM to handle the calls from a 64bit solib, you need to make sure all
pointers, that may be passed as a call arguments, are within 32 bits.
Heap and stack are dealt with by a custom libc, but in order to use
pointers to .bss objects, we need to relocate the solib to the low 32bit
address. But that's not enough, because in order for that lib to be
visible to the code under VM, it must also be mirrored to the VM window
under the map_address = reloc_address+VM_window_start.

RTLD_NORELOCATE solves that problem by allowing the user to mmap the
shared memory into the low 32bit address space and move an object there.
He may want to do so for all the library deps as well (using RTLD_DI_DEPLIST),
or only with the ones he is interested in. Then he maps the shared memory
into the VM window and either calls dlrelocate() or just starts using the
solib, in which case it will be relocated on the first symbol lookup.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 01/14] elf: switch _dl_map_segment() to anonymous mapping
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 02/14] use initial mmap also for ET_EXEC Stas Sergeev
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

_dl_map_segment() was mapping entire file image and then was skipping
the load of the first segment. Switch _dl_map_segment() to anonymous
mapping and do not skip the map of the first segment.

Use PROT_READ|PROT_WRITE as a protection. _dl_map_segments() later
sets the proper protection for both file-mapped and anonymous parts.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-map-segments.h | 69 ++++++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 34 deletions(-)

diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index 504cfc0a41..ed7675cabf 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -22,18 +22,22 @@
 /* Map a segment and align it properly.  */
 
 static __always_inline ElfW(Addr)
-_dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
-		 const size_t maplength, int fd)
+_dl_map_segment (ElfW(Addr) mappref, size_t maplength, size_t mapalign)
 {
-  if (__glibc_likely (c->mapalign <= GLRO(dl_pagesize)))
-    return (ElfW(Addr)) __mmap ((void *) mappref, maplength, c->prot,
-				MAP_COPY|MAP_FILE, fd, c->mapoff);
+  int err;
+  /* MAP_COPY is a special flag combination for solibs. */
+  unsigned int map_flags = MAP_ANONYMOUS | MAP_COPY;
+  unsigned int prot = PROT_READ | PROT_WRITE;
+
+  if (__glibc_likely (mapalign <= GLRO(dl_pagesize)))
+    return (ElfW(Addr)) __mmap ((void *) mappref, maplength, prot,
+				map_flags, -1, 0);
 
   /* If the segment alignment > the page size, allocate enough space to
      ensure that the segment can be properly aligned.  */
-  ElfW(Addr) maplen = (maplength >= c->mapalign
-		       ? (maplength + c->mapalign)
-		       : (2 * c->mapalign));
+  ElfW(Addr) maplen = (maplength >= mapalign
+		       ? (maplength + mapalign)
+		       : (2 * mapalign));
   ElfW(Addr) map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplen,
 					      PROT_NONE,
 					      MAP_ANONYMOUS|MAP_PRIVATE,
@@ -41,26 +45,24 @@ _dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
   if (__glibc_unlikely ((void *) map_start == MAP_FAILED))
     return map_start;
 
-  ElfW(Addr) map_start_aligned = ALIGN_UP (map_start, c->mapalign);
-  map_start_aligned = (ElfW(Addr)) __mmap ((void *) map_start_aligned,
-					   maplength, c->prot,
-					   MAP_COPY|MAP_FILE|MAP_FIXED,
-					   fd, c->mapoff);
-  if (__glibc_unlikely ((void *) map_start_aligned == MAP_FAILED))
-    __munmap ((void *) map_start, maplen);
-  else
+  ElfW(Addr) map_start_aligned = ALIGN_UP (map_start, mapalign);
+  err = __mprotect ((void *) map_start_aligned, maplength, prot);
+  if (__glibc_unlikely (err))
     {
-      /* Unmap the unused regions.  */
-      ElfW(Addr) delta = map_start_aligned - map_start;
-      if (delta)
-	__munmap ((void *) map_start, delta);
-      ElfW(Addr) map_end = map_start_aligned + maplength;
-      map_end = ALIGN_UP (map_end, GLRO(dl_pagesize));
-      delta = map_start + maplen - map_end;
-      if (delta)
-	__munmap ((void *) map_end, delta);
+      __munmap ((void *) map_start, maplen);
+      return (ElfW(Addr)) MAP_FAILED;
     }
 
+  /* Unmap the unused regions.  */
+  ElfW(Addr) delta = map_start_aligned - map_start;
+  if (delta)
+    __munmap ((void *) map_start, delta);
+  ElfW(Addr) map_end = map_start_aligned + maplength;
+  map_end = ALIGN_UP (map_end, GLRO(dl_pagesize));
+  delta = map_start + maplen - map_end;
+  if (delta)
+    __munmap ((void *) map_end, delta);
+
   return map_start_aligned;
 }
 
@@ -98,7 +100,7 @@ _dl_map_segments (struct link_map *l, int fd,
            - MAP_BASE_ADDR (l));
 
       /* Remember which part of the address space this object uses.  */
-      l->l_map_start = _dl_map_segment (c, mappref, maplength, fd);
+      l->l_map_start = _dl_map_segment (mappref, maplength, c->mapalign);
       if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
         return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
 
@@ -123,14 +125,14 @@ _dl_map_segments (struct link_map *l, int fd,
         }
 
       l->l_contiguous = 1;
-
-      goto postmap;
     }
-
-  /* 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;
+  else
+    {
+      /* 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])
     {
@@ -143,7 +145,6 @@ _dl_map_segments (struct link_map *l, int fd,
               == MAP_FAILED))
         return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
 
-    postmap:
       _dl_postprocess_loadcmd (l, header, c);
 
       if (c->allocend > c->dataend)
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 02/14] use initial mmap also for ET_EXEC
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
  2023-05-18  8:28 ` [PATCH 01/14] elf: switch _dl_map_segment() to anonymous mapping Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 03/14] rework maphole Stas Sergeev
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This allows to replace the further anonymous mmaps with mprotect.
Which, in turn, will allow to split the protection stage in the
subsequent patches.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-map-segments.h | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index ed7675cabf..6a6127f773 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -129,7 +129,12 @@ _dl_map_segments (struct link_map *l, int fd,
   else
     {
       /* Remember which part of the address space this object uses.  */
-      l->l_map_start = c->mapstart + l->l_addr;
+      l->l_map_start = (ElfW(Addr)) __mmap ((caddr_t) l->l_addr + c->mapstart,
+                                            maplength, PROT_NONE,
+                                            MAP_ANON|MAP_PRIVATE|MAP_FIXED,
+                                            -1, 0);
+      if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
+        return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
       l->l_map_end = l->l_map_start + maplength;
       l->l_contiguous = !has_holes;
     }
@@ -182,13 +187,11 @@ _dl_map_segments (struct link_map *l, int fd,
 
           if (zeroend > zeropage)
             {
-              /* Map the remaining zero pages in from the zero fill FD.  */
-              caddr_t mapat;
-              mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
-                              c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
-                              -1, 0);
-              if (__glibc_unlikely (mapat == MAP_FAILED))
-                return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
+              /* Protect the remaining zero pages.  */
+              if (__glibc_unlikely (__mprotect ((caddr_t) zeropage,
+                                                zeroend - zeropage,
+                                                c->prot) < 0))
+                return DL_MAP_SEGMENTS_ERROR_MPROTECT;
             }
         }
 
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 03/14] rework maphole
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
  2023-05-18  8:28 ` [PATCH 01/14] elf: switch _dl_map_segment() to anonymous mapping Stas Sergeev
  2023-05-18  8:28 ` [PATCH 02/14] use initial mmap also for ET_EXEC Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 04/14] split do_reloc_1() from dl_open_worker_begin() Stas Sergeev
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

Remove "has_holes" argument that was used to mprotect the entire
initial mapping as PROT_NONE. Instead apply PROT_NONE at each
individual hole.
This is needed to make it possible to split the protection stage
from mmap stage.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-load.c         |  8 +++----
 elf/dl-load.h         |  3 +--
 elf/dl-map-segments.h | 52 ++++++++++++++++++++++++++-----------------
 3 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 39c63ff1b3..4007a4aae3 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1089,7 +1089,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
     /* Scan the program header table, collecting its load commands.  */
     struct loadcmd loadcmds[l->l_phnum];
     size_t nloadcmds = 0;
-    bool has_holes = false;
     bool empty_dynamic = false;
     ElfW(Addr) p_align_max = 0;
 
@@ -1141,6 +1140,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	  if (powerof2 (ph->p_align) && ph->p_align > p_align_max)
 	    p_align_max = ph->p_align;
 	  c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize));
+	  c->maphole = 0;
 
 	  DIAG_PUSH_NEEDS_COMMENT;
 
@@ -1153,8 +1153,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 #endif
 	  /* Determine whether there is a gap between the last segment
 	     and this one.  */
-	  if (nloadcmds > 1 && c[-1].mapend != c->mapstart)
-	    has_holes = true;
+	  if (nloadcmds > 1 && c[-1].mapend < c->mapstart)
+	    c[-1].maphole = c->mapstart - c[-1].mapend;
 	  DIAG_POP_NEEDS_COMMENT;
 
 	  /* Optimize a common case.  */
@@ -1256,7 +1256,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
        l_map_start, l_map_end, l_addr, l_contiguous, l_text_end, l_phdr
      */
     errstring = _dl_map_segments (l, fd, header, type, loadcmds, nloadcmds,
-				  maplength, has_holes, loader);
+				  maplength, loader);
     if (__glibc_unlikely (errstring != NULL))
       {
 	/* Mappings can be in an inconsistent state: avoid unmap.  */
diff --git a/elf/dl-load.h b/elf/dl-load.h
index ecf6910c68..029181e8c8 100644
--- a/elf/dl-load.h
+++ b/elf/dl-load.h
@@ -75,7 +75,7 @@ ELF_PREFERRED_ADDRESS_DATA;
    Its details have been expanded out and converted.  */
 struct loadcmd
 {
-  ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign;
+  ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign, maphole;
   ElfW(Off) mapoff;
   int prot;                             /* PROT_* bits.  */
 };
@@ -118,7 +118,6 @@ static const char *_dl_map_segments (struct link_map *l, int fd,
                                      const struct loadcmd loadcmds[],
                                      size_t nloadcmds,
                                      const size_t maplength,
-                                     bool has_holes,
                                      struct link_map *loader);
 
 /* All the error message strings _dl_map_segments might return are
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index 6a6127f773..080199b76e 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -77,7 +77,7 @@ static __always_inline const char *
 _dl_map_segments (struct link_map *l, int fd,
                   const ElfW(Ehdr) *header, int type,
                   const struct loadcmd loadcmds[], size_t nloadcmds,
-                  const size_t maplength, bool has_holes,
+                  const size_t maplength,
                   struct link_map *loader)
 {
   const struct loadcmd *c = loadcmds;
@@ -106,25 +106,6 @@ _dl_map_segments (struct link_map *l, int fd,
 
       l->l_map_end = l->l_map_start + maplength;
       l->l_addr = l->l_map_start - c->mapstart;
-
-      if (has_holes)
-        {
-          /* Change protection on the excess portion to disallow all access;
-             the portions we do not remap later will be inaccessible as if
-             unallocated.  Then jump into the normal segment-mapping loop to
-             handle the portion of the segment past the end of the file
-             mapping.  */
-	  if (__glibc_unlikely (loadcmds[nloadcmds - 1].mapstart <
-				c->mapend))
-	    return N_("ELF load command address/offset not page-aligned");
-          if (__glibc_unlikely
-              (__mprotect ((caddr_t) (l->l_addr + c->mapend),
-                           loadcmds[nloadcmds - 1].mapstart - c->mapend,
-                           PROT_NONE) < 0))
-            return DL_MAP_SEGMENTS_ERROR_MPROTECT;
-        }
-
-      l->l_contiguous = 1;
     }
   else
     {
@@ -136,11 +117,14 @@ _dl_map_segments (struct link_map *l, int fd,
       if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
         return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
       l->l_map_end = l->l_map_start + maplength;
-      l->l_contiguous = !has_holes;
     }
+  /* Reset to 0 later if hole found. */
+  l->l_contiguous = 1;
 
   while (c < &loadcmds[nloadcmds])
     {
+      ElfW(Addr) hole_start, hole_size;
+
       if (c->mapend > c->mapstart
           /* Map the segment contents from the file.  */
           && (__mmap ((void *) (l->l_addr + c->mapstart),
@@ -157,11 +141,15 @@ _dl_map_segments (struct link_map *l, int fd,
           /* Extra zero pages should appear at the end of this segment,
              after the data mapped from the file.   */
           ElfW(Addr) zero, zeroend, zeropage;
+          ElfW(Off) hole_off;
 
           zero = l->l_addr + c->dataend;
           zeroend = l->l_addr + c->allocend;
           zeropage = ((zero + GLRO(dl_pagesize) - 1)
                       & ~(GLRO(dl_pagesize) - 1));
+          hole_start = ALIGN_UP (c->allocend, GLRO(dl_pagesize));
+          hole_off = hole_start - c->mapend;
+          hole_size = c->maphole - hole_off;
 
           if (zeroend < zeropage)
             /* All the extra data is in the last page of the segment.
@@ -194,6 +182,28 @@ _dl_map_segments (struct link_map *l, int fd,
                 return DL_MAP_SEGMENTS_ERROR_MPROTECT;
             }
         }
+      else
+        {
+          hole_start = c->mapend;
+          hole_size = c->maphole;
+        }
+
+      if (__glibc_unlikely (c->maphole))
+        {
+          if (__glibc_likely (type == ET_DYN))
+            {
+              if (hole_size)
+                {
+                  if (__mprotect ((caddr_t) (l->l_addr + hole_start),
+                                   hole_size, PROT_NONE) < 0)
+                    return DL_MAP_SEGMENTS_ERROR_MPROTECT;
+                }
+            }
+          else if (l->l_contiguous)
+            {
+              l->l_contiguous = 0;
+            }
+        }
 
       ++c;
     }
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 04/14] split do_reloc_1() from dl_open_worker_begin()
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (2 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 03/14] rework maphole Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 05/14] split do_reloc_2() out of do_open_worker() Stas Sergeev
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This is a mostly mechanical code split with no functional changes
intended.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-open.c | 259 +++++++++++++++++++++++++-------------------------
 1 file changed, 132 insertions(+), 127 deletions(-)

diff --git a/elf/dl-open.c b/elf/dl-open.c
index 2d985e21d8..a77a6143e2 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -486,114 +486,8 @@ call_dl_init (void *closure)
 }
 
 static void
-dl_open_worker_begin (void *a)
+do_reloc_1 (struct link_map *new, int mode, Lmid_t nsid, bool call_ctors)
 {
-  struct dl_open_args *args = a;
-  const char *file = args->file;
-  int mode = args->mode;
-  struct link_map *call_map = NULL;
-
-  /* Determine the caller's map if necessary.  This is needed in case
-     we have a DST, when we don't know the namespace ID we have to put
-     the new object in, or when the file name has no path in which
-     case we need to look along the RUNPATH/RPATH of the caller.  */
-  const char *dst = strchr (file, '$');
-  if (dst != NULL || args->nsid == __LM_ID_CALLER
-      || strchr (file, '/') == NULL)
-    {
-      const void *caller_dlopen = args->caller_dlopen;
-
-      /* We have to find out from which object the caller is calling.
-	 By default we assume this is the main application.  */
-      call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
-
-      struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
-
-      if (l)
-	call_map = l;
-
-      if (args->nsid == __LM_ID_CALLER)
-	args->nsid = call_map->l_ns;
-    }
-
-  /* The namespace ID is now known.  Keep track of whether libc.so was
-     already loaded, to determine whether it is necessary to call the
-     early initialization routine (or clear libc_map on error).  */
-  args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;
-
-  /* Retain the old value, so that it can be restored.  */
-  args->original_global_scope_pending_adds
-    = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
-
-  /* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
-     may not be true if this is a recursive call to dlopen.  */
-  _dl_debug_initialize (0, args->nsid);
-
-  /* Load the named object.  */
-  struct link_map *new;
-  args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
-				    mode | __RTLD_CALLMAP, args->nsid);
-
-  /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
-     set and the object is not already loaded.  */
-  if (new == NULL)
-    {
-      assert (mode & RTLD_NOLOAD);
-      return;
-    }
-
-  if (__glibc_unlikely (mode & __RTLD_SPROF))
-    /* This happens only if we load a DSO for 'sprof'.  */
-    return;
-
-  /* This object is directly loaded.  */
-  ++new->l_direct_opencount;
-
-  /* It was already open.  */
-  if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
-    {
-      /* Let the user know about the opencount.  */
-      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
-	_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
-			  new->l_name, new->l_ns, new->l_direct_opencount);
-
-      /* If the user requested the object to be in the global
-	 namespace but it is not so far, prepare to add it now.  This
-	 can raise an exception to do a malloc failure.  */
-      if ((mode & RTLD_GLOBAL) && new->l_global == 0)
-	add_to_global_resize (new);
-
-      /* Mark the object as not deletable if the RTLD_NODELETE flags
-	 was passed.  */
-      if (__glibc_unlikely (mode & RTLD_NODELETE))
-	{
-	  if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)
-	      && !new->l_nodelete_active)
-	    _dl_debug_printf ("marking %s [%lu] as NODELETE\n",
-			      new->l_name, new->l_ns);
-	  new->l_nodelete_active = true;
-	}
-
-      /* Finalize the addition to the global scope.  */
-      if ((mode & RTLD_GLOBAL) && new->l_global == 0)
-	add_to_global_update (new);
-
-      const int r_state __attribute__ ((unused))
-        = _dl_debug_update (args->nsid)->r_state;
-      assert (r_state == RT_CONSISTENT);
-
-      return;
-    }
-
-  /* Schedule NODELETE marking for the directly loaded object if
-     requested.  */
-  if (__glibc_unlikely (mode & RTLD_NODELETE))
-    new->l_nodelete_pending = true;
-
-  /* Load that object's dependencies.  */
-  _dl_map_object_deps (new, NULL, 0, 0,
-		       mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
-
   /* So far, so good.  Now check the versions.  */
   for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i)
     if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL)
@@ -612,23 +506,6 @@ dl_open_worker_begin (void *a)
 #endif
       }
 
-#ifdef SHARED
-  /* Auditing checkpoint: we have added all objects.  */
-  _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT);
-#endif
-
-  /* Notify the debugger all new objects are now ready to go.  */
-  struct r_debug *r = _dl_debug_update (args->nsid);
-  r->r_state = RT_CONSISTENT;
-  _dl_debug_state ();
-  LIBC_PROBE (map_complete, 3, args->nsid, r, new);
-
-  _dl_open_check (new);
-
-  /* Print scope information.  */
-  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
-    _dl_show_scope (new, 0);
-
   /* Only do lazy relocation if `LD_BIND_NOW' is not set.  */
   int reloc_mode = mode & __RTLD_AUDIT;
   if (GLRO(dl_lazy))
@@ -753,20 +630,148 @@ dl_open_worker_begin (void *a)
 
   /* Notify the debugger all new objects have been relocated.  */
   if (relocation_in_progress)
-    LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
+    LIBC_PROBE (reloc_complete, 3, nsid, r, new);
 
   /* If libc.so was not there before, attempt to call its early
      initialization routine.  Indicate to the initialization routine
      whether the libc being initialized is the one in the base
      namespace.  */
-  if (!args->libc_already_loaded)
+  if (call_ctors)
     {
       /* dlopen cannot be used to load an initial libc by design.  */
-      struct link_map *libc_map = GL(dl_ns)[args->nsid].libc_map;
+      struct link_map *libc_map = GL(dl_ns)[nsid].libc_map;
       _dl_call_libc_early_init (libc_map, false);
     }
+}
+
+static void
+dl_open_worker_begin (void *a)
+{
+  struct dl_open_args *args = a;
+  const char *file = args->file;
+  int mode = args->mode;
+  struct link_map *call_map = NULL;
+
+  /* Determine the caller's map if necessary.  This is needed in case
+     we have a DST, when we don't know the namespace ID we have to put
+     the new object in, or when the file name has no path in which
+     case we need to look along the RUNPATH/RPATH of the caller.  */
+  const char *dst = strchr (file, '$');
+  if (dst != NULL || args->nsid == __LM_ID_CALLER
+      || strchr (file, '/') == NULL)
+    {
+      const void *caller_dlopen = args->caller_dlopen;
+
+      /* We have to find out from which object the caller is calling.
+	 By default we assume this is the main application.  */
+      call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+
+      struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
+
+      if (l)
+	call_map = l;
+
+      if (args->nsid == __LM_ID_CALLER)
+	args->nsid = call_map->l_ns;
+    }
+
+  /* The namespace ID is now known.  Keep track of whether libc.so was
+     already loaded, to determine whether it is necessary to call the
+     early initialization routine (or clear libc_map on error).  */
+  args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;
+
+  /* Retain the old value, so that it can be restored.  */
+  args->original_global_scope_pending_adds
+    = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
+
+  /* One might be tempted to assert that we are RT_CONSISTENT at this point, but that
+     may not be true if this is a recursive call to dlopen.  */
+  _dl_debug_initialize (0, args->nsid);
+
+  /* Load the named object.  */
+  struct link_map *new;
+  args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
+				    mode | __RTLD_CALLMAP, args->nsid);
+
+  /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
+     set and the object is not already loaded.  */
+  if (new == NULL)
+    {
+      assert (mode & RTLD_NOLOAD);
+      return;
+    }
+
+  if (__glibc_unlikely (mode & __RTLD_SPROF))
+    /* This happens only if we load a DSO for 'sprof'.  */
+    return;
+
+  /* This object is directly loaded.  */
+  ++new->l_direct_opencount;
+
+  /* It was already open.  */
+  if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
+    {
+      /* Let the user know about the opencount.  */
+      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+	_dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n",
+			  new->l_name, new->l_ns, new->l_direct_opencount);
+
+      /* If the user requested the object to be in the global
+	 namespace but it is not so far, prepare to add it now.  This
+	 can raise an exception to do a malloc failure.  */
+      if ((mode & RTLD_GLOBAL) && new->l_global == 0)
+	add_to_global_resize (new);
+
+      /* Mark the object as not deletable if the RTLD_NODELETE flags
+	 was passed.  */
+      if (__glibc_unlikely (mode & RTLD_NODELETE))
+	{
+	  if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)
+	      && !new->l_nodelete_active)
+	    _dl_debug_printf ("marking %s [%lu] as NODELETE\n",
+			      new->l_name, new->l_ns);
+	  new->l_nodelete_active = true;
+	}
+
+      /* Finalize the addition to the global scope.  */
+      if ((mode & RTLD_GLOBAL) && new->l_global == 0)
+	add_to_global_update (new);
+
+      const int r_state __attribute__ ((unused))
+        = _dl_debug_update (args->nsid)->r_state;
+      assert (r_state == RT_CONSISTENT);
+
+      return;
+    }
+
+  /* Schedule NODELETE marking for the directly loaded object if
+     requested.  */
+  if (__glibc_unlikely (mode & RTLD_NODELETE))
+    new->l_nodelete_pending = true;
+
+  /* Load that object's dependencies.  */
+  _dl_map_object_deps (new, NULL, 0, 0,
+		       mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
+
+#ifdef SHARED
+  /* Auditing checkpoint: we have added all objects.  */
+  _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT);
+#endif
+
+  /* Notify the debugger all new objects are now ready to go.  */
+  struct r_debug *r = _dl_debug_update (args->nsid);
+  r->r_state = RT_CONSISTENT;
+  _dl_debug_state ();
+  LIBC_PROBE (map_complete, 3, args->nsid, r, new);
+
+  _dl_open_check (new);
+
+  /* Print scope information.  */
+  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
+    _dl_show_scope (new, 0);
 
   args->worker_continue = true;
+  do_reloc_1 (new, mode, args->nsid, !args->libc_already_loaded);
 }
 
 static void
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 05/14] split do_reloc_2() out of do_open_worker()
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (3 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 04/14] split do_reloc_1() from dl_open_worker_begin() Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 06/14] move relocation into _dl_object_reloc() func Stas Sergeev
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This is mostly a mechanical split with no functional changes intended.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-open.c | 40 +++++++++++++++++++++++-----------------
 1 file changed, 23 insertions(+), 17 deletions(-)

diff --git a/elf/dl-open.c b/elf/dl-open.c
index a77a6143e2..687a393e0d 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -644,6 +644,28 @@ do_reloc_1 (struct link_map *new, int mode, Lmid_t nsid, bool call_ctors)
     }
 }
 
+static void
+do_reloc_2 (struct link_map *new, int mode, struct dl_open_args *args)
+{
+  /* Run the initializer functions of new objects.  Temporarily
+     disable the exception handler, so that lazy binding failures are
+     fatal.  */
+  {
+    struct dl_init_args init_args =
+      {
+        .new = new,
+        .argc = args->argc,
+        .argv = args->argv,
+        .env = args->env
+      };
+    _dl_catch_exception (NULL, call_dl_init, &init_args);
+  }
+
+  /* Now we can make the new map available in the global scope.  */
+  if (mode & RTLD_GLOBAL)
+    add_to_global_update (new);
+}
+
 static void
 dl_open_worker_begin (void *a)
 {
@@ -801,23 +823,7 @@ dl_open_worker (void *a)
   int mode = args->mode;
   struct link_map *new = args->map;
 
-  /* Run the initializer functions of new objects.  Temporarily
-     disable the exception handler, so that lazy binding failures are
-     fatal.  */
-  {
-    struct dl_init_args init_args =
-      {
-        .new = new,
-        .argc = args->argc,
-        .argv = args->argv,
-        .env = args->env
-      };
-    _dl_catch_exception (NULL, call_dl_init, &init_args);
-  }
-
-  /* Now we can make the new map available in the global scope.  */
-  if (mode & RTLD_GLOBAL)
-    add_to_global_update (new);
+  do_reloc_2 (new, mode, args);
 
   /* Let the user know about the opencount.  */
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 06/14] move relocation into _dl_object_reloc() func
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (4 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 05/14] split do_reloc_2() out of do_open_worker() Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 07/14] split out _dl_finalize_segments() Stas Sergeev
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This is a small refactoring to consolidate the relocation code
in a single place.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-close.c |  2 ++
 elf/dl-open.c  | 55 +++++++++++++++++++++++++++++++++++++++++++++-----
 include/link.h |  2 ++
 3 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/elf/dl-close.c b/elf/dl-close.c
index b887a44888..48ac3663ec 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -690,6 +690,8 @@ _dl_close_worker (struct link_map *map, bool force)
 	  if (imap == GL(dl_initfirst))
 	    GL(dl_initfirst) = NULL;
 
+	  free (imap->l_dlopen_args);
+
 	  free (imap);
 	}
     }
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 687a393e0d..e553403e8b 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -666,6 +666,31 @@ do_reloc_2 (struct link_map *new, int mode, struct dl_open_args *args)
     add_to_global_update (new);
 }
 
+static void
+dl_reloc_worker_begin (void *a)
+{
+  struct dl_open_args *args = a;
+  do_reloc_1 (args->map, args->mode, args->nsid, !args->libc_already_loaded);
+}
+
+static void
+_dl_object_reloc (struct link_map *l)
+{
+  struct dl_exception ex;
+  int err;
+  struct dl_open_args *args = l->l_dlopen_args;
+  int mode = args->mode;
+
+  /* Protects global and module specific TLS state.  */
+  __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
+  err = _dl_catch_exception (&ex, dl_reloc_worker_begin, args);
+  __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
+  if (__glibc_unlikely (ex.errstring != NULL))
+    /* Reraise the error.  */
+    _dl_signal_exception (err, &ex, NULL);
+  do_reloc_2 (l, mode, args);
+}
+
 static void
 dl_open_worker_begin (void *a)
 {
@@ -775,6 +800,27 @@ dl_open_worker_begin (void *a)
   _dl_map_object_deps (new, NULL, 0, 0,
 		       mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT));
 
+  args->worker_continue = true;
+  if (!new->l_dlopen_args)
+    {
+      if (new->l_type == lt_loaded)
+        {
+          new->l_dlopen_args = (struct dl_open_args *)
+                               malloc (sizeof (struct dl_open_args));
+          if (new->l_dlopen_args == NULL)
+            _dl_signal_error (ENOMEM, new->l_name, NULL,
+			      N_("cannot allocate memory buffer"));
+          memcpy (new->l_dlopen_args, args, sizeof (*args));
+        }
+      else
+        new->l_dlopen_args = args;
+    }
+  else
+    {
+      assert (new->l_type == lt_loaded);
+      memcpy (new->l_dlopen_args, args, sizeof (*args));
+    }
+
 #ifdef SHARED
   /* Auditing checkpoint: we have added all objects.  */
   _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT);
@@ -791,9 +837,6 @@ dl_open_worker_begin (void *a)
   /* Print scope information.  */
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES))
     _dl_show_scope (new, 0);
-
-  args->worker_continue = true;
-  do_reloc_1 (new, mode, args->nsid, !args->libc_already_loaded);
 }
 
 static void
@@ -820,10 +863,12 @@ dl_open_worker (void *a)
   if (!args->worker_continue)
     return;
 
-  int mode = args->mode;
   struct link_map *new = args->map;
 
-  do_reloc_2 (new, mode, args);
+  _dl_object_reloc (new);
+  /* For !lt_loaded we do not malloc(), so needs to null out here. */
+  if (new->l_type != lt_loaded)
+    new->l_dlopen_args = NULL;
 
   /* Let the user know about the opencount.  */
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
diff --git a/include/link.h b/include/link.h
index 1d74feb2bd..03b9f82715 100644
--- a/include/link.h
+++ b/include/link.h
@@ -347,6 +347,8 @@ struct link_map
     size_t l_relro_size;
 
     unsigned long long int l_serial;
+
+    void *l_dlopen_args;
   };
 
 #include <dl-relocate-ld.h>
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 07/14] split out _dl_finalize_segments()
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (5 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 06/14] move relocation into _dl_object_reloc() func Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 08/14] finalize elf segments on a relocation step Stas Sergeev
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This is needed so that further patches can move that to the
relocation code.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-load.c         |  3 +++
 elf/dl-load.h         |  5 +++++
 elf/dl-map-segments.h | 36 +++++++++++++++++++++++++++++-------
 3 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 4007a4aae3..28e582fbdf 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1263,6 +1263,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	l->l_map_start = l->l_map_end = 0;
 	goto lose;
       }
+    errstring = _dl_finalize_segments (l, type, loadcmds, nloadcmds);
+    if (__glibc_unlikely (errstring != NULL))
+      goto lose;
   }
 
   if (l->l_ld != 0)
diff --git a/elf/dl-load.h b/elf/dl-load.h
index 029181e8c8..61f5c4fadf 100644
--- a/elf/dl-load.h
+++ b/elf/dl-load.h
@@ -120,6 +120,11 @@ static const char *_dl_map_segments (struct link_map *l, int fd,
                                      const size_t maplength,
                                      struct link_map *loader);
 
+static const char *_dl_finalize_segments (struct link_map *l,
+                                          int type,
+                                          const struct loadcmd loadcmds[],
+                                          size_t nloadcmds);
+
 /* All the error message strings _dl_map_segments might return are
    listed here so that different implementations in different sysdeps
    dl-map-segments.h files all use consistent strings that are
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index 080199b76e..da6b762bca 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -123,12 +123,10 @@ _dl_map_segments (struct link_map *l, int fd,
 
   while (c < &loadcmds[nloadcmds])
     {
-      ElfW(Addr) hole_start, hole_size;
-
       if (c->mapend > c->mapstart
           /* Map the segment contents from the file.  */
           && (__mmap ((void *) (l->l_addr + c->mapstart),
-                      c->mapend - c->mapstart, c->prot,
+                      c->mapend - c->mapstart, PROT_READ | PROT_WRITE,
                       MAP_FIXED|MAP_COPY|MAP_FILE,
                       fd, c->mapoff)
               == MAP_FAILED))
@@ -136,6 +134,34 @@ _dl_map_segments (struct link_map *l, int fd,
 
       _dl_postprocess_loadcmd (l, header, c);
 
+      ++c;
+    }
+
+  /* Notify ELF_PREFERRED_ADDRESS that we have to load this one
+     fixed.  */
+  ELF_FIXED_ADDRESS (loader, c->mapstart);
+
+  return NULL;
+}
+
+static __always_inline const char *
+_dl_finalize_segments (struct link_map *l, int type,
+                       const struct loadcmd loadcmds[], size_t nloadcmds)
+{
+  const struct loadcmd *c = loadcmds;
+
+  while (c < &loadcmds[nloadcmds])
+    {
+      ElfW(Addr) hole_start, hole_size;
+
+      if (c->mapend > c->mapstart)
+        {
+          if (__mprotect ((void *) (l->l_addr + c->mapstart),
+                      c->mapend - c->mapstart, c->prot) < 0)
+            return DL_MAP_SEGMENTS_ERROR_MPROTECT;
+
+        }
+
       if (c->allocend > c->dataend)
         {
           /* Extra zero pages should appear at the end of this segment,
@@ -208,9 +234,5 @@ _dl_map_segments (struct link_map *l, int fd,
       ++c;
     }
 
-  /* Notify ELF_PREFERRED_ADDRESS that we have to load this one
-     fixed.  */
-  ELF_FIXED_ADDRESS (loader, c->mapstart);
-
   return NULL;
 }
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 08/14] finalize elf segments on a relocation step
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (6 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 07/14] split out _dl_finalize_segments() Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 09/14] implement RTLD_NORELOCATE dlopen() flag Stas Sergeev
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This is needed so that the segment finalization can be delayed,
together with the relocation process.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 elf/dl-close.c        |  1 +
 elf/dl-load.c         | 33 ++++++++++++++++++++++-----------
 elf/dl-load.h         |  2 +-
 elf/dl-map-segments.h |  7 ++++++-
 elf/dl-open.c         | 10 +++++++++-
 include/link.h        |  5 ++++-
 6 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/elf/dl-close.c b/elf/dl-close.c
index 48ac3663ec..0640fc0bec 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -691,6 +691,7 @@ _dl_close_worker (struct link_map *map, bool force)
 	    GL(dl_initfirst) = NULL;
 
 	  free (imap->l_dlopen_args);
+	  free (imap->l_loadcmds);
 
 	  free (imap);
 	}
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 28e582fbdf..31514fca84 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -950,6 +950,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
   int type;
   /* Initialize to keep the compiler happy.  */
   const char *errstring = NULL;
+  struct loadcmd *loadcmds = NULL;
   int errval = 0;
 
   /* Get file information.  To match the kernel behavior, do not fill
@@ -969,6 +970,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	lose_errno:
 	  errval = errno;
 	lose:
+	  if (loadcmds)
+	    free (loadcmds);
 	  /* The file might already be closed.  */
 	  if (fd != -1)
 	    __close_nocancel (fd);
@@ -1080,18 +1083,23 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	}
     }
 
-   /* On most platforms presume that PT_GNU_STACK is absent and the stack is
-    * executable.  Other platforms default to a nonexecutable stack and don't
-    * need PT_GNU_STACK to do so.  */
-   unsigned int stack_flags = DEFAULT_STACK_PERMS;
+  /* On most platforms presume that PT_GNU_STACK is absent and the stack is
+   * executable.  Other platforms default to a nonexecutable stack and don't
+   * need PT_GNU_STACK to do so.  */
+  unsigned int stack_flags = DEFAULT_STACK_PERMS;
 
   {
     /* Scan the program header table, collecting its load commands.  */
-    struct loadcmd loadcmds[l->l_phnum];
-    size_t nloadcmds = 0;
+    #define nloadcmds l->l_nloadcmds
     bool empty_dynamic = false;
     ElfW(Addr) p_align_max = 0;
 
+    loadcmds = (struct loadcmd *) malloc (sizeof (struct loadcmd) * l->l_phnum);
+    if (loadcmds == NULL)
+      goto lose;
+    l->l_loadcmds = loadcmds;
+    nloadcmds = 0;
+
     /* The struct is initialized to zero so this is not necessary:
     l->l_ld = 0;
     l->l_phdr = 0;
@@ -1225,8 +1233,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
       }
 
     /* Align all PT_LOAD segments to the maximum p_align.  */
-    for (size_t i = 0; i < nloadcmds; i++)
-      loadcmds[i].mapalign = p_align_max;
+    l->l_map_align = p_align_max;
 
     /* dlopen of an executable is not valid because it is not possible
        to perform proper relocations, handle static TLS, or run the
@@ -1263,9 +1270,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	l->l_map_start = l->l_map_end = 0;
 	goto lose;
       }
-    errstring = _dl_finalize_segments (l, type, loadcmds, nloadcmds);
-    if (__glibc_unlikely (errstring != NULL))
-      goto lose;
+    /* dlopen()ed solibs are finalized on a relocation step. */
+    if (!(mode & __RTLD_DLOPEN))
+      {
+        errstring = _dl_finalize_segments (l, type, loadcmds, nloadcmds);
+        if (__glibc_unlikely (errstring != NULL))
+	  goto lose;
+      }
   }
 
   if (l->l_ld != 0)
diff --git a/elf/dl-load.h b/elf/dl-load.h
index 61f5c4fadf..555eed176d 100644
--- a/elf/dl-load.h
+++ b/elf/dl-load.h
@@ -75,7 +75,7 @@ ELF_PREFERRED_ADDRESS_DATA;
    Its details have been expanded out and converted.  */
 struct loadcmd
 {
-  ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign, maphole;
+  ElfW(Addr) mapstart, mapend, dataend, allocend, maphole;
   ElfW(Off) mapoff;
   int prot;                             /* PROT_* bits.  */
 };
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index da6b762bca..a0078a77c8 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -100,7 +100,7 @@ _dl_map_segments (struct link_map *l, int fd,
            - MAP_BASE_ADDR (l));
 
       /* Remember which part of the address space this object uses.  */
-      l->l_map_start = _dl_map_segment (mappref, maplength, c->mapalign);
+      l->l_map_start = _dl_map_segment (mappref, maplength, l->l_map_align);
       if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
         return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
 
@@ -150,6 +150,9 @@ _dl_finalize_segments (struct link_map *l, int type,
 {
   const struct loadcmd *c = loadcmds;
 
+  if (l->l_map_completed)
+    return NULL;
+
   while (c < &loadcmds[nloadcmds])
     {
       ElfW(Addr) hole_start, hole_size;
@@ -234,5 +237,7 @@ _dl_finalize_segments (struct link_map *l, int type,
       ++c;
     }
 
+  l->l_map_completed = 1;
+
   return NULL;
 }
diff --git a/elf/dl-open.c b/elf/dl-open.c
index e553403e8b..f1f2e8d3a4 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -40,7 +40,8 @@
 
 #include <dl-dst.h>
 #include <dl-prop.h>
-
+#include "dl-load.h"
+#include "dl-map-segments.h"
 
 /* We must be careful not to leave us in an inconsistent state.  Thus we
    catch any error and re-raise it after cleaning up.  */
@@ -543,6 +544,8 @@ do_reloc_1 (struct link_map *new, int mode, Lmid_t nsid, bool call_ctors)
 
   for (unsigned int i = last; i-- > first; )
     {
+      const char *errstring;
+
       l = new->l_initfini[i];
 
       if (l->l_real->l_relocated)
@@ -555,6 +558,11 @@ do_reloc_1 (struct link_map *new, int mode, Lmid_t nsid, bool call_ctors)
 	  relocation_in_progress = 1;
 	}
 
+      errstring = _dl_finalize_segments (l, ET_DYN, l->l_loadcmds,
+                                         l->l_nloadcmds);
+      if (__glibc_unlikely (errstring != NULL))
+        _dl_signal_error (EINVAL, l->l_libname->name, NULL, errstring);
+
 #ifdef SHARED
       if (__glibc_unlikely (GLRO(dl_profile) != NULL))
 	{
diff --git a/include/link.h b/include/link.h
index 03b9f82715..fa16dfa337 100644
--- a/include/link.h
+++ b/include/link.h
@@ -179,6 +179,7 @@ struct link_map
       } l_type:2;
     unsigned int l_dt_relr_ref:1; /* Nonzero if GLIBC_ABI_DT_RELR is
 				     referenced.  */
+    unsigned int l_map_completed:1; /* Nonzero if object fully mapped.  */
     unsigned int l_relocated:1;	/* Nonzero if object's relocations done.  */
     unsigned int l_init_called:1; /* Nonzero if DT_INIT function called.  */
     unsigned int l_global:1;	/* Nonzero if object in _dl_global_scope.  */
@@ -252,7 +253,7 @@ struct link_map
 
     /* Start and finish of memory map for this object.  l_map_start
        need not be the same as l_addr.  */
-    ElfW(Addr) l_map_start, l_map_end;
+    ElfW(Addr) l_map_start, l_map_end, l_map_align;
     /* End of the executable part of the mapping.  */
     ElfW(Addr) l_text_end;
 
@@ -349,6 +350,8 @@ struct link_map
     unsigned long long int l_serial;
 
     void *l_dlopen_args;
+    void *l_loadcmds;
+    size_t l_nloadcmds;
   };
 
 #include <dl-relocate-ld.h>
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 09/14] implement RTLD_NORELOCATE dlopen() flag
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (7 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 08/14] finalize elf segments on a relocation step Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 10/14] add test-case for RTLD_NORELOCATE Stas Sergeev
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This flag allows to delay the relocation of the dlopen()ed object.
If this flag is used, then the relocation is called from
_dl_lookup_symbol_x(), which is called by dlsym() among other places.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 bits/dlfcn.h    |  3 +++
 dlfcn/dlopen.c  |  2 +-
 elf/dl-lookup.c |  6 +++++-
 elf/dl-main.h   |  2 ++
 elf/dl-open.c   | 22 +++++++++++++++++++---
 include/link.h  |  1 +
 6 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/bits/dlfcn.h b/bits/dlfcn.h
index d1e31cf4e0..9cf2d5fb80 100644
--- a/bits/dlfcn.h
+++ b/bits/dlfcn.h
@@ -41,6 +41,9 @@
 #define RTLD_NODELETE	0x01000
 
 #ifdef __USE_GNU
+/* Do not relocte object on dlopen().  */
+#define RTLD_NORELOCATE	0x02000
+
 /* To support profiling of shared objects it is a good idea to call
    the function found using `dlsym' using the following macro since
    these calls do not use the PLT.  But this would mean the dynamic
diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c
index 21ed2c964d..866ccf7a4a 100644
--- a/dlfcn/dlopen.c
+++ b/dlfcn/dlopen.c
@@ -50,7 +50,7 @@ dlopen_doit (void *a)
 
   if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND
 		     | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE
-		     | __RTLD_SPROF))
+		     | __RTLD_SPROF | RTLD_NORELOCATE))
     _dl_signal_error (0, NULL, NULL, _("invalid mode parameter"));
 
   args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 05f36a2507..d60481676d 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -31,7 +31,7 @@
 #include <tls.h>
 #include <atomic.h>
 #include <elf_machine_sym_no_match.h>
-
+#include <dl-main.h>
 #include <assert.h>
 
 #define VERSTAG(tag)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
@@ -759,6 +759,10 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
   struct sym_val current_value = { NULL, NULL };
   struct r_scope_elem **scope = symbol_scope;
 
+  if (undef_map && !undef_map->l_relocated && undef_map->l_reloc_deferred
+      && undef_map->l_type == lt_loaded)
+    _dl_object_reloc (undef_map);
+
   bump_num_relocations ();
 
   /* DL_LOOKUP_RETURN_NEWEST does not make sense for versioned
diff --git a/elf/dl-main.h b/elf/dl-main.h
index 92766d06b4..54d139f2c4 100644
--- a/elf/dl-main.h
+++ b/elf/dl-main.h
@@ -127,4 +127,6 @@ _Noreturn void _dl_help (const char *argv0, struct dl_main_state *state)
 /* Print a diagnostics dump.  */
 _Noreturn void _dl_print_diagnostics (char **environ) attribute_hidden;
 
+extern void _dl_object_reloc (struct link_map *l) attribute_hidden;
+
 #endif /* _DL_MAIN */
diff --git a/elf/dl-open.c b/elf/dl-open.c
index f1f2e8d3a4..5106c9d029 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -223,6 +223,8 @@ _dl_find_dso_for_object (const ElfW(Addr) addr)
 	      || _dl_addr_inside_object (l, (ElfW(Addr)) addr)))
 	{
 	  assert (ns == l->l_ns);
+	  if (!l->l_relocated)
+	    return NULL;
 	  return l;
 	}
   return NULL;
@@ -681,7 +683,7 @@ dl_reloc_worker_begin (void *a)
   do_reloc_1 (args->map, args->mode, args->nsid, !args->libc_already_loaded);
 }
 
-static void
+void
 _dl_object_reloc (struct link_map *l)
 {
   struct dl_exception ex;
@@ -689,6 +691,8 @@ _dl_object_reloc (struct link_map *l)
   struct dl_open_args *args = l->l_dlopen_args;
   int mode = args->mode;
 
+  l->l_reloc_deferred = 0;
+
   /* Protects global and module specific TLS state.  */
   __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
   err = _dl_catch_exception (&ex, dl_reloc_worker_begin, args);
@@ -760,6 +764,10 @@ dl_open_worker_begin (void *a)
     /* This happens only if we load a DSO for 'sprof'.  */
     return;
 
+  if (__glibc_unlikely ((mode & RTLD_NORELOCATE) && new->l_relocated))
+    _dl_signal_error (EINVAL, new->l_name, NULL,
+		      N_("RTLD_NORELOCATE used with already relocated object"));
+
   /* This object is directly loaded.  */
   ++new->l_direct_opencount;
 
@@ -821,7 +829,12 @@ dl_open_worker_begin (void *a)
           memcpy (new->l_dlopen_args, args, sizeof (*args));
         }
       else
-        new->l_dlopen_args = args;
+        {
+          assert (new->l_relocated);
+          /* If relocated, this flag is filtered above. */
+          assert (!(mode & RTLD_NORELOCATE));
+          new->l_dlopen_args = args;
+        }
     }
   else
     {
@@ -873,7 +886,10 @@ dl_open_worker (void *a)
 
   struct link_map *new = args->map;
 
-  _dl_object_reloc (new);
+  if (__glibc_likely (!(args->mode & RTLD_NORELOCATE)))
+    _dl_object_reloc (new);
+  else
+    new->l_reloc_deferred = 1;
   /* For !lt_loaded we do not malloc(), so needs to null out here. */
   if (new->l_type != lt_loaded)
     new->l_dlopen_args = NULL;
diff --git a/include/link.h b/include/link.h
index fa16dfa337..6c11c33417 100644
--- a/include/link.h
+++ b/include/link.h
@@ -180,6 +180,7 @@ struct link_map
     unsigned int l_dt_relr_ref:1; /* Nonzero if GLIBC_ABI_DT_RELR is
 				     referenced.  */
     unsigned int l_map_completed:1; /* Nonzero if object fully mapped.  */
+    unsigned int l_reloc_deferred:1; /* Nonzero if relocation deferred.  */
     unsigned int l_relocated:1;	/* Nonzero if object's relocations done.  */
     unsigned int l_init_called:1; /* Nonzero if DT_INIT function called.  */
     unsigned int l_global:1;	/* Nonzero if object in _dl_global_scope.  */
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 10/14] add test-case for RTLD_NORELOCATE
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (8 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 09/14] implement RTLD_NORELOCATE dlopen() flag Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 11/14] implement dlrelocate() function Stas Sergeev
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

Makes sure that things work as before.
Makes sure that ctors are called upon dlsym().

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 dlfcn/Makefile      |  6 ++--
 dlfcn/ctorlib1.c    | 36 ++++++++++++++++++++++
 dlfcn/tst-noreloc.c | 73 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 2 deletions(-)
 create mode 100644 dlfcn/ctorlib1.c
 create mode 100644 dlfcn/tst-noreloc.c

diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index 1fa7fea1ef..16b9401610 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -51,12 +51,12 @@ endif
 ifeq (yes,$(build-shared))
 tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
 	bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
-	bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen
+	bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen tst-noreloc
 endif
 modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
 		defaultmod2 errmsg1mod modatexit modcxaatexit \
 		bug-dlsym1-lib1 bug-dlsym1-lib2 bug-atexit1-lib \
-		bug-atexit2-lib bug-dl-leaf-lib \
+		bug-atexit2-lib bug-dl-leaf-lib ctorlib1 \
 		bug-dl-leaf-lib-cb moddummy1 moddummy2
 
 failtestmod.so-no-z-defs = yes
@@ -102,6 +102,8 @@ $(objpfx)glrefmain.out: $(objpfx)glrefmain \
 $(objpfx)failtest.out: $(objpfx)failtestmod.so
 
 $(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so
+$(objpfx)tst-noreloc.out: $(objpfx)ctorlib1.so
+LDFLAGS-tst-noreloc = $(LDFLAGS-rdynamic)
 
 $(objpfx)tst-dlinfo.out: $(objpfx)glreflib3.so
 LDFLAGS-glreflib3.so = -Wl,-rpath,:
diff --git a/dlfcn/ctorlib1.c b/dlfcn/ctorlib1.c
new file mode 100644
index 0000000000..cf7a9096ea
--- /dev/null
+++ b/dlfcn/ctorlib1.c
@@ -0,0 +1,36 @@
+/* Test for ctor calling.
+   Copyright (C) 2000-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 <assert.h>
+#include <stdio.h>
+
+extern int ref1 (void);
+int
+ref1 (void)
+{
+  return 42;
+}
+
+void __attribute__((constructor))
+ctor (void)
+{
+  int *ct = (int *) dlsym (RTLD_DEFAULT, "ctor_called");
+  assert (ct);
+  (*ct)++;
+}
diff --git a/dlfcn/tst-noreloc.c b/dlfcn/tst-noreloc.c
new file mode 100644
index 0000000000..78f5a7fb25
--- /dev/null
+++ b/dlfcn/tst-noreloc.c
@@ -0,0 +1,73 @@
+/* Tests for RTLD_NORELOCATE flag.
+   Copyright (C) 2000-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 <errno.h>
+#include <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+
+int ctor_called;
+
+static int
+do_test (void)
+{
+  void *handle;
+  int (*sym) (void);
+  Dl_info info;
+  int ret;
+
+  handle = dlopen ("ctorlib1.so", RTLD_NOW | RTLD_NORELOCATE);
+  if (handle == NULL)
+    error (EXIT_FAILURE, 0, "cannot load: ctorlib1.so");
+
+  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");
+
+  printf ("ret = %d\n", ret);
+  printf ("info.dli_fname = %p (\"%s\")\n", info.dli_fname, info.dli_fname);
+  printf ("info.dli_fbase = %p\n", info.dli_fbase);
+  printf ("info.dli_sname = %p (\"%s\")\n", info.dli_sname, info.dli_sname);
+  printf ("info.dli_saddr = %p\n", info.dli_saddr);
+
+  if (info.dli_fname == NULL)
+    error (EXIT_FAILURE, 0, "dli_fname is NULL");
+  if (info.dli_fbase == NULL)
+    error (EXIT_FAILURE, 0, "dli_fbase is NULL");
+  if (info.dli_sname == NULL)
+    error (EXIT_FAILURE, 0, "dli_sname is NULL");
+  if (info.dli_saddr == NULL)
+    error (EXIT_FAILURE, 0, "dli_saddr is NULL");
+
+  dlclose (handle);
+
+  return 0;
+}
+
+
+#include <support/test-driver.c>
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 11/14] implement dlrelocate() function
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (9 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 10/14] add test-case for RTLD_NORELOCATE Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 12/14] implement RTLD_DI_MAPINFO dlinfo() request Stas Sergeev
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This function allows to relocate the solib previously loaded with
the use of RTLD_NORELOCATE flag, including all its deps.
It allows to handle the relocation errors, and in case of a success,
call the object's ctors.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 dlfcn/Makefile                                |  1 +
 dlfcn/Versions                                |  3 +
 dlfcn/dlfcn.h                                 |  3 +
 dlfcn/dlrelocate.c                            | 68 +++++++++++++++++++
 dlfcn/tst-noreloc.c                           | 20 ++++++
 elf/dl-open.c                                 | 14 ++++
 elf/rtld.c                                    |  1 +
 include/dlfcn.h                               |  7 ++
 sysdeps/generic/ldsodefs.h                    |  1 +
 sysdeps/mach/hurd/i386/libc.abilist           |  1 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |  1 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |  1 +
 sysdeps/unix/sysv/linux/arc/libc.abilist      |  1 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |  1 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |  1 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |  1 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |  1 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |  1 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |  1 +
 .../sysv/linux/loongarch/lp64/libc.abilist    |  1 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |  1 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |  1 +
 .../sysv/linux/microblaze/be/libc.abilist     |  1 +
 .../sysv/linux/microblaze/le/libc.abilist     |  1 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |  1 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |  1 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |  1 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |  1 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |  1 +
 sysdeps/unix/sysv/linux/or1k/libc.abilist     |  1 +
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |  1 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |  1 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |  1 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |  1 +
 .../unix/sysv/linux/riscv/rv32/libc.abilist   |  1 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |  1 +
 .../unix/sysv/linux/s390/s390-32/libc.abilist |  1 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |  1 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |  1 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |  1 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |  1 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |  1 +
 .../unix/sysv/linux/x86_64/64/libc.abilist    |  1 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |  1 +
 44 files changed, 153 insertions(+)
 create mode 100644 dlfcn/dlrelocate.c

diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index 16b9401610..fb56b8aecb 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -26,6 +26,7 @@ routines = \
   dladdr \
   dladdr1 \
   dlclose \
+  dlrelocate \
   dlerror \
   dlinfo \
   dlmopen \
diff --git a/dlfcn/Versions b/dlfcn/Versions
index cc34eb824d..61ab01d764 100644
--- a/dlfcn/Versions
+++ b/dlfcn/Versions
@@ -28,6 +28,9 @@ libc {
     dlsym;
     dlvsym;
   }
+  GLIBC_2.38 {
+    dlrelocate;
+  }
   GLIBC_PRIVATE {
     __libc_dlerror_result;
     _dlerror_run;
diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
index c5d192597d..c3e228c667 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -68,6 +68,9 @@ extern void *dlsym (void *__restrict __handle,
 /* Like `dlopen', but request object to be allocated in a new namespace.  */
 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));
+
 /* 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,
diff --git a/dlfcn/dlrelocate.c b/dlfcn/dlrelocate.c
new file mode 100644
index 0000000000..7ff0b74107
--- /dev/null
+++ b/dlfcn/dlrelocate.c
@@ -0,0 +1,68 @@
+/* Relocate the shared object loaded by `dlopen' with `RTLD_NORELOCATE'.
+   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>
+
+struct dlrelocate_args
+{
+  /* The arguments to dlrelocate_doit.  */
+  void *handle;
+};
+
+static void
+dlrelocate_doit (void *a)
+{
+  struct dlrelocate_args *args = (struct dlrelocate_args *) a;
+
+  GLRO (dl_relocate) (args->handle);
+}
+
+static int
+dlrelocate_implementation (void *handle)
+{
+  struct dlrelocate_args args;
+  args.handle = handle;
+
+  /* Protect against concurrent loads and unloads.  */
+  __rtld_lock_lock_recursive (GL(dl_load_lock));
+
+  int result = (_dlerror_run (dlrelocate_doit, &args) ? -1 : 0);
+
+  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+
+  return result;
+}
+
+int
+__dlrelocate (void *handle)
+{
+#ifdef SHARED
+  if (GLRO (dl_dlfcn_hook) != NULL)
+    return GLRO (dl_dlfcn_hook)->dlrelocate (handle);
+#endif
+  return dlrelocate_implementation (handle);
+}
+#ifdef SHARED
+versioned_symbol (libc, __dlrelocate, dlrelocate, GLIBC_2_38);
+#else /* !SHARED */
+/* Also used with _dlfcn_hook.  */
+weak_alias (__dlrelocate, dlrelocate)
+#endif /* !SHARED */
diff --git a/dlfcn/tst-noreloc.c b/dlfcn/tst-noreloc.c
index 78f5a7fb25..a56e8102bb 100644
--- a/dlfcn/tst-noreloc.c
+++ b/dlfcn/tst-noreloc.c
@@ -44,6 +44,26 @@ 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");
+
+  TEST_COMPARE (ctor_called, 0);
+  ret = dlrelocate (handle);
+  TEST_COMPARE (ret, 0);
+  /* dlrelocate() called ctors. */
+  TEST_COMPARE (ctor_called, 1);
+  /* This time should fail. */
+  ret = dlrelocate (handle);
+  TEST_COMPARE (ret, -1);
+  TEST_COMPARE (ctor_called, 1);
+  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)
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 5106c9d029..178593efe7 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -1043,3 +1043,17 @@ _dl_show_scope (struct link_map *l, int from)
     _dl_debug_printf (" no scope\n");
   _dl_debug_printf ("\n");
 }
+
+void
+_dl_relocate (void *handle)
+{
+  struct link_map *map = handle;
+
+  if (map->l_type != lt_loaded)
+    _dl_signal_error (EINVAL, map->l_name, NULL,
+		      N_("invalid object for dlrelocate()"));
+  if (map->l_relocated || !map->l_reloc_deferred)
+    _dl_signal_error (EINVAL, map->l_name, NULL,
+		      N_("object already relocated"));
+  _dl_object_reloc (handle);
+}
diff --git a/elf/rtld.c b/elf/rtld.c
index c1e383b055..471509a72c 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -368,6 +368,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
     ._dl_lookup_symbol_x = _dl_lookup_symbol_x,
     ._dl_open = _dl_open,
     ._dl_close = _dl_close,
+    ._dl_relocate = _dl_relocate,
     ._dl_catch_error = _dl_catch_error,
     ._dl_error_free = _dl_error_free,
     ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft,
diff --git a/include/dlfcn.h b/include/dlfcn.h
index ae25f05303..7bfd5b9085 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -57,6 +57,8 @@ extern void *__libc_dlvsym (void *map, const char *name, const char *version)
   attribute_hidden;
 extern int   __libc_dlclose (void *__map)
   attribute_hidden;
+extern int   __libc_dlrelocate (void *__map)
+  attribute_hidden;
 
 /* Locate shared object containing the given address.  */
 #ifdef ElfW
@@ -74,6 +76,9 @@ extern void _dl_close (void *map) attribute_hidden;
 extern void _dl_close_worker (struct link_map *map, bool force)
     attribute_hidden;
 
+/* Relocate an object previously opened by _dl_open with RTLD_NORELOCATE.  */
+extern void _dl_relocate (void *handle) attribute_hidden;
+
 /* Look up NAME in shared object HANDLE (which may be RTLD_DEFAULT or
    RTLD_NEXT).  WHO is the calling function, for RTLD_NEXT.  Returns
    the symbol value, which may be NULL.  */
@@ -101,6 +106,7 @@ struct dlfcn_hook
   /* Public interfaces.  */
   void *(*dlopen) (const char *file, int mode, void *dl_caller);
   int (*dlclose) (void *handle);
+  int (*dlrelocate) (void *handle);
   void *(*dlsym) (void *handle, const char *name, void *dl_caller);
   void *(*dlvsym) (void *handle, const char *name, const char *version,
 		   void *dl_caller);
@@ -126,6 +132,7 @@ extern void *__dlopen (const char *file, int mode, void *caller);
 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 void *__dlsym (void *handle, const char *name, void *dl_caller);
 extern void *__dlvsym (void *handle, const char *name, const char *version,
 		       void *dl_caller);
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index ba53176296..53601aa7e2 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -664,6 +664,7 @@ struct rtld_global_ro
   void *(*_dl_open) (const char *file, int mode, const void *caller_dlopen,
 		     Lmid_t nsid, int argc, char *argv[], char *env[]);
   void (*_dl_close) (void *map);
+  void (*_dl_relocate) (void *handle);
   /* libdl in a secondary namespace (after dlopen) must use
      _dl_catch_error from the main namespace, so it has to be
      exported in some way.  */
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index 6925222ff3..53dc594256 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2326,6 +2326,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 0e2d9c3045..9571379cb9 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2665,3 +2665,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index f1bec1978d..cf34f3001c 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2774,6 +2774,7 @@ GLIBC_2.38 __nldbl___isoc23_vsscanf F
 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.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index aa874b88d0..30ab1f6ca6 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -2426,3 +2426,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index afbd57da6f..5ac9dbba3f 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -546,6 +546,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index e7364cd3fe..3c745d1228 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -543,6 +543,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 913fa59215..fb7a6bd8ae 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2702,3 +2702,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 43af3a9811..d03741e927 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2651,6 +2651,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index af72f8fab0..a543c4e1f6 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2835,6 +2835,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 48cbb0fa50..a0d098e09a 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2600,6 +2600,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
index c15884bb0b..d5ccc5044b 100644
--- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
@@ -2186,3 +2186,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 3738db81df..3b40a335f1 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -547,6 +547,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
 GLIBC_2.4 _IO_2_1_stdin_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index ed13627752..5673e771f9 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2778,6 +2778,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 8357738621..6096f8749a 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2751,3 +2751,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index 58c5da583d..c03f9a7681 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2748,3 +2748,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index d3741945cd..21748a22ca 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2743,6 +2743,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 5319fdc204..2f55942c24 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2741,6 +2741,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 1743ea6eb9..1e32a53947 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2749,6 +2749,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 9b1f53c6ac..ab272a1f23 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2651,6 +2651,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index ae1c6ca1b5..fd9d42118e 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2790,3 +2790,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index a7c572c947..19599aa47d 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -2172,3 +2172,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 074fa031a7..8687e97f3e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2817,6 +2817,7 @@ GLIBC_2.38 __nldbl___isoc23_vsscanf F
 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.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index dfcb4bd2d5..17bac95761 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2850,6 +2850,7 @@ GLIBC_2.38 __nldbl___isoc23_vsscanf F
 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.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 63bbccf3f9..fbf6bb0c8c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2571,6 +2571,7 @@ GLIBC_2.38 __nldbl___isoc23_vsscanf F
 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.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index ab85fd61ef..3fcc670919 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2885,3 +2885,4 @@ GLIBC_2.38 __nldbl___isoc23_vsscanf F
 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
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index b716f5c763..20dea1535e 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -2428,3 +2428,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 774e777b65..93084b7ed5 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2628,3 +2628,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 8625135c48..20c110ae92 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2815,6 +2815,7 @@ GLIBC_2.38 __nldbl___isoc23_vsscanf F
 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.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index d00c7eb262..daa7300b54 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2608,6 +2608,7 @@ GLIBC_2.38 __nldbl___isoc23_vsscanf F
 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.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index b63037241d..3bbcad60a6 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2658,6 +2658,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index d80055617d..d08611b8b5 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2655,6 +2655,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5be55c11d2..ce81a96967 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2810,6 +2810,7 @@ GLIBC_2.38 __nldbl___isoc23_vsscanf F
 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.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 475fdaae15..9cfe5dbe8c 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2623,6 +2623,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 6cfb928bc8..2b04d40ce5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2574,6 +2574,7 @@ GLIBC_2.38 __isoc23_wcstoull F
 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.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index c735097172..e8c2ef8cb4 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2680,3 +2680,4 @@ GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
 GLIBC_2.38 __isoc23_wscanf F
+GLIBC_2.38 dlrelocate F
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 12/14] implement RTLD_DI_MAPINFO dlinfo() request
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (10 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 11/14] implement dlrelocate() function Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 13/14] implement dlset_object_base() function Stas Sergeev
  2023-05-18  8:28 ` [PATCH 14/14] implement RTLD_DI_DEPLIST dlinfo() request Stas Sergeev
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

This request fills in the following structure:
typedef struct
{
  void *map_start;             /* Beginning of mapping containing address.  */
  size_t map_length;           /* Length of mapping.  */
  size_t map_align;            /* Alignment of mapping.  */
  int relocated;               /* Indicates whether an object was relocated. */
} Dl_mapinfo;

This structure allows the user to move an unrelocated object.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 dlfcn/dlfcn.h  | 15 ++++++++++++++-
 dlfcn/dlinfo.c | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
index c3e228c667..7671c187a3 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -170,7 +170,12 @@ enum
        the number of program headers in the array.  */
     RTLD_DI_PHDR = 11,
 
-    RTLD_DI_MAX = 11
+    /* Treat ARG as Dl_mapinfo *, and store the mapping information
+       at that location.  The dlinfo call returns 0 on success or
+       -1 on failure.  */
+    RTLD_DI_MAPINFO = 12,
+
+    RTLD_DI_MAX = 12
   };
 
 
@@ -203,6 +208,14 @@ typedef struct
 # endif
 } Dl_serinfo;
 
+typedef struct
+{
+  void *map_start;		/* Beginning of mapping containing address.  */
+  size_t map_length;		/* Length of mapping.  */
+  size_t map_align;		/* Alignment of mapping.  */
+  int relocated;		/* Indicates whether an object was relocated. */
+} Dl_mapinfo;
+
 struct dl_find_object
 {
   __extension__ unsigned long long int dlfo_flags;
diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c
index 1b5dd90ae5..8d7db7dbb8 100644
--- a/dlfcn/dlinfo.c
+++ b/dlfcn/dlinfo.c
@@ -85,6 +85,24 @@ dlinfo_doit (void *argsblock)
       *(const ElfW(Phdr) **) args->arg = l->l_phdr;
       args->result = l->l_phnum;
       break;
+
+    case RTLD_DI_MAPINFO:
+      {
+	Dl_mapinfo *info = (Dl_mapinfo *) args->arg;
+	__rtld_lock_lock_recursive (GL(dl_load_lock));
+	if (l->l_contiguous)
+	  {
+	    info->map_start = (void *) l->l_map_start;
+	    info->map_length = l->l_map_end - l->l_map_start;
+	    info->map_align = l->l_map_align;
+	    info->relocated = l->l_relocated;
+	    args->result = 0;
+	  }
+	else
+	  args->result = -1;
+	__rtld_lock_unlock_recursive (GL(dl_load_lock));
+	break;
+      }
     }
 }
 
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 13/14] implement dlset_object_base() function
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (11 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 12/14] implement RTLD_DI_MAPINFO dlinfo() request Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  2023-05-18  8:28 ` [PATCH 14/14] implement RTLD_DI_DEPLIST dlinfo() request Stas Sergeev
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

`int dlset_object_base(void *handle, void *addr)' - new function to
set the new base address of an unrelocated object, after it was moved.
Returns error if the object is already relocated. The base address
set by this function, will be used when relocation is performed.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 dlfcn/Makefile                                |   1 +
 dlfcn/Versions                                |   1 +
 dlfcn/dlfcn.h                                 |   4 +
 dlfcn/dlset_object_base.c                     | 124 ++++++++++++++++++
 dlfcn/tst-noreloc.c                           |  44 +++++++
 include/dlfcn.h                               |   4 +
 sysdeps/mach/hurd/i386/libc.abilist           |   1 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   1 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/arc/libc.abilist      |   1 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |   1 +
 .../sysv/linux/loongarch/lp64/libc.abilist    |   1 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |   1 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   1 +
 .../sysv/linux/microblaze/be/libc.abilist     |   1 +
 .../sysv/linux/microblaze/le/libc.abilist     |   1 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |   1 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |   1 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |   1 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/or1k/libc.abilist     |   1 +
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |   1 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |   1 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |   1 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |   1 +
 .../unix/sysv/linux/riscv/rv32/libc.abilist   |   1 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |   1 +
 .../unix/sysv/linux/s390/s390-32/libc.abilist |   1 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |   1 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |   1 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |   1 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |   1 +
 .../unix/sysv/linux/x86_64/64/libc.abilist    |   1 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |   1 +
 41 files changed, 213 insertions(+)
 create mode 100644 dlfcn/dlset_object_base.c

diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index fb56b8aecb..da486a9b01 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -27,6 +27,7 @@ routines = \
   dladdr1 \
   dlclose \
   dlrelocate \
+  dlset_object_base \
   dlerror \
   dlinfo \
   dlmopen \
diff --git a/dlfcn/Versions b/dlfcn/Versions
index 61ab01d764..8b1566b7c7 100644
--- a/dlfcn/Versions
+++ b/dlfcn/Versions
@@ -30,6 +30,7 @@ libc {
   }
   GLIBC_2.38 {
     dlrelocate;
+    dlset_object_base;
   }
   GLIBC_PRIVATE {
     __libc_dlerror_result;
diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
index 7671c187a3..eee6343833 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -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,
diff --git a/dlfcn/dlset_object_base.c b/dlfcn/dlset_object_base.c
new file mode 100644
index 0000000000..9221a6b72e
--- /dev/null
+++ b/dlfcn/dlset_object_base.c
@@ -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 */
diff --git a/dlfcn/tst-noreloc.c b/dlfcn/tst-noreloc.c
index a56e8102bb..96c05a4b06 100644
--- a/dlfcn/tst-noreloc.c
+++ b/dlfcn/tst-noreloc.c
@@ -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);
diff --git a/include/dlfcn.h b/include/dlfcn.h
index 7bfd5b9085..96950f72dc 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -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);
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index 53dc594256..6d1c233f3d 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 9571379cb9..f37e388df3 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index cf34f3001c..e0074f1ead 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index 30ab1f6ca6..14eb175e1a 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index 5ac9dbba3f..6fbe0f2c14 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index 3c745d1228..6c3b69a3eb 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index fb7a6bd8ae..9d7e9d2f98 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index d03741e927..ba52a9d463 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index a543c4e1f6..3d71ddd3f4 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index a0d098e09a..8ccb96eeee 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
index d5ccc5044b..08d8c210eb 100644
--- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 3b40a335f1..6486192065 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 5673e771f9..a0edd6aaba 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 6096f8749a..3602d95f46 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index c03f9a7681..da4f93ad6f 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 21748a22ca..5c581c7d7d 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 2f55942c24..b7832c343d 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 1e32a53947..f0becc0684 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index ab272a1f23..6c70fd76d2 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index fd9d42118e..8c8784986c 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index 19599aa47d..8dbeabbed1 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 8687e97f3e..c6066679b1 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 17bac95761..295dd909b9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index fbf6bb0c8c..2cd0bce2fb 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 3fcc670919..046d506558 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index 20dea1535e..0dc396c19d 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 93084b7ed5..95dee89535 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 20c110ae92..9c99e15f6d 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index daa7300b54..ec91d47437 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 3bbcad60a6..4c91900238 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index d08611b8b5..89c7a41098 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index ce81a96967..0d65f5f357 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 9cfe5dbe8c..c39c641445 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 2b04d40ce5..2243b7a05e 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -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
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index e8c2ef8cb4..449991c7bd 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -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
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 14/14] implement RTLD_DI_DEPLIST dlinfo() request
  2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
                   ` (12 preceding siblings ...)
  2023-05-18  8:28 ` [PATCH 13/14] implement dlset_object_base() function Stas Sergeev
@ 2023-05-18  8:28 ` Stas Sergeev
  13 siblings, 0 replies; 15+ messages in thread
From: Stas Sergeev @ 2023-05-18  8:28 UTC (permalink / raw)
  To: libc-alpha; +Cc: Stas Sergeev

`RTLD_DI_DEPLIST' is a new dlinfo() request that fills in this structure:
typedef struct
{
  void **deps;                  /* Array of handles for the deps.  */
  unsigned int ndeps;           /* Number of entries in the list.  */
} Dl_deplist;

It is needed if the user wants to move also the dependencies of the
loaded solib. In this case he needs to traverse the `deps' array,
make RTLD_DI_MAPINFO dlinfo() request per each handle from an array,
find the object he needs by inspecting the filled-in Dl_mapinfo structure,
make sure this object is not relocated yet, and move it, calling
dlset_object_base() at the end.

The test-suite was run on x86_64/64 and showed no regressions.

Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
 dlfcn/Makefile      |  3 +++
 dlfcn/ctorlib1.c    |  9 ++++++---
 dlfcn/dlfcn.h       | 13 ++++++++++++-
 dlfcn/dlinfo.c      | 14 ++++++++++++++
 dlfcn/tst-noreloc.c | 30 +++++++++++++++++++++++++++---
 5 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index da486a9b01..0d6b16c820 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -104,6 +104,9 @@ $(objpfx)glrefmain.out: $(objpfx)glrefmain \
 $(objpfx)failtest.out: $(objpfx)failtestmod.so
 
 $(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so
+
+$(objpfx)ctorlib1.so: $(objpfx)glreflib1.so
+LDFLAGS-ctorlib1 = $(objpfx)glreflib1.so
 $(objpfx)tst-noreloc.out: $(objpfx)ctorlib1.so
 LDFLAGS-tst-noreloc = $(LDFLAGS-rdynamic)
 
diff --git a/dlfcn/ctorlib1.c b/dlfcn/ctorlib1.c
index cf7a9096ea..7d410f6c71 100644
--- a/dlfcn/ctorlib1.c
+++ b/dlfcn/ctorlib1.c
@@ -21,10 +21,12 @@
 #include <stdio.h>
 
 extern int ref1 (void);
+
+extern int cref1 (void);
 int
-ref1 (void)
+cref1 (void)
 {
-  return 42;
+  return 34;
 }
 
 void __attribute__((constructor))
@@ -32,5 +34,6 @@ ctor (void)
 {
   int *ct = (int *) dlsym (RTLD_DEFAULT, "ctor_called");
   assert (ct);
-  (*ct)++;
+  if (ref1 () == 42)
+    (*ct)++;
 }
diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
index eee6343833..5b36330aa9 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -179,7 +179,12 @@ enum
        -1 on failure.  */
     RTLD_DI_MAPINFO = 12,
 
-    RTLD_DI_MAX = 12
+    /* Treat ARG as Dl_deplist *, and store the dependency link-maps
+       at that location.  The dlinfo call returns 0 on success or
+       -1 on failure.  */
+    RTLD_DI_DEPLIST = 13,
+
+    RTLD_DI_MAX = 13
   };
 
 
@@ -220,6 +225,12 @@ typedef struct
   int relocated;		/* Indicates whether an object was relocated. */
 } Dl_mapinfo;
 
+typedef struct
+{
+  void **deps;			/* Array of handles for the deps.  */
+  unsigned int ndeps;		/* Number of entries in the list.  */
+} Dl_deplist;
+
 struct dl_find_object
 {
   __extension__ unsigned long long int dlfo_flags;
diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c
index 8d7db7dbb8..4eb96bc476 100644
--- a/dlfcn/dlinfo.c
+++ b/dlfcn/dlinfo.c
@@ -18,6 +18,7 @@
 
 #include <dlfcn.h>
 #include <link.h>
+#include <assert.h>
 #include <ldsodefs.h>
 #include <libintl.h>
 #include <dl-tls.h>
@@ -103,6 +104,19 @@ dlinfo_doit (void *argsblock)
 	__rtld_lock_unlock_recursive (GL(dl_load_lock));
 	break;
       }
+
+    case RTLD_DI_DEPLIST:
+      {
+	int i = 0;
+	Dl_deplist *list = (Dl_deplist *) args->arg;
+	assert (l == l->l_initfini[0]);
+	list->deps = (void **) &l->l_initfini[1];  /* Skip our own handle. */
+	while (list->deps[i])
+	  i++;
+	list->ndeps = i;
+	args->result = 0;
+	break;
+      }
     }
 }
 
diff --git a/dlfcn/tst-noreloc.c b/dlfcn/tst-noreloc.c
index 96c05a4b06..846d2b9321 100644
--- a/dlfcn/tst-noreloc.c
+++ b/dlfcn/tst-noreloc.c
@@ -29,14 +29,17 @@
 
 int ctor_called;
 
-static void move_object (void *handle)
+static void move_object (void *handle, int is_dep)
 {
   int ret;
   Dl_mapinfo mapinfo;
   void *new_addr;
 
   ret = dlinfo (handle, RTLD_DI_MAPINFO, &mapinfo);
-  TEST_COMPARE (ret, 0);
+  if (!is_dep)
+    TEST_COMPARE (ret, 0);
+  if (is_dep && (ret == -1 || mapinfo.relocated))
+    return;
   TEST_COMPARE (mapinfo.relocated, 0);
   if (mapinfo.map_align != getpagesize ())
     error (EXIT_FAILURE, 0, "unsupported map alignment");
@@ -59,7 +62,10 @@ do_test (void)
   void *handle;
   int (*sym) (void);
   Dl_info info;
+  Dl_info info2;
+  Dl_deplist deplist;
   int ret;
+  int i;
 
   handle = dlopen ("ctorlib1.so", RTLD_NOW | RTLD_NORELOCATE);
   if (handle == NULL)
@@ -97,7 +103,11 @@ do_test (void)
   if (handle == NULL)
     error (EXIT_FAILURE, 0, "cannot load: ctorlib1.so");
 
-  move_object (handle);
+  move_object (handle, 0);
+  ret = dlinfo (handle, RTLD_DI_DEPLIST, &deplist);
+  TEST_COMPARE (ret, 0);
+  for (i = 0; i < deplist.ndeps; i++)
+    move_object (deplist.deps[i], 1);
 
   TEST_COMPARE (ctor_called, 0);
   sym = dlsym (handle, "ref1");
@@ -113,6 +123,20 @@ do_test (void)
   TEST_VERIFY ((uintptr_t) info.dli_fbase < 0x100000000);
 #endif
 
+  sym = dlsym (handle, "cref1");
+  if (sym == NULL)
+    error (EXIT_FAILURE, 0, "dlsym failed");
+  TEST_COMPARE (ctor_called, 1);
+
+  memset (&info2, 0, sizeof (info2));
+  ret = dladdr (sym, &info2);
+  if (ret == 0)
+    error (EXIT_FAILURE, 0, "dladdr failed");
+#if MAP_32BIT != 0
+  TEST_VERIFY ((uintptr_t) info2.dli_fbase < 0x100000000);
+#endif
+  TEST_VERIFY (info2.dli_fbase != info.dli_fbase);
+
   printf ("ret = %d\n", ret);
   printf ("info.dli_fname = %p (\"%s\")\n", info.dli_fname, info.dli_fname);
   printf ("info.dli_fbase = %p\n", info.dli_fbase);
-- 
2.39.2


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-05-18  8:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-18  8:28 [PATCH 00/14] implement RTLD_NORELOCATE api [BZ #30007] Stas Sergeev
2023-05-18  8:28 ` [PATCH 01/14] elf: switch _dl_map_segment() to anonymous mapping Stas Sergeev
2023-05-18  8:28 ` [PATCH 02/14] use initial mmap also for ET_EXEC Stas Sergeev
2023-05-18  8:28 ` [PATCH 03/14] rework maphole Stas Sergeev
2023-05-18  8:28 ` [PATCH 04/14] split do_reloc_1() from dl_open_worker_begin() Stas Sergeev
2023-05-18  8:28 ` [PATCH 05/14] split do_reloc_2() out of do_open_worker() Stas Sergeev
2023-05-18  8:28 ` [PATCH 06/14] move relocation into _dl_object_reloc() func Stas Sergeev
2023-05-18  8:28 ` [PATCH 07/14] split out _dl_finalize_segments() Stas Sergeev
2023-05-18  8:28 ` [PATCH 08/14] finalize elf segments on a relocation step Stas Sergeev
2023-05-18  8:28 ` [PATCH 09/14] implement RTLD_NORELOCATE dlopen() flag Stas Sergeev
2023-05-18  8:28 ` [PATCH 10/14] add test-case for RTLD_NORELOCATE Stas Sergeev
2023-05-18  8:28 ` [PATCH 11/14] implement dlrelocate() function Stas Sergeev
2023-05-18  8:28 ` [PATCH 12/14] implement RTLD_DI_MAPINFO dlinfo() request Stas Sergeev
2023-05-18  8:28 ` [PATCH 13/14] implement dlset_object_base() function Stas Sergeev
2023-05-18  8:28 ` [PATCH 14/14] implement RTLD_DI_DEPLIST dlinfo() request Stas Sergeev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).