📄 dl-machine.h
字号:
for (this = 0; this < nent; this++) { if (p[this].p_type == PT_LOAD) { base = p[this].p_vaddr + l->l_addr; limit = base + p[this].p_memsz; if (stub_pc >= base && stub_pc < limit) return l; } } l = l->l_next; } } _dl_signal_error (0, NULL, NULL, "cannot find runtime link map"); return NULL;}/* Mips has no PLT but define elf_machine_relplt to be elf_machine_rel. */#define elf_machine_relplt elf_machine_rel/* Define mips specific runtime resolver. The function __dl_runtime_resolve is called from assembler function _dl_runtime_resolve which converts special argument registers t7 ($15) and t8 ($24): t7 address to return to the caller of the function t8 index for this function symbol in .dynsym to usual c arguments. */#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) *) D_PTR (l, l_info[DT_SYMTAB]); \ const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); \ const ElfW(Addr) *got \ = (const ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]); \ 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; \ \ /* Look up the symbol's run-time value. */ \ definer = &symtab[sym_index]; \ \ loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer, \ l->l_scope, l->l_name, \ R_MIPS_REL32); \ \ /* 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 \ .previous\n \");/* Mask identifying addresses reserved for the user program, where the dynamic linker should not map anything. */#define ELF_MACHINE_USER_ADDRESS_MASK 0x80000000UL/* 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. Note how we have to be careful about two things: 1) That we allocate a minimal stack of 24 bytes for every function call, the MIPS ABI states that even if all arguments are passed in registers the procedure called can use the 16 byte area pointed to by $sp when it is called to store away the arguments passed to it. 2) That under Linux the entry is named __start and not just plain _start. */#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\ dsubu $29, 16\n\ move $4, $29\n\ jal _dl_start\n\ daddiu $29, 16\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\ # Store the highest stack address\n\ sd $29, __libc_stack_end\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\1: # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\ ld $4, _rtld_local\n\ ld $5, 0($29)\n\ dla $6, 4($29)\n\ dla $7, 8($29)\n\ dsubu $29, 16\n\ # Call the function to run the initializers.\n\ jal _dl_init_internal\n\ daddiu $29, 16\n\ # Pass our finalizer function to the user in ra.\n\ dla $31, _dl_fini\n\ # Jump to the user entry point.\n\1: # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\ lw $4, _rtld_local\n\ lw $5, 0($29)\n\ la $6, 4($29)\n\ la $7, 8($29)\n\ subu $29, 16\n\ # Call the function to run the initializers.\n\ jal _dl_init_internal\n\ addiu $29, 16\n\ # Pass our finalizer function to the user in ra.\n\ 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) \ "\n.previous"\);/* The MIPS never uses Elfxx_Rela relocations. */#define ELF_MACHINE_NO_RELA 1#endif /* !dl_machine_h */#ifdef RESOLVE/* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */static inline voidelf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc, const ElfW(Sym) *sym, const struct r_found_version *version, ElfW(Addr) *const reloc_addr){ const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info); ElfW(Addr) loadbase; ElfW(Addr) undo __attribute__ ((unused)); switch (r_type) { case R_MIPS_REL32: { ElfW(Addr) undo = 0; if (ELFW(ST_BIND) (sym->st_info) == STB_LOCAL && (ELFW(ST_TYPE) (sym->st_info) == STT_SECTION || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE)) { *reloc_addr += map->l_addr; break; }#ifndef RTLD_BOOTSTRAP /* This is defined in rtld.c, but nowhere in the static libc.a; make the reference weak so static programs can still link. This declaration cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the common defn for _dl_rtld_map, which is incompatible with a weak decl in the same file. */# ifndef SHARED weak_extern (GL(dl_rtld_map));# endif if (map == &GL(dl_rtld_map)) /* Undo the relocation done here during bootstrapping. Now we will relocate it anew, possibly using a binding found in the user program or a loaded library rather than the dynamic linker's built-in definitions used while loading those libraries. */ undo = map->l_addr + sym->st_value;#endif loadbase = RESOLVE (&sym, version, 0); *reloc_addr += (sym ? (loadbase + sym->st_value) : 0) - undo; } break;#ifndef RTLD_BOOTSTRAP case R_MIPS_NONE: /* Alright, Wilbur. */ break;#endif default: _dl_reloc_bad_type (map, r_type, 0); break; }}static inline voidelf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc, ElfW(Addr) *const reloc_addr){ /* XXX Nothing to do. There is no relative relocation, right? */}static inline voidelf_machine_lazy_rel (struct link_map *map, ElfW(Addr) l_addr, const ElfW(Rel) *reloc){ /* Do nothing. */}#endif /* RESOLVE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -