]> Git Repo - uclibc-ng.git/commitdiff
Split off the stuff that cannot use function into its own file,
authorEric Andersen <[email protected]>
Sat, 7 Feb 2004 10:40:25 +0000 (10:40 -0000)
committerEric Andersen <[email protected]>
Sat, 7 Feb 2004 10:40:25 +0000 (10:40 -0000)
to make it easier to treat it specially while not bothering the
rest of the code with the same constraints.

26 files changed:
ldso/Makefile
ldso/include/dl-syscall.h
ldso/include/ld_syscall.h
ldso/ldso/Makefile
ldso/ldso/arm/boot1_arch.h
ldso/ldso/arm/dl-startup.h
ldso/ldso/cris/boot1_arch.h
ldso/ldso/cris/dl-startup.h
ldso/ldso/dl-startup.c [new file with mode: 0644]
ldso/ldso/i386/boot1_arch.h
ldso/ldso/i386/dl-startup.h
ldso/ldso/i386/elfinterp.c
ldso/ldso/ldso.c
ldso/ldso/m68k/boot1_arch.h
ldso/ldso/m68k/dl-startup.h
ldso/ldso/mips/boot1_arch.h
ldso/ldso/mips/dl-startup.h
ldso/ldso/powerpc/boot1_arch.h
ldso/ldso/powerpc/dl-startup.h
ldso/ldso/sh/boot1_arch.h
ldso/ldso/sh/dl-startup.h
ldso/ldso/sh64/boot1_arch.h
ldso/ldso/sh64/dl-startup.h
ldso/ldso/sparc/boot1_arch.h
ldso/ldso/sparc/dl-startup.h
ldso/ldso/startup.c [new file with mode: 0644]

index 9aa450015de4ec2516427cf6d507850d5d5fb22b..1c9fc8fef4e3e08f91efd2b98966b232d1afc01d 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for uClibc
 #
-# Copyright (C) 2000,2001 Erik Andersen <[email protected]>
+# Copyright (C) 2000-2004 Erik Andersen <[email protected]>
 #
 # This program is free software; you can redistribute it and/or modify it under
 # the terms of the GNU Library General Public License as published by the Free
 # You should have received a copy of the GNU Library General Public License
 # along with this program; if not, write to the Free Software Foundation, Inc.,
 # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Derived in part from the Linux-8086 C library, the GNU C Library, and several
-# other sundry sources.  Files within this library are copyright by their
-# respective copyright holders.
 
 TOPDIR=../
 include $(TOPDIR)Rules.mak
index 72574b9a9ae2a04f06811844a1673e2fc64a9741..1e2ceccd678e051569163b3498b6b48e0f8c833e 100644 (file)
@@ -131,25 +131,6 @@ static inline _syscall0(gid_t, _dl_getegid);
 #define __NR__dl_getpid __NR_getpid
 static inline _syscall0(gid_t, _dl_getpid);
 
-/*
- * Not an actual syscall, but we need something in assembly to say whether
- * this is OK or not.
- */
-static inline int _dl_suid_ok(void)
-{
-    uid_t uid, euid, gid, egid;
-
-    uid = _dl_getuid();
-    euid = _dl_geteuid();
-    gid = _dl_getgid();
-    egid = _dl_getegid();
-
-    if(uid == euid && gid == egid)
-       return 1;
-    else
-       return 0;
-}
-
 #define __NR__dl_readlink __NR_readlink
 static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);
 
index 72574b9a9ae2a04f06811844a1673e2fc64a9741..1e2ceccd678e051569163b3498b6b48e0f8c833e 100644 (file)
@@ -131,25 +131,6 @@ static inline _syscall0(gid_t, _dl_getegid);
 #define __NR__dl_getpid __NR_getpid
 static inline _syscall0(gid_t, _dl_getpid);
 
-/*
- * Not an actual syscall, but we need something in assembly to say whether
- * this is OK or not.
- */
-static inline int _dl_suid_ok(void)
-{
-    uid_t uid, euid, gid, egid;
-
-    uid = _dl_getuid();
-    euid = _dl_geteuid();
-    gid = _dl_getgid();
-    egid = _dl_getegid();
-
-    if(uid == euid && gid == egid)
-       return 1;
-    else
-       return 0;
-}
-
 #define __NR__dl_readlink __NR_readlink
 static inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, size_t, bufsiz);
 
index 79c381bead3072bd4228b63e45a9bbc49254ef61..8b62961fbca26c6ad70b6026b84b87da634b87aa 100644 (file)
@@ -1,7 +1,6 @@
 # Makefile for uClibc
 #
-# Copyright (C) 2000 by Lineo, inc.
-# Copyright (C) 2000-2002 Erik Andersen <[email protected]>
+# Copyright (C) 2000-2004 Erik Andersen <[email protected]>
 #
 # This program is free software; you can redistribute it and/or modify it under
 # the terms of the GNU Library General Public License as published by the Free
 # You should have received a copy of the GNU Library General Public License
 # along with this program; if not, write to the Free Software Foundation, Inc.,
 # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# Derived in part from the Linux-8086 C library, the GNU C Library, and several
-# other sundry sources.  Files within this library are copyright by their
-# respective copyright holders.
 
 
 TOPDIR=../../
