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);