diff --git a/pressure-vessel/adverb.1.md b/pressure-vessel/adverb.1.md
index 8ebdbbdb9833d60b739a5d0bf259d0559bfe0b72..3ff6d1edcefedae55a45d759c2bd479bce355be6 100644
--- a/pressure-vessel/adverb.1.md
+++ b/pressure-vessel/adverb.1.md
@@ -21,6 +21,9 @@ pressure-vessel-adverb - wrap processes in various ways
 [**--ld-audit** *MODULE*[**:arch=***TUPLE*]...]
 [**--ld-preload** *MODULE*[**:**...]...]
 [**--pass-fd** *FD*...]
+[[**--add-ld.so-path** *PATH*...]
+**--regenerate-ld.so-cache** *PATH*]
+[**--set-ld-library-path** *VALUE*]
 [**--shell** **none**|**after**|**fail**|**instead**]
 [**--subreaper**]
 [**--terminal** **none**|**auto**|**tty**|**xterm**]
@@ -43,6 +46,12 @@ exit status.
 
 # OPTIONS
 
+**--add-ld.so-path** *PATH*
+:   Add *PATH* to the search path for **--regenerate-ld.so-cache**.
+    The final search path will consist of all **--add-ld.so-path**
+    arguments in the order they are given, followed by the lines
+    from `runtime-ld.so.conf` in order.
+
 **--create**
 :   Create each **--lock-file** that appears on the command-line after
     this option if it does not exist, until a **--no-create** option
@@ -106,6 +115,34 @@ exit status.
     through file descriptors 0, 1 and 2
     (**stdin**, **stdout** and **stderr**).
 
+**--regenerate-ld.so-cache** *PATH*
+:   Regenerate "ld.so.cache" in the directory *PATH*.
+
+    On entry to **pressure-vessel-adverb**, *PATH* should
+    contain `runtime-ld.so.conf`, a symbolic link or copy
+    of the runtime's original `/etc/ld.so.conf`. It will
+    usually also contain `ld.so.conf` and `ld.so.cache`
+    as symbolic links or copies of the runtime's original
+    `/etc/ld.so.conf` and `/etc/ld.so.cache`.
+
+    Before executing the *COMMAND*, **pressure-vessel-adverb**
+    will construct a new `ld.so.conf` in *PATH*, consisting of
+    all **--add-ld.so-path** arguments, followed by the contents
+    of `runtime-ld.so.conf`; then it will generate a new
+    `ld.so.cache` from that configuration. Both of these
+    will atomically replace the original files in *PATH*.
+
+    Other filenames in *PATH* will be used temporarily.
+
+    To make use of this feature, a container's `/etc/ld.so.conf`
+    and `/etc/ld.so.cache` should usually be symbolic links into
+    the *PATH* used here, which will typically be below `/run`.
+
+**--set-ld-library-path** *VALUE*
+:   Set the environment variable LD_LIBRARY_PATH to *VALUE* after
+    processing **--regenerate-ld.so-cache** (if used), but before
+    executing *COMMAND*.
+
 **--shell=after**
 :   Run an interactive shell after *COMMAND* exits.
     In that shell, running **"$@"** will re-run *COMMAND*.
diff --git a/pressure-vessel/adverb.c b/pressure-vessel/adverb.c
index 4bf57a30cfd41895d529793ef20b5d2143ee0df9..d255b587a116331c117344c9b0666427f4bab389 100644
--- a/pressure-vessel/adverb.c
+++ b/pressure-vessel/adverb.c
@@ -50,11 +50,14 @@
 
 static const char * const *global_original_environ = NULL;
 static GPtrArray *global_locks = NULL;
+static GPtrArray *global_ld_so_conf_entries = NULL;
 static GArray *global_pass_fds = NULL;
 static gboolean opt_batch = FALSE;
 static gboolean opt_create = FALSE;
 static gboolean opt_exit_with_parent = FALSE;
 static gboolean opt_generate_locales = FALSE;
+static gchar *opt_regenerate_ld_so_cache = NULL;
+static gchar *opt_set_ld_library_path = NULL;
 static PvShell opt_shell = PV_SHELL_NONE;
 static gboolean opt_subreaper = FALSE;
 static PvTerminal opt_terminal = PV_TERMINAL_AUTO;
@@ -251,6 +254,20 @@ opt_fd_cb (const char *name,
   return TRUE;
 }
 
