github.com/afumu/libc@v0.0.6/musl/src/ldso/dlerror.c (about) 1 #include <dlfcn.h> 2 #include <stdlib.h> 3 #include <stdarg.h> 4 #include "pthread_impl.h" 5 #include "dynlink.h" 6 #include "lock.h" 7 8 char *dlerror() 9 { 10 pthread_t self = __pthread_self(); 11 if (!self->dlerror_flag) return 0; 12 self->dlerror_flag = 0; 13 char *s = self->dlerror_buf; 14 if (s == (void *)-1) 15 return "Dynamic linker failed to allocate memory for error message"; 16 else 17 return s; 18 } 19 20 static volatile int freebuf_queue_lock[1]; 21 static void **freebuf_queue; 22 23 void __dl_thread_cleanup(void) 24 { 25 pthread_t self = __pthread_self(); 26 if (self->dlerror_buf && self->dlerror_buf != (void *)-1) { 27 LOCK(freebuf_queue_lock); 28 void **p = (void **)self->dlerror_buf; 29 *p = freebuf_queue; 30 freebuf_queue = p; 31 UNLOCK(freebuf_queue_lock); 32 } 33 } 34 35 hidden void __dl_vseterr(const char *fmt, va_list ap) 36 { 37 LOCK(freebuf_queue_lock); 38 while (freebuf_queue) { 39 void **p = freebuf_queue; 40 freebuf_queue = *p; 41 free(p); 42 } 43 UNLOCK(freebuf_queue_lock); 44 45 va_list ap2; 46 va_copy(ap2, ap); 47 pthread_t self = __pthread_self(); 48 if (self->dlerror_buf != (void *)-1) 49 free(self->dlerror_buf); 50 size_t len = vsnprintf(0, 0, fmt, ap2); 51 if (len < sizeof(void *)) len = sizeof(void *); 52 va_end(ap2); 53 char *buf = malloc(len+1); 54 if (buf) { 55 vsnprintf(buf, len+1, fmt, ap); 56 } else { 57 buf = (void *)-1; 58 } 59 self->dlerror_buf = buf; 60 self->dlerror_flag = 1; 61 } 62 63 hidden void __dl_seterr(const char *fmt, ...) 64 { 65 va_list ap; 66 va_start(ap, fmt); 67 __dl_vseterr(fmt, ap); 68 va_end(ap); 69 } 70 71 static int stub_invalid_handle(void *h) 72 { 73 __dl_seterr("Invalid library handle %p", (void *)h); 74 return 1; 75 } 76 77 weak_alias(stub_invalid_handle, __dl_invalid_handle);