diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index 1fa7fea1ef..68f6916d0a 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -44,8 +44,8 @@ install-lib-ldscripts = libdl.so
 $(inst_libdir)/libdl.so:
 
 ifeq ($(build-shared),yes)
-routines += dlopenold
-shared-only-routines := dlopenold
+routines += dlopenold dlaudit
+shared-only-routines := dlopenold dlaudit
 endif
 
 ifeq (yes,$(build-shared))
diff --git a/dlfcn/Versions b/dlfcn/Versions
index cc34eb824d..30145316d1 100644
--- a/dlfcn/Versions
+++ b/dlfcn/Versions
@@ -28,6 +28,9 @@ libc {
     dlsym;
     dlvsym;
   }
+  GLIBC_2.38 {
+    dlload_audit_module;
+  }
   GLIBC_PRIVATE {
     __libc_dlerror_result;
     _dlerror_run;
diff --git a/dlfcn/dlaudit.c b/dlfcn/dlaudit.c
new file mode 100644
index 0000000000..b124bbf932
--- /dev/null
+++ b/dlfcn/dlaudit.c
@@ -0,0 +1,62 @@
+/* Load an audit module at run time.
+   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 <libintl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <ldsodefs.h>
+#include <shlib-compat.h>
+
+struct dlload_am_args
+{
+  /* The arguments for dlload_am_doit.  */
+  const char *file;
+  int flags;
+  /* The return value of dlload_am_doit.  */
+  void *new;
+};
+
+static void
+dlload_am_doit (void *a)
+{
+  struct dlload_am_args *args = (struct dlload_am_args *) a;
+
+  if (args->flags)
+    _dl_signal_error (0, NULL, NULL, _("invalid flags parameter"));
+
+  args->new = GLRO(dlload_audit_module) (args->file, args->flags);
+}
+
+static void *
+dlload_am_implementation (const char *file, int flags)
+{
+  struct dlload_am_args args;
+  args.file = file;
+  args.flags = flags;
+
+  return _dlerror_run (dlload_am_doit, &args) ? NULL : args.new;
+}
+
+void *
+___dlload_audit_module (const char *file, int flags)
+{
+  return dlload_am_implementation (file, flags);
+}
+versioned_symbol (libc, ___dlload_audit_module, dlload_audit_module,
+                  GLIBC_2_38);
diff --git a/elf/Makefile b/elf/Makefile
index 0d19964d42..863c459bdc 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -822,6 +822,7 @@ modules-names += \
   tst-deep1mod1 \
   tst-deep1mod2 \
   tst-deep1mod3 \
+  tst-dynauditmod \
   tst-dl_find_object-mod1 \
   tst-dl_find_object-mod2 \
   tst-dl_find_object-mod3 \
@@ -1058,6 +1059,7 @@ ifeq (yes,$(build-shared))
 tests += \
   tst-ifunc-fault-bindnow \
   tst-ifunc-fault-lazy \
+  tst-loadaudit \
   # tests
 # Note: sysdeps/x86_64/ifuncmain8.c uses ifuncmain8.
 tests-internal += \
@@ -2352,6 +2354,10 @@ $(objpfx)tst-audit28.out: $(objpfx)tst-auditmod28.so
 $(objpfx)tst-auditmod28.so: $(libsupport)
 tst-audit28-ENV = LD_AUDIT=$(objpfx)tst-auditmod28.so
 