@@ -46,7 +41,7 @@ XXFLAGS+=$(shell $(CC) -print-search-dirs | sed -ne "s/install: *\(.*\)/-I\1incl
 LDFLAGS=$(CPU_LDFLAGS-y) -shared --warn-common --export-dynamic --sort-common \
        -z combreloc --discard-locals --discard-all --no-undefined
 
-CSRC= ldso.c #hash.c readelflib1.c $(TARGET_ARCH)/elfinterp.c
+CSRC= ldso.c startup.c #hash.c readelflib1.c $(TARGET_ARCH)/elfinterp.c
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 ASRC=$(shell ls $(TARGET_ARCH)/*.S)
 AOBJS=$(patsubst %.S,%.o, $(ASRC))
@@ -93,7 +88,7 @@ $(AOBJS): %.o : %.S
        $(CC) $(XXFLAGS) -I../libdl -c $< -o $@
        $(STRIPTOOL) -x -R .note -R .comment $*.o
 
-ldso.o: ldso.c hash.c readelflib1.c $(TARGET_ARCH)/elfinterp.c _dl_progname.h
+ldso.o: $(CSRC)
 
 clean:
        $(RM) $(UCLIBC_LDSO)* $(OBJS) $(LDSO_FULLNAME)* core *.o *.a *.s *.i _dl_progname.h ldso.h *~
index b3ba36117001465c5df880e3e3d8734e61bed3a3..631684c9512ac006d98df1893556eee52e671db5 100644 (file)
@@ -18,13 +18,9 @@ asm("" \
 "      mov     pc, r6\n"               \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
-
-
  /* It seems ARM needs an offset here */
 #undef ELFMAGIC
-#define            ELFMAGIC    ELFMAG+load_addr 
+#define            ELFMAGIC    ELFMAG+load_addr
 
 
 
index b3ba36117001465c5df880e3e3d8734e61bed3a3..631684c9512ac006d98df1893556eee52e671db5 100644 (file)
@@ -18,13 +18,9 @@ asm("" \
 "      mov     pc, r6\n"               \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
-
-
  /* It seems ARM needs an offset here */
 #undef ELFMAGIC
-#define            ELFMAGIC    ELFMAG+load_addr 
+#define            ELFMAGIC    ELFMAG+load_addr
 
 
 
index 9b4a8b52ed0b0ee5da28a3d4626068ed8845eb34..d51cd59d3861c2a29115e9a4b21dae3fb1b46430 100644 (file)
@@ -13,5 +13,3 @@ asm(""                                        \
 "      jsr $r9\n"                      \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X) static void * __attribute__ ((unused)) _dl_boot(X)
index 9b4a8b52ed0b0ee5da28a3d4626068ed8845eb34..d51cd59d3861c2a29115e9a4b21dae3fb1b46430 100644 (file)
@@ -13,5 +13,3 @@ asm(""                                        \
 "      jsr $r9\n"                      \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X) static void * __attribute__ ((unused)) _dl_boot(X)
diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
new file mode 100644 (file)
index 0000000..ec8b792
--- /dev/null
@@ -0,0 +1,583 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (C) 2000-2004 by Erik Andersen <[email protected]>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ *                             David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The main trick with this program is that initially, we ourselves are not
+ * dynamicly linked.  This means that we cannot access any global variables or
+ * call any functions.  No globals initially, since the Global Offset Table
+ * (GOT) is initialized by the linker assuming a virtual address of 0, and no
+ * function calls initially since the Procedure Linkage Table (PLT) is not yet
+ * initialized.
+ *
+ * There are additional initial restrictions - we cannot use large switch
+ * statements, since the compiler generates tables of addresses and jumps
+ * through them.  We cannot use normal syscall stubs, because these all
+ * reference the errno global variable which is not yet initialized.  We _can_
+ * use all of the local stack variables that we want.  We _can_ use inline
+ * functions, because these do not transfer control to a new address, but they
+ * must be static so that they are not exported from the modules.
+ *
+ * Life is further complicated by the fact that initially we do not want to do
+ * a complete dynamic linking.  We want to allow the user to supply new
+ * functions to override symbols (i.e. weak symbols and/or LD_PRELOAD).  So
+ * initially, we only perform relocations for variables that start with "_dl_"
+ * since ANSI specifies that the user is not supposed to redefine any of these
+ * variables.
+ *
+ * Fortunately, the linker itself leaves a few clues lying around, and when the
+ * kernel starts the image, there are a few further clues.  First of all, there
+ * is Auxiliary Vector Table information sitting on which is provided to us by
+ * the kernel, and which includes information about the load address that the
+ * program interpreter was loaded at, the number of sections, the address the
+ * application was loaded at and so forth.  Here this information is stored in
+ * the array auxvt.  For details see linux/fs/binfmt_elf.c where it calls
+ * NEW_AUX_ENT() a bunch of time....
+ *
+ * Next, we need to find the GOT.  On most arches there is a register pointing
+ * to the GOT, but just in case (and for new ports) I've added some (slow) C
+ * code to locate the GOT for you.
+ *
+ * This code was originally written for SVr4, and there the kernel would load
+ * all text pages R/O, so they needed to call mprotect a zillion times to mark
+ * all text pages as writable so dynamic linking would succeed.  Then when they
+ * were done, they would change the protections for all the pages back again.
+ * Well, under Linux everything is loaded writable (since Linux does copy on
+ * write anyways) so all the mprotect stuff has been disabled.
+ *
+ * Initially, we do not have access to _dl_malloc since we can't yet make
+ * function calls, so we mmap one page to use as scratch space.  Later on, when
+ * we can call _dl_malloc we reuse this this memory.  This is also beneficial,
+ * since we do not want to use the same memory pool as malloc anyway - esp if
+ * the user redefines malloc to do something funky.
+ *
+ * Our first task is to perform a minimal linking so that we can call other
+ * portions of the dynamic linker.  Once we have done this, we then build the
+ * list of modules that the application requires, using LD_LIBRARY_PATH if this
+ * is not a suid program (/usr/lib otherwise).  Once this is done, we can do
+ * the dynamic linking as required, and we must omit the things we did to get
+ * the dynamic linker up and running in the first place.  After we have done
+ * this, we just have a few housekeeping chores and we can transfer control to
+ * the user's application.
+ */
+
+#include "ldso.h"
+
+/*  Some arches may need to override this in boot1_arch.h */
+#define        ELFMAGIC ELFMAG
+
+/* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */
+#define LD_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ;  REALIGN();
+
+/* Make sure that the malloc buffer is aligned on 4 byte boundary.  For 64 bit
+ * platforms we may need to increase this to 8, but this is good enough for
+ * now.  This is typically called after LD_MALLOC.  */
+#define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3))
+
+/* Pull in all the arch specific stuff */
+#include "boot1_arch.h"
+
+/* Static declarations */
+int (*_dl_elf_main) (int, char **, char **);
+
+
+
+
+/* When we enter this piece of code, the program stack looks like this:
+        argc            argument counter (integer)
+        argv[0]         program name (pointer)
+        argv[1...N]     program args (pointers)
+        argv[argc-1]    end of args (integer)
+               NULL
+        env[0...N]      environment variables (pointers)
+        NULL
+               auxvt[0...N]   Auxiliary Vector Table elements (mixed types)
+*/
+void _dl_boot2(unsigned long args)
+{
+       unsigned int argc;
+       char **argv, **envp;
+       unsigned long load_addr;
+       unsigned long *got;
+       unsigned long *aux_dat;
+       int goof = 0;
+       ElfW(Ehdr) *header;
+       struct elf_resolve *tpnt;
+       struct elf_resolve *app_tpnt;
+       Elf32_auxv_t auxvt[AT_EGID + 1];
+       unsigned char *malloc_buffer, *mmap_zero;
+       Elf32_Dyn *dpnt;
+       unsigned long *hash_addr;
+       struct r_debug *debug_addr = NULL;
+       int indx;
+#if defined(__i386__)
+       int status = 0;
+#endif
+
+
+       /* WARNING! -- we cannot make _any_ funtion calls until we have
+        * taken care of fixing up our own relocations.  Making static
+        * inline 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);
+#if defined (__arm__) || defined (__mips__) || defined (__cris__)
+       aux_dat += 1;
+#endif
+       argc = *(aux_dat - 1);
+       argv = (char **) aux_dat;
+       aux_dat += argc;                        /* Skip over the argv pointers */
+       aux_dat++;                                      /* Skip over NULL at end of argv */
+       envp = (char **) aux_dat;
+       while (*aux_dat)
+               aux_dat++;                              /* Skip over the envp pointers */
+       aux_dat++;                                      /* Skip over NULL at end of envp */
+
+       /* Place -1 here as a checkpoint.  We later check if it was changed
+        * when we read in the auxvt */
+       auxvt[AT_UID].a_type = -1;
+
+       /* The junk on the stack immediately following the environment is
+        * the Auxiliary Vector Table.  Read out the elements of the auxvt,
+        * sort and store them in auxvt for later use. */
+       while (*aux_dat) {
+               Elf32_auxv_t *auxv_entry = (Elf32_auxv_t *) aux_dat;
+
+               if (auxv_entry->a_type <= AT_EGID) {
+                       _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t));
+               }
+               aux_dat += 2;
+       }
+
+       /* locate the ELF header.   We need this done as soon as possible
+        * (esp since SEND_STDERR() needs this on some platforms... */
+       load_addr = auxvt[AT_BASE].a_un.a_val;
+       header = (ElfW(Ehdr) *) auxvt[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
+#if !defined(__powerpc__) && !defined(__mips__) && !defined(__sh__)
+               || _dl_strncmp((void *) header, ELFMAGIC, SELFMAG) != 0
+#else
+               || header->e_ident[EI_MAG0] != ELFMAG0
+               || header->e_ident[EI_MAG1] != ELFMAG1
+               || header->e_ident[EI_MAG2] != ELFMAG2
+               || header->e_ident[EI_MAG3] != ELFMAG3
+#endif
+               ) {
+               SEND_STDERR("Invalid ELF header\n");
+               _dl_exit(0);
+       }
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("ELF header=");
+       SEND_ADDRESS_STDERR(load_addr, 1);
+#endif
+
+
+       /* 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 find 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));
+#elif defined(__arm__)
+  __asm__("\tmov %0, r10\n\t":"=r"(got));
+#elif defined(__powerpc__)
+  __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
+#elif defined(__mips__)
+  __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
+#elif defined(__sh__) && !defined(__SH5__)
+  __asm__(
+"       mov.l    1f, %0\n"
+"       mova     1f, r0\n"
+"       bra      2f\n"
+"       add r0,  %0\n"
+"       .balign  4\n"
+"1:     .long    _GLOBAL_OFFSET_TABLE_\n"
+"2:" : "=r" (got) : : "r0");
+#elif defined(__cris__)
+  __asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%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 __SUPPORT_LD_DEBUG_EARLY__
+               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 __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("First Dynamic section entry=");
+       SEND_ADDRESS_STDERR(dpnt, 1);
+#endif
+
+
+       /* Call mmap to get a page of writable memory that can be used
+        * for _dl_malloc throughout the shared lib loader. */
+       mmap_zero = malloc_buffer = _dl_mmap((void *) 0, PAGE_SIZE,
+                       PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+       if (_dl_mmap_check_error(mmap_zero)) {
+               SEND_STDERR("dl_boot: mmap of a spare page failed!\n");
+               _dl_exit(13);
+       }
+
+       tpnt = LD_MALLOC(sizeof(struct elf_resolve));
+       _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
+       app_tpnt = LD_MALLOC(sizeof(struct elf_resolve));
+       _dl_memset(app_tpnt, 0, sizeof(struct elf_resolve));
+
+#ifdef __UCLIBC_PIE_SUPPORT__
+       /* Find the runtime load address of the main executable, this may be
+         * different from what the ELF header says for ET_DYN/PIE executables.
+        */
+       {
+               ElfW(Phdr) *ppnt;
+               int i;
+
+               ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+               for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
+                       if (ppnt->p_type == PT_PHDR) {
+                               app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
+                               break;
+                       }
+       }
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("app_tpnt->loadaddr=");
+       SEND_ADDRESS_STDERR(app_tpnt->loadaddr, 1);
+#endif
+#endif
+
+       /*
+        * This is used by gdb to locate the chain of shared libraries that are currently loaded.
+        */
+       debug_addr = LD_MALLOC(sizeof(struct r_debug));
+       _dl_memset(debug_addr, 0, sizeof(struct r_debug));
+
+       /* 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 */
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("scanning DYNAMIC section\n");
+#endif
+       while (dpnt->d_tag) {
+#if defined(__mips__)
+               if (dpnt->d_tag == DT_MIPS_GOTSYM)
+                       tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val;
+               if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
+                       tpnt->mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
+               if (dpnt->d_tag == DT_MIPS_SYMTABNO)
+                       tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val;
+#endif
+               if (dpnt->d_tag < 24) {
+                       tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_TEXTREL) {
+                               tpnt->dynamic_info[DT_TEXTREL] = 1;
+                       }
+               }
+               dpnt++;
+       }
+
+       {
+               ElfW(Phdr) *ppnt;
+               int i;
+
+               ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+               for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
+                       if (ppnt->p_type == PT_DYNAMIC) {
+#ifndef __UCLIBC_PIE_SUPPORT__
+                               dpnt = (Elf32_Dyn *) ppnt->p_vaddr;
+#else
+                               dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
+#endif
+                               while (dpnt->d_tag) {
+#if defined(__mips__)
+                                       if (dpnt->d_tag == DT_MIPS_GOTSYM)
+                                               app_tpnt->mips_gotsym =
+                                                       (unsigned long) dpnt->d_un.d_val;
+                                       if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
+                                               app_tpnt->mips_local_gotno =
+                                                       (unsigned long) dpnt->d_un.d_val;
+                                       if (dpnt->d_tag == DT_MIPS_SYMTABNO)
+                                               app_tpnt->mips_symtabno =
+                                                       (unsigned long) dpnt->d_un.d_val;
+                                       if (dpnt->d_tag > DT_JMPREL) {
+                                               dpnt++;
+                                               continue;
+                                       }
+                                       app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+
+#warning "Debugging threads on mips won't work till someone fixes this..."
+#if 0
+                                       if (dpnt->d_tag == DT_DEBUG) {
+                                               dpnt->d_un.d_val = (unsigned long) debug_addr;
+                                       }
+#endif
+
+#else
+                                       if (dpnt->d_tag > DT_JMPREL) {
+                                               dpnt++;
+                                               continue;
+                                       }
+                                       app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+                                       if (dpnt->d_tag == DT_DEBUG) {
+                                               dpnt->d_un.d_val = (unsigned long) debug_addr;
+                                       }
+#endif
+                                       if (dpnt->d_tag == DT_TEXTREL)
+                                               app_tpnt->dynamic_info[DT_TEXTREL] = 1;
+                                       dpnt++;
+                               }
+                       }
+       }
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("done scanning DYNAMIC section\n");
+#endif
+
+       /* Get some more of the information that we will need to dynamicly link
+          this module to itself */
+
+       hash_addr = (unsigned long *) (tpnt->dynamic_info[DT_HASH] + load_addr);
+       tpnt->nbucket = *hash_addr++;
+       tpnt->nchain = *hash_addr++;
+       tpnt->elf_buckets = hash_addr;
+       hash_addr += tpnt->nbucket;
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("done grabbing link information\n");
+#endif
+
+#ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
+       /* Ugly, ugly.  We need to call mprotect to change the protection of
+          the text pages so that we can do the dynamic linking.  We can set the
+          protection back again once we are done */
+
+       {
+               ElfW(Phdr) *ppnt;
+               int i;
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+               SEND_STDERR("calling mprotect on the shared library/dynamic linker\n");
+#endif
+
+               /* First cover the shared library/dynamic linker. */
+               if (tpnt->dynamic_info[DT_TEXTREL]) {
+                       header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
+                       ppnt = (ElfW(Phdr) *) ((int)auxvt[AT_BASE].a_un.a_ptr +
+                                       header->e_phoff);
+                       for (i = 0; i < header->e_phnum; i++, ppnt++) {
+                               if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
+                                       _dl_mprotect((void *) (load_addr + (ppnt->p_vaddr & PAGE_ALIGN)),
+                                                       (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
+                                                       PROT_READ | PROT_WRITE | PROT_EXEC);
+                               }
+                       }
+               }
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+               SEND_STDERR("calling mprotect on the application program\n");
+#endif
+               /* Now cover the application program. */
+               if (app_tpnt->dynamic_info[DT_TEXTREL]) {
+                       ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+                       for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
+                               if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
+#ifndef __UCLIBC_PIE_SUPPORT__
+                                       _dl_mprotect((void *) (ppnt->p_vaddr & PAGE_ALIGN),
+                                                                (ppnt->p_vaddr & ADDR_ALIGN) +
+                                                                (unsigned long) ppnt->p_filesz,
+                                                                PROT_READ | PROT_WRITE | PROT_EXEC);
+#else
+                                       _dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN),
+                                                                ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) +
+                                                                (unsigned long) ppnt->p_filesz,
+                                                                PROT_READ | PROT_WRITE | PROT_EXEC);
+#endif
+                       }
+               }
+       }
+#endif
+
+#if defined(__mips__)
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
+#endif
+       /* For MIPS we have to do stuff to the GOT before we do relocations.  */
+       PERFORM_BOOTSTRAP_GOT(got);
+#endif
+
+       /* OK, now do the relocations.  We do not do a lazy binding here, so
+          that once we are done, we have considerably more flexibility. */
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("About to do library loader relocations\n");
+#endif
+
+       goof = 0;
+       for (indx = 0; indx < 2; indx++) {
+               unsigned int i;
+               ELF_RELOC *rpnt;
+               unsigned long *reloc_addr;
+               unsigned long symbol_addr;
+               int symtab_index;
+               unsigned long rel_addr, rel_size;
+
+
+               rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt->
+                        dynamic_info[DT_RELOC_TABLE_ADDR]);
+               rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt->
+                        dynamic_info[DT_RELOC_TABLE_SIZE]);
+
+               if (!rel_addr)
+                       continue;
+
+               /* Now parse the relocation information */
+               rpnt = (ELF_RELOC *) (rel_addr + load_addr);
+               for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
+                       reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
+                       symtab_index = ELF32_R_SYM(rpnt->r_info);
+                       symbol_addr = 0;
+                       if (symtab_index) {
+                               char *strtab;
+                               char *symname;
+                               Elf32_Sym *symtab;
+
+                               symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + load_addr);
+                               strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + load_addr);
+                               symname = strtab + symtab[symtab_index].st_name;
+
+                               /* We only do a partial dynamic linking right now.  The user
+                                  is not supposed to define any symbols that start with a
+                                  '_dl', so we can do this with confidence. */
+                               if (!symname || symname[0] != '_' ||
+                                               symname[1] != 'd' || symname[2] != 'l' || symname[3] != '_')
+                               {
+                                       continue;
+                               }
+                               symbol_addr = load_addr + symtab[symtab_index].st_value;
+
+                               if (!symbol_addr) {
+                                       /* This will segfault - you cannot call a function until
+                                        * we have finished the relocations.
+                                        */
+                                       SEND_STDERR("ELF dynamic loader - unable to self-bootstrap - symbol ");
+                                       SEND_STDERR(symname);
+                                       SEND_STDERR(" undefined.\n");
+                                       goof++;
+                               }
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+                               SEND_STDERR("relocating symbol: ");
+                               SEND_STDERR(symname);
+                               SEND_STDERR("\n");
+#endif
+                               PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, &symtab[symtab_index]);
+                       } else {
+                               /* Use this machine-specific macro to perform the actual relocation.  */
+                               PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, NULL);
+                       }
+               }
+       }
+
+       if (goof) {
+               _dl_exit(14);
+       }
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       /* Wahoo!!! */
+       SEND_STDERR("Done relocating library loader, so we can now\n"
+                       "\tuse globals and make function calls!\n");
+#endif
+
+       /* Now we have done the mandatory linking of some things.  We are now
+          free to start using global variables, since these things have all been
+          fixed up by now.  Still no function calls outside of this library ,
+          since the dynamic resolver is not yet ready. */
+       _dl_get_ready_to_run(tpnt, app_tpnt, load_addr, hash_addr,
+                       auxvt, envp, debug_addr, malloc_buffer, mmap_zero, argv);
+
+
+       /* Transfer control to the application.  */
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("transfering control to application\n");
+#endif
+       _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn;
+       START();
+}
+
index cd1f016a61ad4e03ac7c7ab4697b7a3cfe529daf..bab0f88976941fa6ece7d1c86df398e656dde476 100644 (file)
@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define LD_BOOT(X)   void _dl_boot (X)
+#define _dl_boot2 _dl_boot
index cd1f016a61ad4e03ac7c7ab4697b7a3cfe529daf..bab0f88976941fa6ece7d1c86df398e656dde476 100644 (file)
@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define LD_BOOT(X)   void _dl_boot (X)
+#define _dl_boot2 _dl_boot
index 5681d2e416aa846336ecb8441d84345eb17d36e1..867365236d6e8192b2a1026437a2fe9fd630e56f 100644 (file)
@@ -29,6 +29,8 @@
  * SUCH DAMAGE.
  */
 
