diff --git a/src/runtime.c b/src/runtime.c
index 550e1865da9acfb1e7d1f1c0bf364919a51d0824..5c64bcfb17e7db688f63ab00940b3b1b26fbb499 100644
--- a/src/runtime.c
+++ b/src/runtime.c
@@ -1989,6 +1989,59 @@ out:
   return ret;
 }
 
+static gboolean
+pv_runtime_take_ld_so_from_host (PvRuntime *self,
+                                 RuntimeArchitecture *arch,
+                                 const gchar *ld_so_in_runtime,
+                                 FlatpakBwrap *bwrap,
+                                 GError **error)
+{
+  g_autofree gchar *ld_so_in_host = NULL;
+
+  g_debug ("Making host ld.so visible in container");
+
+  ld_so_in_host = realpath (arch->ld_so, NULL);
+
+  if (ld_so_in_host == NULL)
+    return glnx_throw_errno_prefix (error,
+                                    "Unable to determine host path to %s",
+                                    arch->ld_so);
+
+  g_debug ("Host path: %s -> %s", arch->ld_so, ld_so_in_host);
+  /* Might be either absolute, or relative to the root */
+  g_debug ("Container path: %s -> %s", arch->ld_so, ld_so_in_runtime);
+
+  /* If we have a mutable sysroot, we can delete the interoperable path
+   * and replace it with a symlink to what we want.
+   * For example, overwrite /lib/ld-linux.so.2 with a symlink to
+   * /run/host/lib/i386-linux-gnu/ld-2.30.so, or similar. This avoids
+   * having to dereference a long chain of symlinks every time we run
+   * an executable. */
+  if (self->mutable_sysroot != NULL &&
+      !pv_runtime_take_from_host (self, bwrap, ld_so_in_host,
+                                  arch->ld_so, TAKE_FROM_HOST_FLAGS_NONE,
+                                  error))
+    return FALSE;
+
+  /* If we don't have a mutable sysroot, we cannot replace symlinks,
+   * and we also cannot mount onto symlinks (they get dereferenced),
+   * so our only choice is to bind-mount
+   * /lib/i386-linux-gnu/ld-2.30.so onto
+   * /lib/i386-linux-gnu/ld-2.15.so and so on.
+   *
+   * In the mutable sysroot case, we don't strictly need to
+   * overwrite /lib/i386-linux-gnu/ld-2.15.so with a symlink to
+   * /run/host/lib/i386-linux-gnu/ld-2.30.so, but we might as well do
+   * it anyway, for extra robustness: if we ever run a ld.so that
+   * doesn't match the libc we are using (perhaps via an OS-specific,
+   * non-standard path), that's pretty much a disaster, because it will
+   * just crash. However, all of those (chains of) non-standard symlinks
+   * will end up pointing to ld_so_in_runtime. */
+  return pv_runtime_take_from_host (self, bwrap, ld_so_in_host,
+                                    ld_so_in_runtime,
+                                    TAKE_FROM_HOST_FLAGS_NONE, error);
+}
+
 static gboolean
 pv_runtime_use_host_graphics_stack (PvRuntime *self,
                                     FlatpakBwrap *bwrap,
@@ -2110,6 +2163,7 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
           g_autofree gchar *this_dri_path_in_container = g_build_filename (arch->libdir_in_container,
                                                                            "dri", NULL);
           g_autofree gchar *libc = NULL;
+          /* Can either be relative to the sysroot, or absolute */
           g_autofree gchar *ld_so_in_runtime = NULL;
           g_autofree gchar *libdrm = NULL;
           g_autoptr(SrtObjectList) vdpau_drivers = NULL;
@@ -2157,14 +2211,6 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
                   (const char * const *) temp_bwrap->argv->pdata, NULL);
 
               g_clear_pointer (&temp_bwrap, flatpak_bwrap_free);
-
-              if (!g_path_is_absolute (ld_so_in_runtime))
-                {
-                  /* bwrap --ro-bind wants an absolute path */
-                  g_autofree gchar *temp = g_steal_pointer (&ld_so_in_runtime);
-
-                  ld_so_in_runtime = g_build_filename ("/", temp, NULL);
-                }
             }
 
           if (ld_so_in_runtime == NULL)
@@ -2342,24 +2388,12 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
            * then we have to use its ld.so too. */
           if (g_file_test (libc, G_FILE_TEST_IS_SYMLINK))
             {
-              g_autofree gchar *ld_so_in_host = NULL;
               g_autofree char *libc_target = NULL;
 
-              g_debug ("Making host ld.so visible in container");
-
-              ld_so_in_host = realpath (arch->ld_so, NULL);
-
-              if (ld_so_in_host == NULL)
-                return glnx_throw_errno_prefix (error,
-                                                "Unable to determine host path to %s",
-                                                arch->ld_so);
-
-              g_debug ("Host path: %s -> %s", arch->ld_so, ld_so_in_host);
-              g_debug ("Container path: %s -> %s", arch->ld_so, ld_so_in_runtime);
-              flatpak_bwrap_add_args (bwrap,
-                                      "--ro-bind", ld_so_in_host,
-                                      ld_so_in_runtime,
-                                      NULL);
+              if (!pv_runtime_take_ld_so_from_host (self, arch,
+                                                    ld_so_in_runtime,
+                                                    bwrap, error))
+                return FALSE;
 
               /* Collect miscellaneous libraries that libc might dlopen.
                * At the moment this is just libidn2. */