summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2020-01-01 00:15:04 -0500
committerRich Felker <dalias@aerifal.cx>2020-01-01 00:15:04 -0500
commitd6bbea2acf3e69afe0ac87105d6e443a19c43d14 (patch)
tree322962eaeab38bd8b801ee766643e60d46f7db7b
parentb82cd6c78d812d38c31febba5a9e57dbaa7919c4 (diff)
downloadmusl-d6bbea2acf3e69afe0ac87105d6e443a19c43d14.tar.gz
fix fdpic regression in dynamic linker with overly smart compilers
at least gcc 9 broke execution of DT_INIT/DT_FINI for fdpic archs (presently only sh) by recognizing that the stores to the compound-literal function descriptor constructed to call them were dead stores. there's no way to make a "may_alias function", so instead launder the descriptor through an asm-statement barrier. in practice just making the compound literal volatile seemed to have worked too, but this should be less of a hack and more accurately convey the semantics of what transformations are not valid.
-rw-r--r--ldso/dynlink.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index acd2b20a..a18461e3 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -185,8 +185,14 @@ static void *laddr_pg(const struct dso *p, size_t v)
}
return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
}
-#define fpaddr(p, v) ((void (*)())&(struct funcdesc){ \
- laddr(p, v), (p)->got })
+static void (*fdbarrier(void *p))()
+{
+ void (*fd)();
+ __asm__("" : "=r"(fd) : "0"(p));
+ return fd;
+}
+#define fpaddr(p, v) fdbarrier((&(struct funcdesc){ \
+ laddr(p, v), (p)->got }))
#else
#define laddr(p, v) (void *)((p)->base + (v))
#define laddr_pg(p, v) laddr(p, v)