Browse Source

Yet more ldso cleanups. Be more discriminating about when using inlines
and when using real functions. Make things be more portable by
providing a default C routine to locate the got.
-Erik

Eric Andersen 23 years ago
parent
commit
862fef6971

+ 4 - 3
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

+ 0 - 5
ldso/Rules.mak

@@ -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

+ 7 - 4
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 $@

+ 186 - 34
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;
+}
+

+ 5 - 5
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

+ 0 - 5
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.

+ 0 - 5
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.

+ 0 - 5
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.

+ 186 - 34
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;
+}
+

+ 5 - 5
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

+ 66 - 24
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];

+ 1 - 1
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;
 

+ 186 - 34
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;
+}
+

+ 0 - 4
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)		\
 {						\

+ 0 - 4
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)		\
 {						\

+ 0 - 4
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)		\
 {						\

+ 0 - 6
ldso/ldso/sparc/dl-sysdep.h

@@ -10,12 +10,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

+ 0 - 6
ldso/ldso/sparc/ld_sysdep.h

@@ -10,12 +10,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

+ 0 - 6
ldso/ldso/sparc/sysdep.h

@@ -10,12 +10,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

+ 66 - 24
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];

+ 1 - 1
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;
 

+ 2 - 2
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
 

+ 1 - 1
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