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