+#include "ldso.h"
+
 #if defined (__SUPPORT_LD_DEBUG__)
 static const char *_dl_reltypes_tab[] =
 {
@@ -271,8 +273,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 
                if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
 #if defined (__SUPPORT_LD_DEBUG__)
-                       _dl_dprintf(2, "\tglobal symbol '%s' already defined in '%s'\n",
-                                       symname, tpnt->libname);
+                       _dl_dprintf(2, "\tglobal symbol '%s' already defined in '%s', rel type: %s\n",
+                                       symname, tpnt->libname, _dl_reltypes(reloc_type));
 #endif
                        return 0;
                }
index 04dbdcae5d2b0c254ffc3d7d62a5bdc2a1acb5dd..013895227ef6a6c6a27c94e2be615a05d0f2a876 100644 (file)
@@ -1,12 +1,11 @@
 /* vi: set sw=4 ts=4: */
-/* Program to load an ELF binary on a linux system, and run it
+/*
+ * Program to load an ELF binary on a linux system, and run it
  * after resolving ELF shared library symbols
  *
- * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ * Copyright (C) 2000-2004 by Erik Andersen <[email protected]>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
  *                             David Engel, Hongjiu Lu and Mitch D'Souza
- * Copyright (C) 2001-2002, Erik Andersen
- *
- * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * SUCH DAMAGE.
  */
 
