about summary refs log tree commit diff
path: root/ldso
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-03-03 12:12:59 -0500
committerRich Felker <dalias@aerifal.cx>2019-03-03 12:42:16 -0500
commite612d094b1d27e1d61940e58d8aaeb249c54e768 (patch)
tree88f894c3d7df19e6ef152fac878d7d0b01b5f0c8 /ldso
parent2f1f51ae7b2d78247568e7fdb8462f3c19e469a4 (diff)
downloadmusl-e612d094b1d27e1d61940e58d8aaeb249c54e768.tar.gz
musl-e612d094b1d27e1d61940e58d8aaeb249c54e768.tar.xz
musl-e612d094b1d27e1d61940e58d8aaeb249c54e768.zip
avoid malloc of deps array for programs with no external deps
traditionally, we've provided a guarantee that dynamic-linked
applications with no external dependencies (nothing but libc) and no
thread-local storage have no failure paths before the entry point.
normally, thanks to reclaim_gaps, such a malloc will not require a
syscall anyway, but if segment alignment is unlucky, it might. use a
builtin array for this common special case.
Diffstat (limited to 'ldso')
-rw-r--r--ldso/dynlink.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index a2f059cb..255ace2d 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -133,6 +133,7 @@ static size_t tls_cnt, tls_offset, tls_align = MIN_TLS_ALIGN;
 static size_t static_tls_cnt;
 static pthread_mutex_t init_fini_lock;
 static pthread_cond_t ctor_cond;
+static struct dso *builtin_deps[2];
 static struct dso **main_ctor_queue;
 static struct fdpic_loadmap *app_loadmap;
 static struct fdpic_dummy_loadmap app_dummy_loadmap;
@@ -1152,6 +1153,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 static void load_direct_deps(struct dso *p)
 {
 	size_t i, cnt=0;
+
 	if (p->deps) return;
 	/* For head, all preloads are direct pseudo-dependencies.
 	 * Count and include them now to avoid realloc later. */
@@ -1159,7 +1161,10 @@ static void load_direct_deps(struct dso *p)
 		cnt++;
 	for (i=0; p->dynv[i]; i+=2)
 		if (p->dynv[i] == DT_NEEDED) cnt++;
-	p->deps = calloc(cnt+1, sizeof *p->deps);
+	/* Use builtin buffer for apps with no external deps, to
+	 * preserve property of no runtime failure paths. */
+	p->deps = (p==head && cnt<2) ? builtin_deps :
+		calloc(cnt+1, sizeof *p->deps);
 	if (!p->deps) {
 		error("Error loading dependencies for %s", p->name);
 		if (runtime) longjmp(*rtld_fail, 1);
@@ -1195,8 +1200,10 @@ static void extend_bfs_deps(struct dso *p)
 	struct dso **tmp;
 
 	/* Can't use realloc if the original p->deps was allocated at
-	 * program entry and malloc has been replaced. */
-	int no_realloc = __malloc_replaced && !p->runtime_loaded;
+	 * program entry and malloc has been replaced, or if it's
+	 * the builtin non-allocated trivial main program deps array. */
+	int no_realloc = (__malloc_replaced && !p->runtime_loaded)
+		|| p->deps == builtin_deps;
 
 	if (p->bfs_built) return;
 	ndeps_all = p->ndeps_direct;