OSDN Git Service

This commit contains a patch from Stefan Allius <allius@atecom.com> to change
authorEric Andersen <andersen@codepoet.org>
Tue, 1 Oct 2002 05:30:25 +0000 (05:30 -0000)
committerEric Andersen <andersen@codepoet.org>
Tue, 1 Oct 2002 05:30:25 +0000 (05:30 -0000)
how uClibc handles _init and _fini, allowing shared lib constructors and
destructors to initialize things in the correct sequence.  Stefan ported the SH
architecture.  I then ported x86, arm, and mips.  x86 and arm are working fine,
but I don't think I quite got things correct for mips.

21 files changed:
extra/gcc-uClibc/gcc-uClibc.c
extra/scripts/get-needed-libgcc-objects.sh
extra/scripts/initfini.pl
ldso/ldso/arm/elfinterp.c
ldso/ldso/dl-elf.c
ldso/ldso/i386/elfinterp.c
ldso/ldso/ldso.c
ldso/ldso/readelflib1.c
ldso/ldso/sh/boot1_arch.h
ldso/ldso/sh/dl-startup.h
ldso/ldso/sh/dl-sysdep.h
ldso/ldso/sh/elfinterp.c
ldso/ldso/sh/ld_sysdep.h
ldso/ldso/sh/resolve.S
libc/Makefile
libc/misc/internals/__uClibc_main.c
libc/sysdeps/linux/arm/crt0.S
libc/sysdeps/linux/i386/crt0.S
libc/sysdeps/linux/mips/crt0.S
libc/sysdeps/linux/sh/crt0.S
libpthread/Makefile

index f260b5e..13049d1 100644 (file)
@@ -122,7 +122,7 @@ int main(int argc, char **argv)
        int use_build_dir = 0, linking = 1, use_static_linking = 0;
        int use_stdinc = 1, use_nostdinc_plus = 0, use_start = 1, use_stdlib = 1, use_pic = 0;
        int source_count = 0, use_rpath = 0, verbose = 0;
-       int ctor_dtor = 0, cplusplus = 0;
+       int ctor_dtor = 1, cplusplus = 0;
        int i, j, k, l, m, n;
        char ** gcc_argv;
        char ** gcc_argument;
@@ -165,7 +165,6 @@ int main(int argc, char **argv)
                GPLUSPLUS_BIN[len-1]='+';
                GPLUSPLUS_BIN[len-2]='+';
            }
-           ctor_dtor = 1;
            cplusplus = 1;
            use_nostdinc_plus = 1;
        }
@@ -307,8 +306,8 @@ int main(int argc, char **argv)
                                        } else if (strcmp("--uclibc-use-rpath",argv[i]) == 0) {
                                            use_rpath = 1;
                                            argv[i]='\0';
-                                       } else if (strcmp("--uclibc-ctors",argv[i]) == 0) {
-                                           ctor_dtor = 1;
+                                       } else if (strcmp("--uclibc-no-ctors",argv[i]) == 0) {
+                                           ctor_dtor = 0;
                                            argv[i]='\0';
                                        }
                                        break;
index 5d81154..00cfab2 100755 (executable)
@@ -48,7 +48,9 @@ echo Extracting referenced libgcc.a objects ...
 
 rm -f obj.need.0
 touch obj.need.0
-while [ -s obj.need ] && ! cmp -s obj.need obj.need.0 ; do
+
+cmp -s obj.need obj.need.0 ; state=$?
+while [ -s obj.need ] && [ $state -ne 0 ] ; do
     (cd tmp-gcc && cat ../obj.need | sort | uniq | xargs $LD -r -o ../libgcc.ldr)
     cp obj.need obj.need.0
     if $NM --undefined-only libgcc.ldr > sym.need ; then
@@ -58,6 +60,7 @@ while [ -s obj.need ] && ! cmp -s obj.need obj.need.0 ; do
            fi
        done
     fi
+    cmp -s obj.need obj.need.0 ; state=$?
 done
 
 cat obj.need | sort | uniq > obj.need.0
index 431b393..41add5d 100755 (executable)
@@ -84,7 +84,7 @@ while(<INITFINI>) {
        $omitcrtn = 0;
        next;
     }
