From f41c80910d631bacdaf39ec6d11272db79c59d38 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 24 Aug 1997 10:55:18 +0000 Subject: Update. 1997-08-24 12:24 Ulrich Drepper * configure.in (INSTALL): Quote `$'. * libc.map: Add __xpg_basename. * csu/Makefile (initfini.s): Disable optimization. * elf/dl-deps.c: Implement handling of DL_FILTER. * elf/dl-load.c (_dl_init_paths): Add error check. * intl/finddomain.c (_nl_find_domain): Correct comment. * intl/localealias.c: Include not . * libio/stdio.h: Make {,v}snprintf available if __USE_BSD. Change extern inline functions to work correctly in C++. * locale/iso-4217.def: Update for more recent ISO 4217 version. * locale/loadlocale.c (_nl_load_locale): Add cast. * manual/message.texi: Finish gettext section. * posix/getopt_init.c: Don't use relative #include path. (__getopt_clean_environment): Change function to take pointer to environment as argument. Optimize generation of test string a bit. * sysdeps/unix/sysv/linux/init-first.c: Call __getopt_clean_environment with additional argument. * poisx/glob.c: Add prototype for next_brace_sub. * sysdeps/generic/dl-sysdep.c: Recognize AT_BASE value on auxiliary vector. * sysdeps/i386/dl-machine.h (elf_machine_load_address): Rewrite to not generate relocation entry. Suggested by Richard Henderson. (ELF_MACHINE_BEFORE_RTLD_RELOC): Removed. (elf_machine_runtime_setup): Add .aligns. * sysdeps/i386/fpu/fraiseexcpt.c: Add volatile to asms. * sysdeps/i386/fpu/bits/mathinline.h: Partially undo change of 1997-08-14 03:14. gcc 2.7.2* is really broken in some aspects. * sysdeps/standalone/i386/i386.h: Clean up asm statements a bit. * sysdeps/standalone/i960/i960ca.h: Likewise. 1997-08-22 19:04 Richard Henderson * elf/rtld.c (_dl_start): Init _dl_rtld_map.l_opencount due to undocumented test addition in _dl_map_object. Support ET_EXEC versions of ld.so, for debugging at least: * elf/dl-load.c (_dl_map_object): Add_name_to_object could get called despite the DT_SONAME != NULL test, segfaulting. Simplify the code here as well. * elf/dl-lookup.c (do_lookup): Skip objects with no symtab. (_dl_setup_hash): Likewise for hash tables. * elf/dl-version.c (_dl_check_map_versions): Likewise for strtabs. * elf/rtld.c (_dl_start): Likewise for rpath. (_dl_rtld_libname2): New variable. (dl_main): Use it to add an soname for ourselves when we don't have one of our own. Base it on the target's .interp. (dl_main): Again, skip printing of objects that don't have strtabs. Sparc 32 merge: * elf/dl-runtime.c (ELF_FIXUP_RETURN_VALUE): Provide default value. (fixup): Simplify code. Use ELF_FIXUP_RETURN_VALUE. (profile_fixup): Likewise, though this still needs fixing for Sparc32 and PPC. * sysdeps/powerpc/dl-machine.h: Transmute ELF_FIXUP_RETURNS_ADDRESS to ELF_FIXUP_RETURN_VALUE. * sysdeps/sparc/sparc32/dl-machine.h: Implement lazy relocation. Fix up _dl_start_user to handle _dl_skip_args properly. Use _dl_hwcap to determine if "flush" is available/needed. * sysdeps/sparc/configure.in: Remove. It doesn't actually do anything anymore, and what it did do is done somewhere else. * sysdeps/sparc/configure: Likewise. * sysdeps/sparc/fpu/bits/mathdef.h (FP_ILOGB0, FP_ILOGBNAN): New. * sysdeps/sparc/fpu/fraiseexcpt.c: Rearrange for smaller code. * sysdeps/sparc/sparc32/Makefile: Fix sparc->sparc/sparc32 bits in divrem expansions. * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h (END, LOC): New definitions for assembly syntax differences. * sysdeps/sparc/sparc32/__longjmp.S: %g6,%g7 are reserved to the "system". Use %g2,%g3 instead. Use new local label macro. * sysdeps/sparc/sparc32/add_n.S: Use and ENTRY, END, and LOC for proper assembly headers/footers. * sysdeps/sparc/sparc32/addmul_1.S: Likewise. * sysdeps/sparc/sparc32/alloca.S: Likewise. * sysdeps/sparc/sparc32/dotmul.S: Likewise. * sysdeps/sparc/sparc32/lshift.S: Likewise. * sysdeps/sparc/sparc32/mul_1.S: Likewise. * sysdeps/sparc/sparc32/rshift.S: Likewise. * sysdeps/sparc/sparc32/sparcv8/addmul_1.S: Likewise. * sysdeps/sparc/sparc32/sparcv8/mul_1.S: Likewise. * sysdeps/sparc/sparc32/sparcv8/submul_1.S: Likewise. * sysdeps/sparc/sparc32/sparcv8/udiv_qrnnd.S: Likewise. * sysdeps/sparc/sparc32/sub_n.S: Likewise. * sysdeps/sparc/sparc32/submul_1.S: Likewise. * sysdeps/sparc/sparc32/udiv_qrnnd.S: Likewise. * sysdeps/sparc/sparc32/umul.S: Likewise. * sysdeps/sparc/sparc32/divrem.m4: Likewise. * sysdeps/sparc/sparc32/rem.S: Regenerate. * sysdeps/sparc/sparc32/sdiv.S: Regenerate. * sysdeps/sparc/sparc32/udiv.S: Regenerate. * sysdeps/sparc/sparc32/urem.S: Regenerate. * sysdeps/sparc/sparc32/sparcv8/dotmul.S: New file. * sysdeps/sparc/sparc32/sparcv8/rem.S: New file. * sysdeps/sparc/sparc32/sparcv8/sdiv.S: New file. * sysdeps/sparc/sparc32/sparcv8/udiv.S: New file. * sysdeps/sparc/sparc32/sparcv8/umul.S: New file. * sysdeps/sparc/sparc32/sparcv8/urem.S: New file. * sysdeps/sparc/sparc32/bsd-_setjmp.S: Dike out. * sysdeps/sparc/sparc32/bsd-setjmp.S: Likewise. * sysdeps/sparc/sparc32/setjmp.S: Add _setjmp and setjmp entry points. * sysdeps/unix/sysv/linux/sparc/sparc32/__sigtrampoline.S: Clean up PIC code. * sysdeps/sparc/sparc32/elf/start.S: New file, slightly modified from the sparc64 version. * sysdeps/sparc/sparc32/elf/start.c: Removed. * sysdeps/unix/sysv/linux/sparc/sparc32/init-first.h: Rewrite in assembly based on the sparc64 version. * sysdeps/sparc/sparc32/fpu/bits/fenv.h: Duh. Use proper syntax for manipulating %fsr. * sysdeps/sparc/sparc32/fpu/fpu_control.h: Make IEEE conformance be the default. * elf/elf.h (HWCAP_SPARC_*): New definitions. * elf/rtld.c (_dl_hwcap): New variable. * sysdeps/generic/dl-sysdep.c (_dl_sysdep_start): Record AT_HWCAP. * sysdeps/unix/sysv/linux/sparc/sparc32/getpagesize.c: New file. Attempt to get hold of the page size based on what we might have been told at startup time in _dl_pagesize. This will be obsolete when I finish the kernel hooks for a proper sysconf(), stay tuned. Sparc 64 merge: * sysdeps/sparc/sparc64/dl-machine.h (ELF_FIXUP_RETURN_VALUE): New. Figure out the right thing to return based on the .plt format. * sysdeps/sparc/sparc64/fpu/fpu_control.h: Update comment. * sysdeps/unix/sysv/linux/sparc/sparc64/bits/types.h (__dev_t): Should have been 64-bits wide. * sysdeps/unix/sysv/linux/sparc/sparc64/init-first.h: sll->sllx, optimize for branch delay slot usage. 1997-08-22 Andreas Schwab * csu/Makefile ($(objpfx)crt%.o): Fix a missing *.so -> *.os change. 1997-08-20 Andreas Jaeger * math/libm-test.c (identities): Change epsilon. * sysdeps/i386/fpu/bits/mathinline.h: Correct arguments to fabs, fabsf, fabsl, __fabsl. * sysdeps/libm-i387/e_remainderl.S: Pop extra value from FPU stack. * sysdeps/libm-ieee754/s_csinhl.c: Include . --- sysdeps/sparc/sparc32/dl-machine.h | 372 +++++++++++++++++++------------------ 1 file changed, 187 insertions(+), 185 deletions(-) (limited to 'sysdeps/sparc/sparc32/dl-machine.h') diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h index f7bcba0c2f..7c547f24ba 100644 --- a/sysdeps/sparc/sparc32/dl-machine.h +++ b/sysdeps/sparc/sparc32/dl-machine.h @@ -30,7 +30,7 @@ #define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */ #define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */ #define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */ -#define OPCODE_SAVE_SP64 0x9de3bfc0 /* save %sp, -64, %sp */ +#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */ /* Return nonzero iff E_MACHINE is compatible with the running host. */ @@ -55,7 +55,7 @@ elf_machine_dynamic (void) static inline Elf32_Addr elf_machine_load_address (void) { - register Elf32_Addr pc __asm("%o7"), got; + register Elf32_Addr pc __asm("%o7"), pic __asm("%l7"), got; /* Utilize the fact that a local .got entry will be partially initialized at startup awaiting its RELATIVE fixup. */ @@ -64,50 +64,187 @@ elf_machine_load_address (void) ".Load_address:\n\t" "call 1f\n\t" "or %1,%%lo(.Load_address),%1\n" - "1:\tld [%%l7+%1],%1" - : "=r"(pc), "=r"(got)); + "1:\tld [%2+%1],%1" + : "=r"(pc), "=r"(got) : "r"(pic)); return pc - got; } - Elf32_Addr addr; - - asm ( - "add %%fp,0x44,%%o2\n\t" /* o2 = point to argc */ - "ld [%%o2 - 4],%%o0\n\t" /* o0 = load argc */ - "sll %%o0, 2, %%o0\n\t" /* o0 = argc * sizeof (int) */ - "add %%o2,%%o0,%%o2\n\t" /* o2 = skip over argv */ - "add %%o2,4,%%o2\n\t" /* skip over null after argv */ - - /* Now %o2 is pointing to env, skip over that as well. */ - "1:\n\t" - "ld [%%o2],%%o0\n\t" - "cmp %%o0,0\n\t" - "bnz 1b\n\t" - "add %%o2,4,%%o2\n\t" - - /* Note that above, we want to advance the NULL after envp so - we always add 4. */ - - /* Now, search for the AT_BASE property. */ - "2:\n\t" - "ld [%%o2],%%o0\n\t" - "cmp %%o0,0\n\t" - "be,a 3f\n\t" - "or %%g0,%%g0,%0\n\t" - "cmp %%o0,7\n\t" /* AT_BASE = 7 */ - "be,a 3f\n\t" - "ld [%%o2+4],%0\n\t" - "b 2b\n\t" - "add %%o2,8,%%o2\n\t" - /* At this point %0 has the load address for the interpreter */ - "3:\n\t" - : "=r" (addr) - : /* no inputs */ - : "o0", "o2"); - return addr; +/* Set up the loaded object described by L so its unrelocated PLT + entries will jump to the on-demand fixup code in dl-runtime.c. */ + +static inline int +elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) +{ + Elf32_Addr *plt; + extern void _dl_runtime_resolve (Elf32_Word); + + if (l->l_info[DT_JMPREL] && lazy) + { + /* The entries for functions in the PLT have not yet been filled in. + Their initial contents will arrange when called to set the high 22 + bits of %g1 with an offset into the .rela.plt section and jump to + the beginning of the PLT. */ + plt = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr); + + /* The beginning of the PLT does: + + save %sp, -64, %sp + pltpc: call _dl_runtime_resolve + nop + .word MAP + + This saves the register window containing the arguments, and the + PC value (pltpc) implicitly saved in %o7 by the call points near the + location where we store the link_map pointer for this object. */ + + plt[0] = OPCODE_SAVE_SP; + /* Construct PC-relative word address. */ + plt[1] = OPCODE_CALL | (((Elf32_Addr) &_dl_runtime_resolve - + (Elf32_Addr) &plt[1]) >> 2); + plt[2] = OPCODE_NOP; /* Fill call delay slot. */ + plt[3] = (Elf32_Addr) l; + } + + return lazy; } +/* This code is used in dl-runtime.c to call the `fixup' function + and then redirect to the address it returns. */ +#define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ + .globl _dl_runtime_resolve + .type _dl_runtime_resolve, @function +_dl_runtime_resolve: + /* Set up the arguments to fixup -- + %o0 = link_map out of plt0 + %o1 = offset of reloc entry */ + ld [%o7 + 8], %o0 + srl %g1, 10, %o1 + call fixup + sub %o1, 4*12, %o1 + jmp %o0 + restore + .size _dl_runtime_resolve, . - _dl_runtime_resolve"); + +/* The address of the JMP_SLOT reloc is the .plt entry, thus we don't + dereference the reloc's addr to get the final destination. Ideally + there would be a generic way to return the value of the symbol from + elf_machine_relplt, but as it is, the address of the .plt entry is + good enough. */ +#define ELF_FIXUP_RETURN_VALUE(map, result) ((Elf32_Addr) &(result)) + +/* Nonzero iff TYPE should not be allowed to resolve to one of + the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_lookup_noexec_p(type) ((type) == R_SPARC_COPY) + +/* Nonzero iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. */ +#define elf_machine_lookup_noplt_p(type) ((type) == R_SPARC_JMP_SLOT) + +/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ +#define ELF_MACHINE_RELOC_NOPLT R_SPARC_JMP_SLOT + +/* The SPARC never uses Elf32_Rel relocations. */ +#define ELF_MACHINE_NO_REL 1 + +/* The SPARC overlaps DT_RELA and DT_PLTREL. */ +#define ELF_MACHINE_PLTREL_OVERLAP 1 + +/* The PLT uses Elf32_Rela relocs. */ +#define elf_machine_relplt elf_machine_rela + +/* Initial entry point code for the dynamic linker. + The C function `_dl_start' is the real entry point; + its return value is the user program's entry point. */ + +#define RTLD_START __asm__ ("\ +.text + .globl _start + .type _start,@function +_start: + /* Allocate space for functions to drop their arguments. */ + sub %sp, 6*4, %sp + /* Pass pointer to argument block to _dl_start. */ + call _dl_start + add %sp, 22*4, %o0 + /* FALTHRU */ + .globl _dl_start_user + .type _dl_start_user,@function +_dl_start_user: + /* Load the PIC register. */ +1: call 2f + sethi %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7 +2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7 + add %l7, %o7, %l7 + /* Save the user entry point address in %l0 */ + mov %o0, %l0 + /* See if we were run as a command with the executable file name as an + extra leading argument. If so, adjust the contents of the stack. */ + sethi %hi(_dl_skip_args), %g2 + or %g2, %lo(_dl_skip_args), %g2 + ld [%l7+%g2], %i0 + ld [%i0], %i0 + tst %i0 + beq 3f + nop + /* Find out how far to shift. */ + ld [%sp+22*4], %i1 /* load argc */ + sub %i1, %i0, %i1 + sll %i0, 2, %i2 + st %i1, [%sp+22*4] + add %sp, 23*4, %i1 + add %i1, %i2, %i2 + /* Copy down argv */ +21: ld [%i2], %i3 + add %i2, 4, %i2 + tst %i3 + st %i3, [%i1] + bne 21b + add %i1, 4, %i1 + /* Copy down env */ +22: ld [%i2], %i3 + add %i2, 4, %i2 + tst %i3 + st %i3, [%i1] + bne 22b + add %i1, 4, %i1 + /* Copy down auxiliary table. */ +23: ld [%i2], %i3 + ld [%i2+4], %i4 + add %i2, 8, %i2 + tst %i3 + st %i3, [%i1] + st %i4, [%i1+4] + bne 23b + add %i1, 8, %i1 + /* Load _dl_default_scope[2] to pass to _dl_init_next. */ +3: sethi %hi(_dl_default_scope), %g1 + or %g1, %lo(_dl_default_scope), %g1 + ld [%l7+%g1], %l1 + ld [%l1+2*4], %l1 + /* Call _dl_init_next to return the address of an initializer to run. */ +4: call _dl_init_next + mov %l1, %o0 + tst %o0 + beq 5f + nop + jmpl %o0, %o7 + nop + ba,a 4b + /* Clear the startup flag. */ +5: sethi %hi(_dl_starting_up), %g1 + or %g1, %lo(_dl_starting_up), %g1 + ld [%l7+%g1], %g1 + st %g0, [%g1] + /* Pass our finalizer function to the user in %g1. */ + sethi %hi(_dl_fini), %g1 + or %g1, %lo(_dl_fini), %g1 + ld [%l7+%g1], %g1 + /* Jump to the user's entry point and deallocate the extra stack we got. */ + jmp %l0 + add %sp, 6*4, %sp + .size _dl_start_user,.-_dl_start_user"); + #ifdef RESOLVE /* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */ @@ -117,7 +254,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, const Elf32_Sym *sym, const struct r_found_version *version, Elf32_Addr *const reloc_addr) { - Elf32_Addr loadbase; + extern unsigned long _dl_hwcap; if (ELF32_R_TYPE (reloc->r_info) == R_SPARC_RELATIVE) { @@ -144,6 +281,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, switch (ELF32_R_TYPE (reloc->r_info)) { case R_SPARC_COPY: +#ifndef RTLD_BOOTSTRAP if (sym->st_size > refsym->st_size || (_dl_verbose && sym->st_size < refsym->st_size)) { @@ -159,14 +297,21 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, } memcpy (reloc_addr, (void *) value, MIN (sym->st_size, refsym->st_size)); +#endif break; case R_SPARC_GLOB_DAT: case R_SPARC_32: *reloc_addr = value; break; case R_SPARC_JMP_SLOT: - reloc_addr[1] = OPCODE_SETHI_G1 | (value >> 10); + /* For thread safety, write the instructions from the bottom and + flush before we overwrite the critical "b,a". */ reloc_addr[2] = OPCODE_JMP_G1 | (value & 0x3ff); + if (1 || (_dl_hwcap & 1)) /* HWCAP_SPARC_FLUSH */ + __asm __volatile ("flush %0+8" : : "r"(reloc_addr)); + reloc_addr[1] = OPCODE_SETHI_G1 | (value >> 10); + if (1 || (_dl_hwcap & 1)) /* HWCAP_SPARC_FLUSH */ + __asm __volatile ("flush %0+4" : : "r"(reloc_addr)); break; case R_SPARC_8: *(char *) reloc_addr = value; @@ -218,146 +363,3 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc) } #endif /* RESOLVE */ - -/* Nonzero iff TYPE should not be allowed to resolve to one of - the main executable's symbols, as for a COPY reloc. */ -#define elf_machine_lookup_noexec_p(type) ((type) == R_SPARC_COPY) - -/* Nonzero iff TYPE describes relocation of a PLT entry, so - PLT entries should not be allowed to define the value. */ -#define elf_machine_lookup_noplt_p(type) ((type) == R_SPARC_JMP_SLOT) - -/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ -#define ELF_MACHINE_RELOC_NOPLT R_SPARC_JMP_SLOT - -/* The SPARC never uses Elf32_Rel relocations. */ -#define ELF_MACHINE_NO_REL 1 - -/* The SPARC overlaps DT_RELA and DT_PLTREL. */ -#define ELF_MACHINE_PLTREL_OVERLAP 1 - -/* Set up the loaded object described by L so its unrelocated PLT - entries will jump to the on-demand fixup code in dl-runtime.c. */ - -static inline int -elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) -{ - Elf32_Addr *plt; - extern void _dl_runtime_resolve (Elf32_Word); - - if (l->l_info[DT_JMPREL] && lazy) - { - /* The entries for functions in the PLT have not yet been filled in. - Their initial contents will arrange when called to set the high 22 - bits of %g1 with an offset into the .rela.plt section and jump to - the beginning of the PLT. */ - plt = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr); - - /* The beginning of the PLT does: - - save %sp, -64, %sp - pltpc: call _dl_runtime_resolve - nop - .word MAP - - This saves the register window containing the arguments, and the - PC value (pltpc) implicitly saved in %o7 by the call points near the - location where we store the link_map pointer for this object. */ - - plt[0] = OPCODE_SAVE_SP64; /* save %sp, -64, %sp */ - /* Construct PC-relative word address. */ - plt[1] = OPCODE_CALL | (((Elf32_Addr) &_dl_runtime_resolve - - (Elf32_Addr) &plt[1]) >> 2); - plt[2] = OPCODE_NOP; /* Fill call delay slot. */ - plt[3] = (Elf32_Addr *) l; - } - - return lazy; -} - -/* This code is used in dl-runtime.c to call the `fixup' function - and then redirect to the address it returns. */ -#define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ -# Trampoline for _dl_runtime_resolver - .globl _dl_runtime_resolve - .type _dl_runtime_resolve, @function -_dl_runtime_resolve: - t 1 - #call %g0 - # Pass two args to fixup: the PLT address computed from the PC saved - # in the PLT's call insn, and the reloc offset passed in %g1. - #ld [%o7 + 8], %o1 | Second arg, loaded from PLTPC[2]. - #call fixup - #shrl %g1, 22, %o0 | First arg, set in delay slot of call. - # Jump to the real function. - #jmpl %o0, %g0 - # In the delay slot of that jump, restore the register window - # saved by the first insn of the PLT. - #restore - .size _dl_runtime_resolve, . - _dl_runtime_resolve -"); - -/* The PLT uses Elf32_Rela relocs. */ -#define elf_machine_relplt elf_machine_rela - - -/* Mask identifying addresses reserved for the user program, - where the dynamic linker should not map anything. */ -#define ELF_MACHINE_USER_ADDRESS_MASK ??? - -/* Initial entry point code for the dynamic linker. - The C function `_dl_start' is the real entry point; - its return value is the user program's entry point. */ - -#define RTLD_START __asm__ ( \ -".text\n\ - .globl _start\n\ - .type _start,@function\n\ -_start:\n\ - /* Pass pointer to argument block to _dl_start. */\n\ - add %sp,64,%o0\n\ - call _dl_start\n\ - nop\n\ - \n\ - mov %o0,%l0\n\ - \n\ -2:\n\ - call 1f\n\ - nop\n\ -1:\n\ - sethi %hi(_GLOBAL_OFFSET_TABLE_-(2b-.)),%l2\n\ - sethi %hi(_dl_default_scope),%l3\n\ - or %l2,%lo(_GLOBAL_OFFSET_TABLE_-(2b-.)),%l2\n\ - or %l3,%lo(_dl_default_scope),%l3\n\ - add %o7,%l2,%l1\n\ - # %l1 has the GOT. %l3 has _dl_default_scope GOT offset\n\ - ld [%l1+%l3],%l4\n\ - # %l4 has pointer to _dl_default_scope. Now, load _dl_default_scope [2]\n\ - ld [%l4+8],%l4\n\ - # %l4 has _dl_default_scope [2]\n\ - # call _dl_init_next until it returns 0, pass _dl_default_scope [2]\n\ -3:\n\ - call _dl_init_next\n\ - mov %l4,%o0\n\ - cmp %o0,%g0\n\ - bz,a 4f\n\ - nop\n\ - call %o0\n\ - /* Pass pointer to argument block to this init function */\n\ - add %sp,64,%o0\n\ - b,a 3b\n\ -4:\n\ - # Clear the _dl_starting_up variable and pass _dl_fini in %g1 as per ELF ABI.\n\ - sethi %hi(_dl_starting_up),%l4\n\ - sethi %hi(_dl_fini),%l3\n\ - or %l4,%lo(_dl_starting_up),%l4\n\ - or %l3,%lo(_dl_fini),%l3\n\ - # clear _dl_starting_up\n\ - ld [%l1+%l4],%l5\n\ - st %g0,[%l5]\n\ - # load out fini function for atexit in %g1\n\ - ld [%l3+%l1],%g1\n\ - # jump to the user program entry point.\n\ - jmpl %l0,%g0\n\ - nop\n\ -"); -- cgit 1.4.1