• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "malloc_impl.h"
8 
dlerror()9 char *dlerror()
10 {
11 	pthread_t self = __pthread_self();
12 	if (!self->dlerror_flag) return 0;
13 	self->dlerror_flag = 0;
14 	char *s = self->dlerror_buf;
15 	if (s == (void *)-1)
16 		return "Dynamic linker failed to allocate memory for error message";
17 	else
18 		return s;
19 }
20 
21 static volatile int freebuf_queue_lock[1];
22 static void **freebuf_queue;
23 
__dl_thread_cleanup(void)24 void __dl_thread_cleanup(void)
25 {
26 	pthread_t self = __pthread_self();
27 	if (self->dlerror_buf && self->dlerror_buf != (void *)-1) {
28 		LOCK(freebuf_queue_lock);
29 		void **p = (void **)self->dlerror_buf;
30 		*p = freebuf_queue;
31 		freebuf_queue = p;
32 		UNLOCK(freebuf_queue_lock);
33 	}
34 }
35 
__dl_vseterr(const char * fmt,va_list ap)36 hidden void __dl_vseterr(const char *fmt, va_list ap)
37 {
38 	LOCK(freebuf_queue_lock);
39 	while (freebuf_queue) {
40 		void **p = freebuf_queue;
41 		freebuf_queue = *p;
42 		internal_free(p);
43 	}
44 	UNLOCK(freebuf_queue_lock);
45 
46 	va_list ap2;
47 	va_copy(ap2, ap);
48 	pthread_t self = __pthread_self();
49 	if (self->dlerror_buf != (void *)-1)
50 		internal_free(self->dlerror_buf);
51 	size_t len = vsnprintf(0, 0, fmt, ap2);
52 	if (len < sizeof(void *)) len = sizeof(void *);
53 	va_end(ap2);
54 	char *buf = internal_malloc(len+1);
55 	if (buf) {
56 		vsnprintf(buf, len+1, fmt, ap);
57 	} else {
58 		buf = (void *)-1;
59 	}
60 	self->dlerror_buf = buf;
61 	self->dlerror_flag = 1;
62 }
63 
__dl_seterr(const char * fmt,...)64 hidden void __dl_seterr(const char *fmt, ...)
65 {
66 	va_list ap;
67 	va_start(ap, fmt);
68 	__dl_vseterr(fmt, ap);
69 	va_end(ap);
70 }
71 
stub_invalid_handle(void * h)72 static int stub_invalid_handle(void *h)
73 {
74 	__dl_seterr("Invalid library handle %p", (void *)h);
75 	return 1;
76 }
77 
78 weak_alias(stub_invalid_handle, __dl_invalid_handle);
79