-    if (/^i_am_not_a_leaf/) {
+    if (/i_am_not_a_leaf/) {
        $discard = 1;
        next;
     }
index 4f7e6bd..84b9455 100644 (file)
@@ -236,8 +236,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
                }
                else if (res >0)
                {
-                       _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
-                                       _dl_progname, strtab + symtab[symtab_index].st_name);
+                       _dl_dprintf(2, "can't resolve symbol\n");
                        goof += res;
                }
          }
index 4259a42..199726f 100644 (file)
@@ -318,16 +318,13 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        Elf32_Dyn *dpnt;
        struct elf_resolve *tpnt;
        elf_phdr *ppnt;
-       int piclib;
        char *status;
-       int flags;
        char header[4096];
        unsigned long dynamic_info[24];
        unsigned long *lpnt;
        unsigned long libaddr;
        unsigned long minvma = 0xffffffff, maxvma = 0;
-       int i;
-       int infile;
+       int i, flags, piclib, infile;
 
        /* If this file is already loaded, skip this step */
        tpnt = _dl_check_hashed_files(libname);
@@ -544,28 +541,32 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #if defined(__mips__)
        {
                
-               int i = 1;
+               int indx = 1;
                Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
 
                while(dpnt->d_tag) {
                        dpnt++;
-                       i++;
+                       indx++;
                }
-               dynamic_size = i;
+               dynamic_size = indx;
        }
 #endif
 
-       for (i = 0; i < dynamic_size; i++) 
        {
-               if (dpnt->d_tag > DT_JMPREL) {
+               unsigned long indx;
+
+               for (indx = 0; indx < dynamic_size; indx++) 
+               {
+                       if (dpnt->d_tag > DT_JMPREL) {
+                               dpnt++;
+                               continue;
+                       }
+                       dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
+                               dynamic_info[DT_TEXTREL] = 1;
                        dpnt++;
-                       continue;
-               }
-               dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-               if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
-                       dynamic_info[DT_TEXTREL] = 1;
-               dpnt++;
-       };
+               };
+       }
 
        /* If the TEXTREL is set, this means that we need to make the pages
           writable before we perform relocations.  Do this now. They get set
index 2caaa24..2d08bf4 100644 (file)
@@ -230,8 +230,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
                }
                else if (res >0)
                {
-                       _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
-                                       _dl_progname, strtab + symtab[symtab_index].st_name);
+                       _dl_dprintf(2, "can't resolve symbol\n");
                        goof += res;
                }
          }
index ff13675..b81c840 100644 (file)
@@ -303,12 +303,12 @@ LD_BOOT(unsigned long args)
   __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
 #elif defined(__sh__)
   __asm__(
-"         mov.l    1f, %0"
-"         mova     1f, r0"
-"         bra      2f"
-"         add r0,  %0"
-"         .balign  4"
-"1:       .long    _GLOBAL_OFFSET_TABLE_"
+"       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));
@@ -629,6 +629,13 @@ LD_BOOT(unsigned long args)
        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    
 
 static 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], 
@@ -642,7 +649,9 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
        struct elf_resolve *tpnt1;
        unsigned long brk_addr, *lpnt;
        int (*_dl_atexit) (void *);
-
+#if defined (SUPPORT_LD_DEBUG)
+       int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
+#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
@@ -1196,6 +1205,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
        }
 #endif
        _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, NULL, symbolrel);
+#if defined (SUPPORT_LD_DEBUG)
+       _dl_on_exit = (int (*)(void (*)(int, void *),void*)) 
+               (intptr_t) _dl_find_hash("on_exit", NULL, NULL, symbolrel);
+#endif
 
        /*
         * OK, fix one more thing - set up the debug_addr structure to point
@@ -1246,6 +1259,12 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
                }
                if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
                        (*_dl_atexit) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
+#if defined (SUPPORT_LD_DEBUG)
+                       if(_dl_debug && _dl_on_exit)
+                       {
+                               (*_dl_on_exit)(debug_fini, tpnt->libname);
+                       }
+#endif
                }
 #ifdef LD_DEBUG
                else {
@@ -1318,7 +1337,10 @@ int _dl_fixup(struct elf_resolve *tpnt)
                                        tpnt->dynamic_info[DT_PLTRELSZ], 0);
        }
 #if defined (SUPPORT_LD_DEBUG)
-       if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s; finished\n\n", tpnt->libname);   
+       if(_dl_debug) {
+               _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s", tpnt->libname);     
+               _dl_dprintf(_dl_debug_file,"; finished\n\n");
+       }
 #endif    
        return goof;
 }
index 4259a42..199726f 100644 (file)
@@ -318,16 +318,13 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        Elf32_Dyn *dpnt;
        struct elf_resolve *tpnt;
        elf_phdr *ppnt;
-       int piclib;
        char *status;
-       int flags;
        char header[4096];
        unsigned long dynamic_info[24];
        unsigned long *lpnt;
        unsigned long libaddr;
        unsigned long minvma = 0xffffffff, maxvma = 0;
-       int i;
-       int infile;
+       int i, flags, piclib, infile;
 
        /* If this file is already loaded, skip this step */
        tpnt = _dl_check_hashed_files(libname);
