summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldso/Makefile7
-rw-r--r--ldso/Rules.mak5
-rw-r--r--ldso/ldso/Makefile11
-rw-r--r--ldso/ldso/boot1.c220
-rw-r--r--ldso/ldso/hash.h10
-rw-r--r--ldso/ldso/i386/dl-sysdep.h5
-rw-r--r--ldso/ldso/i386/ld_sysdep.h5
-rw-r--r--ldso/ldso/i386/sysdep.h5
-rw-r--r--ldso/ldso/ld-uClibc.c220
-rw-r--r--ldso/ldso/ld_hash.h10
-rw-r--r--ldso/ldso/ld_string.h90
-rw-r--r--ldso/ldso/ld_syscall.h2
-rw-r--r--ldso/ldso/ldso.c220
-rw-r--r--ldso/ldso/m68k/dl-sysdep.h4
-rw-r--r--ldso/ldso/m68k/ld_sysdep.h4
-rw-r--r--ldso/ldso/m68k/sysdep.h4
-rw-r--r--ldso/ldso/sparc/dl-sysdep.h6
-rw-r--r--ldso/ldso/sparc/ld_sysdep.h6
-rw-r--r--ldso/ldso/sparc/sysdep.h6
-rw-r--r--ldso/ldso/string.h90
-rw-r--r--ldso/ldso/syscall.h2
-rw-r--r--ldso/libdl/Makefile4
-rw-r--r--ldso/util/Makefile2
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