public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Carlos O'Donell <carlos@redhat.com>
To: Stas Sergeev <stsp2@yandex.ru>, libc-alpha@sourceware.org
Subject: Re: [PATCH 12/13] dlfcn,elf: implement dlmem() [BZ #11767]
Date: Wed, 29 Mar 2023 09:45:17 -0400	[thread overview]
Message-ID: <b6a96687-9a4b-414f-849a-45a305898274@redhat.com> (raw)
In-Reply-To: <20230318165110.3672749-13-stsp2@yandex.ru>

On 3/18/23 12:51, Stas Sergeev via Libc-alpha wrote:
> This patch adds the following function:
> void *dlmem(const unsigned char *buffer, size_t size, int flags,
>             struct dlmem_args *dlm_args);

I am raising a sustained objection to including dlmem() in glibc.

I appreciate your effort in working on this serious, and I think *many* of
the core changes you propose are good cleanups.

In my experience it is the wrong level of abstraction.

To implement fdlopen on top of dlmem requires PT_LOAD processing and that
will duplicate into userspace a significant part of the complexity of ELF
loading and segment handling. The test case you include below is incomplete
when it comes to implementing a functional fdlopen() across the supported
architectures and toolchain variants.

When an interface requires duplication of complex load segment handling
into a user program it means that we have the abstraction wrong.

You could add an dlload() interface which reads everything from disk, and then
dlmem() to process it, but then why not just make it fdlopen()?

You have previously stated that none of them bring the functionality you need
from dlmem() and that might be true, but glibc is not here to serve individual
purposes, it is here to serve the requirements of the larger ecosystem of
applications and their most standardized requirements. Very specific functionality,
like futexes for example, we don't even export, because they are difficult to use
without a wrapping library that supports their use, similar to io_uring, and other
asynchronous IO mechanisms.

If you strongly believe that dlmem() serves broader applications, then I suggest
looking at previous examples of smaller features entering glibc.

There we tended to do:

- Write up a detailed design document e.g. 
  https://sourceware.org/glibc/wiki/Y2038ProofnessDesign
  https://sourceware.org/glibc/wiki/Proposals/GroupMerging

- Land all cleanups required first.
  - Your cleanups may be useful even outside of the existing design.
  - Auditor additions may be landed independent of the design.
 
- Discuss the blockers, one by one, and attempt to get consensus.
  https://sourceware.org/glibc/wiki/Consensus#How_do_I_build_consensus.3F

Today you have a blocker from me about the level of abstraction of the interface.
You need to convince me that this interface is:

(a) Useful for many applications.

(b) Does not require complex logic on the application part.
    - or -
    Supports the application by providing another API to do loading.
 
> It is the same as dlopen() but allows to dynamic-link solibs from
> the memory buffer, rather than from a file as dlopen() does.
> 
> "buffer" arg is the pointer to the solib image in memory.
> "size" is the solib image size. Must be smaller-or-equal to the
>     actual buffer size.
> "flags" is the same flags argument used in dlopen().
> "dlm_args" is an optional argument that allows to specify the load
>     namespace and a premap callback.
> 
> This implementation is trying a "zero-copy" technique first, but
> it works only with linux kernels 5.13 and newer. So the memcpy()
> fall-back is added as well.
> 
> This patch adds a test-case named tst-dlmem-fdlopen. It implements
> a bsd-compatible fdlopen() on top of dlmem() and loads a test lib
> with it. It then checks /proc/<pid>/maps to make sure the library
> was mmap()ed rather then memcopied. Then it does the regular set
> of solib tests.
> 
> The test-suite was run on x86_64/64 and showed no regressions.
> 
> Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
> ---
>  dlfcn/Makefile                                |   5 +-
>  dlfcn/Versions                                |   3 +
>  dlfcn/dlfcn.h                                 |  22 +++
>  dlfcn/dlmem.c                                 | 102 +++++++++++
>  dlfcn/tst-dlmem-fdlopen.c                     | 106 +++++++++++
>  elf/dl-load.c                                 | 169 ++++++++++++++++++
>  elf/dl-load.h                                 |   3 +
>  elf/dl-main.h                                 |  12 ++
>  elf/dl-open.c                                 |  13 ++
>  elf/rtld.c                                    |   1 +
>  include/dlfcn.h                               |   4 +
>  manual/dynlink.texi                           |   1 +
>  sysdeps/generic/ldsodefs.h                    |   9 +
>  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 +
>  48 files changed, 484 insertions(+), 1 deletion(-)
>  create mode 100644 dlfcn/dlmem.c
>  create mode 100644 dlfcn/tst-dlmem-fdlopen.c
> 
> diff --git a/dlfcn/Makefile b/dlfcn/Makefile
> index 1fa7fea1ef..8bca644168 100644
> --- a/dlfcn/Makefile
> +++ b/dlfcn/Makefile
> @@ -28,6 +28,7 @@ routines = \
>    dlclose \
>    dlerror \
>    dlinfo \
> +  dlmem \
>    dlmopen \
>    dlopen \
>    dlsym \
> @@ -51,7 +52,8 @@ 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-dlmem-fdlopen
> +CPPFLAGS-tst-dlmem-fdlopen.c += -DBUILDDIR=\"$(objpfx)\"
>  endif
>  modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
>  		defaultmod2 errmsg1mod modatexit modcxaatexit \
> @@ -102,6 +104,7 @@ $(objpfx)glrefmain.out: $(objpfx)glrefmain \
>  $(objpfx)failtest.out: $(objpfx)failtestmod.so
>  
>  $(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so
> +$(objpfx)tst-dlmem-fdlopen.out: $(objpfx)glreflib1.so
>  
>  $(objpfx)tst-dlinfo.out: $(objpfx)glreflib3.so
>  LDFLAGS-glreflib3.so = -Wl,-rpath,:
> diff --git a/dlfcn/Versions b/dlfcn/Versions
> index cc34eb824d..b427c9c3a3 100644
> --- a/dlfcn/Versions
> +++ b/dlfcn/Versions
> @@ -28,6 +28,9 @@ libc {
>      dlsym;
>      dlvsym;
>    }
> +  GLIBC_2.38 {
> +    dlmem;
> +  }
>    GLIBC_PRIVATE {
>      __libc_dlerror_result;
>      _dlerror_run;
> diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
> index c5d192597d..87dc4932fd 100644
> --- a/dlfcn/dlfcn.h
> +++ b/dlfcn/dlfcn.h
> @@ -68,6 +68,28 @@ 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;
>  
> +/* Callback for dlmem. */
> +typedef void *
> +(dlmem_premap_t) (void *mappref, size_t maplength, size_t mapalign,
> +	          void *cookie);
> +
> +struct dlmem_args {
> +  /* Optional name to associate with the loaded object. */
> +  const char *soname;
> +  /* Namespace where to load the object. */
> +  Lmid_t nsid;
> +  /* dlmem-specific flags. */
> +  unsigned flags;
> +  /* Optional premap callback. */
> +  dlmem_premap_t *premap;
> +  /* Optional argument for premap callback. */
> +  void *cookie;
> +};
> +
> +/* Like `dlmopen', but loads shared object from memory buffer.  */
> +extern void *dlmem (const unsigned char *buffer, size_t size, int mode,
> +		    struct dlmem_args *dlm_args);
> +
>  /* 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/dlmem.c b/dlfcn/dlmem.c
> new file mode 100644
> index 0000000000..548f6f34eb
> --- /dev/null
> +++ b/dlfcn/dlmem.c
> @@ -0,0 +1,102 @@
> +/* Load a shared object from memory.
> +   Copyright (C) 1995-2022 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 <libintl.h>
> +#include <stddef.h>
> +#include <unistd.h>
> +#include <ldsodefs.h>
> +#include <shlib-compat.h>
> +
> +struct _dlmem_args
> +{
> +  /* The arguments for dlmem_doit.  */
> +  const unsigned char *buffer;
> +  size_t size;
> +  int mode;
> +  struct dlmem_args *args;
> +  /* The return value of dlmem_doit.  */
> +  void *new;
> +  /* Address of the caller.  */
> +  const void *caller;
> +};
> +
> +static void
> +dlmem_doit (void *a)
> +{
> +  struct _dlmem_args *args = (struct _dlmem_args *) a;
> +
> +  if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND
> +		     | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE
> +		     | __RTLD_SPROF))
> +    _dl_signal_error (0, NULL, NULL, _("invalid mode parameter"));
> +
> +  args->new = GLRO(dl_mem) (args->buffer, args->size,
> +			    args->mode | __RTLD_DLOPEN,
> +			    args->args,
> +			    args->caller,
> +			    __libc_argc, __libc_argv, __environ);
> +}
> +
> +
> +static void *
> +dlmem_implementation (const unsigned char *buffer, size_t size, int mode,
> +		      struct dlmem_args *dlm_args, void *dl_caller)
> +{
> +  struct _dlmem_args args;
> +  args.buffer = buffer;
> +  args.size = size;
> +  args.mode = mode;
> +  args.args = dlm_args;
> +  args.caller = dl_caller;
> +
> +  return _dlerror_run (dlmem_doit, &args) ? NULL : args.new;
> +}
> +
> +#ifdef SHARED
> +void *
> +___dlmem (const unsigned char *buffer, size_t size, int mode,
> +	  struct dlmem_args *dlm_args)
> +{
> +  if (GLRO (dl_dlfcn_hook) != NULL)
> +    return GLRO (dl_dlfcn_hook)->dlmem (buffer, size, mode, dlm_args,
> +                                        RETURN_ADDRESS (0));
> +  else
> +    return dlmem_implementation (buffer, size, mode, dlm_args,
> +				 RETURN_ADDRESS (0));
> +}
> +versioned_symbol (libc, ___dlmem, dlmem, GLIBC_2_38);
> +
> +#else /* !SHARED */
> +/* Also used with _dlfcn_hook.  */
> +void *
> +__dlmem (const unsigned char *buffer, size_t size, int mode,
> +	 struct dlmem_args *dlm_args, void *dl_caller)
> +{
> +  return dlmem_implementation (buffer, size, mode, dlm_args, dl_caller);
> +}
> +
> +void *
> +___dlmem (const unsigned char *buffer, size_t size, int mode,
> +	  struct dlmem_args *dlm_args)
> +{
> +  return __dlmem (buffer, size, mode, dlm_args, RETURN_ADDRESS (0));
> +}
> +weak_alias (___dlmem, dlmem)
> +static_link_warning (dlmem)
> +#endif /* !SHARED */
> diff --git a/dlfcn/tst-dlmem-fdlopen.c b/dlfcn/tst-dlmem-fdlopen.c
> new file mode 100644
> index 0000000000..db9b5cf54a
> --- /dev/null
> +++ b/dlfcn/tst-dlmem-fdlopen.c
> @@ -0,0 +1,106 @@
> +/* Test for fdlopen implementation on top of dlmem.
> +   Copyright (C) 2000-2022 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 <link.h>
> +#include <errno.h>
> +#include <error.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <sys/mman.h>
> +#include <support/check.h>
> +
> +static void *
> +fdlopen (int fd, int flags)
> +{
> +  off_t len;
> +  void *addr;
> +  void *handle;
> +
> +  len = lseek (fd, 0, SEEK_END);
> +  lseek (fd, 0, SEEK_SET);
> +  addr = mmap (NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);

This may not meet the requirements of the file being opened.

Each PT_LOAD segment must be mapped according to the requiremenst of the
segment.


> +  if (addr == MAP_FAILED)
> +    {
> +      printf ("cannot mmap, %s\n", strerror(errno));
> +      exit (EXIT_FAILURE);
> +    }
> +  handle = dlmem (addr, len, flags, NULL);
> +  munmap (addr, len);
> +  return handle;
> +}
> +
> +
> +#define TEST_FUNCTION do_test
> +extern int do_test (void);
> +
> +int
> +do_test (void)
> +{
> +  char cmd[256];
> +  void *handle;
> +  int (*sym) (void); /* We load ref1 from glreflib1.c.  */
> +  Dl_info info;
> +  int rc;
> +  int fd = open (BUILDDIR "glreflib1.so", O_RDONLY);
> +  if (fd == -1)
> +    error (EXIT_FAILURE, 0, "cannot open: glreflib1.so");
> +  handle = fdlopen (fd, RTLD_NOW);
> +  close (fd);
> +  if (handle == NULL)
> +    {
> +      printf ("fdlopen failed, %s\n", dlerror());
> +      exit (EXIT_FAILURE);
> +    }
> +
> +  /* Check that the lib is properly mmap()ed, rather than memcpy()ed.
> +     This may fail on linux kernels <5.13. */
> +  snprintf (cmd, sizeof(cmd), "grep glreflib1.so /proc/%i/maps", getpid());
> +  rc = system (cmd);
> +  TEST_COMPARE (rc, 0);
> +
> +  sym = dlsym (handle, "ref1");
> +  if (sym == NULL)
> +    error (EXIT_FAILURE, 0, "dlsym failed");
> +
> +  memset (&info, 0, sizeof (info));
> +  rc = dladdr (sym, &info);
> +  if (rc == 0)
> +    error (EXIT_FAILURE, 0, "dladdr failed");
> +
> +  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");
> +  return 0;
> +}
> +
> +
> +#include <support/test-driver.c>
> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index 7175b99962..2550173f48 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -75,6 +75,7 @@ struct filebuf
>  #include <dl-machine-reject-phdr.h>
>  #include <dl-sysdep-open.h>
>  #include <dl-prop.h>
> +#include <dl-main.h>
>  #include <not-cancel.h>
>  
>  #include <endian.h>
> @@ -2353,6 +2354,174 @@ _dl_map_object (struct link_map *loader, const char *name,
>    return __dl_map_object (loader, name, NULL, type, trace_mode, mode, nsid);
>  }
>  
> +static void *
> +do_memremap (void *addr, size_t length, int prot, int flags,
> +             void *arg, off_t offset)
> +{
> +  const struct dlmem_fbuf *fb = arg;
> +
> +  assert (flags & MAP_FIXED);
> +  if (offset < fb->len)
> +    {
> +      size_t to_copy = length;
> +      if (offset + to_copy > fb->len)
> +        to_copy = fb->len - offset;
> +#ifdef MREMAP_DONTUNMAP
> +      void *addr2 = __mremap ((void *) (fb->buf + offset), to_copy, to_copy,
> +                              MREMAP_MAYMOVE | MREMAP_FIXED | MREMAP_DONTUNMAP,
> +                              addr);
> +      /* MREMAP_DONTUNMAP introduced in linux-5.7, but only works for
> +         file-based maps since commit a460938 went in 5.13.
> +         So have a fall-back. */
> +      if (addr2 == MAP_FAILED)
> +        memcpy (addr, fb->buf + offset, to_copy);
> +#else
> +      /* MREMAP_DONTUNMAP is not always available. This is a fall-back. */
> +      memcpy (addr, fb->buf + offset, to_copy);
> +#endif
> +    }
> +  if (__mprotect (addr, length, prot) == -1)
> +    return MAP_FAILED;
> +  return addr;
> +}
> +
> +static void *
> +do_dlmem_premap (void *mappref, size_t maplength, size_t mapalign,
> +		 void *cookie)
> +{
> +  struct dlmem_fbuf *fb = cookie;
> +  void *ret = MAP_FAILED;
> +
> +  if (fb->dlm_args && fb->dlm_args->premap)
> +    ret = fb->dlm_args->premap (mappref, maplength, mapalign,
> +                                fb->dlm_args->cookie);
> +  if (ret == MAP_FAILED)
> +    ret = (void *) _dl_map_segment ((ElfW(Addr)) mappref, maplength,
> +                                    mapalign);
> +  return ret;
> +}
> +
> +static ssize_t
> +do_pread_memcpy (void *arg, void *buf, size_t count, off_t offset)
> +{
> +  struct dlmem_fbuf *fb = arg;
> +  if (offset >= fb->len)
> +    return -1;
> +  if (offset + count > fb->len)
> +    count = fb->len - offset;
> +  if (count)
> +    memcpy (buf, fb->buf + offset, count);
> +  return count;
> +}
> +
> +static struct link_map *
> +___dl_map_object_from_mem (struct link_map *loader, const char *name,
> +			   void *private, int type, int trace_mode,
> +			   int mode, Lmid_t nsid, struct filebuf *fbp)
> +{
> +  struct link_map *l;
> +  int err;
> +  char *realname;
> +  /* Initialize to keep the compiler happy.  */
> +  const char *errstring = NULL;
> +  int errval = 0;
> +  struct r_debug *r = _dl_debug_update (nsid);
> +  bool make_consistent = false;
> +  struct r_file_id id = {};
> +
> +  assert (nsid >= 0);
> +  assert (nsid < GL(dl_nns));
> +
> +  if (name && *name)
> +    {
> +      /* Look for this name among those already loaded.  */
> +      l = _dl_check_loaded (name, nsid);
> +      if (l)
> +        return l;
> +    }
> +
> +  /* Will be true if we found a DSO which is of the other ELF class.  */
> +  bool found_other_class = false;
> +
> +  err = do_open_verify (name, private, fbp,
> +                        loader ?: GL(dl_ns)[nsid]._ns_loaded,
> +                        &found_other_class, false, do_pread_memcpy);
> +  if (err)
> +    return NULL;
> +
> +  /* In case the LOADER information has only been provided to get to
> +     the appropriate RUNPATH/RPATH information we do not need it
> +     anymore.  */
> +  if (mode & __RTLD_CALLMAP)
> +    loader = NULL;
> +
> +  if (mode & RTLD_NOLOAD)
> +    {
> +      /* We are not supposed to load the object unless it is already
> +	 loaded.  So return now.  */
> +      return NULL;
> +    }
> +
> +  /* Print debugging message.  */
> +  if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
> +    _dl_debug_printf ("dlmem [%lu];  generating link map\n", nsid);
> +
> +  /* _dl_new_object() treats "" separately and doesn't free it. */
> +  realname = *name ? __strdup (name) : (char *) "";
> +  /* Enter the new object in the list of loaded objects.  */
> +  l = _dl_new_object (realname, name, type, loader, mode, nsid);
> +  if (__glibc_unlikely (l == NULL))
> +    {
> +      errstring = N_("cannot create shared object descriptor");
> +      goto lose_errno;
> +    }
> +
> +  void *stack_end = __libc_stack_end;
> +  if (_ld_map_object_1 (l, private, fbp, mode, loader, &stack_end, &errval,
> +                        &errstring, do_memremap, do_dlmem_premap))
> +    goto lose;
> +
> +  _ld_map_object_2 (l, mode, id, NULL, nsid, r, &make_consistent);
> +  return l;
> +
> +lose_errno:
> +  errval = errno;
> +lose:
> +  if (l != NULL && l->l_map_start != 0)
> +    _dl_unmap_segments (l);
> +  if (l != NULL && l->l_origin != (char *) -1l)
> +    free ((char *) l->l_origin);
> +  if (l != NULL && !l->l_libname->dont_free)
> +    free (l->l_libname);
> +  if (l != NULL && l->l_phdr_allocated)
> +    free ((void *) l->l_phdr);
> +  free (l);
> +
> +  if (make_consistent && r != NULL)
> +    {
> +      r->r_state = RT_CONSISTENT;
> +      _dl_debug_state ();
> +      LIBC_PROBE (map_failed, 2, nsid, r);
> +    }
> +
> +  _dl_signal_error (errval, NULL, NULL, errstring);
> +  return NULL;
> +}
> +
> +struct link_map *
> +__dl_map_object_from_mem (struct link_map *loader, const char *name,
> +			  void *private, int type, int trace_mode,
> +			  int mode, Lmid_t nsid)
> +{
> +  struct link_map *ret;
> +  struct filebuf fb = {};
> +
> +  ret = ___dl_map_object_from_mem (loader, name, private, type, trace_mode,
> +                                  mode, nsid, &fb);
> +  filebuf_done (&fb);
> +  return ret;
> +}
> +
>  struct add_path_state
>  {
>    bool counting;
> diff --git a/elf/dl-load.h b/elf/dl-load.h
> index e777da5838..09b2878260 100644
> --- a/elf/dl-load.h
> +++ b/elf/dl-load.h
> @@ -106,6 +106,9 @@ _dl_postprocess_loadcmd (struct link_map *l, const ElfW(Ehdr) *header,
>                                        - c->mapoff);
>  }
>  
> +static void *
> +do_mmap (void *addr, size_t length, int prot, int flags,
> +         void *arg, off_t offset);
>  
>  /* This is a subroutine of _dl_map_object_from_fd.  It is responsible
>     for filling in several fields in *L: l_map_start, l_map_end, l_addr,
> diff --git a/elf/dl-main.h b/elf/dl-main.h
> index 344a87d5e8..e60fafaeb6 100644
> --- a/elf/dl-main.h
> +++ b/elf/dl-main.h
> @@ -104,6 +104,13 @@ struct dl_main_state
>    bool version_info;
>  };
>  
> +struct dlmem_fbuf
> +{
> +  ssize_t len;
> +  const unsigned char *buf;
> +  struct dlmem_args *dlm_args;
> +};
> +
>  /* Open the shared object NAME and map in its segments.
>     LOADER's DT_RPATH is used in searching for NAME.
>     If the object is already opened, returns its existing map.  */
> @@ -112,6 +119,11 @@ __dl_map_object (struct link_map *loader,
>                   const char *name, void *private,
>                   int type, int trace_mode, int mode,
>                   Lmid_t nsid) attribute_hidden;
> +extern struct link_map *
> +__dl_map_object_from_mem (struct link_map *loader,
> +			  const char *name, void *private,
> +			  int type, int trace_mode, int mode,
> +			  Lmid_t nsid) attribute_hidden;
>  
>  /* Helper function to invoke _dl_init_paths with the right arguments
>     from *STATE.  */
> diff --git a/elf/dl-open.c b/elf/dl-open.c
> index f3886c21bc..7c7bb2ef4f 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -953,6 +953,19 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
>                       __dl_map_object);
>  }
>  
> +void *
> +_dl_mem (const unsigned char *buffer, size_t size, int mode,
> +	 struct dlmem_args *dlm_args, const void *caller_dlopen,
> +	 int argc, char *argv[], char *env[])
> +{
> +  struct dlmem_fbuf fb = { .buf = buffer, .len = size, .dlm_args = dlm_args };
> +  Lmid_t nsid = dlm_args ? dlm_args->nsid : LM_ID_BASE;
> +  const char *file = (dlm_args && dlm_args->soname) ? dlm_args->soname : "";
> +
> +  return do_dl_open (file, &fb, mode, caller_dlopen, nsid, argc, argv, env,
> +                     __dl_map_object_from_mem);
> +}
> +
>  void
>  _dl_show_scope (struct link_map *l, int from)
>  {
> diff --git a/elf/rtld.c b/elf/rtld.c
> index f82fbeb132..1877ec9f16 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -370,6 +370,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
>      ._dl_mcount = _dl_mcount,
>      ._dl_lookup_symbol_x = _dl_lookup_symbol_x,
>      ._dl_open = _dl_open,
> +    ._dl_mem = _dl_mem,
>      ._dl_close = _dl_close,
>      ._dl_catch_error = _dl_catch_error,
>      ._dl_error_free = _dl_error_free,
> diff --git a/include/dlfcn.h b/include/dlfcn.h
> index ae25f05303..6205cf407d 100644
> --- a/include/dlfcn.h
> +++ b/include/dlfcn.h
> @@ -100,6 +100,8 @@ struct dlfcn_hook
>  {
>    /* Public interfaces.  */
>    void *(*dlopen) (const char *file, int mode, void *dl_caller);
> +  void *(*dlmem) (const unsigned char *buffer, size_t size, int mode,
> +		  struct dlmem_args *dlm_args, void *dl_caller);
>    int (*dlclose) (void *handle);
>    void *(*dlsym) (void *handle, const char *name, void *dl_caller);
>    void *(*dlvsym) (void *handle, const char *name, const char *version,
> @@ -123,6 +125,8 @@ struct dlfcn_hook
>     the __libc_dl* functions defined in elf/dl-libc.c instead.  */
>  
>  extern void *__dlopen (const char *file, int mode, void *caller);
> +extern void *__dlmem (const unsigned char *file, size_t size, int mode,
> +		      struct dlmem_args *dlm_args, void *caller);
>  extern void *__dlmopen (Lmid_t nsid, const char *file, int mode,
>  			void *dl_caller);
>  extern int __dlclose (void *handle);
> diff --git a/manual/dynlink.texi b/manual/dynlink.texi
> index 6a4a50d3f0..21bc6c067c 100644
> --- a/manual/dynlink.texi
> +++ b/manual/dynlink.texi
> @@ -209,6 +209,7 @@ This function is a GNU extension.
>  @c dladdr1
>  @c dlclose
>  @c dlerror
> +@c dlmem
>  @c dlmopen
>  @c dlopen
>  @c dlsym
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index c99dad77cc..abca95b18c 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -669,6 +669,9 @@ struct rtld_global_ro
>  				   struct link_map *);
>    void *(*_dl_open) (const char *file, int mode, const void *caller_dlopen,
>  		     Lmid_t nsid, int argc, char *argv[], char *env[]);
> +  void *(*_dl_mem) (const unsigned char *buffer, size_t size, int mode,
> +		    struct dlmem_args *dlm_args, const void *caller_dlopen,
> +		    int argc, char *argv[], char *env[]);
>    void (*_dl_close) (void *map);
>    /* libdl in a secondary namespace (after dlopen) must use
>       _dl_catch_error from the main namespace, so it has to be
> @@ -1249,6 +1252,12 @@ extern void *_dl_open (const char *name, int mode, const void *caller,
>  		       Lmid_t nsid, int argc, char *argv[], char *env[])
>       attribute_hidden;
>  
> +/* Open shared object from memory buffer. */
> +extern void *_dl_mem (const unsigned char *buffer, size_t size, int mode,
> +		      struct dlmem_args *dlm_args, const void *caller,
> +		      int argc, char *argv[], char *env[])
> +     attribute_hidden;
> +
>  /* Free or queue for freeing scope OLD.  If other threads might be
>     in the middle of _dl_fixup, _dl_profile_fixup or dl*sym using the
>     old scope, OLD can't be freed until no thread is using it.  */
> diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
> index ed0c4789eb..1880004336 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 dlmem 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..c4d31cabed 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 dlmem F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index f1bec1978d..93b37a1e1d 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 dlmem 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..9fec2308c3 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 dlmem F
> diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
> index afbd57da6f..bd0f04e58a 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 dlmem 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..dccc49c8d6 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 dlmem 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..0df8524ac0 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 dlmem F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index 43af3a9811..fa4680e97a 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 dlmem 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..bfb1bde49d 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 dlmem 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..e53505abe0 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 dlmem 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..9f56cbdcab 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 dlmem F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 3738db81df..d5443b1198 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 dlmem 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..640c8b8c4a 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 dlmem 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..79b400efc6 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 dlmem F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
> index 58c5da583d..38b4098950 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 dlmem 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..9a4f909a25 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 dlmem 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..c8b9f85fdb 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 dlmem 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..0887b67394 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 dlmem 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..1c3a6f4bee 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 dlmem 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..31b23859a4 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 dlmem F
> diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
> index a7c572c947..59f4aa7766 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 dlmem 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..d715d0ae97 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 dlmem 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..3addcf3d17 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 dlmem 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..5365978277 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 dlmem 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..f0af576192 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 dlmem F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
> index b716f5c763..941fd40ea8 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 dlmem F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> index 774e777b65..74f58439ad 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 dlmem 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..cf3a10aa76 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 dlmem 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..2ad97f87b2 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 dlmem 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..7c81b94953 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 dlmem 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..0493d6b456 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 dlmem 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..6fd09f6499 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 dlmem 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..24dbc4801f 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 dlmem 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..522ca8e8aa 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 dlmem 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..42b170c805 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 dlmem F

-- 
Cheers,
Carlos.


  reply	other threads:[~2023-03-29 13:45 UTC|newest]

Thread overview: 107+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-18 16:50 [PATCH v9 0/13] implement dlmem() function Stas Sergeev
2023-03-18 16:50 ` [PATCH 01/13] elf: strdup() l_name if no realname [BZ #30100] Stas Sergeev
2023-03-29 13:54   ` Adhemerval Zanella Netto
2023-03-29 14:12     ` stsp
2023-03-29 14:19       ` Adhemerval Zanella Netto
2023-03-29 14:28         ` stsp
2023-03-29 14:30           ` Adhemerval Zanella Netto
2023-03-29 14:33             ` stsp
2023-03-18 16:50 ` [PATCH 02/13] elf: switch _dl_map_segment() to anonymous mapping Stas Sergeev
2023-03-29 17:01   ` Adhemerval Zanella Netto
2023-03-29 18:00     ` stsp
2023-03-29 18:29       ` Adhemerval Zanella Netto
2023-03-29 18:46         ` stsp
2023-03-29 19:17           ` Adhemerval Zanella Netto
2023-03-29 19:43             ` stsp
2023-03-18 16:51 ` [PATCH 03/13] elf: dont pass fd to _dl_process_pt_xx Stas Sergeev
2023-03-29 17:10   ` Adhemerval Zanella Netto
2023-03-30 16:08     ` stsp
2023-03-30 20:46       ` Adhemerval Zanella Netto
2023-03-31 12:02         ` Szabolcs Nagy
2023-03-31 12:54           ` Adhemerval Zanella Netto
2023-03-31 14:04             ` stsp
2023-03-18 16:51 ` [PATCH 04/13] elf: split _dl_map_object_from_fd() into reusable parts Stas Sergeev
2023-03-18 16:51 ` [PATCH 05/13] elf: split open_verify() " Stas Sergeev
2023-03-18 16:51 ` [PATCH 06/13] elf: load elf hdr fully in open_verify() Stas Sergeev
2023-03-18 16:51 ` [PATCH 07/13] elf: convert pread64 to callback in do_open_verify() Stas Sergeev
2023-03-18 16:51 ` [PATCH 08/13] elf: convert _dl_map_segments's mmap() to a callback Stas Sergeev
2023-03-18 16:51 ` [PATCH 09/13] elf: call _dl_map_segment() via premap callback Stas Sergeev
2023-03-18 16:51 ` [PATCH 10/13] elf: convert _dl_map_object to a callback Stas Sergeev
2023-03-18 16:51 ` [PATCH 11/13] elf: split _dl_check_loaded() from _dl_map_object Stas Sergeev
2023-03-18 16:51 ` [PATCH 12/13] dlfcn,elf: implement dlmem() [BZ #11767] Stas Sergeev
2023-03-29 13:45   ` Carlos O'Donell [this message]
2023-03-29 13:51     ` stsp
2023-03-29 14:10       ` Jonathon Anderson
2023-03-29 14:20         ` stsp
2023-03-29 14:31           ` Adhemerval Zanella Netto
2023-03-29 15:01             ` stsp
2023-03-29 14:35           ` Carlos O'Donell
2023-03-29 14:50             ` stsp
2023-03-29 15:20               ` Carlos O'Donell
2023-03-29 15:34                 ` stsp
2023-03-30  8:09         ` stsp
2023-03-18 16:51 ` [PATCH 13/13] dlfcn,elf: impl DLMEM_DONTREPLACE dlmem() flag Stas Sergeev
2023-03-29 12:32 ` [PATCH v9 0/13] implement dlmem() function Adhemerval Zanella Netto
2023-03-29 13:10   ` stsp
2023-03-29 13:18   ` stsp
2023-03-31 12:20     ` Szabolcs Nagy
2023-03-31 13:51       ` stsp
2023-03-31 14:49         ` Rich Felker
2023-03-31 14:56           ` stsp
2023-03-31 14:58             ` Rich Felker
2023-03-31 15:03               ` stsp
2023-03-31 14:44       ` stsp
2023-03-31 15:12       ` stsp
2023-03-31 17:12         ` Szabolcs Nagy
2023-03-31 17:36           ` stsp
2023-04-01  9:28             ` stsp
2023-04-03 10:04             ` Szabolcs Nagy
2023-04-03 10:43               ` stsp
2023-04-03 12:01                 ` Szabolcs Nagy
2023-04-03 13:07                   ` stsp
2023-04-05  7:29                   ` stsp
2023-04-05  8:51                     ` Szabolcs Nagy
2023-04-05  9:26                       ` stsp
2023-04-05  9:31                       ` Florian Weimer
2023-04-12 17:23                       ` stsp
2023-04-12 18:00                         ` stsp
2023-04-12 18:20                           ` Rich Felker
2023-04-12 18:46                             ` stsp
2023-04-12 19:52                               ` Zack Weinberg
2023-04-12 19:07                             ` stsp
2023-04-13 10:01                             ` stsp
2023-04-13 12:38                               ` Szabolcs Nagy
2023-04-13 15:59                                 ` stsp
2023-04-13 18:09                                   ` Adhemerval Zanella Netto
2023-04-13 18:59                                     ` stsp
2023-04-13 19:12                                       ` Adhemerval Zanella Netto
2023-04-13 19:29                                         ` stsp
2023-04-13 20:02                                           ` Adhemerval Zanella Netto
2023-04-13 20:21                                             ` stsp
2023-04-13 20:57                                             ` stsp
2023-04-14  7:07                                             ` stsp
2023-04-14  7:36                                             ` stsp
2023-04-14 11:30                                             ` stsp
2023-04-14 19:04                                             ` proof for dlmem() (Re: [PATCH v9 0/13] implement dlmem() function) stsp
2023-05-01 23:11                                               ` Zack Weinberg
2023-05-02  5:48                                                 ` stsp
2023-05-08 16:00                                                   ` stsp
2023-05-02  6:24                                                 ` stsp
2023-05-08 15:10                                 ` [PATCH v9 0/13] implement dlmem() function stsp
2023-03-31 18:47           ` stsp
2023-03-31 19:00             ` stsp
2023-03-29 13:17 ` Carlos O'Donell
2023-03-29 13:26   ` stsp
2023-03-29 17:03   ` stsp
2023-03-29 18:13     ` Carlos O'Donell
2023-03-29 18:29       ` stsp
2023-03-31 11:04       ` stsp
2023-04-13 21:17         ` Carlos O'Donell
2023-04-13 21:58           ` stsp
2023-04-13 22:08           ` stsp
2023-04-13 22:50           ` stsp
2023-04-14 16:15           ` Autoconf maintenance (extremely tangential to Re: [PATCH v9 0/13] implement dlmem() function) Zack Weinberg
2023-04-14 20:24             ` Carlos O'Donell
2023-04-14 20:40               ` Zack Weinberg
2023-05-08 15:05           ` [PATCH v9 0/13] implement dlmem() function stsp
2023-05-19  7:26           ` stsp

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b6a96687-9a4b-414f-849a-45a305898274@redhat.com \
    --to=carlos@redhat.com \
    --cc=libc-alpha@sourceware.org \
    --cc=stsp2@yandex.ru \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).