@@ -544,28 +541,32 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #if defined(__mips__)
        {
                
-               int i = 1;
+               int indx = 1;
                Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
 
                while(dpnt->d_tag) {
                        dpnt++;
-                       i++;
+                       indx++;
                }
-               dynamic_size = i;
+               dynamic_size = indx;
        }
 #endif
 
-       for (i = 0; i < dynamic_size; i++) 
        {
-               if (dpnt->d_tag > DT_JMPREL) {
+               unsigned long indx;
+
+               for (indx = 0; indx < dynamic_size; indx++) 
+               {
+                       if (dpnt->d_tag > DT_JMPREL) {
+                               dpnt++;
+                               continue;
+                       }
+                       dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
+                               dynamic_info[DT_TEXTREL] = 1;
                        dpnt++;
-                       continue;
-               }
-               dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-               if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
-                       dynamic_info[DT_TEXTREL] = 1;
-               dpnt++;
-       };
+               };
+       }
 
        /* If the TEXTREL is set, this means that we need to make the pages
           writable before we perform relocations.  Do this now. They get set
index 798121d..40d6a0d 100644 (file)
@@ -7,15 +7,14 @@ asm("\
        .globl  _dl_boot
 _dl_boot:
         mov    r15, r4
-        mov.l  .L_dl_boot2, r1
-       mova    .L_dl_boot2, r0
-       add     r1, r0
-       jsr     @r0
-        add    #4, r4
+       mov.l   .L_dl_boot2, r0
+       bsrf    r0
+       add     #4, r4
+.jmp_loc:
        jmp     @r0
         mov    #0, r4        /* call _start with arg == 0 */
 .L_dl_boot2:\n\
-       .long   _dl_boot2-.\n\
+       .long   _dl_boot2-.jmp_loc\n\
        .previous\n\
 ");
 
index 798121d..40d6a0d 100644 (file)
@@ -7,15 +7,14 @@ asm("\
        .globl  _dl_boot
 _dl_boot:
         mov    r15, r4
-        mov.l  .L_dl_boot2, r1
-       mova    .L_dl_boot2, r0
-       add     r1, r0
-       jsr     @r0
-        add    #4, r4
+       mov.l   .L_dl_boot2, r0
+       bsrf    r0
+       add     #4, r4
+.jmp_loc:
        jmp     @r0
         mov    #0, r4        /* call _start with arg == 0 */
 .L_dl_boot2:\n\
-       .long   _dl_boot2-.\n\
+       .long   _dl_boot2-.jmp_loc\n\
        .previous\n\
 ");
 
index a0ff05f..cf8820e 100644 (file)
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)          \
        switch(ELF32_R_TYPE((RELP)->r_info)){                   \
        case R_SH_REL32:                                        \
-               *(REL) += (RELP)->r_addend - (LOAD);            \
+               *(REL)  = (SYMBOL) + (RELP)->r_addend           \
+                           - (unsigned long)(REL);             \
                break;                                          \
        case R_SH_DIR32:                                        \
-               *(REL) += (SYMBOL) + (RELP)->r_addend;          \
+               *(REL)  = (SYMBOL) + (RELP)->r_addend;          \
                break;                                          \
        case R_SH_RELATIVE:                                     \
-               *(REL) += (LOAD);                               \
+               *(REL)  = (LOAD) + (RELP)->r_addend;            \
                break;                                          \
        case R_SH_NONE:                                         \
                break;                                          \
index 3e0bb87..d94389e 100644 (file)
@@ -236,8 +236,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
                }
                else if (res >0)
                {
-                       _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
-                                       _dl_progname, strtab + symtab[symtab_index].st_name);
+                       _dl_dprintf(2, "can't resolve symbol\n");
                        goof += res;
                }
          }
@@ -289,17 +288,17 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                        /* handled later on */
                        break;
                case R_SH_DIR32:
