summaryrefslogtreecommitdiff
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);
+}