diff options
| -rw-r--r-- | ldso/include/ldso.h | 1 | ||||
| -rw-r--r-- | ldso/ldso/dl-elf.c | 52 | ||||
| -rw-r--r-- | ldso/ldso/dl-hash.c | 4 | ||||
| -rw-r--r-- | ldso/ldso/ldso.c | 8 | ||||
| -rw-r--r-- | ldso/libdl/libdl.c | 3 | 
5 files changed, 54 insertions, 14 deletions
diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index 6c01cebc1..b415a5024 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -65,6 +65,7 @@ extern int   _dl_debug_file;  #endif  extern void *_dl_malloc(int size); +extern void _dl_free(void *);  extern char *_dl_getenv(const char *symbol, char **envp);  extern void _dl_unsetenv(const char *symbol, char **envp);  extern char *_dl_strdup(const char *string); diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index d27e4ccb3..7f0f76c35 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -31,6 +31,7 @@  #include "ldso.h" +void *(*_dl_malloc_function) (size_t size) = NULL;  #ifdef USE_CACHE @@ -405,7 +406,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	tpnt = _dl_check_hashed_files(libname);  	if (tpnt) {  		if (*rpnt) { -			(*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); +			(*rpnt)->next = (struct dyn_elf *) _dl_malloc_function(sizeof(struct dyn_elf));  			_dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));  			(*rpnt)->next->prev = (*rpnt);  			*rpnt = (*rpnt)->next; @@ -691,7 +692,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	 * Add this object into the symbol chain  	 */  	if (*rpnt) { -		(*rpnt)->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); +		(*rpnt)->next = (struct dyn_elf *) _dl_malloc_function(sizeof(struct dyn_elf));  		_dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));  		(*rpnt)->next->prev = (*rpnt);  		*rpnt = (*rpnt)->next; @@ -883,12 +884,21 @@ char *_dl_strdup(const char *string)  	int len;  	len = _dl_strlen(string); -	retval = _dl_malloc(len + 1); +	retval = _dl_malloc_function(len + 1);  	_dl_strcpy(retval, string);  	return retval;  } -void *(*_dl_malloc_function) (size_t size) = NULL; +union __align_type +{ +  void *p; +  void (*fp)(void); +  long long ll; +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +  double d; +#endif +}; +  void *_dl_malloc(int size)  {  	void *retval; @@ -902,11 +912,29 @@ void *_dl_malloc(int size)  	if (_dl_malloc_function)  		return (*_dl_malloc_function) (size); -	if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) { +	if ((int)(_dl_malloc_addr - _dl_mmap_zero + size) > (int)_dl_pagesize) { +		int rounded_size; + +		/* Since the above assumes we get a full page even if +		   we request less than that, make sure we request a +		   full page, since uClinux may give us less than than +		   a full page.  We might round even +		   larger-than-a-page sizes, but we end up never +		   reusing _dl_mmap_zero/_dl_malloc_addr in that case, +		   so we don't do it. + +		   The actual page size doesn't really matter; as long +		   as we're self-consistent here, we're safe.  */ +		if (size < (int)_dl_pagesize) +			rounded_size = (size + _dl_pagesize - 1) & _dl_pagesize; +		else +			rounded_size = size; + +  #ifdef __SUPPORT_LD_DEBUG_EARLY__  		_dl_dprintf(2, "malloc: mmapping more memory\n");  #endif -		_dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size, +		_dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size,  				PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);  		if (_dl_mmap_check_error(_dl_mmap_zero)) {  			_dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname); @@ -920,8 +948,16 @@ void *_dl_malloc(int size)  	 * Align memory to 4 byte boundary.  Some platforms require this, others  	 * simply get better performance.  	 */ -	_dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + 3) & ~(3)); +	_dl_malloc_addr = (unsigned char *) +		(((unsigned long) _dl_malloc_addr + +		  __alignof__(union __align_type) - 1) +		 & ~(__alignof__(union __align_type) - 1));  	return retval;  } - +void (*_dl_free_function) (void *p) = NULL; +void +_dl_free (void *p) { +	if (_dl_free_function) +		(*_dl_free_function) (p); +} diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 251ab6466..c6d4f1233 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -100,13 +100,13 @@ 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_function(sizeof(struct elf_resolve));  		_dl_memset(tpnt, 0, sizeof(struct elf_resolve));  	} else {  		tpnt = _dl_loaded_modules;  		while (tpnt->next)  			tpnt = tpnt->next; -		tpnt->next = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve)); +		tpnt->next = (struct elf_resolve *) _dl_malloc_function(sizeof(struct elf_resolve));  		_dl_memset(tpnt->next, 0, sizeof(struct elf_resolve));  		tpnt->next->prev = tpnt;  		tpnt = tpnt->next; diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 9b7c7380e..1af167985 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -191,7 +191,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt  			_dl_loaded_modules->libtype = elf_executable;  			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;  			_dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val; -			_dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); +			_dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc_function(sizeof(struct dyn_elf));  			_dl_memset(rpnt, 0, sizeof(struct dyn_elf));  			rpnt->dyn = _dl_loaded_modules;  			app_tpnt->usage_count++; @@ -296,7 +296,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt  			len1 = _dl_strlen(dl_debug_output);  			len2 = _dl_strlen(tmp1); -			filename = _dl_malloc(len1+len2+2); +			filename = _dl_malloc_function(len1+len2+2);  			if (filename)  			{ @@ -563,12 +563,12 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt  			tpnt->prev = NULL;  		}  		if (rpnt) { -			rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); +			rpnt->next = (struct dyn_elf *) _dl_malloc_function(sizeof(struct dyn_elf));  			_dl_memset(rpnt->next, 0, sizeof(struct dyn_elf));  			rpnt->next->prev = rpnt;  			rpnt = rpnt->next;  		} else { -			rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); +			rpnt = (struct dyn_elf *) _dl_malloc_function(sizeof(struct dyn_elf));  			_dl_memset(rpnt, 0, sizeof(struct dyn_elf));  		}  		rpnt->dyn = tpnt; diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index ca39473f1..d7cbed733 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -54,6 +54,7 @@ extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__));  extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__));  extern unsigned long _dl_error_number __attribute__ ((__weak__));  extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__)); +extern void (*_dl_free_function) (void *p) __attribute__ ((__weak__));  #ifdef USE_CACHE  int _dl_map_cache(void) __attribute__ ((__weak__));  int _dl_unmap_cache(void) __attribute__ ((__weak__)); @@ -95,6 +96,7 @@ struct r_debug *_dl_debug_addr = NULL;  static unsigned char *_dl_malloc_addr, *_dl_mmap_zero;  void *(*_dl_malloc_function) (size_t size);  int _dl_errno = 0; +void (*_dl_free_function) (void *p);  int _dl_fixup(struct dyn_elf *rpnt, int lazy);  #include "../ldso/dl-progname.h"               /* Pull in the name of ld.so */  #include "../ldso/dl-hash.c" @@ -164,6 +166,7 @@ void *_dlopen(const char *libname, int flag)  	if (!dl_init) {  		dl_init++;  		_dl_malloc_function = malloc; +		_dl_free_function = free;  	}  	/* Cover the trivial case first */  | 
