diff options
| -rw-r--r-- | src/internal/pthread_impl.h | 2 | ||||
| -rw-r--r-- | src/ldso/dynlink.c | 93 | ||||
| -rw-r--r-- | src/thread/pthread_create.c | 2 | 
3 files changed, 65 insertions, 32 deletions
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index a0226a63..56877b3a 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -44,6 +44,8 @@ struct pthread {  	volatile int exitlock[2];  	volatile int startlock[2];  	unsigned long sigmask[_NSIG/8/sizeof(long)]; +	char *dlerror_buf; +	int dlerror_flag;  	void *stdio_locks;  	void **dtv_copy;  }; diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index ccd526f0..62bfed8e 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -21,8 +21,7 @@  #include "libc.h"  #include "dynlink.h" -static int errflag; -static char errbuf[128]; +static void error(const char *, ...);  #ifdef SHARED @@ -139,17 +138,6 @@ static int search_vec(size_t *v, size_t *r, size_t key)  	return 1;  } -static void error(const char *fmt, ...) -{ -	va_list ap; -	va_start(ap, fmt); -	vsnprintf(errbuf, sizeof errbuf, fmt, ap); -	va_end(ap); -	if (runtime) longjmp(*rtld_fail, 1); -	dprintf(2, "%s\n", errbuf); -	ldso_fail = 1; -} -  static uint32_t sysv_hash(const char *s0)  {  	const unsigned char *s = (void *)s0; @@ -283,6 +271,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri  			    || sym->st_info>>4 != STB_WEAK)) {  				error("Error relocating %s: %s: symbol not found",  					dso->name, name); +				if (runtime) longjmp(*rtld_fail, 1);  				continue;  			}  		} else { @@ -347,9 +336,12 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri  			if (stride<3) addend = reloc_addr[1];  			if (runtime && def.dso->tls_id >= static_tls_cnt) {  				struct td_index *new = malloc(sizeof *new); -				if (!new) error( +				if (!new) { +					error(  					"Error relocating %s: cannot allocate TLSDESC for %s",  					dso->name, sym ? name : "(local)" ); +					if (runtime) longjmp(*rtld_fail, 1); +				}  				new->next = dso->td_index;  				dso->td_index = new;  				new->args[0] = def.dso->tls_id; @@ -370,6 +362,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri  		default:  			error("Error relocating %s: unsupported relocation type %d",  				dso->name, type); +			if (runtime) longjmp(*rtld_fail, 1);  			continue;  		}  	} @@ -848,6 +841,7 @@ static void load_deps(struct dso *p)  			if (!dep) {  				error("Error loading shared library %s: %m (needed by %s)",  					p->strings + p->dynv[i+1], p->name); +				if (runtime) longjmp(*rtld_fail, 1);  				continue;  			}  			if (runtime) { @@ -917,6 +911,7 @@ static void reloc_all(struct dso *p)  		    mprotect(p->base+p->relro_start, p->relro_end-p->relro_start, PROT_READ) < 0) {  			error("Error relocating %s: RELRO protection failed: %m",  				p->name); +			if (runtime) longjmp(*rtld_fail, 1);  		}  		p->relocated = 1; @@ -1433,16 +1428,14 @@ void *dlopen(const char *file, int mode)  		tail = orig_tail;  		tail->next = 0;  		p = 0; -		errflag = 1;  		goto end;  	} else p = load_library(file, head);  	if (!p) { -		snprintf(errbuf, sizeof errbuf, noload ? +		error(noload ?  			"Library %s is not already loaded" :  			"Error loading shared library %s: %m",  			file); -		errflag = 1;  		goto end;  	} @@ -1482,8 +1475,7 @@ static int invalid_dso_handle(void *h)  {  	struct dso *p;  	for (p=head; p; p=p->next) if (h==p) return 0; -	snprintf(errbuf, sizeof errbuf, "Invalid library handle %p", (void *)h); -	errflag = 1; +	error("Invalid library handle %p", (void *)h);  	return 1;  } @@ -1535,8 +1527,7 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)  			return p->deps[i]->base + sym->st_value;  	}  failed: -	errflag = 1; -	snprintf(errbuf, sizeof errbuf, "Symbol not found: %s", s); +	error("Symbol not found: %s", s);  	return 0;  } @@ -1639,20 +1630,17 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void  #else  static int invalid_dso_handle(void *h)  { -	snprintf(errbuf, sizeof errbuf, "Invalid library handle %p", (void *)h); -	errflag = 1; +	error("Invalid library handle %p", (void *)h);  	return 1;  }  void *dlopen(const char *file, int mode)  { -	strcpy(errbuf, "Dynamic loading not supported"); -	errflag = 1; +	error("Dynamic loading not supported");  	return 0;  }  void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra)  { -	errflag = 1; -	snprintf(errbuf, sizeof errbuf, "Symbol not found: %s", s); +	error("Symbol not found: %s", s);  	return 0;  }  int __dladdr (const void *addr, Dl_info *info) @@ -1665,8 +1653,7 @@ int __dlinfo(void *dso, int req, void *res)  {  	if (invalid_dso_handle(dso)) return -1;  	if (req != RTLD_DI_LINKMAP) { -		snprintf(errbuf, sizeof errbuf, "Unsupported request %d", req); -		errflag = 1; +		error("Unsupported request %d", req);  		return -1;  	}  	*(struct link_map **)res = dso; @@ -1675,12 +1662,54 @@ int __dlinfo(void *dso, int req, void *res)  char *dlerror()  { -	if (!errflag) return 0; -	errflag = 0; -	return errbuf; +	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); +} + +static void error(const char *fmt, ...) +{ +	va_list ap; +	va_start(ap, fmt); +#ifdef SHARED +	if (!runtime) { +		vdprintf(2, fmt, ap); +		dprintf(2, "\n"); +		ldso_fail = 1; +		va_end(ap); +		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); +	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; +} diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 6963f0d6..d7c0323a 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -17,6 +17,7 @@ weak_alias(dummy_0, __acquire_ptc);  weak_alias(dummy_0, __release_ptc);  weak_alias(dummy_0, __pthread_tsd_run_dtors);  weak_alias(dummy_0, __do_orphaned_stdio_locks); +weak_alias(dummy_0, __dl_thread_cleanup);  _Noreturn void __pthread_exit(void *result)  { @@ -92,6 +93,7 @@ _Noreturn void __pthread_exit(void *result)  	__vm_unlock();  	__do_orphaned_stdio_locks(); +	__dl_thread_cleanup();  	if (self->detached && self->map_base) {  		/* Detached threads must avoid the kernel clear_child_tid  | 