-// Support a list of library preloads in /etc/ld.so.preload
-//#define SUPPORT_LDSO_PRELOAD_FILE
-
-
-/* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
-   I ever taken any courses on internals.  This program was developed using
-   information available through the book "UNIX SYSTEM V RELEASE 4,
-   Programmers guide: Ansi C and Programming Support Tools", which did
-   a more than adequate job of explaining everything required to get this
-   working. */
-
-/*
- * The main trick with this program is that initially, we ourselves are
- * not dynamicly linked.  This means that we cannot access any global
- * variables or call any functions.  No globals initially, since the
- * Global Offset Table (GOT) is initialized by the linker assuming a
- * virtual address of 0, and no function calls initially since the
- * Procedure Linkage Table (PLT) is not yet initialized.
- *
- * There are additional initial restrictions - we cannot use large
- * switch statements, since the compiler generates tables of addresses
- * and jumps through them.  We can use inline functions, because these
- * do not transfer control to a new address, but they must be static so
- * that they are not exported from the modules.  We cannot use normal
- * syscall stubs, because these all reference the errno global variable
- * which is not yet initialized.  We can use all of the local stack
- * variables that we want.
- *
- * Life is further complicated by the fact that initially we do not
- * want to do a complete dynamic linking.  We want to allow the user to
- * supply new functions to override symbols (i.e. weak symbols and/or
- * LD_PRELOAD).  So initially, we only perform relocations for
- * variables that start with "_dl_" since ANSI specifies that the user
- * is not supposed to redefine any of these variables.
- *
- * Fortunately, the linker itself leaves a few clues lying around, and
- * when the kernel starts the image, there are a few further clues.
- * First of all, there is Auxiliary Vector Table information sitting on
- * which is provided to us by the kernel, and which includes
- * information about the load address that the program interpreter was
- * loaded at, the number of sections, the address the application was
- * loaded at and so forth.  Here this information is stored in the
- * array auxvt.  For details see linux/fs/binfmt_elf.c where it calls
- * NEW_AUX_ENT() a bunch of time....
- *
- * Next, we need to find the GOT.  On most arches there is a register
- * pointing to the GOT, but just in case (and for new ports) I've added
- * some (slow) C code to locate the GOT for you. 
- *
- * This code was originally written for SVr4, and there the kernel
- * would load all text pages R/O, so they needed to call mprotect a
- * zillion times to mark all text pages as writable so dynamic linking
- * would succeed.  Then when they were done, they would change the
- * protections for all the pages back again.  Well, under Linux
- * everything is loaded writable (since Linux does copy on write
- * anyways) so all the mprotect stuff has been disabled.
- *
- * Initially, we do not have access to _dl_malloc since we can't yet
- * make function calls, so we mmap one page to use as scratch space.
- * Later on, when we can call _dl_malloc we reuse this this memory.
- * This is also beneficial, since we do not want to use the same memory
- * pool as malloc anyway - esp if the user redefines malloc to do
- * something funky.
- *
- * Our first task is to perform a minimal linking so that we can call
- * other portions of the dynamic linker.  Once we have done this, we
- * then build the list of modules that the application requires, using
- * LD_LIBRARY_PATH if this is not a suid program (/usr/lib otherwise).
- * Once this is done, we can do the dynamic linking as required, and we
- * must omit the things we did to get the dynamic linker up and running
- * in the first place.  After we have done this, we just have a few
- * housekeeping chores and we can transfer control to the user's
- * application.
- */
 
 #include "ldso.h"
 
-
 #define ALLOW_ZERO_PLTGOT
 
-/*  Some arches may need to override this in boot1_arch.h */
-#define            ELFMAGIC    ELFMAG
+/* Pull in the value of _dl_progname */
+#include "_dl_progname.h"
+
+/* Global variables used within the shared library loader */
+char *_dl_library_path         = 0;            /* Where we look for libraries */
+char *_dl_preload              = 0;            /* Things to be loaded before the libs */
+char *_dl_ldsopath             = 0;            /* Location of the shared lib loader */
+unsigned char *_dl_malloc_addr = 0;            /* Lets _dl_malloc use the already allocated memory page */
+unsigned char *_dl_mmap_zero   = 0;            /* Also used by _dl_malloc */
+unsigned long *_dl_brkp        = 0;            /* The end of the data segment for brk and sbrk */
+unsigned long *_dl_envp        = 0;            /* The environment address */
+int _dl_secure                 = 1;            /* Are we dealing with setuid stuff? */
+
 
-/* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */
-#define LD_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ;  REALIGN();
-/*
- * Make sure that the malloc buffer is aligned on 4 byte boundary.  For 64 bit
- * platforms we may need to increase this to 8, but this is good enough for
- * now.  This is typically called after LD_MALLOC.
- */
-#define REALIGN() malloc_buffer = (unsigned char *) (((unsigned long) malloc_buffer + 3) & ~(3))
 
-char *_dl_library_path = 0;            /* Where we look for libraries */
-char *_dl_preload = 0;                 /* Things to be loaded before the libs. */
-char *_dl_ldsopath = 0;
 #ifdef __SUPPORT_LD_DEBUG__
-char *_dl_debug  = 0;
-char *_dl_debug_symbols = 0;
-char *_dl_debug_move    = 0;
-char *_dl_debug_reloc   = 0;
-char *_dl_debug_detail  = 0;
+char *_dl_debug           = 0;
+char *_dl_debug_symbols   = 0;
+char *_dl_debug_move      = 0;
+char *_dl_debug_reloc     = 0;
+char *_dl_debug_detail    = 0;
 char *_dl_debug_nofixups  = 0;
 char *_dl_debug_bindings  = 0;