-                       *reloc_addr += symbol_addr + rpnt->r_addend;
+                       *reloc_addr = symbol_addr + rpnt->r_addend;
                        break;
                case R_SH_JMP_SLOT:
                        *reloc_addr = symbol_addr + rpnt->r_addend;
                        break;
                case R_SH_REL32:
-                       *reloc_addr += rpnt->r_addend -
-                                       (unsigned long) tpnt->loadaddr;
+                       *reloc_addr = symbol_addr + rpnt->r_addend -
+                                       (unsigned long) reloc_addr;
                        break;
                case R_SH_RELATIVE:
-                       *reloc_addr += (unsigned long) tpnt->loadaddr;
+                       *reloc_addr = (unsigned long) tpnt->loadaddr + rpnt->r_addend;
                        break;
                default:
                        return -1; /*call _dl_exit(1) */
index a0ff05f..cf8820e 100644 (file)
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)          \
        switch(ELF32_R_TYPE((RELP)->r_info)){                   \
        case R_SH_REL32:                                        \
-               *(REL) += (RELP)->r_addend - (LOAD);            \
+               *(REL)  = (SYMBOL) + (RELP)->r_addend           \
+                           - (unsigned long)(REL);             \
                break;                                          \
        case R_SH_DIR32:                                        \
-               *(REL) += (SYMBOL) + (RELP)->r_addend;          \
+               *(REL)  = (SYMBOL) + (RELP)->r_addend;          \
                break;                                          \
        case R_SH_RELATIVE:                                     \
-               *(REL) += (LOAD);                               \
+               *(REL)  = (LOAD) + (RELP)->r_addend;            \
                break;                                          \
        case R_SH_NONE:                                         \
                break;                                          \
index 4d8eee6..7fef6d7 100644 (file)
@@ -3,6 +3,7 @@
  */
 
        .text
+       .globl  _dl_linux_resolver
        .globl  _dl_linux_resolve
        .type   _dl_linux_resolve, @function
        .balign 16
@@ -31,13 +32,27 @@ _dl_linux_resolve:
        fmov.s  fr4, @-r15
 #endif
        sts.l   pr, @-r15
+/* Note - The PLT entries have been "optimised" not to use r2.  r2 is used by
+   GCC to return the address of large structures, so it should not be
+   corrupted here.  This does mean however, that those PLTs does not conform
+   to the SH PIC ABI.  That spec says that r0 contains the type of the PLT
+   and r2 contains the GOT id.  The GNU Plt version stores the GOT id in r0 and
+   ignores the type.  We can easily detect this difference however,
+   since the type will always be 0 or 8, and the GOT ids will always be
+   greater than or equal to 12.
 
-       mov     r2, r4          ! link map address
-
-       mov.l   3f, r0
-       jsr     @r0             ! Call resolver
-        mov    r1, r5          ! Reloc offset
-
+   Found in binutils/bfd/elf32-sh.c by Stefan Allius <allius@atecom.com>
+ */
+       mov     #8 ,r5
+       cmp/gt  r5, r0
+       bt      1f
+       mov     r2, r0          ! link map address in r2 (SH PIC ABI)
+1:
+       mov     r0, r4          ! link map address in r0 (GNUs PLT)
+       mov.l   3f, r5
+       bsrf    r5
+       mov     r1, r5          ! Reloc offset
+.jmp_loc:
        lds.l   @r15+, pr       ! Get register content back
 
 #ifdef HAVE_FPU
@@ -64,6 +79,6 @@ _dl_linux_resolve:
 
        .balign 4
 3:
-       .long   _dl_linux_resolver
+       .long   _dl_linux_resolver - .jmp_loc
        .size   _dl_linux_resolve, . - _dl_linux_resolve
 
index 401a566..1809779 100644 (file)
@@ -53,9 +53,9 @@ shared: $(TOPDIR)lib/$(LIBNAME)
                /bin/sh $(TOPDIR)../extra/scripts/get-needed-libgcc-objects.sh)
        $(LD) $(LDFLAGS) $(VERSION_SCRIPT) -soname=$(SHARED_MAJORNAME) -o $(SHARED_FULLNAME) \
                --whole-archive ./tmp/libgcc-need.a $(LIBNAME) --no-whole-archive \
-               $(TOPDIR)/libc/misc/internals/interp.o \
+               -init __uClibc_init $(TOPDIR)/libc/misc/internals/interp.o \
                $(LIBGCC)
