about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-06-26 17:39:17 -0400
committerRich Felker <dalias@aerifal.cx>2011-06-26 17:39:17 -0400
commit6b3d5e508fcf16abe18c163c4c31a47f2d35a306 (patch)
tree6b9a9a4edb8b4b7102ba3accf4a174ce525d10b7
parent6e53a6eca42ec40d12dced55f4840df883e2f76e (diff)
downloadmusl-6b3d5e508fcf16abe18c163c4c31a47f2d35a306.tar.gz
musl-6b3d5e508fcf16abe18c163c4c31a47f2d35a306.tar.xz
musl-6b3d5e508fcf16abe18c163c4c31a47f2d35a306.zip
error handling in dynamic linking
some of the code is not yet used, and is in preparation for dlopen
which needs to be able to handle failure loading libraries without
terminating the program.
-rw-r--r--src/ldso/dynlink.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 9e9415ca..03f09208 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <elf.h>
+#include <setjmp.h>
 
 #include "reloc.h"
 
@@ -44,11 +45,14 @@ struct dso
 	ino_t ino;
 	int global;
 	int relocated;
-	char name[];
+	char *name;
+	char buf[];
 };
 
 static struct dso *head, *tail, *libc;
 static char *env_path, *sys_path;
+static int runtime;
+static jmp_buf rtld_fail;
 
 #define AUX_CNT 15
 #define DYN_CNT 34
@@ -115,6 +119,11 @@ static void do_relocs(unsigned char *base, size_t *rel, size_t rel_size, size_t
 			name = strings + sym->st_name;
 			ctx = IS_COPY(type) ? dso->next : dso;
 			sym_val = (size_t)find_sym(ctx, name, IS_PLT(type));
+			if (!sym_val && sym->st_info>>4 != STB_WEAK) {
+				if (runtime) longjmp(rtld_fail, 1);
+				dprintf(2, "%s: symbol not found\n", name);
+				_exit(127);
+			}
 			sym_size = sym->st_size;
 		}
 		do_single_reloc(reloc_addr, type, sym_val, sym_size, base, rel[2]);
@@ -308,6 +317,7 @@ static struct dso *load_library(const char *name)
 	p->ino = st.st_ino;
 	p->global = 1;
 	p->refcnt = 1;
+	p->name = p->buf;
 	strcpy(p->name, name);
 
 	tail->next = p;
@@ -323,7 +333,12 @@ static void load_deps(struct dso *p)
 	for (; p; p=p->next) {
 		for (i=0; p->dynv[i]; i+=2) {
 			if (p->dynv[i] != DT_NEEDED) continue;
-			load_library(p->strings + p->dynv[i+1]);
+			if (!load_library(p->strings + p->dynv[i+1])) {
+				if (runtime) longjmp(rtld_fail, 1);
+				dprintf(2, "%s: %m (needed by %s)\n",
+					p->strings + p->dynv[i+1], p->name);
+				_exit(127);
+			}
 		}
 	}
 }
@@ -395,6 +410,7 @@ void *__dynlink(int argc, char **argv, size_t *got)
 		.hashtab = (void *)(app_dyn[DT_HASH]),
 		.syms = (void *)(app_dyn[DT_SYMTAB]),
 		.dynv = (void *)(phdr->p_vaddr),
+		.name = argv[0],
 		.next = &lib
 	};
 
@@ -404,6 +420,7 @@ void *__dynlink(int argc, char **argv, size_t *got)
 		.hashtab = (void *)(aux[AT_BASE]+lib_dyn[DT_HASH]),
 		.syms = (void *)(aux[AT_BASE]+lib_dyn[DT_SYMTAB]),
 		.dynv = (void *)(got[0]),
+		.name = "libc.so",
 		.relocated = 1
 	};