-int   _dl_debug_file = 2;
-#else
-#define _dl_debug_file 2
-#endif
-static unsigned char *_dl_malloc_addr, *_dl_mmap_zero;
-
-static int _dl_secure = 0;
-static int (*_dl_elf_main) (int, char **, char **);
-struct r_debug *_dl_debug_addr = NULL;
-unsigned long *_dl_brkp;
-unsigned long *_dl_envp;
-int _dl_fixup(struct dyn_elf *rpnt, int flag);
-void _dl_debug_state(void);
-char *_dl_get_last_path_component(char *path);
-
-#include "boot1_arch.h"
-#include "_dl_progname.h"                              /* Pull in the value of _dl_progname */
-
-/* When we enter this piece of code, the program stack looks like this:
-        argc            argument counter (integer)
-        argv[0]         program name (pointer)
-        argv[1...N]     program args (pointers)
-        argv[argc-1]    end of args (integer)
-               NULL
-        env[0...N]      environment variables (pointers)
-        NULL
-               auxvt[0...N]   Auxiliary Vector Table elements (mixed types)
-*/
-
-LD_BOOT(unsigned long args) __attribute__ ((unused));
-LD_BOOT(unsigned long args)
-{
-       unsigned int argc;
-       char **argv, **envp;
-       unsigned long load_addr;
-       unsigned long *got;
-       unsigned long *aux_dat;
-       int goof = 0;
-       ElfW(Ehdr) *header;
-       struct elf_resolve *tpnt;
-       struct elf_resolve *app_tpnt;
-       Elf32_auxv_t auxvt[AT_EGID + 1];
-       unsigned char *malloc_buffer, *mmap_zero;
-       Elf32_Dyn *dpnt;
-       unsigned long *hash_addr;
-       struct r_debug *debug_addr = NULL;
-       int indx;
-       int status;
-
-
-       /* WARNING! -- we cannot make _any_ funtion calls until we have
-        * taken care of fixing up our own relocations.  Making static
-        * inline 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);
-#if defined (__arm__) || defined (__mips__) || defined (__cris__)
-       aux_dat += 1;
-#endif
-       argc = *(aux_dat - 1);
-       argv = (char **) aux_dat;
-       aux_dat += argc;                        /* Skip over the argv pointers */
-       aux_dat++;                                      /* Skip over NULL at end of argv */
-       envp = (char **) aux_dat;
-       while (*aux_dat)
-               aux_dat++;                              /* Skip over the envp pointers */
-       aux_dat++;                                      /* Skip over NULL at end of envp */
-
-       /* Place -1 here as a checkpoint.  We later check if it was changed
-        * when we read in the auxvt */
-       auxvt[AT_UID].a_type = -1;
-
-       /* The junk on the stack immediately following the environment is  
-        * the Auxiliary Vector Table.  Read out the elements of the auxvt,
-        * sort and store them in auxvt for later use. */
-       while (*aux_dat) {
-               Elf32_auxv_t *auxv_entry = (Elf32_auxv_t *) aux_dat;
-
-               if (auxv_entry->a_type <= AT_EGID) {
-                       _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t));
-               }
-               aux_dat += 2;
-       }
-
-       /* locate the ELF header.   We need this done as soon as possible 
-        * (esp since SEND_STDERR() needs this on some platforms... */
-       load_addr = auxvt[AT_BASE].a_un.a_val;
-       header = (ElfW(Ehdr) *) auxvt[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
-#if !defined(__powerpc__) && !defined(__mips__) && !defined(__sh__)
-               || _dl_strncmp((void *) header, ELFMAGIC, SELFMAG) != 0
-#else
-               || header->e_ident[EI_MAG0] != ELFMAG0
-               || header->e_ident[EI_MAG1] != ELFMAG1
-               || header->e_ident[EI_MAG2] != ELFMAG2
-               || header->e_ident[EI_MAG3] != ELFMAG3
-#endif
-               ) {
-               SEND_STDERR("Invalid ELF header\n");
-               _dl_exit(0);
-       }
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-       SEND_STDERR("ELF header=");
-       SEND_ADDRESS_STDERR(load_addr, 1);
-#endif
-
-
-       /* 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 find 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));
-#elif defined(__arm__)
-  __asm__("\tmov %0, r10\n\t":"=r"(got));
-#elif defined(__powerpc__)
-  __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
-#elif defined(__mips__)
-  __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
-#elif defined(__sh__) && !defined(__SH5__)
-  __asm__(
-"       mov.l    1f, %0\n"
-"       mova     1f, r0\n"
-"       bra      2f\n"
-"       add r0,  %0\n"
-"       .balign  4\n"
-"1:     .long    _GLOBAL_OFFSET_TABLE_\n"
-"2:" : "=r" (got) : : "r0");
-#elif defined(__cris__)
-  __asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%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 __SUPPORT_LD_DEBUG_EARLY__
-               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 __SUPPORT_LD_DEBUG_EARLY__
-       SEND_STDERR("First Dynamic section entry=");
-       SEND_ADDRESS_STDERR(dpnt, 1);
-#endif
-
-
-       /* Call mmap to get a page of writable memory that can be used 
-        * for _dl_malloc throughout the shared lib loader. */
-       mmap_zero = malloc_buffer = _dl_mmap((void *) 0, PAGE_SIZE, 
-                       PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
-       if (_dl_mmap_check_error(mmap_zero)) {
-               SEND_STDERR("dl_boot: mmap of a spare page failed!\n");
-               _dl_exit(13);
-       }
-
-       tpnt = LD_MALLOC(sizeof(struct elf_resolve));
-       _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
-       app_tpnt = LD_MALLOC(sizeof(struct elf_resolve));
-       _dl_memset(app_tpnt, 0, sizeof(struct elf_resolve));
-
-#ifdef __UCLIBC_PIE_SUPPORT__
-       /* Find the runtime load address of the main executable, this may be
-         * different from what the ELF header says for ET_DYN/PIE executables.
-        */
-       {
-               ElfW(Phdr) *ppnt;
-               int i;
-
-               ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
-               for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
-                       if (ppnt->p_type == PT_PHDR) {
-                               app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
-                               break;
-                       }
-       }
-
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-       SEND_STDERR("app_tpnt->loadaddr=");
-       SEND_ADDRESS_STDERR(app_tpnt->loadaddr, 1);
-#endif
-#endif
-
-       /*
-        * This is used by gdb to locate the chain of shared libraries that are currently loaded.
-        */
-       debug_addr = LD_MALLOC(sizeof(struct r_debug));
-       _dl_memset(debug_addr, 0, sizeof(struct r_debug));
-
-       /* 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 */
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-       SEND_STDERR("scanning DYNAMIC section\n");
-#endif
-       while (dpnt->d_tag) {
-#if defined(__mips__)
-               if (dpnt->d_tag == DT_MIPS_GOTSYM)
-                       tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val;
-               if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
-                       tpnt->mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
-               if (dpnt->d_tag == DT_MIPS_SYMTABNO)
-                       tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val;
-#endif
-               if (dpnt->d_tag < 24) {
-                       tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-                       if (dpnt->d_tag == DT_TEXTREL) {
-                               tpnt->dynamic_info[DT_TEXTREL] = 1;
-                       }
-               }
-               dpnt++;
-       }
-
-       {
-               ElfW(Phdr) *ppnt;
-               int i;
-
-               ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
-               for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
-                       if (ppnt->p_type == PT_DYNAMIC) {
-#ifndef __UCLIBC_PIE_SUPPORT__
-                               dpnt = (Elf32_Dyn *) ppnt->p_vaddr;
-#else
-                               dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
-#endif
-                               while (dpnt->d_tag) {
-#if defined(__mips__)
-                                       if (dpnt->d_tag == DT_MIPS_GOTSYM)
-                                               app_tpnt->mips_gotsym =
-                                                       (unsigned long) dpnt->d_un.d_val;
-                                       if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
-                                               app_tpnt->mips_local_gotno =
-                                                       (unsigned long) dpnt->d_un.d_val;
-                                       if (dpnt->d_tag == DT_MIPS_SYMTABNO)
-                                               app_tpnt->mips_symtabno =
-                                                       (unsigned long) dpnt->d_un.d_val;
-                                       if (dpnt->d_tag > DT_JMPREL) {
-                                               dpnt++;
-                                               continue;
-                                       }
-                                       app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-
-#warning "Debugging threads on mips won't work till someone fixes this..."
-#if 0
-                                       if (dpnt->d_tag == DT_DEBUG) {
-                                               dpnt->d_un.d_val = (unsigned long) debug_addr;
-                                       }
-#endif
-
-#else
-                                       if (dpnt->d_tag > DT_JMPREL) {
-                                               dpnt++;
-                                               continue;
-                                       }
-                                       app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-                                       if (dpnt->d_tag == DT_DEBUG) {
-                                               dpnt->d_un.d_val = (unsigned long) debug_addr;
-                                       }
-#endif
-                                       if (dpnt->d_tag == DT_TEXTREL)
-                                               app_tpnt->dynamic_info[DT_TEXTREL] = 1;
-                                       dpnt++;
-                               }
-                       }
-       }
-
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-       SEND_STDERR("done scanning DYNAMIC section\n");
-#endif
-
-       /* Get some more of the information that we will need to dynamicly link
-          this module to itself */
-
-       hash_addr = (unsigned long *) (tpnt->dynamic_info[DT_HASH] + load_addr);
-       tpnt->nbucket = *hash_addr++;
-       tpnt->nchain = *hash_addr++;
-       tpnt->elf_buckets = hash_addr;
-       hash_addr += tpnt->nbucket;
-
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-       SEND_STDERR("done grabbing link information\n");
-#endif
-
-#ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
-       /* Ugly, ugly.  We need to call mprotect to change the protection of
-          the text pages so that we can do the dynamic linking.  We can set the
-          protection back again once we are done */
-
-       {
-               ElfW(Phdr) *ppnt;
-               int i;
-
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-               SEND_STDERR("calling mprotect on the shared library/dynamic linker\n");
-#endif
-
-               /* First cover the shared library/dynamic linker. */
-               if (tpnt->dynamic_info[DT_TEXTREL]) {
-                       header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
-                       ppnt = (ElfW(Phdr) *) ((int)auxvt[AT_BASE].a_un.a_ptr + 
-                                       header->e_phoff);
-                       for (i = 0; i < header->e_phnum; i++, ppnt++) {
-                               if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
-                                       _dl_mprotect((void *) (load_addr + (ppnt->p_vaddr & PAGE_ALIGN)), 
-                                                       (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz, 
-                                                       PROT_READ | PROT_WRITE | PROT_EXEC);
-                               }
-                       }
-               }
-
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-               SEND_STDERR("calling mprotect on the application program\n");
-#endif
-               /* Now cover the application program. */
-               if (app_tpnt->dynamic_info[DT_TEXTREL]) {
-                       ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
-                       for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
-                               if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
-#ifndef __UCLIBC_PIE_SUPPORT__
-                                       _dl_mprotect((void *) (ppnt->p_vaddr & PAGE_ALIGN),
-                                                                (ppnt->p_vaddr & ADDR_ALIGN) +
-#else
-                                       _dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN),
-                                                                ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) +
-#endif
-                                                                (unsigned long) ppnt->p_filesz,
-                                                                PROT_READ | PROT_WRITE | PROT_EXEC);
-                       }
-               }
-       }
-#endif
-       
-#if defined(__mips__)
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-       SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
-#endif
-       /* For MIPS we have to do stuff to the GOT before we do relocations.  */
-       PERFORM_BOOTSTRAP_GOT(got);
-#endif
-
-       /* OK, now do the relocations.  We do not do a lazy binding here, so
-          that once we are done, we have considerably more flexibility. */
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-       SEND_STDERR("About to do library loader relocations\n");
-#endif
-
-       goof = 0;
-       for (indx = 0; indx < 2; indx++) {
-               unsigned int i;
-               ELF_RELOC *rpnt;
-               unsigned long *reloc_addr;
-               unsigned long symbol_addr;
-               int symtab_index;
-               unsigned long rel_addr, rel_size;
-
-
-               rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt->
-                        dynamic_info[DT_RELOC_TABLE_ADDR]);
-               rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt->
-                        dynamic_info[DT_RELOC_TABLE_SIZE]);
-
-               if (!rel_addr)
-                       continue;
-
-               /* Now parse the relocation information */
-               rpnt = (ELF_RELOC *) (rel_addr + load_addr);
-               for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
-                       reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
-                       symtab_index = ELF32_R_SYM(rpnt->r_info);
-                       symbol_addr = 0;
-                       if (symtab_index) {
-                               char *strtab;
-                               Elf32_Sym *symtab;
-
-                               symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + load_addr);
-                               strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + load_addr);
-
-                               /* We only do a partial dynamic linking right now.  The user
-                                  is not supposed to redefine any symbols that start with
-                                  a '_', so we can do this with confidence. */
-                               if (!_dl_symbol(strtab + symtab[symtab_index].st_name))
-                                       continue;
-                               symbol_addr = load_addr + symtab[symtab_index].st_value;
-
-                               if (!symbol_addr) {
-                                       /* This will segfault - you cannot call a function until
-                                        * we have finished the relocations.
-                                        */
-                                       SEND_STDERR("ELF dynamic loader - unable to self-bootstrap - symbol ");
-                                       SEND_STDERR(strtab + symtab[symtab_index].st_name);
-                                       SEND_STDERR(" undefined.\n");
-                                       goof++;
-                               }
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-                               SEND_STDERR("About to fixup symbol: ");
-                               SEND_STDERR(strtab + symtab[symtab_index].st_name);
-                               SEND_STDERR("\n");
-#endif  
-                               PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, &symtab[symtab_index]);
-                       } else {
-                               /*
-                                * Use this machine-specific macro to perform the actual relocation.
-                                */
-                               PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, NULL);
-                       }
-               }
-       }
-
-       if (goof) {
-               _dl_exit(14);
-       }
-#ifdef __SUPPORT_LD_DEBUG_EARLY__
-       /* Wahoo!!! */
-       _dl_dprintf(_dl_debug_file, "Done relocating library loader, so we can now\n\tuse globals and make function calls!\n");
+int   _dl_debug_file      = 2;
 #endif
 