-       @/bin/true #rm -rf tmp
+       @true #rm -rf tmp
        install -d $(TOPDIR)lib
        rm -f $(TOPDIR)lib/$(SHARED_FULLNAME)
        install -m 644 $(SHARED_FULLNAME) $(TOPDIR)lib
index 53f897d..aa4655c 100644 (file)
@@ -20,8 +20,6 @@
  * Prototypes.
  */
 extern int  main(int argc, char **argv, char **envp);
-extern void weak_function _init(void);
-extern void weak_function _fini(void);
 extern void weak_function _stdio_init(void);
 extern int *weak_const_function __errno_location(void);
 extern int *weak_const_function __h_errno_location(void);
@@ -36,10 +34,11 @@ extern void weak_function __pthread_initialize_minimal(void);
 
 
 
+
 /*
  * Declare the __environ global variable and create a weak alias environ.
- * Note: Apparently we must initialize __environ for the weak environ
- * symbol to be included.
+ * Note: Apparently we must initialize __environ to ensure that the weak 
+ * environ symbol is also included.
  */
 
 char **__environ = 0;
@@ -47,68 +46,124 @@ weak_alias(__environ, environ);
 
 
 
+/* __uClibc_init completely initialize uClibc so it is ready to use.
+ *
+ * On ELF systems (with a dynamic loader) this function must be called
+ * from the dynamic loader (see TIS and ELF Specification), so that
+ * constructors of shared libraries (which depend on libc) can use all
+ * the libc code without restriction.  For this we link the shared
+ * version of the uClibc with -init __uClibc_init so DT_INIT for
+ * uClibc is the address of __uClibc_init
+ * 
+ * In all other cases we call it from the main stub
+ * __uClibc_start_main.
+ */
 
