From a4fbc82c8e2a311baa0c6b5a4a4cdbb6c8f66edb Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 25 Jan 2016 17:56:00 -0500 Subject: factor dlerror and error-setting code out of dynlink.c the ultimate goal of this change is to get all code used in libc.a out of dynlink.c, so that the dynamic linker code can be moved to its own tree and object files in the src tree can all be shared between libc.a and libc.so. --- src/ldso/dlerror.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/ldso/dlerror.c (limited to 'src/ldso/dlerror.c') 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 +#include +#include +#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); +} -- cgit v1.2.1