-       if (argv[0]) {
-               _dl_progname = argv[0];
-       }
-
-       /* Start to build the tables of the modules that are required for
-        * this beast to run.  We start with the basic executable, and then
-        * go from there.  Eventually we will run across ourself, and we
-        * will need to properly deal with that as well. */
-
-       /* Make it so _dl_malloc can use the page of memory we have already
-        * allocated, so we shouldn't need to grab any more memory */
-       _dl_malloc_addr = malloc_buffer;
-       _dl_mmap_zero = mmap_zero;
+/* Forward function declarations */
+static void debug_fini (int status, void *arg);
+static int _dl_suid_ok(void);
 
+/*
+ * This stub function is used by some debuggers.  The idea is that they
+ * can set an internal breakpoint on it, so that we are notified when the
+ * address mapping is changed in some way.
+ */
+void _dl_debug_state(void)
+{
+}
 
+/* This global variable is also to communicate with debuggers such as gdb. */
+struct r_debug *_dl_debug_addr = NULL;
 
-       /* Now we have done the mandatory linking of some things.  We are now
-          free to start using global variables, since these things have all been
-          fixed up by now.  Still no function calls outside of this library ,
-          since the dynamic resolver is not yet ready. */
-       _dl_get_ready_to_run(tpnt, app_tpnt, load_addr, hash_addr,
-                       auxvt, envp, debug_addr, malloc_buffer, mmap_zero, argv);
 
 
-       /* Transfer control to the application.  */
-       status = 0;                                     /* Used on x86, but not on other arches */
-#if defined (__SUPPORT_LD_DEBUG__)
-       if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ntransfering control: %s\n\n", _dl_progname);        
-#endif    
-       _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn;
-       START();
-}
-
 #if defined (__SUPPORT_LD_DEBUG__)
 static void debug_fini (int status, void *arg)
 {
        (void)status;
        _dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg);
 }
-#endif    
+#endif
 
 void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt,
                unsigned long load_addr, unsigned long *hash_addr,
                Elf32_auxv_t auxvt[AT_EGID + 1], char **envp, struct r_debug *debug_addr,
                unsigned char *malloc_buffer, unsigned char *mmap_zero, char **argv)
