diff options
-rw-r--r-- | include/elf.h | 7 | ||||
-rw-r--r-- | ldso/include/dl-string.h | 40 | ||||
-rw-r--r-- | ldso/include/ldso.h | 2 | ||||
-rw-r--r-- | ldso/ldso/dl-elf.c | 47 | ||||
-rw-r--r-- | ldso/ldso/dl-hash.c | 23 | ||||
-rw-r--r-- | ldso/ldso/dl-startup.c | 7 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 264 | ||||
-rw-r--r-- | ldso/libdl/libdl.c | 61 | ||||
-rw-r--r-- | utils/ldd.c | 20 | ||||
-rw-r--r-- | utils/readelf.c | 33 |
10 files changed, 252 insertions, 252 deletions
diff --git a/include/elf.h b/include/elf.h index 4ebe15c23..3e174bccf 100644 --- a/include/elf.h +++ b/include/elf.h @@ -120,6 +120,13 @@ typedef struct /* Conglomeration of the identification bytes, for easy testing as a word. */ #define ELFMAG "\177ELF" #define SELFMAG 4 +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define ELFMAG_U32 ((uint32_t)(ELFMAG0 + 0x100 * (ELFMAG1 + (0x100 * (ELFMAG2 + 0x100 * ELFMAG3))))) +#elif __BYTE_ORDER == __BIG_ENDIAN +# define ELFMAG_U32 ((uint32_t)((((ELFMAG0 * 0x100) + ELFMAG1) * 0x100 + ELFMAG2) * 0x100 + ELFMAG3)) +#else +# error Unknown host byte order! +#endif #define EI_CLASS 4 /* File class byte index */ #define ELFCLASSNONE 0 /* Invalid class */ diff --git a/ldso/include/dl-string.h b/ldso/include/dl-string.h index 746bd91c6..1a47e31ed 100644 --- a/ldso/include/dl-string.h +++ b/ldso/include/dl-string.h @@ -19,26 +19,26 @@ # define do_div_10(result, remain) ((result) /= 10) #endif -static size_t _dl_strlen(const char * str); +static size_t _dl_strlen(const char *str); static char *_dl_strcat(char *dst, const char *src); -static char * _dl_strcpy(char * dst,const char *src); -static int _dl_strcmp(const char * s1,const char * s2); -static int _dl_strncmp(const char * s1,const char * s2,size_t len); -static char * _dl_strchr(const char * str,int c); +static char *_dl_strcpy(char *dst, const char *src); +static int _dl_strcmp(const char *s1, const char *s2); +static int _dl_strncmp(const char *s1, const char *s2, size_t len); +static char *_dl_strchr(const char *str, int c); static char *_dl_strrchr(const char *str, int c); static char *_dl_strstr(const char *s1, const char *s2); -static void * _dl_memcpy(void * dst, const void * src, size_t len); -static int _dl_memcmp(const void * s1,const void * s2,size_t len); -static void *_dl_memset(void * str,int c,size_t len); +static void *_dl_memcpy(void *dst, const void *src, size_t len); +static int _dl_memcmp(const void *s1, const void *s2, size_t len); +static void *_dl_memset(void *str, int c, size_t len); static char *_dl_get_last_path_component(char *path); -static char *_dl_simple_ltoa(char * local, unsigned long i); -static char *_dl_simple_ltoahex(char * local, unsigned long i); +static char *_dl_simple_ltoa(char *local, unsigned long i); +static char *_dl_simple_ltoahex(char *local, unsigned long i); #ifndef NULL #define NULL ((void *) 0) #endif -static __always_inline size_t _dl_strlen(const char * str) +static __always_inline size_t _dl_strlen(const char *str) { register const char *ptr = (char *) str-1; while (*++ptr) @@ -59,7 +59,7 @@ static __always_inline char * _dl_strcat(char *dst, const char *src) return dst; } -static __always_inline char * _dl_strcpy(char * dst,const char *src) +static __always_inline char * _dl_strcpy(char *dst, const char *src) { register char *ptr = dst; @@ -70,7 +70,7 @@ static __always_inline char * _dl_strcpy(char * dst,const char *src) return ptr; } -static __always_inline int _dl_strcmp(const char * s1,const char * s2) +static __always_inline int _dl_strcmp(const char *s1, const char *s2) { register unsigned char c1, c2; s1--;s2--; @@ -84,7 +84,7 @@ static __always_inline int _dl_strcmp(const char * s1,const char * s2) return c1 - c2; } -static __always_inline int _dl_strncmp(const char * s1,const char * s2,size_t len) +static __always_inline int _dl_strncmp(const char *s1, const char *s2, size_t len) { register unsigned char c1 = '\0'; register unsigned char c2 = '\0'; @@ -100,7 +100,7 @@ static __always_inline int _dl_strncmp(const char * s1,const char * s2,size_t le return c1 - c2; } -static __always_inline char * _dl_strchr(const char * str,int c) +static __always_inline char * _dl_strchr(const char *str, int c) { register char ch; str--; @@ -147,7 +147,7 @@ static __always_inline char * _dl_strstr(const char *s1, const char *s2) } while (1); } -static __always_inline void * _dl_memcpy(void * dst, const void * src, size_t len) +static __always_inline void * _dl_memcpy(void *dst, const void *src, size_t len) { register char *a = dst-1; register const char *b = src-1; @@ -159,7 +159,7 @@ static __always_inline void * _dl_memcpy(void * dst, const void * src, size_t le return dst; } -static __always_inline int _dl_memcmp(const void * s1,const void * s2,size_t len) +static __always_inline int _dl_memcmp(const void *s1, const void *s2, size_t len) { unsigned char *c1 = (unsigned char *)s1-1; unsigned char *c2 = (unsigned char *)s2-1; @@ -200,7 +200,7 @@ lessthan4: return to; } #else -static __always_inline void * _dl_memset(void * str,int c,size_t len) +static __always_inline void * _dl_memset(void *str, int c, size_t len) { register char *a = str; @@ -232,7 +232,7 @@ static __always_inline char * _dl_get_last_path_component(char *path) /* Early on, we can't call printf, so use this to print out * numbers using the SEND_STDERR() macro. Avoid using mod * or using long division */ -static __always_inline char * _dl_simple_ltoa(char * local, unsigned long i) +static __always_inline char * _dl_simple_ltoa(char *local, unsigned long i) { /* 20 digits plus a null terminator should be good for * 64-bit or smaller ints (2^64 - 1)*/ @@ -247,7 +247,7 @@ static __always_inline char * _dl_simple_ltoa(char * local, unsigned long i) return p; } -static __always_inline char * _dl_simple_ltoahex(char * local, unsigned long i) +static __always_inline char * _dl_simple_ltoahex(char *local, unsigned long i) { /* 16 digits plus a leading "0x" plus a null terminator, * should be good for 64-bit or smaller ints */ diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index ec0663cea..df4a1d479 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -63,7 +63,7 @@ extern char *_dl_library_path; /* Where we look for libraries */ extern char *_dl_preload; /* Things to be loaded before the libs */ extern char *_dl_ldsopath; /* Where the shared lib loader was found */ extern const char *_dl_progname; /* The name of the executable being run */ -extern int _dl_secure; /* Are we dealing with setuid stuff? */ +//now static: extern int _dl_secure; /* Are we dealing with setuid stuff? */ extern size_t _dl_pagesize; /* Store the page size for use later */ #ifdef __SUPPORT_LD_DEBUG__ 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" diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index f914cf3be..8646a74d8 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -67,8 +67,7 @@ extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, in extern char *_dl_debug; #endif - -#else /* SHARED */ +#else /* !SHARED */ #define _dl_malloc malloc #define _dl_free free @@ -77,20 +76,20 @@ extern char *_dl_debug; * the symbols that otherwise would have been loaded in from ldso... */ #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; -int _dl_debug_file = 2; +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 = NULL; #endif const char *_dl_progname = ""; /* Program name */ void *(*_dl_malloc_function)(size_t); void (*_dl_free_function) (void *p); -char *_dl_library_path = 0; /* Where we look for libraries */ -char *_dl_ldsopath = 0; /* Location of the shared lib loader */ +char *_dl_library_path = NULL; /* Where we look for libraries */ +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 = PAGE_SIZE; /* Store the page size for use later */ /* This global variable is also to communicate with debuggers such as gdb. */ @@ -117,7 +116,7 @@ struct r_debug *_dl_debug_addr = NULL; static int do_dlclose(void *, int need_fini); -static const char *dl_error_names[] = { +static const char *const dl_error_names[] = { "", "File not found", "Unable to open /dev/zero", @@ -222,7 +221,8 @@ void *dlopen(const char *libname, int flag) tfrom = tpnt; } } - for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt=rpnt->next); + for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt = rpnt->next) + continue; relro_ptr = rpnt; now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0; @@ -265,18 +265,17 @@ void *dlopen(const char *libname, int flag) } } return dyn_chain; - } else { - tpnt->init_flag |= DL_OPENED; } + tpnt->init_flag |= DL_OPENED; + _dl_if_debug_print("Looking for needed libraries\n"); nlist = 0; runp = alloca(sizeof(*runp)); runp->tpnt = tpnt; runp->next = NULL; dep_list = runp2 = runp; - for (; runp; runp = runp->next) - { + for (; runp; runp = runp->next) { ElfW(Dyn) *dpnt; char *lpntstr; @@ -397,7 +396,6 @@ void *dlopen(const char *libname, int flag) } /* TODO: Should we set the protections of all pages back to R/O now ? */ - /* Notify the debugger we have added some objects. */ if (_dl_debug_addr) { dl_brk = (void (*)(void)) _dl_debug_addr->r_brk; @@ -453,10 +451,10 @@ void *dlsym(void *vhandle, const char *name) char *name2 = tmp_buf; size_t nlen = strlen (name) + 1; if (nlen + 1 > sizeof (tmp_buf)) - name2 = malloc (nlen + 1); + name2 = malloc (nlen + 1); if (name2 == 0) { - _dl_error_number = LD_ERROR_MMAP_FAILED; - return 0; + _dl_error_number = LD_ERROR_MMAP_FAILED; + return 0; } name2[0] = '_'; memcpy (name2 + 1, name, nlen); @@ -500,7 +498,7 @@ void *dlsym(void *vhandle, const char *name) } tpnt = NULL; if (handle == _dl_symbol_tables) - tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */ + tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */ ret = _dl_find_hash(name2, handle, tpnt, ELF_RTYPE_CLASS_DLSYM); /* @@ -566,8 +564,9 @@ static int do_dlclose(void *vhandle, int need_fini) if (--tpnt->usage_count == 0) { if ((tpnt->dynamic_info[DT_FINI] || tpnt->dynamic_info[DT_FINI_ARRAY]) - && need_fini && - !(tpnt->init_flag & FINI_FUNCS_CALLED)) { + && need_fini + && !(tpnt->init_flag & FINI_FUNCS_CALLED) + ) { tpnt->init_flag |= FINI_FUNCS_CALLED; _dl_run_fini_array(tpnt); @@ -600,8 +599,8 @@ static int do_dlclose(void *vhandle, int need_fini) _dl_loaded_modules = tpnt->next; if (_dl_loaded_modules) _dl_loaded_modules->prev = 0; - } else - for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) + } else { + for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) { if (run_tpnt->next == tpnt) { _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname); run_tpnt->next = run_tpnt->next->next; @@ -609,6 +608,8 @@ static int do_dlclose(void *vhandle, int need_fini) run_tpnt->next->prev = run_tpnt; break; } + } + } /* Next, remove tpnt from the global symbol table list */ if (_dl_symbol_tables) { @@ -616,7 +617,7 @@ static int do_dlclose(void *vhandle, int need_fini) _dl_symbol_tables = _dl_symbol_tables->next; if (_dl_symbol_tables) _dl_symbol_tables->prev = 0; - } else + } else { for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) { if (rpnt1->next->dyn == tpnt) { _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname); @@ -628,6 +629,7 @@ static int do_dlclose(void *vhandle, int need_fini) break; } } + } } free(tpnt->libname); free(tpnt); @@ -636,7 +638,6 @@ static int do_dlclose(void *vhandle, int need_fini) free(handle->init_fini.init_fini); free(handle); - if (_dl_debug_addr) { dl_brk = (void (*)(void)) _dl_debug_addr->r_brk; if (dl_brk != NULL) { @@ -671,7 +672,7 @@ char *dlerror(void) * Dump information to stderr about the current loaded modules */ #ifdef __USE_GNU -static char *type[] = { "Lib", "Exe", "Int", "Mod" }; +static const char type[][4] = { "Lib", "Exe", "Int", "Mod" }; int dlinfo(void) { diff --git a/utils/ldd.c b/utils/ldd.c index 17bab2079..289d163b2 100644 --- a/utils/ldd.c +++ b/utils/ldd.c @@ -238,31 +238,27 @@ static char *elf_find_rpath(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic) int check_elf_header(ElfW(Ehdr) *const ehdr) { - if (!ehdr || strncmp((char *)ehdr, ELFMAG, SELFMAG) != 0 || - ehdr->e_ident[EI_CLASS] != ELFCLASSM || - ehdr->e_ident[EI_VERSION] != EV_CURRENT) - { + if (!ehdr || *(uint32_t*)ehdr != ELFMAG_U32 + || ehdr->e_ident[EI_CLASS] != ELFCLASSM + || ehdr->e_ident[EI_VERSION] != EV_CURRENT + ) { return 1; } /* Check if the target endianness matches the host's endianness */ byteswap = 0; #if __BYTE_ORDER == __LITTLE_ENDIAN - if (ehdr->e_ident[5] == ELFDATA2MSB) { - /* Ick -- we will have to byte-swap everything */ + if (ehdr->e_ident[5] == ELFDATA2MSB) byteswap = 1; - } #elif __BYTE_ORDER == __BIG_ENDIAN - if (ehdr->e_ident[5] == ELFDATA2LSB) { - /* Ick -- we will have to byte-swap everything */ + if (ehdr->e_ident[5] == ELFDATA2LSB) byteswap = 1; - } #else #error Unknown host byte order! #endif - /* Be vary lazy, and only byteswap the stuff we use */ - if (byteswap == 1) { + /* Be very lazy, and only byteswap the stuff we use */ + if (byteswap) { ehdr->e_type = bswap_16(ehdr->e_type); ehdr->e_phoff = byteswap_to_host(ehdr->e_phoff); ehdr->e_shoff = byteswap_to_host(ehdr->e_shoff); diff --git a/utils/readelf.c b/utils/readelf.c index 2af4b5ca9..60f14a6bf 100644 --- a/utils/readelf.c +++ b/utils/readelf.c @@ -93,36 +93,33 @@ static void * elf_find_dynamic( int64_t const key, ElfW(Dyn) *dynp, static int check_elf_header(ElfW(Ehdr) *const ehdr) { - if (! ehdr || strncmp((void *)ehdr, ELFMAG, SELFMAG) != 0 || - (ehdr->e_ident[EI_CLASS] != ELFCLASS32 && - ehdr->e_ident[EI_CLASS] != ELFCLASS64) || - ehdr->e_ident[EI_VERSION] != EV_CURRENT) - { + if (!ehdr || *(uint32_t*)ehdr != ELFMAG_U32 + || (ehdr->e_ident[EI_CLASS] != ELFCLASS32 + && ehdr->e_ident[EI_CLASS] != ELFCLASS64) + || ehdr->e_ident[EI_VERSION] != EV_CURRENT + ) { return 1; } /* Check if the target endianness matches the host's endianness */ byteswap = 0; #if __BYTE_ORDER == __LITTLE_ENDIAN - if (ehdr->e_ident[5] == ELFDATA2MSB) { - /* Ick -- we will have to byte-swap everything */ + if (ehdr->e_ident[5] == ELFDATA2MSB) byteswap = 1; - } #elif __BYTE_ORDER == __BIG_ENDIAN - if (ehdr->e_ident[5] == ELFDATA2LSB) { + if (ehdr->e_ident[5] == ELFDATA2LSB) byteswap = 1; - } #else #error Unknown host byte order! #endif - /* Be vary lazy, and only byteswap the stuff we use */ - if (byteswap==1) { - ehdr->e_type=bswap_16(ehdr->e_type); - ehdr->e_machine=bswap_16(ehdr->e_machine); - ehdr->e_phoff=byteswap_to_host(ehdr->e_phoff); - ehdr->e_shoff=byteswap_to_host(ehdr->e_shoff); - ehdr->e_phnum=bswap_16(ehdr->e_phnum); - ehdr->e_shnum=bswap_16(ehdr->e_shnum); + /* Be very lazy, and only byteswap the stuff we use */ + if (byteswap) { + ehdr->e_type = bswap_16(ehdr->e_type); + ehdr->e_machine = bswap_16(ehdr->e_machine); + ehdr->e_phoff = byteswap_to_host(ehdr->e_phoff); + ehdr->e_shoff = byteswap_to_host(ehdr->e_shoff); + ehdr->e_phnum = bswap_16(ehdr->e_phnum); + ehdr->e_shnum = bswap_16(ehdr->e_shnum); } return 0; } |