+$(objpfx)tst-loadaudit.out: $(objpfx)tst-dynauditmod.so \
+			  $(objpfx)tst-audit18mod.so
+tst-loadaudit-ARGS = -- $(host-test-program-cmd)
+
 # tst-sonamemove links against an older implementation of the library.
 LDFLAGS-tst-sonamemove-linkmod1.so = \
   -Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index 00e794aa26..0770bd52b2 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -27,8 +27,8 @@
 void
 _dl_audit_activity_map (struct link_map *l, int action)
 {
-  struct audit_ifaces *afct = GLRO(dl_audit);
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  struct audit_ifaces *afct = GL(dl_audit);
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       if (afct->activity != NULL)
 	afct->activity (&link_map_audit_state (l, cnt)->cookie, action);
@@ -43,8 +43,7 @@ _dl_audit_activity_nsid (Lmid_t nsid, int action)
      does not give us a way to signal LA_ACT_CONSISTENT for it because the
      first loaded module is used to identify the namespace.  */
   struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
-  if (__glibc_likely (GLRO(dl_naudit) == 0)
-      || head == NULL || head->l_auditing)
+  if (__glibc_likely (head == NULL || head->l_naudit == 0 || head->l_auditing))
     return;
 
   _dl_audit_activity_map (head, action);
@@ -56,8 +55,8 @@ _dl_audit_objsearch (const char *name, struct link_map *l, unsigned int code)
   if (l == NULL || l->l_auditing || code == 0)
     return name;
 
-  struct audit_ifaces *afct = GLRO(dl_audit);
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  struct audit_ifaces *afct = GL(dl_audit);
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       if (afct->objsearch != NULL)
 	{
@@ -75,11 +74,11 @@ _dl_audit_objsearch (const char *name, struct link_map *l, unsigned int code)
 void
 _dl_audit_objopen (struct link_map *l, Lmid_t nsid)
 {
-  if (__glibc_likely (GLRO(dl_naudit) == 0))
+  if (__glibc_likely (l->l_naudit == 0))
     return;
 
-  struct audit_ifaces *afct = GLRO(dl_audit);
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  struct audit_ifaces *afct = GL(dl_audit);
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       if (afct->objopen != NULL)
 	{
@@ -95,12 +94,12 @@ _dl_audit_objopen (struct link_map *l, Lmid_t nsid)
 void
 _dl_audit_objclose (struct link_map *l)
 {
-  if (__glibc_likely (GLRO(dl_naudit) == 0)
+  if (__glibc_likely (l->l_naudit == 0)
       || GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
     return;
 
-  struct audit_ifaces *afct = GLRO(dl_audit);
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  struct audit_ifaces *afct = GL(dl_audit);
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       if (afct->objclose != NULL)
 	{
@@ -116,11 +115,11 @@ _dl_audit_objclose (struct link_map *l)
 void
 _dl_audit_preinit (struct link_map *l)
 {
-  if (__glibc_likely (GLRO(dl_naudit) == 0))
+  if (__glibc_likely (l->l_naudit == 0))
     return;
 
-  struct audit_ifaces *afct = GLRO(dl_audit);
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  struct audit_ifaces *afct = GL(dl_audit);
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       if (afct->preinit != NULL)
 	afct->preinit (&link_map_audit_state (l, cnt)->cookie);
@@ -145,8 +144,8 @@ _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value,
   ElfW(Sym) sym = *ref;
   sym.st_value = (ElfW(Addr)) *value;
 
-  struct audit_ifaces *afct = GLRO(dl_audit);
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  struct audit_ifaces *afct = GL(dl_audit);
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       struct auditstate *match_audit = link_map_audit_state (l, cnt);
       struct auditstate *result_audit = link_map_audit_state (result, cnt);
@@ -212,9 +211,9 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
   const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]);
 
   unsigned int flags = 0;
-  struct audit_ifaces *afct = GLRO(dl_audit);
+  struct audit_ifaces *afct = GL(dl_audit);
   uintptr_t new_value = (uintptr_t) sym.st_value;
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       /* XXX Check whether both DSOs must request action or only one */
       struct auditstate *l_state = link_map_audit_state (l, cnt);
@@ -267,7 +266,7 @@ _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
 		    DL_FIXUP_VALUE_TYPE *value, void *regs, long int *framesize)
 {
   /* Don't do anything if no auditor wants to intercept this call.  */
-  if (GLRO(dl_naudit) == 0
+  if (l->l_naudit == 0
       || (reloc_result->enterexit & LA_SYMB_NOPLTENTER))
     return;
 
@@ -290,8 +289,8 @@ _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
   /* Keep track of overwritten addresses.  */
   unsigned int flags = reloc_result->flags;
 
-  struct audit_ifaces *afct = GLRO(dl_audit);
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  struct audit_ifaces *afct = GL(dl_audit);
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       if (afct->ARCH_LA_PLTENTER != NULL
 	  && (reloc_result->enterexit
@@ -363,8 +362,8 @@ _dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
 					     l_info[DT_STRTAB]);
   const char *symname = strtab + sym.st_name;
 
-  struct audit_ifaces *afct = GLRO(dl_audit);
-  for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+  struct audit_ifaces *afct = GL(dl_audit);
+  for (unsigned int cnt = 0; cnt < l->l_naudit; ++cnt)
     {
       if (afct->ARCH_LA_PLTEXIT != NULL
 	  && (reloc_result->enterexit
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 9acb64f47c..a96f769953 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -129,7 +129,7 @@ _dl_fini (void)
     }
 
 #ifdef SHARED
-  if (! do_audit && GLRO(dl_naudit) > 0)
+  if (! do_audit && GL(dl_naudit) > 0)
     {
       do_audit = 1;
       goto again;
diff --git a/elf/dl-load.c b/elf/dl-load.c
index fcb39a78d4..720324ccfb 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1032,6 +1032,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
       l->l_addr = l->l_real->l_addr;
       l->l_ld = l->l_real->l_ld;
 
+      /* Do not call audit when this lm closes. */
+      l->l_naudit = 0;
+
       /* No need to bump the refcount of the real object, ld.so will
 	 never be unloaded.  */
       __close_nocancel (fd);
@@ -1607,7 +1610,7 @@ open_verify (const char *name, int fd,
 
 #ifdef SHARED
   /* Give the auditing libraries a chance.  */
-  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
+  if (__glibc_unlikely (GL(dl_naudit) > 0))
     {
       const char *original_name = name;
       name = _dl_audit_objsearch (name, loader, whatcode);
@@ -2001,7 +2004,7 @@ _dl_map_object (struct link_map *loader, const char *name,
 #ifdef SHARED
   /* Give the auditing libraries a chance to change the name before we
      try anything.  */
-  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
+  if (__glibc_unlikely (GL(dl_naudit) > 0))
     {
       const char *before = name;
       name = _dl_audit_objsearch (name, loader, LA_SER_ORIG);
diff --git a/elf/dl-object.c b/elf/dl-object.c
index f1f2ec956c..497c57154a 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -77,7 +77,7 @@ _dl_new_object (char *realname, const char *libname, int type,
       naudit = DL_NNS;
     }
   else
-    naudit = GLRO (dl_naudit);
+    naudit = GL (dl_naudit);
 #endif
 
   size_t libname_len = strlen (libname) + 1;
@@ -136,6 +136,8 @@ _dl_new_object (char *realname, const char *libname, int type,
   new->l_ns = nsid;
 
 #ifdef SHARED
+  /* GL(dl_naudit) is a current value and naudit is maximum value. */
+  new->l_naudit = GL (dl_naudit);
   for (unsigned int cnt = 0; cnt < naudit; ++cnt)
     /* No need to initialize bindflags due to calloc.  */
     link_map_audit_state (new, cnt)->cookie = (uintptr_t) new;
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 1d558c1e0c..8aedbc0d96 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -222,8 +222,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
   /* If we are auditing, install the same handlers we need for profiling.  */
   if ((reloc_mode & __RTLD_AUDIT) == 0)
     {
-      struct audit_ifaces *afct = GLRO(dl_audit);
-      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+      struct audit_ifaces *afct = GL(dl_audit);
+      for (unsigned int cnt = 0; cnt < GL(dl_naudit); ++cnt)
 	{
 	  /* Profiling is needed only if PLT hooks are provided.  */
 	  if (afct->ARCH_LA_PLTENTER != NULL
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index d35a725415..672d6fb702 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -313,7 +313,7 @@ _dl_profile_fixup (
       /* Auditing checkpoint: we have a new binding.  Provide the
 	 auditing libraries the possibility to change the value and
 	 tell us whether further auditing is wanted.  */
-      if (defsym != NULL && GLRO(dl_naudit) > 0)
+      if (defsym != NULL && GL(dl_naudit) > 0)
 	_dl_audit_symbind (l, reloc_result, defsym, &value, result);
 #endif
 
diff --git a/elf/dl-sym-post.h b/elf/dl-sym-post.h
index 5623d63ac8..0cc50349ca 100644
--- a/elf/dl-sym-post.h
+++ b/elf/dl-sym-post.h
@@ -50,7 +50,7 @@ _dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value,
   /* Auditing checkpoint: we have a new binding.  Provide the
      auditing libraries the possibility to change the value and
      tell us whether further auditing is wanted.  */
-  if (__glibc_unlikely (GLRO(dl_naudit) > 0))
+  if (__glibc_unlikely (GL(dl_naudit) > 0))
     {
       if (match == NULL)
         match = _dl_sym_find_caller_link_map (caller);
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 7e1cc4452a..22b5d566eb 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -148,7 +148,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
 			       skip_ifunc);
 #if defined SHARED
 	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
-		  && GLRO(dl_naudit) > 0)
+		  && GL(dl_naudit) > 0)
 		{
 		  struct link_map *sym_map
 		    = RESOLVE_MAP (map, scope, &sym, rversion,
@@ -193,7 +193,7 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
 			       skip_ifunc);
 # if defined SHARED
 	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
-		  && GLRO(dl_naudit) > 0)
+		  && GL(dl_naudit) > 0)
 		{
 		  struct link_map *sym_map
 		    = RESOLVE_MAP (map, scope, &sym,
diff --git a/elf/rtld.c b/elf/rtld.c
index f82fbeb132..714152f4b7 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -151,6 +151,10 @@ static const char *audit_list_next (struct audit_list *);
 /* Initialize *STATE with the defaults.  */
 static void dl_main_state_init (struct dl_main_state *state);
 
+/* Loads audit module. */
+static void *
+_dlload_audit_module (const char *name, int flags);
+
 /* Process all environments variables the dynamic linker must recognize.
    Since all of them start with `LD_' we are a bit smarter while finding
    all the entries.  */
@@ -272,7 +276,7 @@ audit_list_next (struct audit_list *list)
     }
 }
 
-/* Count audit modules before they are loaded so GLRO(dl_naudit)
+/* Count audit modules before they are loaded so GL(dl_naudit)
    is not yet usable.  */
 static size_t
 audit_list_count (struct audit_list *list)
@@ -375,6 +379,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
     ._dl_error_free = _dl_error_free,
     ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft,
     ._dl_libc_freeres = __rtld_libc_freeres,
+    ._dlload_audit_module = _dlload_audit_module,
   };
 /* If we would use strong_alias here the compiler would see a
    non-hidden definition.  This would undo the effect of the previous
@@ -930,8 +935,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 }
 
 /* Load one audit module.  */
-static void
-load_audit_module (const char *name, struct audit_ifaces **last_audit)
+static void *
+_load_audit_module (const char *name, const void *caller_dlopen,
+                   struct audit_ifaces **last_audit, bool dynload)
 {
   int original_tls_idx = GL(dl_tls_max_dtv_idx);
 
@@ -946,7 +952,7 @@ load_audit_module (const char *name, struct audit_ifaces **last_audit)
   if (__glibc_unlikely (err_str != NULL))
     {
       report_audit_module_load_error (name, err_str, malloced);
-      return;
+      return NULL;
     }
 
   struct lookup_args largs;
@@ -957,7 +963,7 @@ load_audit_module (const char *name, struct audit_ifaces **last_audit)
     {
       unload_audit_module (dlmargs.map, original_tls_idx);
       report_audit_module_load_error (name, err_str, malloced);
-      return;
+      return NULL;
     }
 
   unsigned int (*laversion) (unsigned int) = largs.result;
@@ -977,7 +983,7 @@ load_audit_module (const char *name, struct audit_ifaces **last_audit)
 file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
 			  dlmargs.map->l_name, dlmargs.map->l_ns);
       unload_audit_module (dlmargs.map, original_tls_idx);
-      return;
+      return NULL;
     }
 
   if (!_dl_audit_check_version (lav))
@@ -986,7 +992,7 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
 ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n",
 			name, lav, LAV_CURRENT);
       unload_audit_module (dlmargs.map, original_tls_idx);
-      return;
+      return NULL;
     }
 
   enum { naudit_ifaces = 8 };
@@ -998,53 +1004,88 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
   if (newp == NULL)
     _dl_fatal_printf ("Out of memory while loading audit modules\n");
 
-  /* Names of the auditing interfaces.  All in one
-     long string.  */
-  static const char audit_iface_names[] =
-    "la_activity\0"
-    "la_objsearch\0"
-    "la_objopen\0"
-    "la_preinit\0"
-    LA_SYMBIND "\0"
+  /* Names of the auditing interfaces.  */
+  struct audit_ifname
+  {
+    const char *name;
+    bool dyn_allowed;
+  } audit_iface_names[] =
+  {
+    { "la_activity", true },
+    { "la_objsearch", true },
+    { "la_objopen", true },
+    { "la_preinit", true },
+    { LA_SYMBIND, false },
 #define STRING(s) __STRING (s)
-    "la_" STRING (ARCH_LA_PLTENTER) "\0"
-    "la_" STRING (ARCH_LA_PLTEXIT) "\0"
-    "la_objclose\0";
-  unsigned int cnt = 0;
-  const char *cp = audit_iface_names;
-  do
+    { "la_" STRING (ARCH_LA_PLTENTER), false },
+    { "la_" STRING (ARCH_LA_PLTEXIT), false },
+    { "la_objclose", true },
+  };
+  unsigned int cnt;
+  for (cnt = 0; cnt < naudit_ifaces; cnt++)
     {
-      largs.name = cp;
+      struct audit_ifname *cp = &audit_iface_names[cnt];
+      largs.name = cp->name;
       _dl_catch_error (&objname, &err_str, &malloced, lookup_doit, &largs);
 
       /* Store the pointer.  */
       if (err_str == NULL && largs.result != NULL)
-	newp->fptr[cnt] = largs.result;
+        {
+          if (dynload && !cp->dyn_allowed)
+            {
+              unload_audit_module (dlmargs.map, original_tls_idx);
+              _dl_signal_error (EINVAL, name, NULL, N_("\
+unacceptable interfaces for dlload_audit_module()"));
+              return NULL;
+            }
+          else
+	    newp->fptr[cnt] = largs.result;
+	}
       else
 	newp->fptr[cnt] = NULL;
-      ++cnt;
-
-      cp = strchr (cp, '\0') + 1;
     }
-  while (*cp != '\0');
-  assert (cnt == naudit_ifaces);
 
   /* Now append the new auditing interface to the list.  */
   newp->ifaces.next = NULL;
   if (*last_audit == NULL)
-    *last_audit = GLRO(dl_audit) = &newp->ifaces;
+    *last_audit = GL(dl_audit) = &newp->ifaces;
   else
     *last_audit = (*last_audit)->next = &newp->ifaces;
 
   /* The dynamic linker link map is statically allocated, so the
      cookie in _dl_new_object has not happened.  */
-  link_map_audit_state (&GL (dl_rtld_map), GLRO (dl_naudit))->cookie
+  link_map_audit_state (&GL (dl_rtld_map), GL (dl_naudit))->cookie
     = (intptr_t) &GL (dl_rtld_map);
 
-  ++GLRO(dl_naudit);
+  ++GL(dl_naudit);
 
   /* Mark the DSO as being used for auditing.  */
   dlmargs.map->l_auditing = 1;
+  return dlmargs.map;
+}
+
+static void
+load_audit_module (const char *name, struct audit_ifaces **last_audit)
+{
+  if (_load_audit_module (name, dl_main, last_audit, false))
+    {
+      struct link_map *l;
+
+      /* Global audit module can audit all existing objects. */
+      for (l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l; l = l->l_next)
+        l->l_naudit++;
+    }
+}
+
+static void *
+_dlload_audit_module (const char *name, int flags)
+{
+  struct audit_ifaces *last_audit = GL(dl_audit);
+
+  /* Find last audit list entry. */
+  while (last_audit && last_audit->next)
+    last_audit = last_audit->next;
+  return _load_audit_module (name, _dlload_audit_module, &last_audit, true);
 }
 
 /* Load all audit modules.  */
@@ -1063,7 +1104,7 @@ load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
 
   /* Notify audit modules of the initially loaded modules (the main
      program and the dynamic linker itself).  */
-  if (GLRO(dl_naudit) > 0)
+  if (GL(dl_naudit) > 0)
     {
       _dl_audit_objopen (main_map, LM_ID_BASE);
       _dl_audit_objopen (&GL(dl_rtld_map), LM_ID_BASE);
@@ -1822,7 +1863,7 @@ dl_main (const ElfW(Phdr) *phdr,
 
       /* The count based on audit strings may overestimate the number
 	 of audit modules that got loaded, but not underestimate.  */
-      assert (GLRO(dl_naudit) <= naudit);
+      assert (GL(dl_naudit) <= naudit);
     }
 
   /* Keep track of the currently loaded modules to count how many
diff --git a/elf/tst-dynauditmod.c b/elf/tst-dynauditmod.c
new file mode 100644
index 0000000000..46941f7d37
--- /dev/null
+++ b/elf/tst-dynauditmod.c
@@ -0,0 +1,79 @@
+/* Audit mod for dlload_audit_module.
+   Copyright (C) 2021-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 <stdio.h>
+#include <link.h>
+#include <assert.h>
+
+/* la_objopen() sets the cookie to this value. Other call-backs check
+ * the value to see if la_objopen() was not somehow skipped. */
+#define TST_COOKIE_VAL 12
+
+unsigned int
+la_version (unsigned int version)
+{
+  fprintf (stderr, "%s\n", __func__);
+  return LAV_CURRENT;
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+  fprintf (stderr, "%s\n", __func__);
+  assert (*cookie == TST_COOKIE_VAL);
+  return (char *) name;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+  struct link_map *map = (void *) *cookie;
+  fprintf (stderr, "%s\n", __func__);
+  if (*cookie != TST_COOKIE_VAL)
+    fprintf (stderr, "%s\n", map->l_name);
+  *cookie = TST_COOKIE_VAL;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  fprintf (stderr, "%s\n", __func__);
+  fprintf (stderr, "%s\n", map->l_name);
+  *cookie = TST_COOKIE_VAL;
+  return LA_FLG_BINDTO | LA_FLG_BINDFROM;
+}
+
+unsigned int
+la_objclose (uintptr_t *cookie)
+{
+  fprintf (stderr, "%s\n", __func__);
+  if (*cookie != TST_COOKIE_VAL)
+    {
+      struct link_map *map = (void *) *cookie;
+      fprintf (stderr, "%s\n", map->l_name);
+    }
+  assert (*cookie == TST_COOKIE_VAL);
+  return 0;
+}
+
+void
+la_preinit (uintptr_t *cookie)
+{
+  fprintf (stderr, "%s\n", __func__);
+  assert (*cookie == TST_COOKIE_VAL);
+}
diff --git a/elf/tst-loadaudit.c b/elf/tst-loadaudit.c
new file mode 100644
index 0000000000..f6db808afb
--- /dev/null
+++ b/elf/tst-loadaudit.c
@@ -0,0 +1,142 @@
+/* Check dlload_audit_module.
+   Copyright (C) 2021-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 <array_length.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <gnu/lib-names.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 },
+void *
+dlload_audit_module (const char *file, int flags);
+
+static int
+handle_restart (void)
+{
+  void *ah;
+
+  ah = dlload_audit_module ("tst-auditmod18.so", 0);
+  TEST_VERIFY (ah == NULL);
+  fprintf (stderr, "%s\n", dlerror ());
+  ah = dlload_audit_module ("tst-dynauditmod.so", 0);
+  TEST_VERIFY (ah != NULL);
+
+  {
+    void *h = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
+
+    pid_t (*s) (void) = xdlsym (h, "getpid");
+    TEST_COMPARE (s (), getpid ());
+
+    xdlclose (h);
+  }
+
+  {
+    void *h = xdlmopen (LM_ID_NEWLM, "tst-audit18mod.so", RTLD_NOW);
+
+    int (*foo) (void) = xdlsym (h, "foo");
+    TEST_COMPARE (foo (), 10);
+
+    xdlclose (h);
+  }
+
+  return 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  /* We must have either:
+     - One our fource parameters left if called initially:
+       + path to ld.so         optional
+       + "--library-path"      optional
+       + the library path      optional
+       + the application name  */
+
+  if (restart)
+    return handle_restart ();
+
+  char *spargv[9];
+  int i = 0;
+  for (; i < argc - 1; i++)
+    spargv[i] = argv[i + 1];
+  spargv[i++] = (char *) "--direct";
+  spargv[i++] = (char *) "--restart";
+  spargv[i] = NULL;
+
+  struct support_capture_subprocess result
+    = support_capture_subprogram (spargv[0], spargv);
+  support_capture_subprocess_check (&result, "tst-loadaudit", 0, sc_allow_stderr);
+
+  struct
+  {
+    const char *name;
+    bool found;
+  } audit_iface[] =
+  {
+    { "la_version", false },
+    { "la_objsearch", false },
+    { "la_activity", false },
+    { "la_objopen", false },
+    { "la_objclose", false },
+#if __WORDSIZE == 32
+    { "la_symbind32", false },
+#elif __WORDSIZE == 64
+    { "la_symbind64", false },
+#endif
+#define STRING(s) __STRING (s)
+    { "la_" STRING (ARCH_LA_PLTENTER), false },
+    { "la_" STRING (ARCH_LA_PLTEXIT), false },
+  };
+
+  /* Some hooks are called more than once but the test only check if any
+     is called at least once.  */
+  FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
+  TEST_VERIFY (out != NULL);
+  char *buffer = NULL;
+  size_t buffer_length = 0;
+  while (xgetline (&buffer, &buffer_length, out))
+    {
+      for (int i = 0; i < array_length (audit_iface); i++)
+	if (strncmp (buffer, audit_iface[i].name,
+		     strlen (audit_iface[i].name)) == 0)
+	  audit_iface[i].found = true;
+    }
+  free (buffer);
+  xfclose (out);
+
+  /* Check that symbols are resolved, except for the last 3.
+     symbind, pltenter, pltexit are not allowed for dynamically loaded mod. */
+  for (int i = 0; i < array_length (audit_iface); i++)
+    TEST_COMPARE (audit_iface[i].found, i < array_length (audit_iface) - 3);
+
+  support_capture_subprocess_free (&result);
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/include/link.h b/include/link.h
index 1d74feb2bd..31f34540fc 100644
--- a/include/link.h
+++ b/include/link.h
@@ -347,6 +347,7 @@ struct link_map
     size_t l_relro_size;
 
     unsigned long long int l_serial;
+    unsigned int l_naudit;
   };
 
 #include <dl-relocate-ld.h>
diff --git a/manual/dynlink.texi b/manual/dynlink.texi
index 6a4a50d3f0..898354ebe9 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 dlload_audit_module
 @c dlmopen
 @c dlopen
 @c dlsym
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index c99dad77cc..1a377061f8 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -399,6 +399,10 @@ struct rtld_global
   /* Used to store the audit information for the link map of the
      dynamic loader.  */
   struct auditstate _dl_rtld_auditstate[DL_NNS];
+
+  /* List of auditing interfaces.  */
+  struct audit_ifaces *_dl_audit;
+  unsigned int _dl_naudit;
 #endif
 
 #if !PTHREAD_IN_LIBC && defined SHARED \
@@ -689,12 +693,11 @@ struct rtld_global_ro
      dlopen.  */
   int (*_dl_find_object) (void *, struct dl_find_object *);
 
+  /* Loads audit module.  */
+  void *(*_dlload_audit_module) (const char *name, int flags);
+
   /* Dynamic linker operations used after static dlopen.  */
   const struct dlfcn_hook *_dl_dlfcn_hook;
-
-  /* List of auditing interfaces.  */
-  struct audit_ifaces *_dl_audit;
-  unsigned int _dl_naudit;
 };
 # define __rtld_global_attribute__
 # if IS_IN (rtld)
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index a0419a13d0..c4618b690d 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2314,6 +2314,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 62e80648e8..6d29418617 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2653,3 +2653,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 9d490fdee8..14376cece0 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2750,6 +2750,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 50874e92fc..e936e68b4f 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -2414,3 +2414,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index 544b5b2741..ac7f0b6116 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -534,6 +534,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 da532a0191..4452bd3079 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -531,6 +531,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 6c74a60d69..68e22923fc 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2690,3 +2690,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 13d30e646f..f0a1f78c68 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2639,6 +2639,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 f5dfa2a20e..32516113f9 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2823,6 +2823,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 58f1526030..5810db8371 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2588,6 +2588,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 46ce2437fe..72f140e522 100644
--- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
@@ -2174,3 +2174,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index f34085ce35..9ead06cdf0 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -535,6 +535,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 349377d154..c3aee9fa16 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2766,6 +2766,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 38e7fb9b2a..7cb4e492a4 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2739,3 +2739,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index ec4ca27b75..e1d6672d64 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2736,3 +2736,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index bd3f3404fb..3e29d05c1b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2731,6 +2731,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 9b09fab6ec..36d550962d 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2729,6 +2729,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 3b8f2b8ca3..f2773be8d6 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2737,6 +2737,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 497553414d..65d15b6f03 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2639,6 +2639,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 f67f241498..c64625787b 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2778,3 +2778,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index a59a58f44c..8f6e1c7a59 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -2160,3 +2160,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index a1bcf79955..e79b46489f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2793,6 +2793,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 c0f28aea45..94dc5ba72c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2826,6 +2826,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 6b4459964f..9a0401ef37 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2547,6 +2547,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 e90fb502d2..bbdc0d40d3 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2849,3 +2849,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index 29be561b60..fad99a0af2 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -2416,3 +2416,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 506a4e6a65..1f3e3a81d9 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2616,3 +2616,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 976cd741ee..5ad8f9e052 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2791,6 +2791,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 909ec927dc..3532cb3b68 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2584,6 +2584,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 31a777c4aa..93d7641f76 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2646,6 +2646,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 8d43e8c952..6134cec1e4 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2643,6 +2643,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 91c552dc4c..cda6bb9e29 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2786,6 +2786,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 c5c5e5cf9a..59435bd0b8 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2611,6 +2611,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 e51996e046..c52cbd8aba 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2562,6 +2562,7 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module 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 388536b3be..f830b889ca 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2668,3 +2668,4 @@ GLIBC_2.38 __isoc23_wcstoul_l F
 GLIBC_2.38 __isoc23_wcstoull F
 GLIBC_2.38 __isoc23_wcstoull_l F
 GLIBC_2.38 __isoc23_wcstoumax F
+GLIBC_2.38 dlload_audit_module F