-
 {
        ElfW(Phdr) *ppnt;
        char *lpntstr;
@@ -658,6 +103,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
        int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
 #endif
 
+
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
     /* Wahoo!!! */
     SEND_STDERR("Cool, we managed to make a function call.\n");
@@ -673,7 +119,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
         * free to start using global variables, since these things have all been
         * fixed up by now.  Still no function calls outside of this library ,
         * since the dynamic resolver is not yet ready. */
-
        if (argv[0]) {
                _dl_progname = argv[0];
        }
@@ -702,7 +147,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
 
        /* OK, this was a big step, now we need to scan all of the user images
           and load them properly. */
-
        {
                ElfW(Ehdr) *epnt;
                ElfW(Phdr) *myppnt;
@@ -1275,15 +719,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt
        _dl_debug_state();
 }
 
-/*
- * This stub function is used by some debuggers.  The idea is that they
- * can set an internal breakpoint on it, so that we are notified when the
- * address mapping is changed in some way.
- */
-void _dl_debug_state(void)
-{
-}
-
 char *_dl_getenv(const char *symbol, char **envp)
 {
        char *pnt;
@@ -1317,5 +752,21 @@ void _dl_unsetenv(const char *symbol, char **envp)
        return;
 }
 
+static int _dl_suid_ok(void)
+{
+       __kernel_uid_t uid, euid;
+       __kernel_gid_t gid, egid;
+
+       uid = _dl_getuid();
+       euid = _dl_geteuid();
+       gid = _dl_getgid();
+       egid = _dl_getegid();
+
+       if(uid == euid && gid == egid) {
+               return 1;
+       }
+       return 0;
+}
+
 #include "hash.c"
 #include "readelflib1.c"
index cd1f016a61ad4e03ac7c7ab4697b7a3cfe529daf..bab0f88976941fa6ece7d1c86df398e656dde476 100644 (file)
@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define LD_BOOT(X)   void _dl_boot (X)
+#define _dl_boot2 _dl_boot
index cd1f016a61ad4e03ac7c7ab4697b7a3cfe529daf..bab0f88976941fa6ece7d1c86df398e656dde476 100644 (file)
@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define LD_BOOT(X)   void _dl_boot (X)
+#define _dl_boot2 _dl_boot
index 90284f6d471e6caaa06c613628676097e2ae8976..ace21f8e14fa7e45c294ed5a4a0d0e898cf42f07 100644 (file)
@@ -34,5 +34,3 @@ asm("" \
 "      jr $25\n"                       \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X)   static void __attribute__ ((unused)) _dl_boot (X)
index 90284f6d471e6caaa06c613628676097e2ae8976..ace21f8e14fa7e45c294ed5a4a0d0e898cf42f07 100644 (file)
@@ -34,5 +34,3 @@ asm("" \
 "      jr $25\n"                       \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X)   static void __attribute__ ((unused)) _dl_boot (X)
index e50e8eabdccd7dbc7d95bbb95761628572f6238b..284207f17a3efec8d1ffe8753032e973f774cee5 100644 (file)
@@ -17,6 +17,3 @@ asm("" \
 ".previous\n"                          \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X) static void __attribute__ ((unused)) _dl_boot (X)
-
index e50e8eabdccd7dbc7d95bbb95761628572f6238b..284207f17a3efec8d1ffe8753032e973f774cee5 100644 (file)
@@ -17,6 +17,3 @@ asm("" \
 ".previous\n"                          \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X) static void __attribute__ ((unused)) _dl_boot (X)
-
index 81d29d1192eedc46395ba85dabf72d68bbf9d1a9..83451bc562c3761213c5f09690d51061a4f4e855 100644 (file)
@@ -18,5 +18,3 @@ asm("" \
 "      .previous\n"                    \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
index 81d29d1192eedc46395ba85dabf72d68bbf9d1a9..83451bc562c3761213c5f09690d51061a4f4e855 100644 (file)
@@ -18,5 +18,3 @@ asm("" \
 "      .previous\n"                    \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
index 0a538ac304c70c8e55c151304d18712969d72f4b..7c4c3bc64bd22ac48972ccd2bdaf7473a64256b7 100644 (file)
@@ -21,5 +21,3 @@ asm("" \
 "      blink   tr0, r18        ! call _dl_boot2 - user EP is in r2\n"  \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X)   static void * __attribute__ ((unused)) _dl_boot (X)
index 0a538ac304c70c8e55c151304d18712969d72f4b..7c4c3bc64bd22ac48972ccd2bdaf7473a64256b7 100644 (file)
@@ -21,5 +21,3 @@ asm("" \
 "      blink   tr0, r18        ! call _dl_boot2 - user EP is in r2\n"  \
 );
 
-#define _dl_boot _dl_boot2
-#define LD_BOOT(X)   static void * __attribute__ ((unused)) _dl_boot (X)
index cd1f016a61ad4e03ac7c7ab4697b7a3cfe529daf..bab0f88976941fa6ece7d1c86df398e656dde476 100644 (file)
@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define LD_BOOT(X)   void _dl_boot (X)
+#define _dl_boot2 _dl_boot
index cd1f016a61ad4e03ac7c7ab4697b7a3cfe529daf..bab0f88976941fa6ece7d1c86df398e656dde476 100644 (file)
@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define LD_BOOT(X)   void _dl_boot (X)
+#define _dl_boot2 _dl_boot
diff --git a/ldso/ldso/startup.c b/ldso/ldso/startup.c
new file mode 100644 (file)
index 0000000..ec8b792
--- /dev/null
@@ -0,0 +1,583 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (C) 2000-2004 by Erik Andersen <[email protected]>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ *                             David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The main trick with this program is that initially, we ourselves are not
+ * dynamicly linked.  This means that we cannot access any global variables or
+ * call any functions.  No globals initially, since the Global Offset Table
+ * (GOT) is initialized by the linker assuming a virtual address of 0, and no
+ * function calls initially since the Procedure Linkage Table (PLT) is not yet
+ * initialized.
+ *
+ * There are additional initial restrictions - we cannot use large switch
+ * statements, since the compiler generates tables of addresses and jumps
+ * through them.  We cannot use normal syscall stubs, because these all
+ * reference the errno global variable which is not yet initialized.  We _can_
+ * use all of the local stack variables that we want.  We _can_ use inline
+ * functions, because these do not transfer control to a new address, but they
+ * must be static so that they are not exported from the modules.
+ *
+ * Life is further complicated by the fact that initially we do not want to do
+ * a complete dynamic linking.  We want to allow the user to supply new
+ * functions to override symbols (i.e. weak symbols and/or LD_PRELOAD).  So
+ * initially, we only perform relocations for variables that start with "_dl_"
+ * since ANSI specifies that the user is not supposed to redefine any of these
+ * variables.
+ *
+ * Fortunately, the linker itself leaves a few clues lying around, and when the
+ * kernel starts the image, there are a few further clues.  First of all, there
+ * is Auxiliary Vector Table information sitting on which is provided to us by
+ * the kernel, and which includes information about the load address that the
+ * program interpreter was loaded at, the number of sections, the address the
+ * application was loaded at and so forth.  Here this information is stored in
+ * the array auxvt.  For details see linux/fs/binfmt_elf.c where it calls
+ * NEW_AUX_ENT() a bunch of time....
+ *
+ * Next, we need to find the GOT.  On most arches there is a register pointing
+ * to the GOT, but just in case (and for new ports) I've added some (slow) C
+ * code to locate the GOT for you.
+ *
+ * This code was originally written for SVr4, and there the kernel would load
+ * all text pages R/O, so they needed to call mprotect a zillion times to mark
+ * all text pages as writable so dynamic linking would succeed.  Then when they
+ * were done, they would change the protections for all the pages back again.
+ * Well, under Linux everything is loaded writable (since Linux does copy on
+ * write anyways) so all the mprotect stuff has been disabled.
+ *
+ * Initially, we do not have access to _dl_malloc since we can't yet make
+ * function calls, so we mmap one page to use as scratch space.  Later on, when
+ * we can call _dl_malloc we reuse this this memory.  This is also beneficial,
+ * since we do not want to use the same memory pool as malloc anyway - esp if
+ * the user redefines malloc to do something funky.
+ *
+ * Our first task is to perform a minimal linking so that we can call other
+ * portions of the dynamic linker.  Once we have done this, we then build the
+ * list of modules that the application requires, using LD_LIBRARY_PATH if this
+ * is not a suid program (/usr/lib otherwise).  Once this is done, we can do
+ * the dynamic linking as required, and we must omit the things we did to get
+ * the dynamic linker up and running in the first place.  After we have done
+ * this, we just have a few housekeeping chores and we can transfer control to
+ * the user's application.
+ */
+
+#include "ldso.h"
+
+/*  Some arches may need to override this in boot1_arch.h */
+#define        ELFMAGIC ELFMAG
+
+/* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */
+#define LD_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ;  REALIGN();
+
+/* Make sure that the malloc buffer is aligned on 4 byte boundary.  For 64 bit
+ * platforms we may need to increase this to 8, but this is good enough for
+ * now.  This is typically called after LD_MALLOC.  */
+#define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3))
+
+/* Pull in all the arch specific stuff */
+#include "boot1_arch.h"
+
+/* Static declarations */
+int (*_dl_elf_main) (int, char **, char **);
+
+
+
+
+/* When we enter this piece of code, the program stack looks like this:
+        argc            argument counter (integer)
+        argv[0]         program name (pointer)
+        argv[1...N]     program args (pointers)
+        argv[argc-1]    end of args (integer)
+               NULL
+        env[0...N]      environment variables (pointers)
+        NULL
+               auxvt[0...N]   Auxiliary Vector Table elements (mixed types)
+*/
+void _dl_boot2(unsigned long args)
+{
+       unsigned int argc;
+       char **argv, **envp;
+       unsigned long load_addr;
+       unsigned long *got;
+       unsigned long *aux_dat;
+       int goof = 0;
+       ElfW(Ehdr) *header;
+       struct elf_resolve *tpnt;
+       struct elf_resolve *app_tpnt;
+       Elf32_auxv_t auxvt[AT_EGID + 1];
+       unsigned char *malloc_buffer, *mmap_zero;
+       Elf32_Dyn *dpnt;
+       unsigned long *hash_addr;
+       struct r_debug *debug_addr = NULL;
+       int indx;
+#if defined(__i386__)
+       int status = 0;
+#endif
+
+
+       /* WARNING! -- we cannot make _any_ funtion calls until we have
+        * taken care of fixing up our own relocations.  Making static
+        * inline 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);
+#if defined (__arm__) || defined (__mips__) || defined (__cris__)
+       aux_dat += 1;
+#endif
+       argc = *(aux_dat - 1);
+       argv = (char **) aux_dat;
+       aux_dat += argc;                        /* Skip over the argv pointers */
+       aux_dat++;                                      /* Skip over NULL at end of argv */
+       envp = (char **) aux_dat;
+       while (*aux_dat)
+               aux_dat++;                              /* Skip over the envp pointers */
+       aux_dat++;                                      /* Skip over NULL at end of envp */
+
+       /* Place -1 here as a checkpoint.  We later check if it was changed
+        * when we read in the auxvt */
+       auxvt[AT_UID].a_type = -1;
+
+       /* The junk on the stack immediately following the environment is
+        * the Auxiliary Vector Table.  Read out the elements of the auxvt,
+        * sort and store them in auxvt for later use. */
+       while (*aux_dat) {
+               Elf32_auxv_t *auxv_entry = (Elf32_auxv_t *) aux_dat;
+
+               if (auxv_entry->a_type <= AT_EGID) {
+                       _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t));
+               }
+               aux_dat += 2;
+       }
+
+       /* locate the ELF header.   We need this done as soon as possible
+        * (esp since SEND_STDERR() needs this on some platforms... */
+       load_addr = auxvt[AT_BASE].a_un.a_val;
+       header = (ElfW(Ehdr) *) auxvt[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
+#if !defined(__powerpc__) && !defined(__mips__) && !defined(__sh__)
+               || _dl_strncmp((void *) header, ELFMAGIC, SELFMAG) != 0
+#else
+               || header->e_ident[EI_MAG0] != ELFMAG0
+               || header->e_ident[EI_MAG1] != ELFMAG1
+               || header->e_ident[EI_MAG2] != ELFMAG2
+               || header->e_ident[EI_MAG3] != ELFMAG3
+#endif
+               ) {
+               SEND_STDERR("Invalid ELF header\n");
+               _dl_exit(0);
+       }
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("ELF header=");
+       SEND_ADDRESS_STDERR(load_addr, 1);
+#endif
+
+
+       /* 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 find 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));
+#elif defined(__arm__)
+  __asm__("\tmov %0, r10\n\t":"=r"(got));
+#elif defined(__powerpc__)
+  __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
+#elif defined(__mips__)
+  __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
+#elif defined(__sh__) && !defined(__SH5__)
+  __asm__(
+"       mov.l    1f, %0\n"
+"       mova     1f, r0\n"
+"       bra      2f\n"
+"       add r0,  %0\n"
+"       .balign  4\n"
+"1:     .long    _GLOBAL_OFFSET_TABLE_\n"
+"2:" : "=r" (got) : : "r0");
+#elif defined(__cris__)
+  __asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%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 __SUPPORT_LD_DEBUG_EARLY__
+               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 __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("First Dynamic section entry=");
+       SEND_ADDRESS_STDERR(dpnt, 1);
+#endif
+
+
+       /* Call mmap to get a page of writable memory that can be used
+        * for _dl_malloc throughout the shared lib loader. */
+       mmap_zero = malloc_buffer = _dl_mmap((void *) 0, PAGE_SIZE,
+                       PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+       if (_dl_mmap_check_error(mmap_zero)) {
+               SEND_STDERR("dl_boot: mmap of a spare page failed!\n");
+               _dl_exit(13);
+       }
+
+       tpnt = LD_MALLOC(sizeof(struct elf_resolve));
+       _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
+       app_tpnt = LD_MALLOC(sizeof(struct elf_resolve));
+       _dl_memset(app_tpnt, 0, sizeof(struct elf_resolve));
+
+#ifdef __UCLIBC_PIE_SUPPORT__
+       /* Find the runtime load address of the main executable, this may be
+         * different from what the ELF header says for ET_DYN/PIE executables.
+        */
+       {
+               ElfW(Phdr) *ppnt;
+               int i;
+
+               ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+               for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
+                       if (ppnt->p_type == PT_PHDR) {
+                               app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
+                               break;
+                       }
+       }
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("app_tpnt->loadaddr=");
+       SEND_ADDRESS_STDERR(app_tpnt->loadaddr, 1);
+#endif
+#endif
+
+       /*
+        * This is used by gdb to locate the chain of shared libraries that are currently loaded.
+        */
+       debug_addr = LD_MALLOC(sizeof(struct r_debug));
+       _dl_memset(debug_addr, 0, sizeof(struct r_debug));
+
+       /* 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 */
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("scanning DYNAMIC section\n");
+#endif
+       while (dpnt->d_tag) {
+#if defined(__mips__)
+               if (dpnt->d_tag == DT_MIPS_GOTSYM)
+                       tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val;
+               if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
+                       tpnt->mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
+               if (dpnt->d_tag == DT_MIPS_SYMTABNO)
+                       tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val;
+#endif
+               if (dpnt->d_tag < 24) {
+                       tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_TEXTREL) {
+                               tpnt->dynamic_info[DT_TEXTREL] = 1;
+                       }
+               }
+               dpnt++;
+       }
+
+       {
+               ElfW(Phdr) *ppnt;
+               int i;
+
+               ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+               for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
+                       if (ppnt->p_type == PT_DYNAMIC) {
+#ifndef __UCLIBC_PIE_SUPPORT__
+                               dpnt = (Elf32_Dyn *) ppnt->p_vaddr;
+#else
+                               dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
+#endif
+                               while (dpnt->d_tag) {
+#if defined(__mips__)
+                                       if (dpnt->d_tag == DT_MIPS_GOTSYM)
+                                               app_tpnt->mips_gotsym =
+                                                       (unsigned long) dpnt->d_un.d_val;
+                                       if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
+                                               app_tpnt->mips_local_gotno =
+                                                       (unsigned long) dpnt->d_un.d_val;
+                                       if (dpnt->d_tag == DT_MIPS_SYMTABNO)
+                                               app_tpnt->mips_symtabno =
+                                                       (unsigned long) dpnt->d_un.d_val;
+                                       if (dpnt->d_tag > DT_JMPREL) {
+                                               dpnt++;
+                                               continue;
+                                       }
+                                       app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+
+#warning "Debugging threads on mips won't work till someone fixes this..."
+#if 0
+                                       if (dpnt->d_tag == DT_DEBUG) {
+                                               dpnt->d_un.d_val = (unsigned long) debug_addr;
+                                       }
+#endif
+
+#else
+                                       if (dpnt->d_tag > DT_JMPREL) {
+                                               dpnt++;
+                                               continue;
+                                       }
+                                       app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+                                       if (dpnt->d_tag == DT_DEBUG) {
+                                               dpnt->d_un.d_val = (unsigned long) debug_addr;
+                                       }
+#endif
+                                       if (dpnt->d_tag == DT_TEXTREL)
+                                               app_tpnt->dynamic_info[DT_TEXTREL] = 1;
+                                       dpnt++;
+                               }
+                       }
+       }
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("done scanning DYNAMIC section\n");
+#endif
+
+       /* Get some more of the information that we will need to dynamicly link
+          this module to itself */
+
+       hash_addr = (unsigned long *) (tpnt->dynamic_info[DT_HASH] + load_addr);
+       tpnt->nbucket = *hash_addr++;
+       tpnt->nchain = *hash_addr++;
+       tpnt->elf_buckets = hash_addr;
+       hash_addr += tpnt->nbucket;
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("done grabbing link information\n");
+#endif
+
+#ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
+       /* Ugly, ugly.  We need to call mprotect to change the protection of
+          the text pages so that we can do the dynamic linking.  We can set the
+          protection back again once we are done */
+
+       {
+               ElfW(Phdr) *ppnt;
+               int i;
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+               SEND_STDERR("calling mprotect on the shared library/dynamic linker\n");
+#endif
+
+               /* First cover the shared library/dynamic linker. */
+               if (tpnt->dynamic_info[DT_TEXTREL]) {
+                       header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
+                       ppnt = (ElfW(Phdr) *) ((int)auxvt[AT_BASE].a_un.a_ptr +
+                                       header->e_phoff);
+                       for (i = 0; i < header->e_phnum; i++, ppnt++) {
+                               if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
+                                       _dl_mprotect((void *) (load_addr + (ppnt->p_vaddr & PAGE_ALIGN)),
+                                                       (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
+                                                       PROT_READ | PROT_WRITE | PROT_EXEC);
+                               }
+                       }
+               }
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+               SEND_STDERR("calling mprotect on the application program\n");
+#endif
+               /* Now cover the application program. */
+               if (app_tpnt->dynamic_info[DT_TEXTREL]) {
+                       ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+                       for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
+                               if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
+#ifndef __UCLIBC_PIE_SUPPORT__
+                                       _dl_mprotect((void *) (ppnt->p_vaddr & PAGE_ALIGN),
+                                                                (ppnt->p_vaddr & ADDR_ALIGN) +
+                                                                (unsigned long) ppnt->p_filesz,
+                                                                PROT_READ | PROT_WRITE | PROT_EXEC);
+#else
+                                       _dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN),
+                                                                ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) +
+                                                                (unsigned long) ppnt->p_filesz,
+                                                                PROT_READ | PROT_WRITE | PROT_EXEC);
+#endif
+                       }
+               }
+       }
+#endif
+
+#if defined(__mips__)
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
+#endif
+       /* For MIPS we have to do stuff to the GOT before we do relocations.  */
+       PERFORM_BOOTSTRAP_GOT(got);
+#endif
+
+       /* OK, now do the relocations.  We do not do a lazy binding here, so
+          that once we are done, we have considerably more flexibility. */
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("About to do library loader relocations\n");
+#endif
+
+       goof = 0;
+       for (indx = 0; indx < 2; indx++) {
+               unsigned int i;
+               ELF_RELOC *rpnt;
+               unsigned long *reloc_addr;
+               unsigned long symbol_addr;
+               int symtab_index;
+               unsigned long rel_addr, rel_size;
+
+
+               rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt->
+                        dynamic_info[DT_RELOC_TABLE_ADDR]);
+               rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt->
+                        dynamic_info[DT_RELOC_TABLE_SIZE]);
+
+               if (!rel_addr)
+                       continue;
+
+               /* Now parse the relocation information */
+               rpnt = (ELF_RELOC *) (rel_addr + load_addr);
+               for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
+                       reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
+                       symtab_index = ELF32_R_SYM(rpnt->r_info);
+                       symbol_addr = 0;
+                       if (symtab_index) {
+                               char *strtab;
+                               char *symname;
+                               Elf32_Sym *symtab;
+
+                               symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + load_addr);
+                               strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + load_addr);
+                               symname = strtab + symtab[symtab_index].st_name;
+
+                               /* We only do a partial dynamic linking right now.  The user
+                                  is not supposed to define any symbols that start with a
+                                  '_dl', so we can do this with confidence. */
+                               if (!symname || symname[0] != '_' ||
+                                               symname[1] != 'd' || symname[2] != 'l' || symname[3] != '_')
+                               {
+                                       continue;
+                               }
+                               symbol_addr = load_addr + symtab[symtab_index].st_value;
+
+                               if (!symbol_addr) {
+                                       /* This will segfault - you cannot call a function until
+                                        * we have finished the relocations.
+                                        */
+                                       SEND_STDERR("ELF dynamic loader - unable to self-bootstrap - symbol ");
+                                       SEND_STDERR(symname);
+                                       SEND_STDERR(" undefined.\n");
+                                       goof++;
+                               }
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+                               SEND_STDERR("relocating symbol: ");
+                               SEND_STDERR(symname);
+                               SEND_STDERR("\n");
+#endif
+                               PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, &symtab[symtab_index]);
+                       } else {
+                               /* Use this machine-specific macro to perform the actual relocation.  */
+                               PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, NULL);
+                       }
+               }
+       }
+
+       if (goof) {
+               _dl_exit(14);
+       }
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       /* Wahoo!!! */
+       SEND_STDERR("Done relocating library loader, so we can now\n"
+                       "\tuse globals and make function calls!\n");
+#endif
+
+       /* Now we have done the mandatory linking of some things.  We are now
+          free to start using global variables, since these things have all been
+          fixed up by now.  Still no function calls outside of this library ,
+          since the dynamic resolver is not yet ready. */
+       _dl_get_ready_to_run(tpnt, app_tpnt, load_addr, hash_addr,
+                       auxvt, envp, debug_addr, malloc_buffer, mmap_zero, argv);
+
+
+       /* Transfer control to the application.  */
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+       SEND_STDERR("transfering control to application\n");
+#endif
+       _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn;
+       START();
+}
+
This page took 0.126705 seconds and 4 git commands to generate.