about summary refs log tree commit diff
path: root/src/ldso/dlerror.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ldso/dlerror.c')
-rw-r--r--src/ldso/dlerror.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/ldso/dlerror.c b/src/ldso/dlerror.c
new file mode 100644
index 00000000..588828e9
--- /dev/null
+++ b/src/ldso/dlerror.c
@@ -0,0 +1,52 @@
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "pthread_impl.h"
+
+char *dlerror()
+{
+	pthread_t self = __pthread_self();
+	if (!self->dlerror_flag) return 0;
+	self->dlerror_flag = 0;
+	char *s = self->dlerror_buf;
+	if (s == (void *)-1)
+		return "Dynamic linker failed to allocate memory for error message";
+	else
+		return s;
+}
+
+void __dl_thread_cleanup(void)
+{
+	pthread_t self = __pthread_self();
+	if (self->dlerror_buf != (void *)-1)
+		free(self->dlerror_buf);
+}
+
+__attribute__((__visibility__("hidden")))
+void __dl_vseterr(const char *fmt, va_list ap)
+{
+	va_list ap2;
+	va_copy(ap2, ap);
+	pthread_t self = __pthread_self();
+	if (self->dlerror_buf != (void *)-1)
+		free(self->dlerror_buf);
+	size_t len = vsnprintf(0, 0, fmt, ap2);
+	va_end(ap2);
+	char *buf = malloc(len+1);
+	if (buf) {
+		vsnprintf(buf, len+1, fmt, ap);
+	} else {
+		buf = (void *)-1;	
+	}
+	self->dlerror_buf = buf;
+	self->dlerror_flag = 1;
+}
+
+__attribute__((__visibility__("hidden")))
+void __dl_seterr(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	__dl_vseterr(fmt, ap);
+	va_end(ap);
+}