factor dlerror and error-setting code out of dynlink.c

the ultimate goal of this change is to get all code used in libc.a out
of dynlink.c, so that the dynamic linker code can be moved to its own
tree and object files in the src tree can all be shared between libc.a
and libc.so.
This commit is contained in:
Rich Felker 2016-01-25 17:56:00 -05:00
parent e7a1118984
commit a4fbc82c8e
2 changed files with 55 additions and 32 deletions

52
src/ldso/dlerror.c Normal file
View File

@ -0,0 +1,52 @@
#include <dlfcn.h>
#include <stdlib.h>
#include <stdarg.h>
#include "pthread_impl.h"
char *dlerror()
{
pthread_t self = __pthread_self();
if (!self->dlerror_flag) return 0;
self->dlerror_flag = 0;
char *s = self->dlerror_buf;
if (s == (void *)-1)
return "Dynamic linker failed to allocate memory for error message";
else
return s;
}
void __dl_thread_cleanup(void)
{
pthread_t self = __pthread_self();
if (self->dlerror_buf != (void *)-1)
free(self->dlerror_buf);
}
__attribute__((__visibility__("hidden")))
void __dl_vseterr(const char *fmt, va_list ap)
{
va_list ap2;
va_copy(ap2, ap);
pthread_t self = __pthread_self();
if (self->dlerror_buf != (void *)-1)
free(self->dlerror_buf);
size_t len = vsnprintf(0, 0, fmt, ap2);
va_end(ap2);
char *buf = malloc(len+1);
if (buf) {
vsnprintf(buf, len+1, fmt, ap);
} else {
buf = (void *)-1;
}
self->dlerror_buf = buf;
self->dlerror_flag = 1;
}
__attribute__((__visibility__("hidden")))
void __dl_seterr(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
__dl_vseterr(fmt, ap);
va_end(ap);
}

View File

@ -1945,29 +1945,13 @@ int __dlinfo(void *dso, int req, void *res)
return 0;
}
char *dlerror()
{
pthread_t self = __pthread_self();
if (!self->dlerror_flag) return 0;
self->dlerror_flag = 0;
char *s = self->dlerror_buf;
if (s == (void *)-1)
return "Dynamic linker failed to allocate memory for error message";
else
return s;
}
int dlclose(void *p)
{
return invalid_dso_handle(p);
}
void __dl_thread_cleanup(void)
{
pthread_t self = __pthread_self();
if (self->dlerror_buf != (void *)-1)
free(self->dlerror_buf);
}
__attribute__((__visibility__("hidden")))
void __dl_vseterr(const char *, va_list);
static void error(const char *fmt, ...)
{
@ -1982,19 +1966,6 @@ static void error(const char *fmt, ...)
return;
}
#endif
pthread_t self = __pthread_self();
if (self->dlerror_buf != (void *)-1)
free(self->dlerror_buf);
size_t len = vsnprintf(0, 0, fmt, ap);
__dl_vseterr(fmt, ap);
va_end(ap);
char *buf = malloc(len+1);
if (buf) {
va_start(ap, fmt);
vsnprintf(buf, len+1, fmt, ap);
va_end(ap);
} else {
buf = (void *)-1;
}
self->dlerror_buf = buf;
self->dlerror_flag = 1;
}