define and use internal macros for hidden visibility, weak refs
[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 hidden void __dl_vseterr(const char *fmt, va_list ap)
27 {
28         va_list ap2;
29         va_copy(ap2, ap);
30         pthread_t self = __pthread_self();
31         if (self->dlerror_buf != (void *)-1)
32                 free(self->dlerror_buf);
33         size_t len = vsnprintf(0, 0, fmt, ap2);
34         va_end(ap2);
35         char *buf = malloc(len+1);
36         if (buf) {
37                 vsnprintf(buf, len+1, fmt, ap);
38         } else {
39                 buf = (void *)-1;       
40         }
41         self->dlerror_buf = buf;
42         self->dlerror_flag = 1;
43 }
44
45 hidden void __dl_seterr(const char *fmt, ...)
46 {
47         va_list ap;
48         va_start(ap, fmt);
49         __dl_vseterr(fmt, ap);
50         va_end(ap);
51 }
52
53 hidden int __dl_invalid_handle(void *);
54
55 static int stub_invalid_handle(void *h)
56 {
57         __dl_seterr("Invalid library handle %p", (void *)h);
58         return 1;
59 }
60
61 weak_alias(stub_invalid_handle, __dl_invalid_handle);