+static gboolean
+opt_add_ld_so_cb (const char *name,
+                  const char *value,
+                  gpointer data,
+                  GError **error)
+{
+  g_return_val_if_fail (global_ld_so_conf_entries != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  g_return_val_if_fail (value != NULL, FALSE);
+
+  g_ptr_array_add (global_ld_so_conf_entries, g_strdup (value));
+  return TRUE;
+}
+
 static gboolean
 opt_ld_something (const char *option,
                   gsize index_in_preload_variables,
@@ -616,6 +633,113 @@ generate_lib_temp_dirs (LibTempDirs *lib_temp_dirs,
   return TRUE;
 }
 
+static gboolean
+regenerate_ld_so_cache (const GPtrArray *ld_so_cache_paths,
+                        const char *dir,
+                        GError **error)
+{
+  g_autoptr(GPtrArray) argv = g_ptr_array_new ();
+  g_autoptr(GString) conf = g_string_new ("");
+  g_autofree gchar *child_stdout = NULL;
+  g_autofree gchar *child_stderr = NULL;
+  g_autofree gchar *conf_path = g_build_filename (dir, "ld.so.conf", NULL);
+  g_autofree gchar *rt_conf_path = g_build_filename (dir, "runtime-ld.so.conf", NULL);
+  g_autofree gchar *replace_path = g_build_filename (dir, "ld.so.cache", NULL);
+  g_autofree gchar *new_path = g_build_filename (dir, "new-ld.so.cache", NULL);
+  g_autofree gchar *contents = NULL;
+  int wait_status;
+  gsize i;
+
+  for (i = 0; ld_so_cache_paths != NULL && i < ld_so_cache_paths->len; i++)
+    {
+      const gchar *value = g_ptr_array_index (ld_so_cache_paths, i);
+      if (strchr (value, '\n') != NULL
+          || strchr (value, '\t') != NULL
+          || value[0] != '/')
+        return glnx_throw (error,
+                           "Cannot include path entry \"%s\" in ld.so.conf",
+                           value);
+
+      g_debug ("%s: Adding \"%s\" to beginning of ld.so.conf",
+               G_STRFUNC, value);
+      g_string_append (conf, value);
+      g_string_append_c (conf, '\n');
+    }
+
+  /* Ignore read error, if any */
+  if (g_file_get_contents (rt_conf_path, &contents, NULL, NULL))
+    {
+      g_debug ("%s: Appending runtime's ld.so.conf:\n%s", G_STRFUNC, contents);
+      g_string_append (conf, contents);
+    }
+
+  /* This atomically replaces conf_path, so we don't need to do the
+   * atomic bit ourselves */
+  if (!g_file_set_contents (conf_path, conf->str, -1, error))
+    return FALSE;
+
+  while (TRUE)
+    {
+      char *newline = strchr (conf->str, '\n');
+
+      if (newline != NULL)
+        *newline = '\0';
+
+      g_debug ("%s: final ld.so.conf: %s", G_STRFUNC, conf->str);
+
+      if (newline != NULL)
+        g_string_erase (conf, 0, newline + 1 - conf->str);
+      else
+        break;
+    }
+
+  /* Items in this GPtrArray are borrowed, not copied.
+   *
+   * /sbin/ldconfig might be a symlink into /run/host, or it might
+   * be from the runtime, depending which version of glibc we're
+   * using.
+   *
+   * ldconfig overwrites the file in-place rather than atomically,
+   * so we write to a new filename, and do the atomic-overwrite
+   * ourselves if ldconfig succeeds. */
+  g_ptr_array_add (argv, (char *) "/sbin/ldconfig");
+  g_ptr_array_add (argv, (char *) "-f");    /* Path to ld.so.conf */
+  g_ptr_array_add (argv, conf_path);
+  g_ptr_array_add (argv, (char *) "-C");    /* Path to new cache */
+  g_ptr_array_add (argv, new_path);
+  g_ptr_array_add (argv, (char *) "-X");    /* Don't update symlinks */
+
+  if (opt_verbose)
+    g_ptr_array_add (argv, (char *) "-v");
+
+  g_ptr_array_add (argv, NULL);
+
+  if (!run_helper_sync (dir,
+                        (const char * const *) argv->pdata,
+                        global_original_environ,
+                        &child_stdout,
+                        &child_stderr,
+                        &wait_status,
+                        error))
+    return glnx_prefix_error (error, "Cannot run /sbin/ldconfig");
+
+  if (child_stdout != NULL && child_stdout[0] != '\0')
+    g_debug ("Output:\n%s", child_stdout);
+
+  if (child_stderr != NULL && child_stderr[0] != '\0')
+    g_debug ("Diagnostic output:\n%s", child_stderr);
+
+  if (!g_spawn_check_exit_status (wait_status, error))
+    return glnx_prefix_error (error, "Unable to generate %s", new_path);
+
+  /* Atomically replace ld.so.cache with new-ld.so.cache. */
+  if (!glnx_renameat (AT_FDCWD, new_path, AT_FDCWD, replace_path, error))
+    return glnx_prefix_error (error, "Cannot move %s to %s",
+                              new_path, replace_path);
+
+  return TRUE;
+}
+
 static gboolean
 generate_locales (gchar **locpath_out,
                   GError **error)
@@ -769,6 +893,23 @@ static GOptionEntry options[] =
     G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_generate_locales,
     "Don't generate any missing locales [default].", NULL },
 
+  { "regenerate-ld.so-cache", '\0',
+    G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_regenerate_ld_so_cache,
+    "Regenerate ld.so.cache in the given directory, incorporating "
+    "the paths from \"add-ld.so-path\", if any. An empty argument results in "
+    "not doing this [default].",
+    "PATH" },
+  { "add-ld.so-path", '\0',
+    G_OPTION_FLAG_FILENAME, G_OPTION_ARG_CALLBACK, opt_add_ld_so_cb,
+    "While regenerating the ld.so.cache, include PATH as an additional "
+    "ld.so.conf.d entry. May be repeated.",
+    "PATH" },
+  { "set-ld-library-path", '\0',
+    G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_set_ld_library_path,
+    "Set the environment variable LD_LIBRARY_PATH to VALUE before "
+    "executing COMMAND.",
+    "VALUE" },
+
   { "write", '\0',
     G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_write,
     "Lock each subsequent lock file for write access.",
@@ -863,6 +1004,7 @@ main (int argc,
       char *argv[])
 {
   g_auto(GStrv) original_environ = NULL;
+  g_autoptr(GPtrArray) ld_so_conf_entries = NULL;
   g_autoptr(GPtrArray) locks = NULL;
   g_autoptr(GOptionContext) context = NULL;
   g_autoptr(GError) local_error = NULL;
@@ -895,6 +1037,9 @@ main (int argc,
   original_environ = g_get_environ ();
   global_original_environ = (const char * const *) original_environ;
 
+  ld_so_conf_entries = g_ptr_array_new_with_free_func (g_free);
+  global_ld_so_conf_entries = ld_so_conf_entries;
+
   locks = g_ptr_array_new_with_free_func ((GDestroyNotify) pv_bwrap_lock_free);
   global_locks = locks;
 
@@ -1158,6 +1303,24 @@ main (int argc,
         }
     }
 
+  if (opt_regenerate_ld_so_cache != NULL
+      && opt_regenerate_ld_so_cache[0] != '\0')
+    {
+      if (!regenerate_ld_so_cache (global_ld_so_conf_entries, opt_regenerate_ld_so_cache,
+                                   error))
+        {
+          goto out;
+        }
+      g_debug ("Generated ld.so.cache in %s", opt_regenerate_ld_so_cache);
+    }
+
+  if (opt_set_ld_library_path != NULL)
+    {
+      g_debug ("Setting LD_LIBARY_PATH to \"%s\"", opt_set_ld_library_path);
+      flatpak_bwrap_set_env (wrapped_command, "LD_LIBRARY_PATH",
+                             opt_set_ld_library_path, TRUE);
+    }
+
   if (opt_generate_locales)
     {
       G_GNUC_UNUSED g_autoptr(SrtProfilingTimer) profiling =
@@ -1309,8 +1472,10 @@ main (int argc,
     }
 
 out:
+  global_ld_so_conf_entries = NULL;
   global_locks = NULL;
   g_clear_pointer (&global_pass_fds, g_array_unref);
+  g_clear_pointer (&opt_regenerate_ld_so_cache, g_free);
 
   if (locales_temp_dir != NULL)
     _srt_rm_rf (locales_temp_dir);
diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c
index f471ae1f1e6aa91dac04f37f9595aee9f4a10125..62fb34ef2fdd41f2b2c39249cd48802d8770d22f 100644
--- a/pressure-vessel/runtime.c
+++ b/pressure-vessel/runtime.c
@@ -2437,7 +2437,7 @@ bind_runtime_base (PvRuntime *self,
     NULL
   };
   g_autofree gchar *xrd = g_strdup_printf ("/run/user/%ld", (long) geteuid ());
-  gsize i, j;
+  gsize i;
   const gchar *member;
 
   g_return_val_if_fail (PV_IS_RUNTIME (self), FALSE);
@@ -2544,6 +2544,16 @@ bind_runtime_base (PvRuntime *self,
           if (self->provider != NULL && g_strv_contains (from_provider, dest))
             continue;
 
+          if (self->mutable_sysroot != NULL)
+            {
+              /* If we have a mutable sysroot, we handle ld.so.cache
+               * separately later, because we want to set it up to be
+               * possible for the -adverb to overwrite it. */
+              if (strcmp (dest, "/etc/ld.so.cache") == 0
+                  || strcmp (dest, "/etc/ld.so.conf") == 0)
+                continue;
+            }
+
           full = g_build_filename (self->runtime_files,
                                    bind_mutable[i],
                                    member,
@@ -2564,44 +2574,6 @@ bind_runtime_base (PvRuntime *self,
         }
     }
 
-  /* glibc from some distributions will want to load the ld.so cache from
-   * a distribution-specific path, e.g. Clear Linux uses
-   * /var/cache/ldconfig/ld.so.cache. For simplicity, we make all these
-   * paths symlinks to /etc/ld.so.cache, so that we only have to populate
-   * the cache in one place. */
-  for (i = 0; pv_other_ld_so_cache[i] != NULL; i++)
-    {
-      const char *path = pv_other_ld_so_cache[i];
-
-      flatpak_bwrap_add_args (bwrap,
-                              "--symlink", "/etc/ld.so.cache", path,
-                              NULL);
-    }
-
-  /* glibc from some distributions will want to load the ld.so cache from
-   * a distribution- and architecture-specific path, e.g. Exherbo
-   * does this. Again, for simplicity we direct all these to the same path:
-   * it's OK to mix multiple architectures' libraries into one cache,
-   * as done in upstream glibc (and Debian, Arch, etc.). */
-  for (i = 0; i < PV_N_SUPPORTED_ARCHITECTURES; i++)
-    {
-      const PvMultiarchDetails *details = &pv_multiarch_details[i];
-
-      for (j = 0; j < G_N_ELEMENTS (details->other_ld_so_cache); j++)
-        {
-          const char *base = details->other_ld_so_cache[j];
-          g_autofree gchar *path = NULL;
-
-          if (base == NULL)
-            break;
-
-          path = g_build_filename ("/etc", base, NULL);
-          flatpak_bwrap_add_args (bwrap,
-                                  "--symlink", "/etc/ld.so.cache", path,
-                                  NULL);
-        }
-    }
-
   /* If we are in a Flatpak environment, we need to test if these files are
    * available in the host, and not in the current environment, because we will
    * run bwrap in the host system */
@@ -2677,6 +2649,211 @@ bind_runtime_base (PvRuntime *self,
   return TRUE;
 }
 
+/*
+ * Exactly as symlinkat(2), except that if the destination already exists,
+ * it will be removed.
+ */
+static gboolean
+pv_runtime_symlinkat (const gchar *target,
+                      int destination_dirfd,
+                      const gchar *destination,
+                      GError **error)
+{
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  if (!glnx_shutil_rm_rf_at (destination_dirfd, destination, NULL, error))
+    return FALSE;
+
+  if (TEMP_FAILURE_RETRY (symlinkat (target, destination_dirfd, destination)) != 0)
+    return glnx_throw_errno_prefix (error,
+                                    "Unable to create symlink \".../%s\" -> \"%s\"",
+                                    destination, target);
+
+  return TRUE;
+}
+
+static gboolean
+bind_runtime_ld_so (PvRuntime *self,
+                    FlatpakBwrap *bwrap,
+                    PvEnviron *container_env,
+                    GError **error)
+{
+  gsize i, j;
+
+  g_return_val_if_fail (PV_IS_RUNTIME (self), FALSE);
+  g_return_val_if_fail (bwrap == NULL || !pv_bwrap_was_finished (bwrap), FALSE);
+  g_return_val_if_fail (self->is_flatpak_env || bwrap != NULL, FALSE);
+  g_return_val_if_fail (self->mutable_sysroot != NULL || !self->is_flatpak_env, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  if (self->is_flatpak_env)
+    {
+      const gchar *xrd = NULL;
+      g_autofree gchar *ldso_runtime_dir = NULL;
+      g_autofree gchar *xrd_ld_so_conf = NULL;
+      g_autofree gchar *xrd_ld_so_cache = NULL;
+      glnx_autofd int sysroot_etc_dirfd = -1;
+      glnx_autofd int ldso_runtime_dirfd = -1;
+
+      sysroot_etc_dirfd = _srt_resolve_in_sysroot (self->mutable_sysroot_fd,
+                                                   "/etc",
+                                                   SRT_RESOLVE_FLAGS_MKDIR_P,
+                                                   NULL, error);
+      if (sysroot_etc_dirfd < 0)
+        return FALSE;
+
+      /* Because we're running under Flatpak in this code path,
+       * we expect that there is a XDG_RUNTIME_DIR even if the host system
+       * doesn't provide one; and because we require Flatpak 1.11.1,
+       * we can assume it's shared between our current sandbox and the
+       * game's subsandbox, with the same path in both. */
+      xrd = g_environ_getenv (self->original_environ, "XDG_RUNTIME_DIR");
+      if (xrd == NULL)
+        {
+          g_warning ("The environment variable XDG_RUNTIME_DIR is not set, skipping regeneration of ld.so");
+          return TRUE;
+        }
+
+      ldso_runtime_dir = g_build_filename (xrd, "pressure-vessel", "ldso", NULL);
+      if (g_mkdir_with_parents (ldso_runtime_dir, 0700) != 0)
+        return glnx_throw_errno_prefix (error, "Unable to create %s",
+                                        ldso_runtime_dir);
+
+      xrd_ld_so_conf = g_build_filename (ldso_runtime_dir, "ld.so.conf", NULL);
+      xrd_ld_so_cache = g_build_filename (ldso_runtime_dir, "ld.so.cache", NULL);
+
+      if (!glnx_opendirat (-1, ldso_runtime_dir, TRUE, &ldso_runtime_dirfd, error))
+        return FALSE;
+
+      /* Rename the original ld.so.cache and conf because we will create
+       * symlinks in their places */
+      if (!glnx_renameat (self->mutable_sysroot_fd, "etc/ld.so.cache",
+                          self->mutable_sysroot_fd, "etc/runtime-ld.so.cache", error))
+        return FALSE;
+      if (!glnx_renameat (self->mutable_sysroot_fd, "etc/ld.so.conf",
+                          self->mutable_sysroot_fd, "etc/runtime-ld.so.conf", error))
+        return FALSE;
+
+      if (!pv_runtime_symlinkat (xrd_ld_so_cache, self->mutable_sysroot_fd,
+                                 "etc/ld.so.cache", error))
+        return FALSE;
+      if (!pv_runtime_symlinkat (xrd_ld_so_conf, self->mutable_sysroot_fd,
+                                 "etc/ld.so.conf", error))
+        return FALSE;
+
+      /* Create a symlink to the runtime's version */
+      if (!pv_runtime_symlinkat ("/etc/runtime-ld.so.cache", ldso_runtime_dirfd,
+                                 "runtime-ld.so.cache", error))
+        return FALSE;
+      if (!pv_runtime_symlinkat ("/etc/runtime-ld.so.conf", ldso_runtime_dirfd,
+                                 "runtime-ld.so.conf", error))
+        return FALSE;
+
+      /* Initially it's a symlink to the runtime's version and we rely on
+       * LD_LIBRARY_PATH for our overrides, but -adverb will overwrite this
+       * symlink */
+      if (!pv_runtime_symlinkat ("runtime-ld.so.cache", ldso_runtime_dirfd,
+                                 "ld.so.cache", error))
+        return FALSE;
+      if (!pv_runtime_symlinkat ("runtime-ld.so.conf", ldso_runtime_dirfd,
+                                 "ld.so.conf", error))
+        return FALSE;
+
+      /* Initially we have the following situation:
+       * ($XRD is an abbreviation for $XDG_RUNTIME_DIR)
+       * ${mutable_sysroot}/etc/ld.so.cache -> $XRD/pressure-vessel/ldso/ld.so.cache
+       * $XRD/pressure-vessel/ldso/ld.so.cache -> runtime-ld.so.cache
+       * $XRD/pressure-vessel/ldso/runtime-ld.so.cache -> ${mutable_sysroot}/etc/runtime-ld.so.cache
+       * ${mutable_sysroot}/etc/runtime-ld.so.cache is the original runtime's ld.so.cache
+       *
+       * After exectuting -adverb we expect the symlink $XRD/pressure-vessel/ldso/ld.so.cache
+       * to be replaced with a newly generated ld.so.cache that incorporates the
+       * necessary paths from LD_LIBRARY_PATH */
+    }
+  else
+    {
+      g_assert (bwrap != NULL);
+
+      const gchar *ld_so_cache_path = "/run/pressure-vessel/ldso/ld.so.cache";
+      g_autofree gchar *ld_so_cache_on_host = NULL;
+      g_autofree gchar *ld_so_conf_on_host = NULL;
+
+      /* We only support runtimes that include /etc/ld.so.cache and
+        * /etc/ld.so.conf at their interoperable path. */
+      ld_so_cache_on_host = g_build_filename (self->runtime_files_on_host,
+                                              "etc", "ld.so.cache", NULL);
+      ld_so_conf_on_host = g_build_filename (self->runtime_files_on_host,
+                                              "etc", "ld.so.conf", NULL);
+
+      flatpak_bwrap_add_args (bwrap,
+                              "--tmpfs", "/run/pressure-vessel/ldso",
+                              /* We put the ld.so.cache somewhere that we can
+                              * overwrite from inside the container by
+                              * replacing the symlink. */
+                              "--symlink",
+                              ld_so_cache_path,
+                              "/etc/ld.so.cache",
+                              "--symlink",
+                              "/run/pressure-vessel/ldso/ld.so.conf",
+                              "/etc/ld.so.conf",
+                              /* Initially it's a symlink to the runtime's
+                              * version and we rely on LD_LIBRARY_PATH
+                              * for our overrides, but -adverb will
+                              * overwrite this symlink. */
+                              "--symlink",
+                              "runtime-ld.so.cache",
+                              ld_so_cache_path,
+                              "--symlink",
+                              "runtime-ld.so.conf",
+                              "/run/pressure-vessel/ldso/ld.so.conf",
+                              /* Put the runtime's version in place too. */
+                              "--ro-bind", ld_so_cache_on_host,
+                              "/run/pressure-vessel/ldso/runtime-ld.so.cache",
+                              "--ro-bind", ld_so_conf_on_host,
+                              "/run/pressure-vessel/ldso/runtime-ld.so.conf",
+                              NULL);
+
+      /* glibc from some distributions will want to load the ld.so cache from
+       * a distribution-specific path, e.g. Clear Linux uses
+       * /var/cache/ldconfig/ld.so.cache. For simplicity, we make all these paths
+       * symlinks, so that we only have to populate the cache in one place. */
+      for (i = 0; pv_other_ld_so_cache[i] != NULL; i++)
+        {
+          const char *path = pv_other_ld_so_cache[i];
+
+          flatpak_bwrap_add_args (bwrap,
+                                  "--symlink", ld_so_cache_path, path,
+                                  NULL);
+        }
+
+      /* glibc from some distributions will want to load the ld.so cache from
+       * a distribution- and architecture-specific path, e.g. Exherbo
+       * does this. Again, for simplicity we direct all these to the same path:
+       * it's OK to mix multiple architectures' libraries into one cache,
+       * as done in upstream glibc (and Debian, Arch, etc.). */
+      for (i = 0; i < PV_N_SUPPORTED_ARCHITECTURES; i++)
+        {
+          const PvMultiarchDetails *details = &pv_multiarch_details[i];
+
+          for (j = 0; j < G_N_ELEMENTS (details->other_ld_so_cache); j++)
+            {
+              const char *base = details->other_ld_so_cache[j];
+              g_autofree gchar *path = NULL;
+
+              if (base == NULL)
+                break;
+
+              path = g_build_filename ("/etc", base, NULL);
+              flatpak_bwrap_add_args (bwrap,
+                                      "--symlink", ld_so_cache_path, path,
+                                      NULL);
+            }
+        }
+    }
+
+  return TRUE;
+}
+
 static void
 bind_runtime_finish (PvRuntime *self,
                      FlatpakExports *exports,
@@ -5282,6 +5459,7 @@ pv_runtime_bind (PvRuntime *self,
                  FlatpakExports *exports,
                  FlatpakBwrap *bwrap,
                  PvEnviron *container_env,
+                 gchar **regenerate_ld_so_cache,
                  GError **error)
 {
   g_return_val_if_fail (PV_IS_RUNTIME (self), FALSE);
@@ -5306,6 +5484,12 @@ pv_runtime_bind (PvRuntime *self,
       && !bind_runtime_base (self, bwrap, container_env, error))
     return FALSE;
 
+  if (bwrap != NULL || self->is_flatpak_env)
+    {
+      if (!bind_runtime_ld_so (self, bwrap, container_env, error))
+        return FALSE;
+    }
+
   if (self->provider != NULL)
     {
       if (!pv_runtime_use_provider_graphics_stack (self, bwrap,
@@ -5430,6 +5614,26 @@ pv_runtime_bind (PvRuntime *self,
 
   pv_runtime_set_search_paths (self, container_env);
 
+  if (regenerate_ld_so_cache != NULL)
+    {
+      if (self->is_flatpak_env)
+        {
+          const gchar *xrd;
+          /* As in bind_runtime_ld_so(), we expect Flatpak to provide this
+           * in practice, even if the host system does not. */
+          xrd = g_environ_getenv (self->original_environ, "XDG_RUNTIME_DIR");
+          if (xrd == NULL)
+            *regenerate_ld_so_cache = NULL;
+          else
+            *regenerate_ld_so_cache = g_build_filename (xrd, "pressure-vessel",
+                                                        "ldso", NULL);
+        }
+      else
+        {
+          *regenerate_ld_so_cache = g_strdup ("/run/pressure-vessel/ldso");
+        }
+    }
+
   return TRUE;
 }
 
@@ -5441,10 +5645,10 @@ pv_runtime_set_search_paths (PvRuntime *self,
   g_autofree char *terminfo_path = NULL;
   gsize i;
 
-  /* TODO: Adapt the use_ld_so_cache code from Flatpak instead
-   * of setting LD_LIBRARY_PATH, for better robustness against
-   * games that set their own LD_LIBRARY_PATH ignoring what they
-   * got from the environment */
+  /* We need to set LD_LIBRARY_PATH here so that we can run
+   * pressure-vessel-adverb, even if it is going to regenerate
+   * the ld.so.cache for better robustness before launching the
+   * actual game */
   g_assert (pv_multiarch_tuples[PV_N_SUPPORTED_ARCHITECTURES] == NULL);
 
   for (i = 0; i < PV_N_SUPPORTED_ARCHITECTURES; i++)
diff --git a/pressure-vessel/runtime.h b/pressure-vessel/runtime.h
index c201a920638bead3e46f98dcec026afe508c658b..dfb9f19f47ba299fe111763bdf8cdc04dd570985 100644
--- a/pressure-vessel/runtime.h
+++ b/pressure-vessel/runtime.h
@@ -98,6 +98,7 @@ gboolean pv_runtime_bind (PvRuntime *self,
                           FlatpakExports *exports,
                           FlatpakBwrap *bwrap,
                           PvEnviron *container_env,
+                          gchar **regenerate_ld_so_cache,
                           GError **error);
 const char *pv_runtime_get_modified_usr (PvRuntime *self);
 const char *pv_runtime_get_modified_app (PvRuntime *self);
diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c
index dab5cdefbc5169fee973e8ee355f22422c28d36c..13acbb2a330673069dda6019f4a58cd5b16a39f0 100644
--- a/pressure-vessel/wrap.c
+++ b/pressure-vessel/wrap.c
@@ -1310,11 +1310,13 @@ main (int argc,
   g_autofree gchar *cwd_p = NULL;
   g_autofree gchar *cwd_l = NULL;
   g_autofree gchar *cwd_p_host = NULL;
+  g_autofree gchar *container_ld_library_path = NULL;
   const gchar *home;
   g_autofree gchar *tools_dir = NULL;
   g_autoptr(PvRuntime) runtime = NULL;
   g_autoptr(FILE) original_stdout = NULL;
   g_autoptr(GArray) pass_fds_through_adverb = g_array_new (FALSE, FALSE, sizeof (int));
+  g_autofree gchar *regenerate_ld_so_cache = NULL;
   const char *steam_app_id;
   g_autoptr(GPtrArray) adverb_preload_argv = NULL;
   int result;
@@ -1928,6 +1930,7 @@ main (int argc,
                             exports,
                             bwrap_filesystem_arguments,
                             container_env,
+                            &regenerate_ld_so_cache,
                             error))
         goto out;
 
@@ -2365,6 +2368,10 @@ main (int argc,
         goto out;
     }
 
+  /* Save this value before freeing container_env */
+  container_ld_library_path = g_strdup (pv_environ_getenv (container_env,
+                                                           "LD_LIBRARY_PATH"));
+
   if (is_flatpak_env)
     {
       g_autoptr(GList) vars = NULL;
@@ -2509,6 +2516,37 @@ main (int argc,
         {
           if (!pv_runtime_get_adverb (runtime, adverb_argv))
             goto out;
+
+          if (regenerate_ld_so_cache != NULL)
+            {
+              g_autoptr(GString) adverb_ld_library_path = g_string_new ("");
+              g_auto(GStrv) parts = NULL;
+
+              flatpak_bwrap_add_args (adverb_argv,
+                                      "--regenerate-ld.so-cache",
+                                      regenerate_ld_so_cache,
+                                      NULL);
+
+              if (container_ld_library_path != NULL)
+                parts = g_strsplit (container_ld_library_path, ":", 0);
+
+              for (i = 0; parts != NULL && parts[i] != NULL; i++)
+                {
+                  if (g_str_has_suffix (parts[i], "/aliases"))
+                    pv_search_path_append (adverb_ld_library_path, parts[i]);
+                  else
+                    flatpak_bwrap_add_args (adverb_argv,
+                                            "--add-ld.so-path",
+                                            parts[i],
+                                            NULL);
+                }
+
+              if (adverb_ld_library_path->len > 0)
+                flatpak_bwrap_add_args (adverb_argv,
+                                        "--set-ld-library-path",
+                                        adverb_ld_library_path->str,
+                                        NULL);
+            }
         }
       else
         {
diff --git a/tests/pressure-vessel/inside-runtime.py b/tests/pressure-vessel/inside-runtime.py
index f425a56f64291a3d2b9a2202301cf93995b7dcc7..a282f6a24660c5318fac91e30ed51b520cdcee33 100755
--- a/tests/pressure-vessel/inside-runtime.py
+++ b/tests/pressure-vessel/inside-runtime.py
@@ -164,6 +164,26 @@ class TestInsideRuntime(BaseTest):
         with open('/run/host/container-manager', 'r') as reader:
             self.assertEqual(reader.read(), 'pressure-vessel\n')
 
+        self.assertIsNotNone(os.environ.get('LD_LIBRARY_PATH'))
+
+        parts = os.environ.get('LD_LIBRARY_PATH', '').split(':')
+
+        if os.getenv('TEST_INSIDE_RUNTIME_IS_COPY'):
+            for path in parts:
+                self.assertTrue(path.endswith('/aliases'))
+        else:
+            if (
+                'HOST_LD_LINUX_SO_REALPATH' in os.environ
+                and Path('/usr/lib/i386-linux-gnu').is_dir()
+            ):
+                self.assertIn('/overrides/lib/i386-linux-gnu', parts)
+
+            if (
+                'HOST_LD_LINUX_X86_64_SO_REALPATH' in os.environ
+                and Path('/usr/lib/x86_64-linux-gnu').is_dir()
+            ):
+                self.assertIn('/overrides/lib/x86_64-linux-gnu', parts)
+
     def test_overrides(self) -> None:
         if os.getenv('TEST_INSIDE_RUNTIME_IS_COPY'):
             target = os.readlink('/overrides')
@@ -172,6 +192,62 @@ class TestInsideRuntime(BaseTest):
         self.assertTrue(Path('/overrides').is_dir())
         self.assertTrue(Path('/overrides/lib').is_dir())
 
+        if (
+            'HOST_LD_LINUX_SO_REALPATH' in os.environ
+            and Path('/usr/lib/i386-linux-gnu').is_dir()
+        ):
+            self.assertTrue(Path('/overrides/lib/i386-linux-gnu').is_dir())
+
+        if (
+            'HOST_LD_LINUX_X86_64_SO_REALPATH' in os.environ
+            and Path('/usr/lib/x86_64-linux-gnu').is_dir()
+        ):
+            self.assertTrue(Path('/overrides/lib/x86_64-linux-gnu').is_dir())
+
+        if os.getenv('TEST_INSIDE_RUNTIME_IS_COPY'):
+            # /etc/ld.so.* are symlinks to the mutable version
+            target = os.readlink('/etc/ld.so.cache')
+            self.assertEqual(target, '/run/pressure-vessel/ldso/ld.so.cache')
+            target = os.readlink('/etc/ld.so.conf')
+            self.assertEqual(target, '/run/pressure-vessel/ldso/ld.so.conf')
+
+            # Exherbo compatibility symlinks also exist
+            target = os.readlink('/etc/ld-i686-pc-linux-gnu.cache')
+            self.assertEqual(target, '/run/pressure-vessel/ldso/ld.so.cache')
+            target = os.readlink('/etc/ld-x86_64-pc-linux-gnu.cache')
+            self.assertEqual(target, '/run/pressure-vessel/ldso/ld.so.cache')
+            # Clear Linux compatibility symlinks, too
+            target = os.readlink('/var/cache/ldconfig/ld.so.cache')
+            self.assertEqual(target, '/run/pressure-vessel/ldso/ld.so.cache')
+
+            with open('/run/pressure-vessel/ldso/runtime-ld.so.conf') as reader:
+                lines_originally = reader.readlines()
+
+            with open('/etc/ld.so.conf') as reader:
+                lines_used = reader.readlines()
+
+            for line in lines_originally:
+                self.assertIn(line, lines_used)
+
+            if (
+                'HOST_LD_LINUX_SO_REALPATH' in os.environ
+                and Path('/usr/lib/i386-linux-gnu').is_dir()
+            ):
+                self.assertIn(
+                    '/usr/lib/pressure-vessel/overrides/lib/i386-linux-gnu\n',
+                    lines_used,
+                )
+
+            if (
+                'HOST_LD_LINUX_X86_64_SO_REALPATH' in os.environ
+                and Path('/usr/lib/x86_64-linux-gnu').is_dir()
+            ):
+                self.assertIn(
+                    ('/usr/lib/pressure-vessel/overrides/'
+                     'lib/x86_64-linux-gnu\n'),
+                    lines_used,
+                )
+
     def test_glibc(self) -> None:
         glibc = ctypes.cdll.LoadLibrary('libc.so.6')
         gnu_get_libc_version = glibc.gnu_get_libc_version