-void __attribute__ ((__noreturn__)) 
-__uClibc_main(int argc, char **argv, char **envp) 
+void __uClibc_init(void) 
 {
-       /* If we are dynamically linked the shared lib loader
-        * already did this for us.  But if we are statically
-        * linked, we need to do this for ourselves. */
-       if (__environ==NULL) {
-               /* Statically linked. */ 
-               __environ = envp;
-       }
+    static int been_there_done_that = 0;
+
+    if (been_there_done_that) 
+       return;
+    been_there_done_that++;
 
 #ifdef __UCLIBC_HAS_THREADS__
-       if (likely(__pthread_initialize_minimal!=NULL))
-           __pthread_initialize_minimal();
+    /* Before we start initialzing uClibc we have to call
+     * __pthread_initialize_minimal so we can use pthread_locks 
+     * whenever they are needed.
+     */
+    if (likely(__pthread_initialize_minimal!=NULL))
+       __pthread_initialize_minimal();
 #endif
 
 #if 0
-       /* Some security at this point.  Prevent starting a SUID binary
-        * where the standard file descriptors are not opened.  We have
-        * to do this only for statically linked applications since
-        * otherwise the dynamic loader did the work already.  */
-       if (unlikely (__libc_enable_secure!=NULL))
-               __libc_check_standard_fds ();
+    /* Some security at this point.  Prevent starting a SUID binary
+     * where the standard file descriptors are not opened.  We have
+     * to do this only for statically linked applications since
+     * otherwise the dynamic loader did the work already.  */
+    if (unlikely (__libc_enable_secure!=NULL))
+       __libc_check_standard_fds ();
 #endif
 
 #ifdef __UCLIBC_HAS_LOCALE__
-       /* Initialize the global locale structure. */
-       if (likely(_locale_init!=NULL))
-           _locale_init();
+    /* Initialize the global locale structure. */
+    if (likely(_locale_init!=NULL))
+       _locale_init();
 #endif
 
-       /*
-        * Initialize stdio here.  In the static library case, this will
-        * be bypassed if not needed because of the weak alias above.
-        */
-       if (likely(_stdio_init != NULL))
-               _stdio_init();
-
-       /* Arrange for dtors to run at exit.  */
-       if (likely(_fini!=NULL && atexit)) {
-               atexit (&_fini);
-       }
-
-       /* Run all ctors now.  */
-       if (likely(_init!=NULL))
-               _init();
-
-       /*
-        * Note: It is possible that any initialization done above could
-        * have resulted in errno being set nonzero, so set it to 0 before
-        * we call main.
-        */
-       if (likely(__errno_location!=NULL))
-               *(__errno_location()) = 0;
-
-       /* Set h_errno to 0 as well */
-       if (likely(__h_errno_location!=NULL))
-               *(__h_errno_location()) = 0;
-
-       /*
-        * Finally, invoke application's main and then exit.
-        */
-       exit(main(argc, argv, envp));
+    /*
+     * Initialize stdio here.  In the static library case, this will
+     * be bypassed if not needed because of the weak alias above.
+     */
+    if (likely(_stdio_init != NULL))
+       _stdio_init();
+
+}
+
+
+/* __uClibc_start_main is the new main stub for uClibc. This function is 
+ * called from crt0 (version 0.9.16 or newer), after ALL shared libraries 
+ * are initialized, just before we call the application's main function.
+ */
+void __attribute__ ((__noreturn__)) 
+__uClibc_start_main(int argc, char **argv, char **envp, 
+       void (*app_init)(void), void (*app_fini)(void))
+{
+
+    /* If we are dynamically linked the shared lib loader already
+     * did this for us.  But if we are statically linked, we need
+     * to do this for ourselves.  */
+    if (__environ==NULL) {
+       /* Statically linked. */ 
+       __environ = envp;
+    }
+
+    /* We need to initialize uClibc.  If we are dynamically linked this
+     * may have already been completed by the shared lib loader.  We call 
+     * __uClibc_init() regardless, to be sure the right thing happens. */
+    __uClibc_init();
+
+    /* Arrange for the application's dtors to run before we exit.  */
+    if (app_fini!=NULL && atexit) {
+       atexit (app_fini);
+    }
+
+    /* Run all the application's ctors now.  */
+    if (app_init!=NULL) {
+       app_init();
+    }
+
+    /* Note: It is possible that any initialization done above could
+     * have resulted in errno being set nonzero, so set it to 0 before
+     * we call main.
+     */
+    if (likely(__errno_location!=NULL))
+       *(__errno_location()) = 0;
+
+    /* Set h_errno to 0 as well */
+    if (likely(__h_errno_location!=NULL))
+       *(__h_errno_location()) = 0;
+
+    /*
+     * Finally, invoke application's main and then exit.
+     */
+    exit(main(argc, argv, envp));
+}
+
+
+/* __uClibc_main is the old main stub of the uClibc. This
+ * function is called from crt0 (uClibc 0.9.15 and older) after
+ * ALL shared libraries are initialized, and just before we call
+ * the application's main() function.  
+ *
+ * Attention: This stub does not call the .init/.fini sections of
+ * the application. If you need this, please fix your uClibc port
+ * so that  __uClibc_start_main is called by your crt0.S with
+ * _init and _fini properly set.
+*/
+void __attribute__ ((__noreturn__)) 
+__uClibc_main(int argc, char **argv, char ** envp)
+{
+    __uClibc_start_main(argc, argv, envp, NULL, NULL);
 }
+
index 442c9e8..dc0ec87 100644 (file)
@@ -50,20 +50,10 @@ ARM register quick reference:
 
 .text
        .global _start
-       .global __uClibc_main
-
        .type   _start,%function
-       .type   __uClibc_main,%function
 
 .text
 _start:
-#if 0 /* some old code the I feel should not be here - davidm */
-       @ adjust the data segment base pointer
-       ldr r3,=__data_start
-       sub sl,sl,r3
-       mov BASEREG,sl
-#endif
-
        /* clear the frame pointer */
        mov     fp, #0
 
@@ -78,10 +68,11 @@ _start:
           we find there (hopefully the environment) in r2 */
        add     r2, r1, r0, lsl #2
        add     r2, r2, #4
