diff options
| -rw-r--r-- | src/ldso/dynlink.c | 35 | 
1 files changed, 21 insertions, 14 deletions
| diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 263593ab..0a64ef8a 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -322,6 +322,7 @@ static void decode_dyn(struct dso *p)  static struct dso *load_library(const char *name)  {  	char buf[2*NAME_MAX+2]; +	const char *pathname;  	unsigned char *base, *map;  	size_t dyno, map_len;  	struct dso *p; @@ -346,16 +347,17 @@ static struct dso *load_library(const char *name)  			}  		}  	} -	/* Search for the name to see if it's already loaded */ -	for (p=head->next; p; p=p->next) { -		if (!strcmp(p->shortname, name)) { -			p->refcnt++; -			return p; -		} -	}  	if (strchr(name, '/')) { +		pathname = name;  		fd = open(name, O_RDONLY);  	} else { +		/* Search for the name to see if it's already loaded */ +		for (p=head->next; p; p=p->next) { +			if (p->shortname && !strcmp(p->shortname, name)) { +				p->refcnt++; +				return p; +			} +		}  		if (strlen(name) > NAME_MAX) return 0;  		fd = -1;  		if (r_path) fd = path_open(name, r_path, buf, sizeof buf); @@ -372,6 +374,7 @@ static struct dso *load_library(const char *name)  			if (sys_path) fd = path_open(name, sys_path, buf, sizeof buf);  			else fd = path_open(name, "/lib:/usr/local/lib:/usr/lib", buf, sizeof buf);  		} +		pathname = buf;  	}  	if (fd < 0) return 0;  	if (fstat(fd, &st) < 0) { @@ -380,6 +383,10 @@ static struct dso *load_library(const char *name)  	}  	for (p=head->next; p; p=p->next) {  		if (p->dev == st.st_dev && p->ino == st.st_ino) { +			/* If this library was previously loaded with a +			 * pathname but a search found the same inode, +			 * setup its shortname so it can be found by name. */ +			if (!p->shortname) p->shortname = strrchr(p->name, '/')+1;  			close(fd);  			p->refcnt++;  			return p; @@ -388,7 +395,7 @@ static struct dso *load_library(const char *name)  	map = map_library(fd, &map_len, &base, &dyno);  	close(fd);  	if (!map) return 0; -	p = calloc(1, sizeof *p + strlen(buf) + 1); +	p = calloc(1, sizeof *p + strlen(pathname) + 1);  	if (!p) {  		munmap(map, map_len);  		return 0; @@ -404,15 +411,15 @@ static struct dso *load_library(const char *name)  	p->ino = st.st_ino;  	p->refcnt = 1;  	p->name = p->buf; -	strcpy(p->name, buf); -	if (!strchr(name, '/')) p->shortname = strrchr(p->name, '/'); -	if (!p->shortname) p->shortname = p->name; +	strcpy(p->name, pathname); +	/* Add a shortname only if name arg was not an explicit pathname. */ +	if (pathname != name) p->shortname = strrchr(p->name, '/')+1;  	tail->next = p;  	p->prev = tail;  	tail = p; -	if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, buf, base); +	if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, base);  	return p;  } @@ -576,7 +583,7 @@ void *__dynlink(int argc, char **argv)  			if (phdr->p_type == PT_PHDR)  				app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);  		} -		app->name = app->shortname = argv[0]; +		app->name = argv[0];  		app->dynv = (void *)(app->base + find_dyn(  			(void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT]));  	} else { @@ -605,7 +612,7 @@ void *__dynlink(int argc, char **argv)  		}  		runtime = 0;  		close(fd); -		app->name = app->shortname = argv[0]; +		app->name = argv[0];  		app->dynv = (void *)(app->base + dyno);  		aux[AT_ENTRY] = ehdr->e_entry;  	} | 
