diff options
| -rw-r--r-- | ldso/ldso/dl-hash.c | 155 | ||||
| -rw-r--r-- | ldso/ldso/hash.c | 155 | 
2 files changed, 90 insertions, 220 deletions
| diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 1eb7c5dd9..1e4acd979 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -1,12 +1,12 @@  /* vi: set sw=4 ts=4: */ -/* Program to load an ELF binary on a linux system, and run it +/* + * Program to load an ELF binary on a linux system, and run it   * after resolving ELF shared library symbols   * - * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,  + * Copyright (C) 2004 by Joakim Tjernlund <joakim.tjernlund@lumentis.se> + * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org> + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,   *				David Engel, Hongjiu Lu and Mitch D'Souza - * Copyright (C) 2001-2002, Erik Andersen - * - * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without   * modification, are permitted provided that the following conditions @@ -35,10 +35,9 @@  /*   * This is the start of the linked list that describes all of the files present - * in the system with pointers to all of the symbol, string, and hash tables,  + * in the system with pointers to all of the symbol, string, and hash tables,   * as well as all of the other good stuff in the binary.   */ -  struct elf_resolve *_dl_loaded_modules = NULL;  /* @@ -55,12 +54,9 @@ struct dyn_elf *_dl_symbol_tables = NULL;  struct dyn_elf *_dl_handles = NULL; -/* - * This is the hash function that is used by the ELF linker to generate - * the hash table that each executable and library is required to - * have.  We need it to decode the hash table. - */ - +/* This is the hash function that is used by the ELF linker to generate the + * hash table that each executable and library is required to have.  We need + * it to decode the hash table.  */  unsigned long _dl_elf_hash(const char *name)  {  	unsigned long hash = 0; @@ -75,9 +71,7 @@ unsigned long _dl_elf_hash(const char *name)  	return hash;  } -/* - * Check to see if a library has already been added to the hash chain. - */ +/* Check to see if a library has already been added to the hash chain.  */  struct elf_resolve *_dl_check_hashed_files(const char *libname)  {  	struct elf_resolve *tpnt; @@ -97,9 +91,8 @@ struct elf_resolve *_dl_check_hashed_files(const char *libname)   * We add the relevant info to the symbol chain, so that we can resolve all   * externals properly.   */ - -struct elf_resolve *_dl_add_elf_hash_table(const char *libname,  -	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,  +struct elf_resolve *_dl_add_elf_hash_table(const char *libname, +	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,  	unsigned long dynamic_size)  {  	unsigned long *hash_addr; @@ -107,8 +100,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,  	int i;  	if (!_dl_loaded_modules) { -		tpnt = _dl_loaded_modules =  -		    (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve)); +		tpnt = _dl_loaded_modules = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));  		_dl_memset(tpnt, 0, sizeof(struct elf_resolve));  	} else {  		tpnt = _dl_loaded_modules; @@ -161,21 +153,18 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,   * This function resolves externals, and this is either called when we process   * relocations or when we call an entry in the PLT table for the first time.   */ - -char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  +char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  	struct elf_resolve *f_tpnt, enum caller_type caller_type)  {  	struct elf_resolve *tpnt;  	int si; -	char *pnt;  	int pass;  	char *strtab;  	Elf32_Sym *symtab;  	unsigned long elf_hash_number, hn;  	char *weak_result; -	struct elf_resolve *first_def;  	struct dyn_elf *rpnt, first; -	char *data_result = 0;		/* nakao */ +	const ElfW(Sym) *sym;  	weak_result = 0;  	elf_hash_number = _dl_elf_hash(name); @@ -185,7 +174,7 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  	   that any shared library data symbols referenced in the executable  	   will be seen at the same address by the executable, shared libraries  	   and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */ -	if (_dl_symbol_tables && !caller_type && rpnt1) { +	if (_dl_symbol_tables && rpnt1) {  		first = (*_dl_symbol_tables);  		first.next = rpnt1;  		rpnt1 = (&first); @@ -222,24 +211,16 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  		if (pass != 0) {  			if (rpnt1 == NULL)  				break; -			if ((rpnt1->flags & RTLD_GLOBAL) == 0) -				continue; +			//if ((rpnt1->flags & RTLD_GLOBAL) == 0) +				//continue;  		}  		for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {  			tpnt = rpnt->dyn; -			/* -			 * The idea here is that if we are using dlsym, we want to -			 * first search the entire chain loaded from dlopen, and -			 * return a result from that if we found anything.  If this -			 * fails, then we continue the search into the stuff loaded -			 * when the image was activated.  For normal lookups, we start -			 * with rpnt == NULL, so we should never hit this.   -			 */ -			if (tpnt->libtype == elf_executable && weak_result != 0) { -				break; -			} +			/* Don't search the executable when resolving a copy reloc. */ +			if (tpnt->libtype == elf_executable && caller_type == copyrel) +				continue;  			/*  			 * Avoid calling .urem here. @@ -247,81 +228,35 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  			do_rem(hn, elf_hash_number, tpnt->nbucket);  			symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);  			strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); -			/* -			 * This crap is required because the first instance of a -			 * symbol on the chain will be used for all symbol references. -			 * Thus this instance must be resolved to an address that -			 * contains the actual function,  -			 */ - -			first_def = NULL; - -			for (si = tpnt->elf_buckets[hn]; si; si = tpnt->chains[si]) { -				pnt = strtab + symtab[si].st_name; - -				if (_dl_strcmp(pnt, name) == 0 && -				    symtab[si].st_value != 0) -				{ -				  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC || -				       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE || -				       ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) && -				      symtab[si].st_shndx != SHN_UNDEF) { - -					/* Here we make sure that we find a module where the symbol is -					 * actually defined. -					 */ - -					if (f_tpnt) { -						if (!first_def) -							first_def = tpnt; -						if (first_def == f_tpnt -							&& symtab[si].st_shndx == 0) -							continue; -					} -					switch (ELF32_ST_BIND(symtab[si].st_info)) { -					case STB_GLOBAL: -						if (tpnt->libtype != elf_executable &&  -							ELF32_ST_TYPE(symtab[si].st_info)  -							== STT_NOTYPE)  -						{	/* nakao */ -							data_result = (char *)tpnt->loadaddr +  -							    symtab[si].st_value;	/* nakao */ -							break;	/* nakao */ -						} else	/* nakao */ -							return (char*)tpnt->loadaddr + symtab[si].st_value; -					case STB_WEAK: -						if (!weak_result) -							weak_result = (char *)tpnt->loadaddr + symtab[si].st_value; -						break; -					default:	/* Do local symbols need to be examined? */ -						break; -					} -				  } -#ifndef __mips__ -				  /* -				   * References to the address of a function from an executable file and -				   * the shared objects associated with it might not resolve to the same -				   * value. To allow comparisons of function addresses we must resolve -				   * to the address of the plt entry of the executable instead of the -				   * real function address. -				   * see "TIS ELF Specification Version 1.2, Book 3, A-11 (Function -				   * Adresses)  -				   */				  -				  if (resolver != caller_type && -				      NULL==f_tpnt && /*trick: don't  handle R_??_JMP_SLOT reloc type*/ -				      tpnt->libtype == elf_executable && -				      ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC && -				      symtab[si].st_shndx == SHN_UNDEF) -				  { -				      return (char*)symtab[si].st_value; -				  } +			for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) { +				sym = &symtab[si]; + +				if (sym->st_value == 0) +					continue; +				if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC) +					continue; +				if (sym->st_shndx == SHN_UNDEF && caller_type != copyrel) +					continue; +				if (_dl_strcmp(strtab + sym->st_name, name) != 0) +					continue; + +				switch (ELF32_ST_BIND(sym->st_info)) { +				case STB_WEAK: +//Disable this to match current glibc behavior.  Of course, +//this doesn't actually work yet and will cause segfaults... +#if 1 +					if (!weak_result) +						weak_result = (char *)tpnt->loadaddr + sym->st_value; +					break;  #endif +				case STB_GLOBAL: +					return (char*)tpnt->loadaddr + sym->st_value; +				default:	/* Local symbols not handled here */ +					break;  				}  			}  		}  	} -	if (data_result) -		return data_result;		/* nakao */  	return weak_result;  } diff --git a/ldso/ldso/hash.c b/ldso/ldso/hash.c index 1eb7c5dd9..1e4acd979 100644 --- a/ldso/ldso/hash.c +++ b/ldso/ldso/hash.c @@ -1,12 +1,12 @@  /* vi: set sw=4 ts=4: */ -/* Program to load an ELF binary on a linux system, and run it +/* + * Program to load an ELF binary on a linux system, and run it   * after resolving ELF shared library symbols   * - * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,  + * Copyright (C) 2004 by Joakim Tjernlund <joakim.tjernlund@lumentis.se> + * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org> + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,   *				David Engel, Hongjiu Lu and Mitch D'Souza - * Copyright (C) 2001-2002, Erik Andersen - * - * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without   * modification, are permitted provided that the following conditions @@ -35,10 +35,9 @@  /*   * This is the start of the linked list that describes all of the files present - * in the system with pointers to all of the symbol, string, and hash tables,  + * in the system with pointers to all of the symbol, string, and hash tables,   * as well as all of the other good stuff in the binary.   */ -  struct elf_resolve *_dl_loaded_modules = NULL;  /* @@ -55,12 +54,9 @@ struct dyn_elf *_dl_symbol_tables = NULL;  struct dyn_elf *_dl_handles = NULL; -/* - * This is the hash function that is used by the ELF linker to generate - * the hash table that each executable and library is required to - * have.  We need it to decode the hash table. - */ - +/* This is the hash function that is used by the ELF linker to generate the + * hash table that each executable and library is required to have.  We need + * it to decode the hash table.  */  unsigned long _dl_elf_hash(const char *name)  {  	unsigned long hash = 0; @@ -75,9 +71,7 @@ unsigned long _dl_elf_hash(const char *name)  	return hash;  } -/* - * Check to see if a library has already been added to the hash chain. - */ +/* Check to see if a library has already been added to the hash chain.  */  struct elf_resolve *_dl_check_hashed_files(const char *libname)  {  	struct elf_resolve *tpnt; @@ -97,9 +91,8 @@ struct elf_resolve *_dl_check_hashed_files(const char *libname)   * We add the relevant info to the symbol chain, so that we can resolve all   * externals properly.   */ - -struct elf_resolve *_dl_add_elf_hash_table(const char *libname,  -	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,  +struct elf_resolve *_dl_add_elf_hash_table(const char *libname, +	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,  	unsigned long dynamic_size)  {  	unsigned long *hash_addr; @@ -107,8 +100,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,  	int i;  	if (!_dl_loaded_modules) { -		tpnt = _dl_loaded_modules =  -		    (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve)); +		tpnt = _dl_loaded_modules = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));  		_dl_memset(tpnt, 0, sizeof(struct elf_resolve));  	} else {  		tpnt = _dl_loaded_modules; @@ -161,21 +153,18 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,   * This function resolves externals, and this is either called when we process   * relocations or when we call an entry in the PLT table for the first time.   */ - -char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  +char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  	struct elf_resolve *f_tpnt, enum caller_type caller_type)  {  	struct elf_resolve *tpnt;  	int si; -	char *pnt;  	int pass;  	char *strtab;  	Elf32_Sym *symtab;  	unsigned long elf_hash_number, hn;  	char *weak_result; -	struct elf_resolve *first_def;  	struct dyn_elf *rpnt, first; -	char *data_result = 0;		/* nakao */ +	const ElfW(Sym) *sym;  	weak_result = 0;  	elf_hash_number = _dl_elf_hash(name); @@ -185,7 +174,7 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  	   that any shared library data symbols referenced in the executable  	   will be seen at the same address by the executable, shared libraries  	   and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */ -	if (_dl_symbol_tables && !caller_type && rpnt1) { +	if (_dl_symbol_tables && rpnt1) {  		first = (*_dl_symbol_tables);  		first.next = rpnt1;  		rpnt1 = (&first); @@ -222,24 +211,16 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  		if (pass != 0) {  			if (rpnt1 == NULL)  				break; -			if ((rpnt1->flags & RTLD_GLOBAL) == 0) -				continue; +			//if ((rpnt1->flags & RTLD_GLOBAL) == 0) +				//continue;  		}  		for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {  			tpnt = rpnt->dyn; -			/* -			 * The idea here is that if we are using dlsym, we want to -			 * first search the entire chain loaded from dlopen, and -			 * return a result from that if we found anything.  If this -			 * fails, then we continue the search into the stuff loaded -			 * when the image was activated.  For normal lookups, we start -			 * with rpnt == NULL, so we should never hit this.   -			 */ -			if (tpnt->libtype == elf_executable && weak_result != 0) { -				break; -			} +			/* Don't search the executable when resolving a copy reloc. */ +			if (tpnt->libtype == elf_executable && caller_type == copyrel) +				continue;  			/*  			 * Avoid calling .urem here. @@ -247,81 +228,35 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,  			do_rem(hn, elf_hash_number, tpnt->nbucket);  			symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);  			strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); -			/* -			 * This crap is required because the first instance of a -			 * symbol on the chain will be used for all symbol references. -			 * Thus this instance must be resolved to an address that -			 * contains the actual function,  -			 */ - -			first_def = NULL; - -			for (si = tpnt->elf_buckets[hn]; si; si = tpnt->chains[si]) { -				pnt = strtab + symtab[si].st_name; - -				if (_dl_strcmp(pnt, name) == 0 && -				    symtab[si].st_value != 0) -				{ -				  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC || -				       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE || -				       ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) && -				      symtab[si].st_shndx != SHN_UNDEF) { - -					/* Here we make sure that we find a module where the symbol is -					 * actually defined. -					 */ - -					if (f_tpnt) { -						if (!first_def) -							first_def = tpnt; -						if (first_def == f_tpnt -							&& symtab[si].st_shndx == 0) -							continue; -					} -					switch (ELF32_ST_BIND(symtab[si].st_info)) { -					case STB_GLOBAL: -						if (tpnt->libtype != elf_executable &&  -							ELF32_ST_TYPE(symtab[si].st_info)  -							== STT_NOTYPE)  -						{	/* nakao */ -							data_result = (char *)tpnt->loadaddr +  -							    symtab[si].st_value;	/* nakao */ -							break;	/* nakao */ -						} else	/* nakao */ -							return (char*)tpnt->loadaddr + symtab[si].st_value; -					case STB_WEAK: -						if (!weak_result) -							weak_result = (char *)tpnt->loadaddr + symtab[si].st_value; -						break; -					default:	/* Do local symbols need to be examined? */ -						break; -					} -				  } -#ifndef __mips__ -				  /* -				   * References to the address of a function from an executable file and -				   * the shared objects associated with it might not resolve to the same -				   * value. To allow comparisons of function addresses we must resolve -				   * to the address of the plt entry of the executable instead of the -				   * real function address. -				   * see "TIS ELF Specification Version 1.2, Book 3, A-11 (Function -				   * Adresses)  -				   */				  -				  if (resolver != caller_type && -				      NULL==f_tpnt && /*trick: don't  handle R_??_JMP_SLOT reloc type*/ -				      tpnt->libtype == elf_executable && -				      ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC && -				      symtab[si].st_shndx == SHN_UNDEF) -				  { -				      return (char*)symtab[si].st_value; -				  } +			for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) { +				sym = &symtab[si]; + +				if (sym->st_value == 0) +					continue; +				if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC) +					continue; +				if (sym->st_shndx == SHN_UNDEF && caller_type != copyrel) +					continue; +				if (_dl_strcmp(strtab + sym->st_name, name) != 0) +					continue; + +				switch (ELF32_ST_BIND(sym->st_info)) { +				case STB_WEAK: +//Disable this to match current glibc behavior.  Of course, +//this doesn't actually work yet and will cause segfaults... +#if 1 +					if (!weak_result) +						weak_result = (char *)tpnt->loadaddr + sym->st_value; +					break;  #endif +				case STB_GLOBAL: +					return (char*)tpnt->loadaddr + sym->st_value; +				default:	/* Local symbols not handled here */ +					break;  				}  			}  		}  	} -	if (data_result) -		return data_result;		/* nakao */  	return weak_result;  } | 