+
 #else
        /*
-        * uClinux stacks look a little different to MMU stacks
-        * for no good reason
+        * uClinux stacks look a little different from normal
+        * MMU-full Linux stacks (for no good reason)
         */
        /* pull argc, argv and envp off the stack */
        ldr r0,[sp, #0]
@@ -89,8 +80,19 @@ _start:
        ldr r2,[sp, #8]
 #endif
 
+       /* Store the address of _init in r3 as an argument to main() */
+       ldr r3, =_init
+
+       /* Push _fini onto the stack as the final argument to main() */
+       stmfd sp!, {r0}
+       ldr a1, =_fini
+       stmfd sp!, {r0}
+
        /* Ok, now run uClibc's main() -- shouldn't return */
-       bl      __uClibc_main
+       bl      __uClibc_start_main
+
+       /* Crash if somehow `exit' returns anyways.  */
+       bl abort
 
 /* Stick in a dummy reference to main(), so that if an application
  * is linking when the main() function is in a static library (.a)
index 3623fe8..97f1fde 100644 (file)
@@ -33,11 +33,11 @@ Cambridge, MA 02139, USA.  */
 .text
        .align 4
 
-.globl _start
-       .type    _start,@function
+       .globl _start
+       .type _start,@function
 
 _start:
-       /* First locate the start of the environment variables */
+       /* locate the start of the environment variables */
        popl %ecx       /* Store argc into %ecx */
        movl %esp,%ebx  /* Store argv into ebx */
        movl %esp,%eax  /* Store argv into eax as well*/
@@ -52,7 +52,6 @@ _start:
            %eax = env      ; argv + (argc * 4) + 4
        */
 
-
        /* Set up an invalid (NULL return address, NULL frame pointer)
           callers stack frame so anybody unrolling the stack knows where
           to stop */
@@ -62,20 +61,18 @@ _start:
        pushl %ebp      /* callers %ebp (frame pointer) */
        movl %esp,%ebp  /* mark callers stack frame as invalid */
 
-       /* Now set the environment, argc, and argv where the app can get to them */
-       pushl %eax      /* Environment pointer */
-       pushl %ebx       /* Argument pointer */
-       pushl %ecx      /* And the argument count */
+       /* Push .init and .fini arguments to __uClibc_start_main() on the stack */
+       pushl $_fini
+       pushl $_init
 
-#if 0
-       /* Make sure we are not using iBCS2 personality. (i.e. force linux).  */
-       movl $136,%eax
-       sub %ebx,%ebx
-       int $0x80
-#endif
+       /* Push envp, argc, and argc arguments to __uClibc_start_main() on the stack */ 
+       pushl %eax      /* Environment pointer */
+       pushl %ebx      /* Argument pointer */
+       pushl %ecx      /* And the argument count */
 
        /* Ok, now run uClibc's main() -- shouldn't return */
-       call __uClibc_main
+       call __uClibc_start_main
+
        /* Crash if somehow `exit' returns anyways.  */
        hlt
 
index 6770ab0..7ff3b25 100644 (file)
@@ -30,9 +30,22 @@ __start:
        addu a2, a0, 1      /* load envp */
         sll  a2, a2, 2
        add  a2, a2, a1
+
+       /* Store the address of _init in a3 as an argument to __uClibc_start_main() */
+       la   a3, _init
+
+       /* Push _fini onto the stack as the final argument to __uClibc_start_main()
+           I don't think I am doing this properly but it at least compiles... 
+       */
+       la   t0, _fini
+       sw   t0,16(sp)
+       
        /* Ok, now run uClibc's main() -- shouldn't return */
-       jal     __uClibc_main
-       hlt:    b hlt                   /* Crash if somehow it does return.  */
+       jal  __uClibc_start_main
+
+       /* Crash if somehow `exit' returns anyways.  */
+hlt:
+       b   hlt
 
 /* Stick in a dummy reference to main(), so that if an application
  * is linking when the main() function is in a static library (.a)
index 10915d5..e74ae86 100644 (file)
 
        At this entry point, most registers' values are unspecified, except:
 
-   r4          Contains a function pointer to be registered with `atexit'.
-               This is how the dynamic linker arranges to have DT_FINI
-               functions called for shared libraries that have been loaded
-               before this code runs.
-               WARNING: At that stage only static linker is supported. For
-               uCLinux we won't bother with r4.
-
    sp          The stack contains the arguments and environment:
                0(sp)                   argc
                4(sp)                   argv[0]
                ...
                                        NULL
 */
+       .file "crt0.S"
        .text
        .globl _start
        .type _start,@function
        .size _start,_start_end - _start
 _start:
-       /* Clear the frame pointer since this is the outermost frame. (in delay slot) */
+       /* Clear the frame pointer since this is the outermost frame. */
        mov #0, r14
 
        /* Pop argc off the stack and save a pointer to argv */
        mov.l @r15+,r4
        mov r15, r5
 
+       /* Push the finip argument to __uClibc_start_main() onto the stack */
+       mov.l L_fini,r6
+       mov.l r6,@-r15
+
+       /* Setup the value for the initp argument */
+       mov.l L_init, r7
+
        /*
         * Setup the value for the environment pointer:
         * r6 = (argc + 1) * 4
@@ -62,27 +63,39 @@ _start:
        mov r4,r6
        add #1,r6
        shll2 r6
-       add r5,r6
 
-       /* call main */
+       /* jump to __uClibc_start_main (argc, argv, envp, app_init, app_fini) */
        mov.l L_main, r0
        jsr @r0
-       nop /* delay slot */
-
+       add r5, r6  /* delay slot */
        /* We should not get here. */
        mov.l L_abort, r0
-       jsr @r0
-       nop /* delay slot */
+       jmp @r0
+       nop
 
 _start_end:    
        .align  2
 
+       .weak   _init
+       .type   _init,@function
+_init:
+       rts
+       nop
+
+.Lfe1:
+       .size   _init,.Lfe1-_init
+       .weak   _fini
+       .set    _fini,_init
 
 L_main:
-       .long   __uClibc_main
+       .long   __uClibc_start_main /* in libuClibc.*.so */
 
-L_abort:
-       .long   abort
+L_init:
+      .long   _init
+L_fini:
+      .long   _fini
+L_abort: 
+      .long   abort   
 
 /* Stick in a dummy reference to main(), so that if an application
  * is linking when the main() function is in a static library (.a)
@@ -90,5 +103,3 @@ L_abort:
 L_dummy_main_reference:
        .long   main
 
-       .data
-
index 7566b47..7edf34f 100644 (file)
@@ -36,6 +36,15 @@ ifeq ($(strip $(DODEBUG)),true)
 endif
 endif
 
+GCC_LIB_DIR = $(dir $(shell $(CC) -print-libgcc-file-name ))
+ifeq ($(strip $(DOPIC)),true)
+    START_FILES  = $(TOPDIR)lib/crti.o     $(GCC_LIB_DIR)crtbeginS.o
+    END_FILES    = $(GCC_LIB_DIR)crtendS.o $(TOPDIR)lib/crtn.o
+else
+    START_FILES  = $(TOPDIR)lib/crti.o    $(GCC_LIB_DIR)crtbegin.o
+    END_FILES    = $(GCC_LIB_DIR)crtend.o $(TOPDIR)lib/crtn.o
+endif
+
 ALL_SUBDIRS = linuxthreads linuxthreads_db
 
 all: $(LIBPTHREAD) $(LIBTHREAD_DB)
@@ -67,9 +76,9 @@ shared: all
        if [ -f $(LIBPTHREAD) ] ; then \
                set -e; \
                $(LD) $(LDFLAGS) -soname=$(LIBPTHREAD_SHARED).$(MAJOR_VERSION) \
-                       -o $(LIBPTHREAD_SHARED_FULLNAME) --whole-archive $(LIBPTHREAD) \
+                       -o $(LIBPTHREAD_SHARED_FULLNAME) $(START_FILES) --whole-archive $(LIBPTHREAD) \
                        --no-whole-archive $(TOPDIR)/libc/misc/internals/interp.o \
-                       -L$(TOPDIR)/lib -lc; \
+                       -L$(TOPDIR)/lib -lc $(END_FILES); \
                install -d $(TOPDIR)lib; \
                rm -f $(TOPDIR)lib/$(LIBPTHREAD_SHARED_FULLNAME) \
                        $(TOPDIR)lib/$(LIBPTHREAD_SHARED).$(MAJOR_VERSION); \
@@ -82,9 +91,9 @@ shared: all
        if [ -f $(LIBTHREAD_DB) ] ; then \
                set -e; \
                $(LD) $(LDFLAGS) -soname=$(LIBTHREAD_DB_SHARED).$(MAJOR_VERSION) \
-                       -o $(LIBTHREAD_DB_SHARED_FULLNAME) --whole-archive $(LIBTHREAD_DB) \
+                       -o $(LIBTHREAD_DB_SHARED_FULLNAME) $(START_FILES) --whole-archive $(LIBTHREAD_DB) \
                        --no-whole-archive $(TOPDIR)/libc/misc/internals/interp.o \
-                       -L$(TOPDIR)/lib -lc; \
+                       -L$(TOPDIR)/lib -lc $(END_FILES); \
                install -d $(TOPDIR)lib; \
                rm -f $(TOPDIR)lib/$(LIBTHREAD_DB_SHARED_FULLNAME) \
                        $(TOPDIR)lib/$(LIBTHREAD_DB_SHARED).$(MAJOR_VERSION); \