diff options
-rw-r--r-- | ldso/Makefile | 7 | ||||
-rw-r--r-- | ldso/Rules.mak | 5 | ||||
-rw-r--r-- | ldso/ldso/Makefile | 11 | ||||
-rw-r--r-- | ldso/ldso/boot1.c | 220 | ||||
-rw-r--r-- | ldso/ldso/hash.h | 10 | ||||
-rw-r--r-- | ldso/ldso/i386/dl-sysdep.h | 5 | ||||
-rw-r--r-- | ldso/ldso/i386/ld_sysdep.h | 5 | ||||
-rw-r--r-- | ldso/ldso/i386/sysdep.h | 5 | ||||
-rw-r--r-- | ldso/ldso/ld-uClibc.c | 220 | ||||
-rw-r--r-- | ldso/ldso/ld_hash.h | 10 | ||||
-rw-r--r-- | ldso/ldso/ld_string.h | 90 | ||||
-rw-r--r-- | ldso/ldso/ld_syscall.h | 2 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 220 | ||||
-rw-r--r-- | ldso/ldso/m68k/dl-sysdep.h | 4 | ||||
-rw-r--r-- | ldso/ldso/m68k/ld_sysdep.h | 4 | ||||
-rw-r--r-- | ldso/ldso/m68k/sysdep.h | 4 | ||||
-rw-r--r-- | ldso/ldso/sparc/dl-sysdep.h | 6 | ||||
-rw-r--r-- | ldso/ldso/sparc/ld_sysdep.h | 6 | ||||
-rw-r--r-- | ldso/ldso/sparc/sysdep.h | 6 | ||||
-rw-r--r-- | ldso/ldso/string.h | 90 | ||||
-rw-r--r-- | ldso/ldso/syscall.h | 2 | ||||
-rw-r--r-- | ldso/libdl/Makefile | 4 | ||||
-rw-r--r-- | ldso/util/Makefile | 2 |
23 files changed, 716 insertions, 222 deletions
diff --git a/ldso/Makefile b/ldso/Makefile index 9fb609c6d..f26489eee 100644 --- a/ldso/Makefile +++ b/ldso/Makefile @@ -1,7 +1,8 @@ TOPDIR=../ -include Rules.mak +include $(TOPDIR)Rules.mak -SUBDIRS = util libdl # d-link man +SUBDIRS = util libdl +ALL_SUBDIRS = util libdl d-link all: @if [ -d $(TOPDIR)ldso/d-link/$(TARGET_ARCH) ] ; then \ @@ -14,5 +15,5 @@ shared: fi; clean: - set -e ; for d in $(SUBDIRS) ; do $(MAKE) -C $$d $@ ; done + set -e ; for d in $(ALL_SUBDIRS) ; do $(MAKE) -C $$d $@ ; done -find . -name '*~' | xargs rm -f diff --git a/ldso/Rules.mak b/ldso/Rules.mak deleted file mode 100644 index b45e2df80..000000000 --- a/ldso/Rules.mak +++ /dev/null @@ -1,5 +0,0 @@ -include $(TOPDIR)Rules.mak - -# Do NOT use -fomit-frame-pointer -- It won't work! -CFLAGS += -DUCLIBC_ROOT_DIR=\"$(ROOT_DIR)\" -CC = $(TOPDIR)extra/gcc-uClibc/$(TARGET_ARCH)-uclibc-gcc diff --git a/ldso/ldso/Makefile b/ldso/ldso/Makefile index d69823c9c..d9efabcaa 100644 --- a/ldso/ldso/Makefile +++ b/ldso/ldso/Makefile @@ -22,7 +22,7 @@ TOPDIR=../../ -include $(TOPDIR)/ldso/Rules.mak +include $(TOPDIR)Rules.mak LDSO_FULLNAME=ld-uclibc-$(MAJOR_VERSION).$(MINOR_VERSION).so @@ -34,7 +34,10 @@ AOBJS=$(patsubst %.S,%.o, $(ASRC)) OBJS=$(AOBJS) $(COBJS) -CFLAGS += -DUSE_CACHE -fPIC -D__PIC__ #-DDL_DEBUG #-funroll-loops +CFLAGS=-Wall -Os -fPIC -D__PIC__ --uclibc-use-build-dir -I. -DUCLIBC_ROOT_DIR=\"$(ROOT_DIR)\" +CC = $(TOPDIR)extra/gcc-uClibc/$(NATIVE_ARCH)-uclibc-gcc + +CFLAGS += #-DDL_DEBUG #-funroll-loops all: lib @@ -45,8 +48,8 @@ lib:: ld.so.h $(OBJS) $(DLINK_OBJS) install -m 755 $(LDSO_FULLNAME) $(TOPDIR)lib; \ (cd $(TOPDIR)lib;ln -sf $(LDSO_FULLNAME) $(UCLIBC_LDSO)); -ld.so.h: - echo "char *_dl_progname = \""$(UCLIBC_LDSO)"\";" > ld.so.h +ld.so.h: Makefile + echo "#define _dl_static_progname \""$(UCLIBC_LDSO)"\"" > ld.so.h $(COBJS): %.o : %.c $(CC) -I. -I./$(TARGET_ARCH) -I../libdl $(CFLAGS) -c $< -o $@ diff --git a/ldso/ldso/boot1.c b/ldso/ldso/boot1.c index 52c9bcb4e..1da2b3466 100644 --- a/ldso/ldso/boot1.c +++ b/ldso/ldso/boot1.c @@ -112,22 +112,11 @@ */ #define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3)) -#define ELF_HASH(RESULT,NAME) { \ - unsigned long hash = 0; \ - unsigned long tmp; \ - char * name = NAME; \ - while (*name){ \ - hash = (hash << 4) + *name++; \ - if((tmp = hash & 0xf0000000)) hash ^= tmp >> 24; \ - hash &= ~tmp; \ - } \ - RESULT = hash; \ -} - static char *_dl_malloc_addr, *_dl_mmap_zero; char *_dl_library_path = 0; /* Where we look for libraries */ char *_dl_preload = 0; /* Things to be loaded before the libs. */ #include "ld.so.h" /* Pull in the name of ld.so */ +const char *_dl_progname=_dl_static_progname; static char *_dl_not_lazy = 0; static char *_dl_warn = 0; /* Used by ldd */ static char *_dl_trace_loaded_objects = 0; @@ -180,9 +169,14 @@ void _dl_boot(unsigned int args) int indx; int _dl_secure; + + /* WARNING! -- we cannot make _any_ funtion calls until we have + * taken care of fixing up our own relocations. Making static + * lnline calls is ok, but _no_ function calls. Not yet + * anyways. */ + /* First obtain the information on the stack that tells us more about what binary is loaded, where it is loaded, etc, etc */ - GET_ARGV(aux_dat, args); argc = *(aux_dat - 1); argv = (char **) aux_dat; @@ -193,7 +187,7 @@ void _dl_boot(unsigned int args) aux_dat++; /* Skip over the envp pointers */ aux_dat++; /* Skip over NULL at end of envp */ - /* Place -1 here as a checkpoint. We check later to see if it got changed + /* Place -1 here as a checkpoint. We check later to see if it was changed * when we read in the auxv_t */ auxv_t[AT_UID].a_type = -1; @@ -205,35 +199,92 @@ void _dl_boot(unsigned int args) Elf32_auxv_t *auxv_entry = (Elf32_auxv_t*) aux_dat; if (auxv_entry->a_type <= AT_EGID) { - _dl_memcpy(&(auxv_t[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t)); + _dl_memcpy_inline(&(auxv_t[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t)); } aux_dat += 2; } - - /* Next, locate the GOT */ + + /* locate the ELF header. We need this done as easly as possible + * (esp since SEND_STDERR() needs this on some platforms... */ load_addr = auxv_t[AT_BASE].a_un.a_val; - if (load_addr == 0x0) { - /* Looks like they decided to run ld-linux-uclibc.so as - * an executable. Exit gracefully for now. */ - - /* TODO -- actually accept executables and args to run... */ - //SEND_STDERR("Usage: ld.so EXECUTABLE [ARGS...]\n"); - SEND_STDERR("You have run `ld.so', the helper program for shared\n"); - SEND_STDERR("library executables. You probably did not intend to\n"); - SEND_STDERR("run this as a program. Goodbye.\n\n"); + header = (elfhdr *) auxv_t[AT_BASE].a_un.a_ptr; + + /* check the ELF header to make sure everything looks ok. */ + if (! header || header->e_ident[EI_CLASS] != ELFCLASS32 || + header->e_ident[EI_VERSION] != EV_CURRENT || + _dl_strncmp_inline((void *)header, ELFMAG, SELFMAG) != 0) + { + SEND_STDERR("invalid ELF header\n"); _dl_exit(0); } #ifdef DL_DEBUG - SEND_STDERR("load_addr="); + SEND_STDERR("ELF header ="); SEND_STDERR(_dl_simple_ltoahex(load_addr)); SEND_STDERR("\n"); #endif - GET_GOT(got); + + + /* Locate the global offset table. Since this code must be PIC + * we can take advantage of the magic offset register, if we + * happen to know what that is for this architecture. If not, + * we can always read stuff out of the ELF file to fine it... */ +#if defined(__i386__) + __asm__("\tmovl %%ebx,%0\n\t" : "=a" (got)); +#elif defined(__m68k__) + __asm__ ("movel %%a5,%0" : "=g" (got)) +#elif defined(__sparc__) + __asm__("\tmov %%l7,%0\n\t" : "=r" (got)) +#else + /* Do things the slow way in C */ + { + unsigned long tx_reloc; + Elf32_Dyn *dynamic=NULL; + Elf32_Shdr *shdr; + Elf32_Phdr *pt_load; + #ifdef DL_DEBUG - SEND_STDERR("Found got="); - SEND_STDERR(_dl_simple_ltoahex((unsigned long)*got)); - SEND_STDERR("\n"); + SEND_STDERR("Finding the got using C code to read the ELF file\n"); #endif + /* Find where the dynamic linking information section is hiding */ + shdr = (Elf32_Shdr *)(header->e_shoff + (char *)header); + for (indx = header->e_shnum; --indx>=0; ++shdr) { + if (shdr->sh_type == SHT_DYNAMIC) { + goto found_dynamic; + } + } + SEND_STDERR("missing dynamic linking information section \n"); + _dl_exit(0); + +found_dynamic: + dynamic = (Elf32_Dyn*)(shdr->sh_offset + (char *)header); + + /* Find where PT_LOAD is hiding */ + pt_load = (Elf32_Phdr *)(header->e_phoff + (char *)header); + for (indx = header->e_phnum; --indx>=0; ++pt_load) { + if (pt_load->p_type == PT_LOAD) { + goto found_pt_load; + } + } + SEND_STDERR("missing loadable program segment\n"); + _dl_exit(0); + +found_pt_load: + /* Now (finally) find where DT_PLTGOT is hiding */ + tx_reloc = pt_load->p_vaddr - pt_load->p_offset; + for (; DT_NULL!=dynamic->d_tag; ++dynamic) { + if (dynamic->d_tag == DT_PLTGOT) { + goto found_got; + } + } + SEND_STDERR("missing global offset table\n"); + _dl_exit(0); + +found_got: + got = (unsigned long *)(dynamic->d_un.d_val - tx_reloc + (char *)header ); + } +#endif + + /* Now, finally, fix up the location of the dynamic stuff */ dpnt = (Elf32_Dyn *) (*got + load_addr); #ifdef DL_DEBUG SEND_STDERR("First Dynamic section entry="); @@ -252,15 +303,15 @@ void _dl_boot(unsigned int args) } tpnt = DL_MALLOC(sizeof(struct elf_resolve)); - _dl_memset(tpnt, 0, sizeof(*tpnt)); + _dl_memset_inline(tpnt, 0, sizeof(*tpnt)); app_tpnt = DL_MALLOC(sizeof(struct elf_resolve)); - _dl_memset(app_tpnt, 0, sizeof(*app_tpnt)); + _dl_memset_inline(app_tpnt, 0, sizeof(*app_tpnt)); /* * 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(*debug_addr)); + _dl_memset_inline(debug_addr, 0, sizeof(*debug_addr)); /* OK, that was easy. Next scan the DYNAMIC section of the image. We are only doing ourself right now - we will have to do the rest later */ @@ -1053,3 +1104,104 @@ char *_dl_get_last_path_component(char *path) return s+1; } +size_t _dl_strlen(const char * str) +{ + register char *ptr = (char *) str; + + while (*ptr) + ptr++; + return (ptr - str); +} + +char * _dl_strcpy(char * dst,const char *src) +{ + register char *ptr = dst; + + while (*src) + *dst++ = *src++; + *dst = '\0'; + + return ptr; +} + +int _dl_strcmp(const char * s1,const char * s2) +{ + unsigned register char c1, c2; + + do { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; +} + +int _dl_strncmp(const char * s1,const char * s2,size_t len) +{ + unsigned register char c1 = '\0'; + unsigned register char c2 = '\0'; + + while (len > 0) { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + len--; + } + + return c1 - c2; +} + +char * _dl_strchr(const char * str,int c) +{ + register char ch; + + do { + if ((ch = *str) == c) + return (char *) str; + str++; + } + while (ch); + + return 0; +} + +char *_dl_strrchr(const char *str, int c) +{ + register char *prev = 0; + register char *ptr = (char *) str; + + while (*ptr != '\0') { + if (*ptr == c) + prev = ptr; + ptr++; + } + if (c == '\0') + return(ptr); + return(prev); +} + +void * _dl_memcpy(void * dst, const void * src, size_t len) +{ + register char *a = dst; + register const char *b = src; + + while (len--) + *a++ = *b++; + + return dst; +} + +void * _dl_memset(void * str,int c,size_t len) +{ + register char *a = str; + + while (len--) + *a++ = c; + + return str; +} + diff --git a/ldso/ldso/hash.h b/ldso/ldso/hash.h index 74bac2f7d..cc1c56c42 100644 --- a/ldso/ldso/hash.h +++ b/ldso/ldso/hash.h @@ -77,25 +77,25 @@ extern int _dl_linux_dynamic_link(void); #define SEND_STDERR(X) \ { const char *__s = (X); \ if (__s < (const char *) load_addr) __s += load_addr; \ - _dl_write (2, __s, _dl_strlen (__s)); \ + _dl_write (2, __s, _dl_strlen_inline (__s)); \ } #else -#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen(X)); +#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen_inline(X)); #endif extern int _dl_fdprintf(int, const char *, ...); extern char * _dl_library_path; extern char * _dl_not_lazy; extern char * _dl_strdup(const char *); -extern inline int _dl_symbol(char * name); -unsigned long _dl_elf_hash(const char * name); +extern unsigned long _dl_elf_hash(const char * name); -extern inline int _dl_symbol(char * name) +static inline int _dl_symbol(char * name) { if(name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') return 0; return 1; } + #define DL_ERROR_NOFILE 1 #define DL_ERROR_NOZERO 2 #define DL_ERROR_NOTELF 3 diff --git a/ldso/ldso/i386/dl-sysdep.h b/ldso/ldso/i386/dl-sysdep.h index 8e7fb656b..d44b020ee 100644 --- a/ldso/ldso/i386/dl-sysdep.h +++ b/ldso/ldso/i386/dl-sysdep.h @@ -14,11 +14,6 @@ * do something a little more subtle here. */ #define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) & ARGS) -/* - * Get the address of the Global offset table. This must be absolute, not - * relative. - */ -#define GET_GOT(X) __asm__("\tmovl %%ebx,%0\n\t" : "=a" (X)) /* * Initialization sequence for a GOT. diff --git a/ldso/ldso/i386/ld_sysdep.h b/ldso/ldso/i386/ld_sysdep.h index 8e7fb656b..d44b020ee 100644 --- a/ldso/ldso/i386/ld_sysdep.h +++ b/ldso/ldso/i386/ld_sysdep.h @@ -14,11 +14,6 @@ * do something a little more subtle here. */ #define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) & ARGS) -/* - * Get the address of the Global offset table. This must be absolute, not - * relative. - */ -#define GET_GOT(X) __asm__("\tmovl %%ebx,%0\n\t" : "=a" (X)) /* * Initialization sequence for a GOT. diff --git a/ldso/ldso/i386/sysdep.h b/ldso/ldso/i386/sysdep.h index 8e7fb656b..d44b020ee 100644 --- a/ldso/ldso/i386/sysdep.h +++ b/ldso/ldso/i386/sysdep.h @@ -14,11 +14,6 @@ * do something a little more subtle here. */ #define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) & ARGS) -/* - * Get the address of the Global offset table. This must be absolute, not - * relative. - */ -#define GET_GOT(X) __asm__("\tmovl %%ebx,%0\n\t" : "=a" (X)) /* * Initialization sequence for a GOT. diff --git a/ldso/ldso/ld-uClibc.c b/ldso/ldso/ld-uClibc.c index 52c9bcb4e..1da2b3466 100644 --- a/ldso/ldso/ld-uClibc.c +++ b/ldso/ldso/ld-uClibc.c @@ -112,22 +112,11 @@ */ #define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3)) -#define ELF_HASH(RESULT,NAME) { \ - unsigned long hash = 0; \ - unsigned long tmp; \ - char * name = NAME; \ - while (*name){ \ - hash = (hash << 4) + *name++; \ - if((tmp = hash & 0xf0000000)) hash ^= tmp >> 24; \ - hash &= ~tmp; \ - } \ - RESULT = hash; \ -} - static char *_dl_malloc_addr, *_dl_mmap_zero; char *_dl_library_path = 0; /* Where we look for libraries */ char *_dl_preload = 0; /* Things to be loaded before the libs. */ #include "ld.so.h" /* Pull in the name of ld.so */ +const char *_dl_progname=_dl_static_progname; static char *_dl_not_lazy = 0; static char *_dl_warn = 0; /* Used by ldd */ static char *_dl_trace_loaded_objects = 0; @@ -180,9 +169,14 @@ void _dl_boot(unsigned int args) int indx; int _dl_secure; + + /* WARNING! -- we cannot make _any_ funtion calls until we have + * taken care of fixing up our own relocations. Making static + * lnline calls is ok, but _no_ function calls. Not yet + * anyways. */ + /* First obtain the information on the stack that tells us more about what binary is loaded, where it is loaded, etc, etc */ - GET_ARGV(aux_dat, args); argc = *(aux_dat - 1); argv = (char **) aux_dat; @@ -193,7 +187,7 @@ void _dl_boot(unsigned int args) aux_dat++; /* Skip over the envp pointers */ aux_dat++; /* Skip over NULL at end of envp */ - /* Place -1 here as a checkpoint. We check later to see if it got changed + /* Place -1 here as a checkpoint. We check later to see if it was changed * when we read in the auxv_t */ auxv_t[AT_UID].a_type = -1; @@ -205,35 +199,92 @@ void _dl_boot(unsigned int args) Elf32_auxv_t *auxv_entry = (Elf32_auxv_t*) aux_dat; if (auxv_entry->a_type <= AT_EGID) { - _dl_memcpy(&(auxv_t[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t)); + _dl_memcpy_inline(&(auxv_t[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t)); } aux_dat += 2; } - - /* Next, locate the GOT */ + + /* locate the ELF header. We need this done as easly as possible + * (esp since SEND_STDERR() needs this on some platforms... */ load_addr = auxv_t[AT_BASE].a_un.a_val; - if (load_addr == 0x0) { - /* Looks like they decided to run ld-linux-uclibc.so as - * an executable. Exit gracefully for now. */ - - /* TODO -- actually accept executables and args to run... */ - //SEND_STDERR("Usage: ld.so EXECUTABLE [ARGS...]\n"); - SEND_STDERR("You have run `ld.so', the helper program for shared\n"); - SEND_STDERR("library executables. You probably did not intend to\n"); - SEND_STDERR("run this as a program. Goodbye.\n\n"); + header = (elfhdr *) auxv_t[AT_BASE].a_un.a_ptr; + + /* check the ELF header to make sure everything looks ok. */ + if (! header || header->e_ident[EI_CLASS] != ELFCLASS32 || + header->e_ident[EI_VERSION] != EV_CURRENT || + _dl_strncmp_inline((void *)header, ELFMAG, SELFMAG) != 0) + { + SEND_STDERR("invalid ELF header\n"); _dl_exit(0); } #ifdef DL_DEBUG - SEND_STDERR("load_addr="); + SEND_STDERR("ELF header ="); SEND_STDERR(_dl_simple_ltoahex(load_addr)); SEND_STDERR("\n"); #endif - GET_GOT(got); + + + /* Locate the global offset table. Since this code must be PIC + * we can take advantage of the magic offset register, if we + * happen to know what that is for this architecture. If not, + * we can always read stuff out of the ELF file to fine it... */ +#if defined(__i386__) + __asm__("\tmovl %%ebx,%0\n\t" : "=a" (got)); +#elif defined(__m68k__) + __asm__ ("movel %%a5,%0" : "=g" (got)) +#elif defined(__sparc__) + __asm__("\tmov %%l7,%0\n\t" : "=r" (got)) +#else + /* Do things the slow way in C */ + { + unsigned long tx_reloc; + Elf32_Dyn *dynamic=NULL; + Elf32_Shdr *shdr; + Elf32_Phdr *pt_load; + #ifdef DL_DEBUG - SEND_STDERR("Found got="); - SEND_STDERR(_dl_simple_ltoahex((unsigned long)*got)); - SEND_STDERR("\n"); + SEND_STDERR("Finding the got using C code to read the ELF file\n"); #endif + /* Find where the dynamic linking information section is hiding */ + shdr = (Elf32_Shdr *)(header->e_shoff + (char *)header); + for (indx = header->e_shnum; --indx>=0; ++shdr) { + if (shdr->sh_type == SHT_DYNAMIC) { + goto found_dynamic; + } + } + SEND_STDERR("missing dynamic linking information section \n"); + _dl_exit(0); + +found_dynamic: + dynamic = (Elf32_Dyn*)(shdr->sh_offset + (char *)header); + + /* Find where PT_LOAD is hiding */ + pt_load = (Elf32_Phdr *)(header->e_phoff + (char *)header); + for (indx = header->e_phnum; --indx>=0; ++pt_load) { + if (pt_load->p_type == PT_LOAD) { + goto found_pt_load; + } + } + SEND_STDERR("missing loadable program segment\n"); + _dl_exit(0); + +found_pt_load: + /* Now (finally) find where DT_PLTGOT is hiding */ + tx_reloc = pt_load->p_vaddr - pt_load->p_offset; + for (; DT_NULL!=dynamic->d_tag; ++dynamic) { + if (dynamic->d_tag == DT_PLTGOT) { + goto found_got; + } + } + SEND_STDERR("missing global offset table\n"); + _dl_exit(0); + +found_got: + got = (unsigned long *)(dynamic->d_un.d_val - tx_reloc + (char *)header ); + } +#endif + + /* Now, finally, fix up the location of the dynamic stuff */ dpnt = (Elf32_Dyn *) (*got + load_addr); #ifdef DL_DEBUG SEND_STDERR("First Dynamic section entry="); @@ -252,15 +303,15 @@ void _dl_boot(unsigned int args) } tpnt = DL_MALLOC(sizeof(struct elf_resolve)); - _dl_memset(tpnt, 0, sizeof(*tpnt)); + _dl_memset_inline(tpnt, 0, sizeof(*tpnt)); app_tpnt = DL_MALLOC(sizeof(struct elf_resolve)); - _dl_memset(app_tpnt, 0, sizeof(*app_tpnt)); + _dl_memset_inline(app_tpnt, 0, sizeof(*app_tpnt)); /* * 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(*debug_addr)); + _dl_memset_inline(debug_addr, 0, sizeof(*debug_addr)); /* OK, that was easy. Next scan the DYNAMIC section of the image. We are only doing ourself right now - we will have to do the rest later */ @@ -1053,3 +1104,104 @@ char *_dl_get_last_path_component(char *path) return s+1; } +size_t _dl_strlen(const char * str) +{ + register char *ptr = (char *) str; + + while (*ptr) + ptr++; + return (ptr - str); +} + +char * _dl_strcpy(char * dst,const char *src) +{ + register char *ptr = dst; + + while (*src) + *dst++ = *src++; + *dst = '\0'; + + return ptr; +} + +int _dl_strcmp(const char * s1,const char * s2) +{ + unsigned register char c1, c2; + + do { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; +} + +int _dl_strncmp(const char * s1,const char * s2,size_t len) +{ + unsigned register char c1 = '\0'; + unsigned register char c2 = '\0'; + + while (len > 0) { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + len--; + } + + return c1 - c2; +} + +char * _dl_strchr(const char * str,int c) +{ + register char ch; + + do { + if ((ch = *str) == c) + return (char *) str; + str++; + } + while (ch); + + return 0; +} + +char *_dl_strrchr(const char *str, int c) +{ + register char *prev = 0; + register char *ptr = (char *) str; + + while (*ptr != '\0') { + if (*ptr == c) + prev = ptr; + ptr++; + } + if (c == '\0') + return(ptr); + return(prev); +} + +void * _dl_memcpy(void * dst, const void * src, size_t len) +{ + register char *a = dst; + register const char *b = src; + + while (len--) + *a++ = *b++; + + return dst; +} + +void * _dl_memset(void * str,int c,size_t len) +{ + register char *a = str; + + while (len--) + *a++ = c; + + return str; +} + diff --git a/ldso/ldso/ld_hash.h b/ldso/ldso/ld_hash.h index 74bac2f7d..cc1c56c42 100644 --- a/ldso/ldso/ld_hash.h +++ b/ldso/ldso/ld_hash.h @@ -77,25 +77,25 @@ extern int _dl_linux_dynamic_link(void); #define SEND_STDERR(X) \ { const char *__s = (X); \ if (__s < (const char *) load_addr) __s += load_addr; \ - _dl_write (2, __s, _dl_strlen (__s)); \ + _dl_write (2, __s, _dl_strlen_inline (__s)); \ } #else -#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen(X)); +#define SEND_STDERR(X) _dl_write(2, X, _dl_strlen_inline(X)); #endif extern int _dl_fdprintf(int, const char *, ...); extern char * _dl_library_path; extern char * _dl_not_lazy; extern char * _dl_strdup(const char *); -extern inline int _dl_symbol(char * name); -unsigned long _dl_elf_hash(const char * name); +extern unsigned long _dl_elf_hash(const char * name); -extern inline int _dl_symbol(char * name) +static inline int _dl_symbol(char * name) { if(name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') return 0; return 1; } + #define DL_ERROR_NOFILE 1 #define DL_ERROR_NOZERO 2 #define DL_ERROR_NOTELF 3 diff --git a/ldso/ldso/ld_string.h b/ldso/ldso/ld_string.h index 5e912ea9d..4a3462683 100644 --- a/ldso/ldso/ld_string.h +++ b/ldso/ldso/ld_string.h @@ -3,11 +3,26 @@ #include <sys/types.h> /* for size_t */ +extern void *_dl_malloc(int size); +extern char *_dl_getenv(char *symbol, char **envp); +extern void _dl_unsetenv(char *symbol, char **envp); +extern char *_dl_strdup(const char *string); +extern char *_dl_get_last_path_component(char *path); +extern size_t _dl_strlen(const char * str); +extern char * _dl_strcpy(char * dst,const char *src); +extern int _dl_strcmp(const char * s1,const char * s2); +extern int _dl_strncmp(const char * s1,const char * s2,size_t len); +extern char * _dl_strchr(const char * str,int c); +extern char *_dl_strrchr(const char *str, int c); +extern void * _dl_memcpy(void * dst, const void * src, size_t len); +extern int _dl_memcmp(const void * s1,const void * s2,size_t len); +extern void * _dl_memset(void * str,int c,size_t len); + #ifndef NULL #define NULL ((void *) 0) #endif -extern inline size_t _dl_strlen(const char * str) +static inline size_t _dl_strlen_inline(const char * str) { register char *ptr = (char *) str; @@ -16,7 +31,7 @@ extern inline size_t _dl_strlen(const char * str) return (ptr - str); } -extern inline char * _dl_strcpy(char * dst,const char *src) +static inline char * _dl_strcpy_inline(char * dst,const char *src) { register char *ptr = dst; @@ -27,7 +42,7 @@ extern inline char * _dl_strcpy(char * dst,const char *src) return ptr; } -extern inline int _dl_strcmp(const char * s1,const char * s2) +static inline int _dl_strcmp_inline(const char * s1,const char * s2) { unsigned register char c1, c2; @@ -42,7 +57,7 @@ extern inline int _dl_strcmp(const char * s1,const char * s2) return c1 - c2; } -extern inline int _dl_strncmp(const char * s1,const char * s2,size_t len) +static inline int _dl_strncmp_inline(const char * s1,const char * s2,size_t len) { unsigned register char c1 = '\0'; unsigned register char c2 = '\0'; @@ -58,7 +73,7 @@ extern inline int _dl_strncmp(const char * s1,const char * s2,size_t len) return c1 - c2; } -extern inline char * _dl_strchr(const char * str,int c) +static inline char * _dl_strchr_inline(const char * str,int c) { register char ch; @@ -72,25 +87,22 @@ extern inline char * _dl_strchr(const char * str,int c) return 0; } -static inline char *_dl_strrchr(const char *str, int c) +static inline char *_dl_strrchr_inline(const char *str, int c) { - register char *prev = 0; - register char *ptr = (char *) str; - - /* For null it's just like strlen */ - if (c == '\0') { - return ptr + _dl_strlen(ptr); - } - - /* everything else just step along the string. */ - while ((ptr = _dl_strchr(ptr, c)) != 0) { - prev = ptr; - ptr++; - } - return prev; + register char *prev = 0; + register char *ptr = (char *) str; + + while (*ptr != '\0') { + if (*ptr == c) + prev = ptr; + ptr++; + } + if (c == '\0') + return(ptr); + return(prev); } -extern inline void * _dl_memcpy(void * dst, const void * src, size_t len) +static inline void * _dl_memcpy_inline(void * dst, const void * src, size_t len) { register char *a = dst; register const char *b = src; @@ -102,7 +114,7 @@ extern inline void * _dl_memcpy(void * dst, const void * src, size_t len) } -extern inline int _dl_memcmp(const void * s1,const void * s2,size_t len) +static inline int _dl_memcmp_inline(const void * s1,const void * s2,size_t len) { unsigned char *c1 = (unsigned char *)s1; unsigned char *c2 = (unsigned char *)s2; @@ -116,7 +128,7 @@ extern inline int _dl_memcmp(const void * s1,const void * s2,size_t len) return 0; } -extern inline void * _dl_memset(void * str,int c,size_t len) +static inline void * _dl_memset_inline(void * str,int c,size_t len) { register char *a = str; @@ -126,9 +138,39 @@ extern inline void * _dl_memset(void * str,int c,size_t len) return str; } +static inline char *_dl_get_last_path_component_inline(char *path) +{ + char *s; + register char *ptr = path; + register char *prev = 0; + + while (*ptr) + ptr++; + s = ptr - 1; + + /* strip trailing slashes */ + while (s != path && *s == '/') { + *s-- = '\0'; + } + + /* find last component */ + ptr = path; + while (*ptr != '\0') { + if (*ptr == '/') + prev = ptr; + ptr++; + } + s = prev; + + if (s == NULL || s[1] == '\0') + return path; + else + return s+1; +} + /* Early on, we can't call printf, so use this to print out * numbers using the SEND_STDERR() macro */ -static inline char *_dl_simple_ltoa(unsigned long i) +static inline char *_dl_simple_ltoa_inline(unsigned long i) { /* 21 digits plus null terminator, good for 64-bit or smaller ints */ static char local[22]; diff --git a/ldso/ldso/ld_syscall.h b/ldso/ldso/ld_syscall.h index ebc8739ea..28c002cbf 100644 --- a/ldso/ldso/ld_syscall.h +++ b/ldso/ldso/ld_syscall.h @@ -99,7 +99,7 @@ static inline _syscall0(gid_t, _dl_getegid); * Not an actual syscall, but we need something in assembly to say whether * this is OK or not. */ -extern inline int _dl_suid_ok(void) +static inline int _dl_suid_ok(void) { uid_t uid, euid, gid, egid; diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 52c9bcb4e..1da2b3466 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -112,22 +112,11 @@ */ #define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3)) -#define ELF_HASH(RESULT,NAME) { \ - unsigned long hash = 0; \ - unsigned long tmp; \ - char * name = NAME; \ - while (*name){ \ - hash = (hash << 4) + *name++; \ - if((tmp = hash & 0xf0000000)) hash ^= tmp >> 24; \ - hash &= ~tmp; \ - } \ - RESULT = hash; \ -} - static char *_dl_malloc_addr, *_dl_mmap_zero; char *_dl_library_path = 0; /* Where we look for libraries */ char *_dl_preload = 0; /* Things to be loaded before the libs. */ #include "ld.so.h" /* Pull in the name of ld.so */ +const char *_dl_progname=_dl_static_progname; static char *_dl_not_lazy = 0; static char *_dl_warn = 0; /* Used by ldd */ static char *_dl_trace_loaded_objects = 0; @@ -180,9 +169,14 @@ void _dl_boot(unsigned int args) int indx; int _dl_secure; + + /* WARNING! -- we cannot make _any_ funtion calls until we have + * taken care of fixing up our own relocations. Making static + * lnline calls is ok, but _no_ function calls. Not yet + * anyways. */ + /* First obtain the information on the stack that tells us more about what binary is loaded, where it is loaded, etc, etc */ - GET_ARGV(aux_dat, args); argc = *(aux_dat - 1); argv = (char **) aux_dat; @@ -193,7 +187,7 @@ void _dl_boot(unsigned int args) aux_dat++; /* Skip over the envp pointers */ aux_dat++; /* Skip over NULL at end of envp */ - /* Place -1 here as a checkpoint. We check later to see if it got changed + /* Place -1 here as a checkpoint. We check later to see if it was changed * when we read in the auxv_t */ auxv_t[AT_UID].a_type = -1; @@ -205,35 +199,92 @@ void _dl_boot(unsigned int args) Elf32_auxv_t *auxv_entry = (Elf32_auxv_t*) aux_dat; if (auxv_entry->a_type <= AT_EGID) { - _dl_memcpy(&(auxv_t[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t)); + _dl_memcpy_inline(&(auxv_t[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t)); } aux_dat += 2; } - - /* Next, locate the GOT */ + + /* locate the ELF header. We need this done as easly as possible + * (esp since SEND_STDERR() needs this on some platforms... */ load_addr = auxv_t[AT_BASE].a_un.a_val; - if (load_addr == 0x0) { - /* Looks like they decided to run ld-linux-uclibc.so as - * an executable. Exit gracefully for now. */ - - /* TODO -- actually accept executables and args to run... */ - //SEND_STDERR("Usage: ld.so EXECUTABLE [ARGS...]\n"); - SEND_STDERR("You have run `ld.so', the helper program for shared\n"); - SEND_STDERR("library executables. You probably did not intend to\n"); - SEND_STDERR("run this as a program. Goodbye.\n\n"); + header = (elfhdr *) auxv_t[AT_BASE].a_un.a_ptr; + + /* check the ELF header to make sure everything looks ok. */ + if (! header || header->e_ident[EI_CLASS] != ELFCLASS32 || + header->e_ident[EI_VERSION] != EV_CURRENT || + _dl_strncmp_inline((void *)header, ELFMAG, SELFMAG) != 0) + { + SEND_STDERR("invalid ELF header\n"); _dl_exit(0); } #ifdef DL_DEBUG - SEND_STDERR("load_addr="); + SEND_STDERR("ELF header ="); SEND_STDERR(_dl_simple_ltoahex(load_addr)); SEND_STDERR("\n"); #endif - GET_GOT(got); + + + /* Locate the global offset table. Since this code must be PIC + * we can take advantage of the magic offset register, if we + * happen to know what that is for this architecture. If not, + * we can always read stuff out of the ELF file to fine it... */ +#if defined(__i386__) + __asm__("\tmovl %%ebx,%0\n\t" : "=a" (got)); +#elif defined(__m68k__) + __asm__ ("movel %%a5,%0" : "=g" (got)) +#elif defined(__sparc__) + __asm__("\tmov %%l7,%0\n\t" : "=r" (got)) +#else + /* Do things the slow way in C */ + { + unsigned long tx_reloc; + Elf32_Dyn *dynamic=NULL; + Elf32_Shdr *shdr; + Elf32_Phdr *pt_load; + #ifdef DL_DEBUG - SEND_STDERR("Found got="); - SEND_STDERR(_dl_simple_ltoahex((unsigned long)*got)); - SEND_STDERR("\n"); + SEND_STDERR("Finding the got using C code to read the ELF file\n"); #endif + /* Find where the dynamic linking information section is hiding */ + shdr = (Elf32_Shdr *)(header->e_shoff + (char *)header); + for (indx = header->e_shnum; --indx>=0; ++shdr) { + if (shdr->sh_type == SHT_DYNAMIC) { + goto found_dynamic; + } + } + SEND_STDERR("missing dynamic linking information section \n"); + _dl_exit(0); + +found_dynamic: + dynamic = (Elf32_Dyn*)(shdr->sh_offset + (char *)header); + + /* Find where PT_LOAD is hiding */ + pt_load = (Elf32_Phdr *)(header->e_phoff + (char *)header); + for (indx = header->e_phnum; --indx>=0; ++pt_load) { + if (pt_load->p_type == PT_LOAD) { + goto found_pt_load; + } + } + SEND_STDERR("missing loadable program segment\n"); + _dl_exit(0); + +found_pt_load: + /* Now (finally) find where DT_PLTGOT is hiding */ + tx_reloc = pt_load->p_vaddr - pt_load->p_offset; + for (; DT_NULL!=dynamic->d_tag; ++dynamic) { + if (dynamic->d_tag == DT_PLTGOT) { + goto found_got; + } + } + SEND_STDERR("missing global offset table\n"); + _dl_exit(0); + +found_got: + got = (unsigned long *)(dynamic->d_un.d_val - tx_reloc + (char *)header ); + } +#endif + + /* Now, finally, fix up the location of the dynamic stuff */ dpnt = (Elf32_Dyn *) (*got + load_addr); #ifdef DL_DEBUG SEND_STDERR("First Dynamic section entry="); @@ -252,15 +303,15 @@ void _dl_boot(unsigned int args) } tpnt = DL_MALLOC(sizeof(struct elf_resolve)); - _dl_memset(tpnt, 0, sizeof(*tpnt)); + _dl_memset_inline(tpnt, 0, sizeof(*tpnt)); app_tpnt = DL_MALLOC(sizeof(struct elf_resolve)); - _dl_memset(app_tpnt, 0, sizeof(*app_tpnt)); + _dl_memset_inline(app_tpnt, 0, sizeof(*app_tpnt)); /* * 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(*debug_addr)); + _dl_memset_inline(debug_addr, 0, sizeof(*debug_addr)); /* OK, that was easy. Next scan the DYNAMIC section of the image. We are only doing ourself right now - we will have to do the rest later */ @@ -1053,3 +1104,104 @@ char *_dl_get_last_path_component(char *path) return s+1; } +size_t _dl_strlen(const char * str) +{ + register char *ptr = (char *) str; + + while (*ptr) + ptr++; + return (ptr - str); +} + +char * _dl_strcpy(char * dst,const char *src) +{ + register char *ptr = dst; + + while (*src) + *dst++ = *src++; + *dst = '\0'; + + return ptr; +} + +int _dl_strcmp(const char * s1,const char * s2) +{ + unsigned register char c1, c2; + + do { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; +} + +int _dl_strncmp(const char * s1,const char * s2,size_t len) +{ + unsigned register char c1 = '\0'; + unsigned register char c2 = '\0'; + + while (len > 0) { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + len--; + } + + return c1 - c2; +} + +char * _dl_strchr(const char * str,int c) +{ + register char ch; + + do { + if ((ch = *str) == c) + return (char *) str; + str++; + } + while (ch); + + return 0; +} + +char *_dl_strrchr(const char *str, int c) +{ + register char *prev = 0; + register char *ptr = (char *) str; + + while (*ptr != '\0') { + if (*ptr == c) + prev = ptr; + ptr++; + } + if (c == '\0') + return(ptr); + return(prev); +} + +void * _dl_memcpy(void * dst, const void * src, size_t len) +{ + register char *a = dst; + register const char *b = src; + + while (len--) + *a++ = *b++; + + return dst; +} + +void * _dl_memset(void * str,int c,size_t len) +{ + register char *a = str; + + while (len--) + *a++ = c; + + return str; +} + diff --git a/ldso/ldso/m68k/dl-sysdep.h b/ldso/ldso/m68k/dl-sysdep.h index 24af47ca0..a9089286b 100644 --- a/ldso/ldso/m68k/dl-sysdep.h +++ b/ldso/ldso/m68k/dl-sysdep.h @@ -10,10 +10,6 @@ to do something a little more subtle here. */ #define GET_ARGV(ARGVP, ARGS) ((ARGVP) = ((unsigned int *) &(ARGS))) -/* Get the address of the Global offset table. This must be absolute, - not relative. */ -#define GET_GOT(X) __asm__ ("movel %%a5,%0" : "=g" (X)) - /* Initialization sequence for a GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ { \ diff --git a/ldso/ldso/m68k/ld_sysdep.h b/ldso/ldso/m68k/ld_sysdep.h index 24af47ca0..a9089286b 100644 --- a/ldso/ldso/m68k/ld_sysdep.h +++ b/ldso/ldso/m68k/ld_sysdep.h @@ -10,10 +10,6 @@ to do something a little more subtle here. */ #define GET_ARGV(ARGVP, ARGS) ((ARGVP) = ((unsigned int *) &(ARGS))) -/* Get the address of the Global offset table. This must be absolute, - not relative. */ -#define GET_GOT(X) __asm__ ("movel %%a5,%0" : "=g" (X)) - /* Initialization sequence for a GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ { \ diff --git a/ldso/ldso/m68k/sysdep.h b/ldso/ldso/m68k/sysdep.h index 24af47ca0..a9089286b 100644 --- a/ldso/ldso/m68k/sysdep.h +++ b/ldso/ldso/m68k/sysdep.h @@ -10,10 +10,6 @@ to do something a little more subtle here. */ #define GET_ARGV(ARGVP, ARGS) ((ARGVP) = ((unsigned int *) &(ARGS))) -/* Get the address of the Global offset table. This must be absolute, - not relative. */ -#define GET_GOT(X) __asm__ ("movel %%a5,%0" : "=g" (X)) - /* Initialization sequence for a GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ { \ diff --git a/ldso/ldso/sparc/dl-sysdep.h b/ldso/ldso/sparc/dl-sysdep.h index 1d4c0354f..3c8d9b8d1 100644 --- a/ldso/ldso/sparc/dl-sysdep.h +++ b/ldso/ldso/sparc/dl-sysdep.h @@ -11,12 +11,6 @@ #define ELF_USES_RELOCA /* - * Get the address of the Global offset table. This must be absolute, not - * relative. - */ -#define GET_GOT(X) __asm__("\tmov %%l7,%0\n\t" : "=r" (X)) - -/* * Get a pointer to the argv array. On many platforms this can be just * the address if the first argument, on other platforms we need to * do something a little more subtle here. We assume that argc is stored diff --git a/ldso/ldso/sparc/ld_sysdep.h b/ldso/ldso/sparc/ld_sysdep.h index 1d4c0354f..3c8d9b8d1 100644 --- a/ldso/ldso/sparc/ld_sysdep.h +++ b/ldso/ldso/sparc/ld_sysdep.h @@ -11,12 +11,6 @@ #define ELF_USES_RELOCA /* - * Get the address of the Global offset table. This must be absolute, not - * relative. - */ -#define GET_GOT(X) __asm__("\tmov %%l7,%0\n\t" : "=r" (X)) - -/* * Get a pointer to the argv array. On many platforms this can be just * the address if the first argument, on other platforms we need to * do something a little more subtle here. We assume that argc is stored diff --git a/ldso/ldso/sparc/sysdep.h b/ldso/ldso/sparc/sysdep.h index 1d4c0354f..3c8d9b8d1 100644 --- a/ldso/ldso/sparc/sysdep.h +++ b/ldso/ldso/sparc/sysdep.h @@ -11,12 +11,6 @@ #define ELF_USES_RELOCA /* - * Get the address of the Global offset table. This must be absolute, not - * relative. - */ -#define GET_GOT(X) __asm__("\tmov %%l7,%0\n\t" : "=r" (X)) - -/* * Get a pointer to the argv array. On many platforms this can be just * the address if the first argument, on other platforms we need to * do something a little more subtle here. We assume that argc is stored diff --git a/ldso/ldso/string.h b/ldso/ldso/string.h index 5e912ea9d..4a3462683 100644 --- a/ldso/ldso/string.h +++ b/ldso/ldso/string.h @@ -3,11 +3,26 @@ #include <sys/types.h> /* for size_t */ +extern void *_dl_malloc(int size); +extern char *_dl_getenv(char *symbol, char **envp); +extern void _dl_unsetenv(char *symbol, char **envp); +extern char *_dl_strdup(const char *string); +extern char *_dl_get_last_path_component(char *path); +extern size_t _dl_strlen(const char * str); +extern char * _dl_strcpy(char * dst,const char *src); +extern int _dl_strcmp(const char * s1,const char * s2); +extern int _dl_strncmp(const char * s1,const char * s2,size_t len); +extern char * _dl_strchr(const char * str,int c); +extern char *_dl_strrchr(const char *str, int c); +extern void * _dl_memcpy(void * dst, const void * src, size_t len); +extern int _dl_memcmp(const void * s1,const void * s2,size_t len); +extern void * _dl_memset(void * str,int c,size_t len); + #ifndef NULL #define NULL ((void *) 0) #endif -extern inline size_t _dl_strlen(const char * str) +static inline size_t _dl_strlen_inline(const char * str) { register char *ptr = (char *) str; @@ -16,7 +31,7 @@ extern inline size_t _dl_strlen(const char * str) return (ptr - str); } -extern inline char * _dl_strcpy(char * dst,const char *src) +static inline char * _dl_strcpy_inline(char * dst,const char *src) { register char *ptr = dst; @@ -27,7 +42,7 @@ extern inline char * _dl_strcpy(char * dst,const char *src) return ptr; } -extern inline int _dl_strcmp(const char * s1,const char * s2) +static inline int _dl_strcmp_inline(const char * s1,const char * s2) { unsigned register char c1, c2; @@ -42,7 +57,7 @@ extern inline int _dl_strcmp(const char * s1,const char * s2) return c1 - c2; } -extern inline int _dl_strncmp(const char * s1,const char * s2,size_t len) +static inline int _dl_strncmp_inline(const char * s1,const char * s2,size_t len) { unsigned register char c1 = '\0'; unsigned register char c2 = '\0'; @@ -58,7 +73,7 @@ extern inline int _dl_strncmp(const char * s1,const char * s2,size_t len) return c1 - c2; } -extern inline char * _dl_strchr(const char * str,int c) +static inline char * _dl_strchr_inline(const char * str,int c) { register char ch; @@ -72,25 +87,22 @@ extern inline char * _dl_strchr(const char * str,int c) return 0; } -static inline char *_dl_strrchr(const char *str, int c) +static inline char *_dl_strrchr_inline(const char *str, int c) { - register char *prev = 0; - register char *ptr = (char *) str; - - /* For null it's just like strlen */ - if (c == '\0') { - return ptr + _dl_strlen(ptr); - } - - /* everything else just step along the string. */ - while ((ptr = _dl_strchr(ptr, c)) != 0) { - prev = ptr; - ptr++; - } - return prev; + register char *prev = 0; + register char *ptr = (char *) str; + + while (*ptr != '\0') { + if (*ptr == c) + prev = ptr; + ptr++; + } + if (c == '\0') + return(ptr); + return(prev); } -extern inline void * _dl_memcpy(void * dst, const void * src, size_t len) +static inline void * _dl_memcpy_inline(void * dst, const void * src, size_t len) { register char *a = dst; register const char *b = src; @@ -102,7 +114,7 @@ extern inline void * _dl_memcpy(void * dst, const void * src, size_t len) } -extern inline int _dl_memcmp(const void * s1,const void * s2,size_t len) +static inline int _dl_memcmp_inline(const void * s1,const void * s2,size_t len) { unsigned char *c1 = (unsigned char *)s1; unsigned char *c2 = (unsigned char *)s2; @@ -116,7 +128,7 @@ extern inline int _dl_memcmp(const void * s1,const void * s2,size_t len) return 0; } -extern inline void * _dl_memset(void * str,int c,size_t len) +static inline void * _dl_memset_inline(void * str,int c,size_t len) { register char *a = str; @@ -126,9 +138,39 @@ extern inline void * _dl_memset(void * str,int c,size_t len) return str; } +static inline char *_dl_get_last_path_component_inline(char *path) +{ + char *s; + register char *ptr = path; + register char *prev = 0; + + while (*ptr) + ptr++; + s = ptr - 1; + + /* strip trailing slashes */ + while (s != path && *s == '/') { + *s-- = '\0'; + } + + /* find last component */ + ptr = path; + while (*ptr != '\0') { + if (*ptr == '/') + prev = ptr; + ptr++; + } + s = prev; + + if (s == NULL || s[1] == '\0') + return path; + else + return s+1; +} + /* Early on, we can't call printf, so use this to print out * numbers using the SEND_STDERR() macro */ -static inline char *_dl_simple_ltoa(unsigned long i) +static inline char *_dl_simple_ltoa_inline(unsigned long i) { /* 21 digits plus null terminator, good for 64-bit or smaller ints */ static char local[22]; diff --git a/ldso/ldso/syscall.h b/ldso/ldso/syscall.h index ebc8739ea..28c002cbf 100644 --- a/ldso/ldso/syscall.h +++ b/ldso/ldso/syscall.h @@ -99,7 +99,7 @@ static inline _syscall0(gid_t, _dl_getegid); * Not an actual syscall, but we need something in assembly to say whether * this is OK or not. */ -extern inline int _dl_suid_ok(void) +static inline int _dl_suid_ok(void) { uid_t uid, euid, gid, egid; diff --git a/ldso/libdl/Makefile b/ldso/libdl/Makefile index 7d5f27d29..f52027250 100644 --- a/ldso/libdl/Makefile +++ b/ldso/libdl/Makefile @@ -22,7 +22,7 @@ TOPDIR=../../ -include $(TOPDIR)/ldso/Rules.mak +include $(TOPDIR)Rules.mak LIBDL=libdl.a LIBDL_SHARED=libdl.so @@ -32,7 +32,7 @@ TARGET_CC= $(TOPDIR)extra/gcc-uClibc/$(TARGET_ARCH)-uclibc-gcc CSRC= dlib.c OBJS=$(patsubst %.c,%.o, $(CSRC)) -CFLAGS += -DUSE_CACHE #-fPIC -D__PIC__ #-funroll-loops +CFLAGS += --uclibc-use-build-dir -DUSE_CACHE #-fPIC -D__PIC__ #-funroll-loops all: $(OBJS) $(LIBDL) shared diff --git a/ldso/util/Makefile b/ldso/util/Makefile index 725fc9b8e..f2486fdaa 100644 --- a/ldso/util/Makefile +++ b/ldso/util/Makefile @@ -1,7 +1,7 @@ TOPDIR=../../ include $(TOPDIR)Rules.mak -CFLAGS=-Wall -Os -I- -I. --uclibc-use-build-dir +CFLAGS=-Wall -Os -I. --uclibc-use-build-dir CC = $(TOPDIR)extra/gcc-uClibc/$(NATIVE_ARCH)-uclibc-gcc all: ldconfig ldd readelf |