@@ -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
+CPPFLAGS-tst-dlmem.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.out: $(objpfx)glreflib1.so
$(objpfx)tst-dlinfo.out: $(objpfx)glreflib3.so
LDFLAGS-glreflib3.so = -Wl,-rpath,:
@@ -28,6 +28,9 @@ libc {
dlsym;
dlvsym;
}
+ GLIBC_2.38 {
+ dlmem;
+ }
GLIBC_PRIVATE {
__libc_dlerror_result;
_dlerror_run;
@@ -68,6 +68,21 @@ 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,
+ unsigned prot, void *cookie);
+
+struct dlmem_args {
+ Lmid_t nsid;
+ dlmem_premap_t *premap;
+ 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,
new file mode 100644
@@ -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 */
@@ -22,3 +22,5 @@ ref1 (void)
{
return 42;
}
+
+int bar = 35;
new file mode 100644
@@ -0,0 +1,166 @@
+/* Test for 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 size_t maplen;
+
+static void *
+premap_dlmem (void *mappref, size_t maplength, size_t mapalign,
+ unsigned prot, void *cookie)
+{
+ int fd = * (int *) cookie;
+ int err;
+
+ /* See if we support such parameters. */
+ if (mappref || mapalign > 4096)
+ return MAP_FAILED;
+
+ fprintf (stderr, "%s\n", __func__);
+
+ err = ftruncate (fd, maplength);
+ if (err)
+ error (EXIT_FAILURE, 0, "ftruncate() failed");
+ maplen = maplength;
+ return mmap (NULL, maplength, prot, MAP_SHARED | MAP_FILE
+#ifdef MAP_32BIT
+ | MAP_32BIT
+#endif
+ , fd, 0);
+}
+
+#define TEST_FUNCTION do_test
+extern int do_test (void);
+
+int
+do_test (void)
+{
+ void *handle;
+ void *addr;
+ int (*sym) (void); /* We load ref1 from glreflib1.c. */
+ int *bar, *bar2;
+ unsigned char *addr2;
+ Dl_info info;
+ int ret;
+ int fd;
+ int num;
+ off_t len;
+ struct link_map *lm;
+ const char *shm_name = "/tst-dlmem";
+ int shm_fd;
+ struct dlmem_args a;
+
+ shm_fd = memfd_create (shm_name, 0);
+ if (shm_fd == -1)
+ error (EXIT_FAILURE, 0, "shm_open() failed");
+
+ fd = open (BUILDDIR "glreflib1.so", O_RDONLY);
+ if (fd == -1)
+ error (EXIT_FAILURE, 0, "cannot open: glreflib1.so");
+ len = lseek (fd, 0, SEEK_END);
+ lseek (fd, 0, SEEK_SET);
+ addr = mmap (NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (addr == MAP_FAILED)
+ error (EXIT_FAILURE, 0, "cannot mmap: glreflib1.so");
+ a.nsid = LM_ID_BASE;
+ a.premap = premap_dlmem;
+ a.cookie = &shm_fd;
+ handle = dlmem (addr, len, RTLD_NOW | RTLD_LOCAL, &a);
+ if (handle == NULL)
+ error (EXIT_FAILURE, 0, "cannot load: glreflib1.so");
+ munmap (addr, len);
+ close (fd);
+ /* Check if premap was called. */
+ TEST_VERIFY (maplen != 0);
+
+ sym = dlsym (handle, "ref1");
+ if (sym == NULL)
+ error (EXIT_FAILURE, 0, "dlsym failed");
+
+ memset (&info, 0, sizeof (info));
+ ret = dladdr (sym, &info);
+ if (ret == 0)
+ error (EXIT_FAILURE, 0, "dladdr failed");
+#ifdef MAP_32BIT
+ /* Make sure MAP_32BIT worked. */
+ if ((unsigned long) info.dli_fbase >= 0x100000000)
+ error (EXIT_FAILURE, 0, "premap audit didn't work");
+#endif
+ ret = dlinfo (handle, RTLD_DI_LINKMAP, &lm);
+ if (ret != 0)
+ error (EXIT_FAILURE, 0, "dlinfo 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);
+ printf ("lm->l_addr = %lx\n", lm->l_addr);
+
+ 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");
+
+ num = sym ();
+ if (num != 42)
+ error (EXIT_FAILURE, 0, "bad return from ref1");
+
+ /* Now try symbol duplication. */
+ bar = dlsym (handle, "bar");
+ if (bar == NULL)
+ error (EXIT_FAILURE, 0, "dlsym failed");
+ TEST_COMPARE (*bar, 35);
+ /* write another value */
+#define TEST_BAR_VAL 48
+ *bar = TEST_BAR_VAL;
+
+ /* Create second instance of the solib. */
+ addr2 = mmap (NULL, maplen, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_SHARED, shm_fd, 0);
+ if (addr2 == MAP_FAILED)
+ error (EXIT_FAILURE, 0, "cannot mmap shm\n");
+ /* Find our bar symbol duplicate. */
+ ret = dladdr (bar, &info);
+ if (ret == 0)
+ error (EXIT_FAILURE, 0, "dladdr failed");
+ bar2 = (int *) (addr2 + (info.dli_saddr - info.dli_fbase));
+ /* See if we found the right one. */
+ TEST_COMPARE (*bar2, TEST_BAR_VAL);
+
+ munmap (addr2, maplen);
+ dlclose (handle);
+
+ return 0;
+}
+
+
+#include <support/test-driver.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>
@@ -2344,6 +2345,153 @@ _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_mmapcpy (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 (__mprotect (addr, length, PROT_READ | PROT_WRITE) == -1)
+ return MAP_FAILED;
+ if (offset < fb->len)
+ {
+ size_t to_copy = length;
+ if (offset + to_copy > fb->len)
+ to_copy = fb->len - offset;
+ memcpy (addr, fb->buf + offset, to_copy);
+ }
+ if (__mprotect (addr, length, prot) == -1)
+ return MAP_FAILED;
+ return addr;
+}
+
+static void *
+do_dlmem_premap (void *mappref, size_t maplength, size_t mapalign,
+ unsigned prot, 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, prot,
+ fb->dlm_args->cookie);
+ if (ret == MAP_FAILED)
+ ret = (void *) _dl_map_segment ((ElfW(Addr)) mappref, maplength,
+ mapalign, prot);
+ 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;
+ /* 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));
+
+ /* 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);
+
+ /* Enter the new object in the list of loaded objects. */
+ l = _dl_new_object ((char *) name, 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_mmapcpy, 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;
@@ -107,6 +107,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,
@@ -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. */
@@ -953,6 +953,18 @@ _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;
+
+ return do_dl_open ("", &fb, mode, caller_dlopen, nsid, argc, argv, env,
+ __dl_map_object_from_mem);
+}
+
void
_dl_show_scope (struct link_map *l, int from)
{
@@ -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,
@@ -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);
@@ -209,6 +209,7 @@ This function is a GNU extension.
@c dladdr1
@c dlclose
@c dlerror
+@c dlmem
@c dlmopen
@c dlopen
@c dlsym
@@ -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. */
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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