}
-/* Return the link-time address of _DYNAMIC. Conveniently, this is the
- first element of the GOT. This must be inlined in a function which
- uses global data. */
-static inline ElfW(Addr)
-elf_machine_dynamic (void)
-{
- register ElfW(Addr) gp asm ("$28");
- return * (ElfW(Addr) *) (gp - 0x7ff0);
-}
-
/* Return the run-time load address of the shared object. */
static inline ElfW(Addr)
elf_machine_load_address (void)
{
ElfW(Addr) addr;
-#ifdef __mips64
- asm (" .set noreorder\n"
- " dla %0, here\n"
- " bltzal $0, here\n"
- " nop\n"
- "here: dsubu %0, $31, %0\n"
- " .set reorder\n"
- : "=r" (addr)
- : /* No inputs */
- : "$31");
-#else
asm (" .set noreorder\n"
" la %0, here\n"
" bltzal $0, here\n"
: "=r" (addr)
: /* No inputs */
: "$31");
-#endif
return addr;
}
t8 index for this function symbol in .dynsym
to usual c arguments. */
-#ifdef __mips64
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-/* The flag _dl_mips_gnu_objects is set if all dynamic objects are \
- generated by the gnu linker. */ \
-int _dl_mips_gnu_objects = 1; \
- \
-/* This is called from assembly stubs below which the compiler can't see. */ \
-static ElfW(Addr) \
-__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr)) \
- __attribute__ ((unused)); \
- \
-static ElfW(Addr) \
-__dl_runtime_resolve (ElfW(Word) sym_index, \
- ElfW(Word) return_address, \
- ElfW(Addr) old_gpreg, \
- ElfW(Addr) stub_pc) \
-{ \
- struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc); \
- const ElfW(Sym) *const symtab \
- = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr); \
- const char *strtab \
- = (void *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); \
- const ElfW(Addr) *got \
- = (const ElfW(Addr) *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr); \
- const ElfW(Word) local_gotno \
- = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; \
- const ElfW(Word) gotsym \
- = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val; \
- const ElfW(Sym) *definer; \
- ElfW(Addr) loadbase; \
- ElfW(Addr) funcaddr; \
- struct link_map **scope; \
- \
- /* Look up the symbol's run-time value. */ \
- scope = _dl_object_relocation_scope (l); \
- definer = &symtab[sym_index]; \
- \
- loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer, \
- scope, l->l_name, ELF_MACHINE_RELOC_NOPLT); \
- \
- *_dl_global_scope_end = NULL; \
- \
- /* Apply the relocation with that value. */ \
- funcaddr = loadbase + definer->st_value; \
- *(got + local_gotno + sym_index - gotsym) = funcaddr; \
- \
- return funcaddr; \
-} \
- \
-asm ("\n \
- .text\n \
- .align 3\n \
- .globl _dl_runtime_resolve\n \
- .type _dl_runtime_resolve,@function\n \
- .ent _dl_runtime_resolve\n \
-_dl_runtime_resolve:\n \
- .set noreorder\n \
- # Save old GP to $3.\n \
- move $3,$28\n \
- # Modify t9 ($25) so as to point .cpload instruction.\n \
- daddu $25,2*8\n \
- # Compute GP.\n \
- .cpload $25\n \
- .set reorder\n \
- # Save slot call pc.\n \
- move $2, $31\n \
- # Save arguments and sp value in stack.\n \
- dsubu $29, 10*8\n \
- .cprestore 8*8\n \
- sd $15, 9*8($29)\n \
- sd $4, 3*8($29)\n \
- sd $5, 4*8($29)\n \
- sd $6, 5*8($29)\n \
- sd $7, 6*8($29)\n \
- sd $16, 7*8($29)\n \
- move $16, $29\n \
- move $4, $24\n \
- move $5, $15\n \
- move $6, $3\n \
- move $7, $2\n \
- jal __dl_runtime_resolve\n \
- move $29, $16\n \
- ld $31, 9*8($29)\n \
- ld $4, 3*8($29)\n \
- ld $5, 4*8($29)\n \
- ld $6, 5*8($29)\n \
- ld $7, 6*8($29)\n \
- ld $16, 7*8($29)\n \
- daddu $29, 10*8\n \
- move $25, $2\n \
- jr $25\n \
- .end _dl_runtime_resolve\n \
-");
-#else
#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
/* The flag _dl_mips_gnu_objects is set if all dynamic objects are \
generated by the gnu linker. */ \
jr $25\n \
.end _dl_runtime_resolve\n \
");
-#endif
/* Mask identifying addresses reserved for the user program,
where the dynamic linker should not map anything. */
2) That under Linux the entry is named __start
and not just plain _start. */
-#ifdef __mips64
-#define RTLD_START asm ("\
- .text\n\
- .align 3\n"\
-_RTLD_PROLOGUE (ENTRY_POINT)\
-" .globl _dl_start_user\n\
- .set noreorder\n\
- bltzal $0, 0f\n\
- nop\n\
-0: .cpload $31\n\
- .set reorder\n\
- # i386 ABI book says that the first entry of GOT holds\n\
- # the address of the dynamic structure. Though MIPS ABI\n\
- # doesn't say nothing about this, I emulate this here.\n\
- dla $4, _DYNAMIC\n\
- sd $4, -0x7ff0($28)\n\
- move $4, $29\n\
- jal _dl_start\n\
- # Get the value of label '_dl_start_user' in t9 ($25).\n\
- dla $25, _dl_start_user\n\
-_dl_start_user:\n\
- .set noreorder\n\
- .cpload $25\n\
- .set reorder\n\
- move $16, $28\n\
- # Save the user entry point address in saved register.\n\
- move $17, $2\n\
- # See if we were run as a command with the executable file\n\
- # name as an extra leading argument.\n\
- ld $2, _dl_skip_args\n\
- beq $2, $0, 1f\n\
- # Load the original argument count.\n\
- ld $4, 0($29)\n\
- # Subtract _dl_skip_args from it.\n\
- dsubu $4, $2\n\
- # Adjust the stack pointer to skip _dl_skip_args words.\n\
- dsll $2,2\n\
- daddu $29, $2\n\
- # Save back the modified argument count.\n\
- sd $4, 0($29)\n\
- # Get _dl_default_scope[2] as argument in _dl_init_next call below.\n\
-1: dla $2, _dl_default_scope\n\
- ld $4, 2*8($2)\n\
- # Call _dl_init_next to return the address of an initializer\n\
- # function to run.\n\
- jal _dl_init_next\n\
- move $28, $16\n\
- # Check for zero return, when out of initializers.\n\
- beq $2, $0, 2f\n\
- # Call the shared object initializer function.\n\
- move $25, $2\n\
- ld $4, 0($29)\n\
- ld $5, 1*8($29)\n\
- ld $6, 2*8($29)\n\
- ld $7, 3*8($29)\n\
- jalr $25\n\
- move $28, $16\n\
- # Loop to call _dl_init_next for the next initializer.\n\
- b 1b\n\
- # Pass our finalizer function to the user in ra.\n\
-2: dla $31, _dl_fini\n\
- # Jump to the user entry point.\n\
- move $25, $17\n\
- ld $4, 0($29)\n\
- ld $5, 1*8($29)\n\
- ld $6, 2*8$29)\n\
- ld $7, 3*8($29)\n\
- jr $25\n"\
-_RTLD_EPILOGUE(ENTRY_POINT) \
-);
-
-#else
#define RTLD_START asm ("\
.text\n"\
_RTLD_PROLOGUE(ENTRY_POINT)\
lw $7, 12($29)\n\
jr $25\n"\
_RTLD_EPILOGUE(ENTRY_POINT)\
-");
-#endif
+);
/* The MIPS never uses Elfxx_Rela relocations. */
#define ELF_MACHINE_NO_RELA 1