1#include <dlfcn.h>
2#include <stdlib.h>
3#include <stdarg.h>
4#include "pthread_impl.h"
5#include "libc.h"
6
7char *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
19void __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")))
27void __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")))
47void __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")))
56int __dl_invalid_handle(void *);
57
58static int stub_invalid_handle(void *h)
59{
60	__dl_seterr("Invalid library handle %p", (void *)h);
61	return 1;
62}
63
64weak_alias(stub_invalid_handle, __dl_invalid_handle);
65