From 27d501fdbf0c6932e6170e8dece4d178d912bf94 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sat, 10 Jan 2009 21:02:48 +0000 Subject: simple optimizations and style fixes in dynamic loading text data bss dec hex filename - 16709 240 92 17041 4291 lib/ld-uClibc.so + 16634 236 92 16962 4242 lib/ld-uClibc.so - 4602 344 4 4950 1356 lib/libdl-0.9.30-svn.so + 4571 328 4 4903 1327 lib/libdl-0.9.30-svn.so - 4602 344 4 4950 1356 lib/libdl.so + 4571 328 4 4903 1327 lib/libdl.so --- ldso/ldso/dl-elf.c | 47 +++++---- ldso/ldso/dl-hash.c | 23 ++--- ldso/ldso/dl-startup.c | 7 +- ldso/ldso/ldso.c | 264 +++++++++++++++++++++++++------------------------ 4 files changed, 170 insertions(+), 171 deletions(-) (limited to 'ldso/ldso') diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index ecaaa552c..5f59162a7 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -272,13 +272,14 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE); for (i = 0; i < header->nlibs; i++) { - if ((libent[i].flags == LIB_ELF || - libent[i].flags == LIB_ELF_LIBC0 || - libent[i].flags == LIB_ELF_LIBC5) && - _dl_strcmp(libname, strs + libent[i].sooffset) == 0 && - (tpnt1 = _dl_load_elf_shared_library(secure, - rpnt, strs + libent[i].liboffset))) + if ((libent[i].flags == LIB_ELF + || libent[i].flags == LIB_ELF_LIBC0 + || libent[i].flags == LIB_ELF_LIBC5) + && _dl_strcmp(libname, strs + libent[i].sooffset) == 0 + && (tpnt1 = _dl_load_elf_shared_library(secure, rpnt, strs + libent[i].liboffset)) + ) { return tpnt1; + } } } #endif @@ -286,26 +287,22 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, /* Look for libraries wherever the shared library loader * was installed */ _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath); - if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) - { + tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt); + if (tpnt1 != NULL) return tpnt1; - } - /* Lastly, search the standard list of paths for the library. This list must exactly match the list in uClibc/ldso/util/ldd.c */ _dl_if_debug_dprint("\tsearching full lib path list\n"); - if ((tpnt1 = search_for_named_library(libname, secure, + tpnt1 = search_for_named_library(libname, secure, UCLIBC_RUNTIME_PREFIX "lib:" UCLIBC_RUNTIME_PREFIX "usr/lib" #ifndef __LDSO_CACHE_SUPPORT__ ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib" #endif - , rpnt) - ) != NULL) - { + , rpnt); + if (tpnt1 != NULL) return tpnt1; - } goof: /* Well, we shot our wad on that one. All we can do now is punt */ @@ -358,11 +355,12 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, } /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), we don't load the library if it isn't setuid. */ - if (secure) + if (secure) { if (!(st.st_mode & S_ISUID)) { _dl_close(infile); return NULL; } + } /* Check if file is already loaded */ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { @@ -384,11 +382,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, _dl_read(infile, header, _dl_pagesize); epnt = (ElfW(Ehdr) *) (intptr_t) header; - if (epnt->e_ident[0] != 0x7f || - epnt->e_ident[1] != 'E' || - epnt->e_ident[2] != 'L' || - epnt->e_ident[3] != 'F') - { + if (*((uint32_t*) &epnt->e_ident) != ELFMAG_U32) { _dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname, libname); _dl_internal_error_number = LD_ERROR_NOTELF; @@ -688,14 +682,17 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__ ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; for (i = 0; i < epnt->e_phnum; i++, ppnt++) { - if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) + if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) { _dl_mprotect((void *) ((piclib ? libaddr : 0) + (ppnt->p_vaddr & PAGE_ALIGN)), (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC); + } } #else - _dl_dprintf(_dl_debug_file, "Can't modify %s's text section. Use GCC option -fPIC for shared objects, please.\n",libname); + _dl_dprintf(_dl_debug_file, "Can't modify %s's text section." + " Use GCC option -fPIC for shared objects, please.\n", + libname); _dl_exit(1); #endif } @@ -713,7 +710,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 = _dl_malloc(sizeof(struct dyn_elf)); _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf)); (*rpnt)->next->prev = (*rpnt); *rpnt = (*rpnt)->next; @@ -724,7 +721,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, * and initialize the _dl_symbol_table. */ else { - *rpnt = _dl_symbol_tables = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); + *rpnt = _dl_symbol_tables = _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(*rpnt, 0, sizeof(struct dyn_elf)); } #endif diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index a251aaff3..4809c4348 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -95,17 +95,18 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, struct elf_resolve *tpnt; int i; - if (!_dl_loaded_modules) { - 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; - while (tpnt->next) - tpnt = tpnt->next; - tpnt->next = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve)); - _dl_memset(tpnt->next, 0, sizeof(struct elf_resolve)); - tpnt->next->prev = tpnt; - tpnt = tpnt->next; + tpnt = _dl_malloc(sizeof(struct elf_resolve)); + _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); + + if (!_dl_loaded_modules) + _dl_loaded_modules = tpnt; + else { + struct elf_resolve *t = _dl_loaded_modules; + while (t->next) + t = t->next; + t->next = tpnt; + t->next->prev = t; + tpnt = t->next; } tpnt->next = NULL; diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index efd02da46..6b69c7498 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -176,11 +176,8 @@ DL_START(unsigned long args) /* Do not use an inline _dl_strncmp here or some arches * will blow chunks, i.e. those that need to relocate all * string constants... */ - || header->e_ident[EI_MAG0] != ELFMAG0 - || header->e_ident[EI_MAG1] != ELFMAG1 - || header->e_ident[EI_MAG2] != ELFMAG2 - || header->e_ident[EI_MAG3] != ELFMAG3) - { + || *((uint32_t*) &header->e_ident) != ELFMAG_U32 + ) { SEND_EARLY_STDERR("Invalid ELF header\n"); _dl_exit(0); } diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index f631fd983..4dcd99bfe 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -42,24 +42,25 @@ #include LDSO_ELFINTERP /* Global variables used within the shared library loader */ -char *_dl_library_path = 0; /* Where we look for libraries */ -char *_dl_preload = 0; /* Things to be loaded before the libs */ -char *_dl_ldsopath = 0; /* Location of the shared lib loader */ -int _dl_secure = 1; /* Are we dealing with setuid stuff? */ +char *_dl_library_path = NULL; /* Where we look for libraries */ +char *_dl_preload = NULL; /* Things to be loaded before the libs */ +char *_dl_ldsopath = NULL; /* Location of the shared lib loader */ int _dl_errno = 0; /* We can't use the real errno in ldso */ size_t _dl_pagesize = 0; /* Store the page size for use later */ struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */ void *(*_dl_malloc_function) (size_t size) = NULL; void (*_dl_free_function) (void *p) = NULL; +static int _dl_secure = 1; /* Are we dealing with setuid stuff? */ + #ifdef __SUPPORT_LD_DEBUG__ -char *_dl_debug = 0; -char *_dl_debug_symbols = 0; -char *_dl_debug_move = 0; -char *_dl_debug_reloc = 0; -char *_dl_debug_detail = 0; -char *_dl_debug_nofixups = 0; -char *_dl_debug_bindings = 0; +char *_dl_debug = NULL; +char *_dl_debug_symbols = NULL; +char *_dl_debug_move = NULL; +char *_dl_debug_reloc = NULL; +char *_dl_debug_detail = NULL; +char *_dl_debug_nofixups = NULL; +char *_dl_debug_bindings = NULL; int _dl_debug_file = 2; #endif @@ -69,8 +70,6 @@ const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being #include "dl-startup.c" #include "dl-symbols.c" #include "dl-array.c" -/* Forward function declarations */ -static int _dl_suid_ok(void); /* * This stub function is used by some debuggers. The idea is that they @@ -88,8 +87,8 @@ void _dl_debug_state(void) } rtld_hidden_def(_dl_debug_state); -static unsigned char *_dl_malloc_addr = 0; /* Lets _dl_malloc use the already allocated memory page */ -static unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */ +static unsigned char *_dl_malloc_addr = NULL; /* Lets _dl_malloc use the already allocated memory page */ +static unsigned char *_dl_mmap_zero = NULL; /* Also used by _dl_malloc */ static struct elf_resolve **init_fini_list; static unsigned int nlist; /* # items in init_fini_list */ @@ -110,6 +109,118 @@ uintptr_t __guard attribute_relro; # endif #endif +char *_dl_getenv(const char *symbol, char **envp) +{ + char *pnt; + const char *pnt1; + + while ((pnt = *envp++)) { + pnt1 = symbol; + while (*pnt && *pnt == *pnt1) + pnt1++, pnt++; + if (!*pnt || *pnt != '=' || *pnt1) + continue; + return pnt + 1; + } + return 0; +} + +void _dl_unsetenv(const char *symbol, char **envp) +{ + char *pnt; + const char *pnt1; + char **newenvp = envp; + + for (pnt = *envp; pnt; pnt = *++envp) { + pnt1 = symbol; + while (*pnt && *pnt == *pnt1) + pnt1++, pnt++; + if (!*pnt || *pnt != '=' || *pnt1) + *newenvp++ = *envp; + } + *newenvp++ = *envp; + return; +} + +static int _dl_suid_ok(void) +{ + __kernel_uid_t uid, euid; + __kernel_gid_t gid, egid; + + uid = _dl_getuid(); + euid = _dl_geteuid(); + gid = _dl_getgid(); + egid = _dl_getegid(); + + if (uid == euid && gid == egid) { + return 1; + } + return 0; +} + +void *_dl_malloc(size_t size) +{ + void *retval; + +#if 0 + _dl_debug_early("request for %d bytes\n", size); +#endif + + if (_dl_malloc_function) + return (*_dl_malloc_function) (size); + + if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) { + size_t 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 < _dl_pagesize) + rounded_size = (size + ADDR_ALIGN) & _dl_pagesize; + else + rounded_size = size; + + _dl_debug_early("mmapping more memory\n"); + _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(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname); + _dl_exit(20); + } + } + retval = _dl_malloc_addr; + _dl_malloc_addr += size; + + /* + * Align memory to DL_MALLOC_ALIGN byte boundary. Some + * platforms require this, others simply get better + * performance. + */ + _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1)); + return retval; +} + +static void *_dl_zalloc(size_t size) +{ + void *p = _dl_malloc(size); + if (p) + _dl_memset(p, 0, size); + return p; +} + +void _dl_free (void *p) +{ + if (_dl_free_function) + (*_dl_free_function) (p); +} + static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void) { unsigned int i; @@ -158,7 +269,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, * setup so we can use _dl_dprintf() to print debug noise * instead of the SEND_STDERR macros used in dl-startup.c */ - _dl_memset(app_tpnt, 0x00, sizeof(*app_tpnt)); + _dl_memset(app_tpnt, 0, sizeof(*app_tpnt)); /* Store the page size for later use */ _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; @@ -219,7 +330,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, do { _dl_unsetenv (nextp, envp); /* We could use rawmemchr but this need not be fast. */ - nextp = (char *) _dl_strchr(nextp, '\0') + 1; + nextp = _dl_strchr(nextp, '\0') + 1; } while (*nextp != '\0'); _dl_preload = NULL; _dl_library_path = NULL; @@ -269,8 +380,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, * This is used by gdb to locate the chain of shared libraries that are * currently loaded. */ - debug_addr = _dl_malloc(sizeof(struct r_debug)); - _dl_memset(debug_addr, 0, sizeof(struct r_debug)); + debug_addr = _dl_zalloc(sizeof(struct r_debug)); ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { @@ -324,7 +434,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, _dl_loaded_modules->libtype = elf_executable; _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; _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 = _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); rpnt->dyn = _dl_loaded_modules; app_tpnt->mapaddr = app_mapaddr; @@ -389,14 +499,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, len1 = _dl_strlen(dl_debug_output); len2 = _dl_strlen(tmp1); - filename = _dl_malloc(len1+len2+2); + filename = _dl_malloc(len1 + len2 + 2); if (filename) { _dl_strcpy (filename, dl_debug_output); filename[len1] = '.'; _dl_strcpy (&filename[len1+1], tmp1); - _dl_debug_file= _dl_open(filename, O_WRONLY|O_CREAT, 0644); + _dl_debug_file = _dl_open(filename, O_WRONLY|O_CREAT, 0644); if (_dl_debug_file < 0) { _dl_debug_file = 2; _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename); @@ -711,13 +821,11 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, tpnt->usage_count++; tpnt->symbol_scope = _dl_symbol_tables; if (rpnt) { - rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); - _dl_memset(rpnt->next, 0, sizeof(struct dyn_elf)); + rpnt->next = _dl_zalloc(sizeof(struct dyn_elf)); rpnt->next->prev = rpnt; rpnt = rpnt->next; } else { - rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); - _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); + rpnt = _dl_zalloc(sizeof(struct dyn_elf)); } rpnt->dyn = tpnt; tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */ @@ -840,109 +948,5 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, _dl_debug_state(); } -char *_dl_getenv(const char *symbol, char **envp) -{ - char *pnt; - const char *pnt1; - - while ((pnt = *envp++)) { - pnt1 = symbol; - while (*pnt && *pnt == *pnt1) - pnt1++, pnt++; - if (!*pnt || *pnt != '=' || *pnt1) - continue; - return pnt + 1; - } - return 0; -} - -void _dl_unsetenv(const char *symbol, char **envp) -{ - char *pnt; - const char *pnt1; - char **newenvp = envp; - - for (pnt = *envp; pnt; pnt = *++envp) { - pnt1 = symbol; - while (*pnt && *pnt == *pnt1) - pnt1++, pnt++; - if (!*pnt || *pnt != '=' || *pnt1) - *newenvp++ = *envp; - } - *newenvp++ = *envp; - return; -} - -static int _dl_suid_ok(void) -{ - __kernel_uid_t uid, euid; - __kernel_gid_t gid, egid; - - uid = _dl_getuid(); - euid = _dl_geteuid(); - gid = _dl_getgid(); - egid = _dl_getegid(); - - if (uid == euid && gid == egid) { - return 1; - } - return 0; -} - -void *_dl_malloc(size_t size) -{ - void *retval; - -#if 0 - _dl_debug_early("request for %d bytes\n", size); -#endif - - if (_dl_malloc_function) - return (*_dl_malloc_function) (size); - - if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) { - size_t 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 < _dl_pagesize) - rounded_size = (size + ADDR_ALIGN) & _dl_pagesize; - else - rounded_size = size; - - _dl_debug_early("mmapping more memory\n"); - _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(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname); - _dl_exit(20); - } - } - retval = _dl_malloc_addr; - _dl_malloc_addr += size; - - /* - * Align memory to DL_MALLOC_ALIGN byte boundary. Some - * platforms require this, others simply get better - * performance. - */ - _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1)); - return retval; -} - -void _dl_free (void *p) -{ - if (_dl_free_function) - (*_dl_free_function) (p); -} - #include "dl-hash.c" #include "dl-elf.c" -- cgit v1.2.3