Message ID | 1386926366-16910-4-git-send-email-vgupta@synopsys.com |
---|---|
State | Accepted, archived |
Headers | show |
On Fri, Dec 13, 2013 at 02:49:22PM +0530, Vineet Gupta wrote: > Signed-off-by: Vineet Gupta <vgupta@synopsys.com> > --- > ldso/ldso/arc/dl-debug.h | 68 +++++++++++ > ldso/ldso/arc/dl-startup.h | 89 ++++++++++++++ > ldso/ldso/arc/dl-syscalls.h | 5 + > ldso/ldso/arc/dl-sysdep.h | 150 ++++++++++++++++++++++++ > ldso/ldso/arc/elfinterp.c | 279 ++++++++++++++++++++++++++++++++++++++++++++ > ldso/ldso/arc/resolve.S | 57 +++++++++ > 6 files changed, 648 insertions(+) > create mode 100644 ldso/ldso/arc/dl-debug.h > create mode 100644 ldso/ldso/arc/dl-startup.h > create mode 100644 ldso/ldso/arc/dl-syscalls.h > create mode 100644 ldso/ldso/arc/dl-sysdep.h > create mode 100644 ldso/ldso/arc/elfinterp.c > create mode 100644 ldso/ldso/arc/resolve.S > > diff --git a/ldso/ldso/arc/dl-debug.h b/ldso/ldso/arc/dl-debug.h > new file mode 100644 > index 000000000000..ff559f27fa31 > --- /dev/null > +++ b/ldso/ldso/arc/dl-debug.h > @@ -0,0 +1,68 @@ > +/* > + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) > + * > + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. > + */ > +static const char *_dl_reltypes_tab[] = > +{ > + "R_ARC_NONE", /* 0 */ > + "R_ARC_8", > + "R_ARC_16", > + "R_ARC_24", > + "R_ARC_32", > + "R_ARC_B26", /* 5 */ > + "R_ARC_B22_PCREL", > + "R_ARC_H30", > + "R_ARC_N8", > + "R_ARC_N16", > + "R_ARC_N24", /* 10 */ > + "R_ARC_N32", > + "R_ARC_SDA", > + "R_ARC_SECTOFF", > + "R_ARC_S21H_PCREL", > + "R_ARC_S21W_PCREL", /* 15 */ > + "R_ARC_S25H_PCREL", > + "R_ARC_S25W_PCREL", > + "R_ARC_SDA32", > + "R_ARC_SDA_LDST", > + "R_ARC_SDA_LDST1", /* 20 */ > + "R_ARC_SDA_LDST2", > + "R_ARC_SDA16_LD", > + "R_ARC_SDA16_LD1", > + "R_ARC_SDA16_LD2", > + "R_ARC_S13_PCREL", /* 25 */ > + "R_ARC_W", > + "R_ARC_32_ME", > + "R_ARC_N32_ME", > + "R_ARC_SECTOFF_ME", > + "R_ARC_SDA32_ME", /* 30 */ > + "R_ARC_W_ME", > + "R_ARC_H30_ME", > + "R_ARC_SECTOFF_U8", > + "R_ARC_SECTOFF_S9", > + "R_AC_SECTOFF_U8", /* 35 */ > + "R_AC_SECTOFF_U8_1", > + "R_AC_SECTOFF_U8_2", > + "R_AC_SECTOFF_S9", > + "R_AC_SECTOFF_S9_1", > + "R_AC_SECTOFF_S9_2", /* 40 */ > + "R_ARC_SECTOFF_ME_1", > + "R_ARC_SECTOFF_ME_2", > + "R_ARC_SECTOFF_1", > + "R_ARC_SECTOFF_2", > + "", /* 45 */ > + "", > + "", > + "", > + "", > + "R_ARC_PC32", /* 50 */ > + "R_ARC_GOTPC32", > + "R_ARC_PLT32", > + "R_ARC_COPY", > + "R_ARC_GLOB_DAT", > + "R_ARC_JMP_SLOT", /* 55 */ > + "R_ARC_RELATIVE", > + "R_ARC_GOTOFF", > + "R_ARC_GOTPC", > + "R_ARC_GOT32", > +}; > diff --git a/ldso/ldso/arc/dl-startup.h b/ldso/ldso/arc/dl-startup.h > new file mode 100644 > index 000000000000..4a8d5d786b63 > --- /dev/null > +++ b/ldso/ldso/arc/dl-startup.h > @@ -0,0 +1,89 @@ > +/* > + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) > + * > + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. > + */ > + > +/* > + * vineetg: Refactoring/cleanup of loader entry point > + * Removed 6 useless insns > + * Joern Improved it even further: > + * -better insn scheduling > + * -no need for conditional code for _dl_skip_args > + * -use of assembler .&2 expressions vs. @gotpc refs (avoids need for GP) > + * > + * What this code does: > + * -ldso starts execution here when kernel returns from execve() > + * -calls into generic ldso entry point _dl_start( ) > + * -optionally adjusts argc for executable if exec passed as cmd > + * -calls into app main with address of finaliser > + */ > +__asm__( > + ".section .text \n" > + ".align 4 \n" > + ".global _start \n" > + ".hidden _start \n" > + ".type _start,@function \n" > + > + "_start: \n" > + " ; ldso entry point, returns app entry point \n" > + " bl.d _dl_start \n" > + " mov_s r0, sp ; pass ptr to aux vector tbl \n" > + > + " ; If ldso ran as cmd with executable file nm as arg \n" > + " ; as arg, skip the extra args calc by dl_start() \n" too many "as arg" > + " ld_s r1, [sp] ; orig argc from aux-vec Tbl \n" > +#ifdef STAR_9000535888_FIXED what is that STAR_9000535888_FIXED thing, can we remove this? > + " ld r12, [pcl, _dl_skip_args-.+(.&2)] \n" > +#else > + " add r12, pcl, _dl_skip_args-.+(.&2) \n" > + " ld r12, [r12] \n" > +#endif > + > + " add r2, pcl, _dl_fini-.+(.&2) ; finalizer \n" > + > + " add2 sp, sp, r12 ; discard argv entries from stack\n" > + " sub_s r1, r1, r12 ; adjusted argc, on stack \n" > + " st_s r1, [sp] \n" > + > + " j_s.d [r0] ; app entry point \n" > + " mov_s r0, r2 ; ptr to finalizer _dl_fini \n" > + > + ".size _start,.-_start \n" > + ".previous \n" > +); > + > +/* > + * Get a pointer to the argv array. On many platforms this can be just > + * the address if the first argument, on other platforms we need to > + * do something a little more subtle here. > + */ > +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS + 1) > + > +/* > + * Dynamic loader bootstrapping: > + * Since we don't modify text at runtime, these can only be data relos > + * (so safe to assume that they are word aligned). > + * And also they HAVE to be RELATIVE relos only > + * @RELP is the relo entry being processed > + * @REL is the pointer to the address we are relocating. > + * @SYMBOL is the symbol involved in the relocation > + * @LOAD is the load address. > + */ > + > +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ > +do { \ > + int type = ELF32_R_TYPE((RELP)->r_info); \ > + if (likely(type == R_ARC_RELATIVE)) \ > + *REL += (unsigned long) LOAD; \ > + else \ > + _dl_exit(1); \ > +}while(0) > + > +/* > + * This will go away once we have DT_RELACOUNT > + */ > +#define ARCH_NEEDS_BOOTSTRAP_RELOCS > + > +/* we dont need to spit out argc, argv etc for debugging */ > +#define NO_EARLY_SEND_STDERR 1 > diff --git a/ldso/ldso/arc/dl-syscalls.h b/ldso/ldso/arc/dl-syscalls.h > new file mode 100644 > index 000000000000..a0b5afc9ec78 > --- /dev/null > +++ b/ldso/ldso/arc/dl-syscalls.h > @@ -0,0 +1,5 @@ > +/* > + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) > + * > + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. > + */ I would have added a /* stub for arch-specific syscall issues */ but ok as is. > diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h > new file mode 100644 > index 000000000000..dfde3323373b > --- /dev/null > +++ b/ldso/ldso/arc/dl-sysdep.h > @@ -0,0 +1,150 @@ > +/* > + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) > + * > + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. > + */ > + > +#include "elf.h" > + > +/* > + * Define this if the system uses RELOCA. > + */ > +#define ELF_USES_RELOCA > + > +/* > + * Dynamic Linking ABI for ARCompact ISA > + * > + * PLT > + * -------------------------------- > + * | ld r11, [pcl, off-to-GOT[1] | 0 (20 bytes) > + * | | 4 > + * plt0 | ld r10, [pcl, off-to-GOT[2] | 8 > + * | | 12 > + * | j [r10] | 16 > + * -------------------------------- > + * | Base address of GOT | 20 > + * -------------------------------- > + * | ld r12, [pcl, off-to-GOT[3] | 24 (12 bytes each) > + * plt1 | | > + * | j_s.d [r12] | 32 plt0 and plt1 lines are still broken, please fix. > + * | mov_s r12, pcl | 34 > + * -------------------------------- > + * | | 36 > + * ~ ~ > + * ~ ~ > + * | | > + * -------------------------------- > + * > + * GOT > + * -------------- > + * | [0] | > + * -------------- > + * | [1] | Module info - setup by ldso > + * -------------- > + * | [2] | resolver entry point > + * -------------- > + * | [3] | > + * | ... | Runtime address for function symbols > + * | [f] | > + * -------------- > + * | [f+1] | > + * | ... | Runtime address for data symbols > + * | [last] | > + * -------------- > + */ > + > +/* > + * Initialization sequence for a GOT. > + * Caller elf_resolve() seeds @GOT_BASE from DT_PLTGOT - which essentially is > + * pointer to first PLT entry. The actual GOT base is 5th word in PLT > + * > + */ > +#define INIT_GOT(GOT_BASE,MODULE) \ > +do { \ > + unsigned long *__plt_base = (unsigned long *)GOT_BASE; \ > + GOT_BASE = (unsigned long *)(__plt_base[5] + \ > + (unsigned long)MODULE->loadaddr); \ > + GOT_BASE[1] = (unsigned long) MODULE; \ > + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ > +} while(0) > + > +/* Here we define the magic numbers that this dynamic loader should accept */ > +#define MAGIC1 EM_ARCOMPACT > +#undef MAGIC2 > + > +/* Used for error messages */ > +#define ELF_TARGET "ARC" > + > +struct elf_resolve; > +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, > + unsigned int plt_pc); > + > +extern unsigned __udivmodsi4(unsigned, unsigned) attribute_hidden; > + > +#define do_rem(result, n, base) ((result) = \ > + \ > + __builtin_constant_p (base) ? (n) % (unsigned) (base) : \ > + __extension__ ({ \ > + register unsigned r1 __asm__ ("r1") = (base); \ > + \ > + __asm("bl.d @__udivmodsi4` mov r0,%1" \ __asm__ > + : "=r" (r1) \ > + : "r" (n), "r" (r1) \ > + : "r0", "r2", "r3", "r4", "lp_count", "blink", "cc"); \ > + \ > + r1; \ > + }) \ > +) > + > +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so > + PLT entries should not be allowed to define the value. > + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one > + of the main executable's symbols, as for a COPY reloc. */ > +#define elf_machine_type_class(type) \ > + ((((type) == R_ARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ > + | (((type) == R_ARC_COPY) * ELF_RTYPE_CLASS_COPY)) > + > +/* > + * Get the runtime address of GOT[0] > + */ > +static __always_inline Elf32_Addr elf_machine_dynamic(void) > +{ > + Elf32_Addr dyn; > + > + __asm__("ld %0,[pcl,_DYNAMIC@gotpc]\n\t" : "=r" (dyn)); > + return dyn; > + > +/* > + * Another way would have been to simply return GP, which due to some > + * PIC reference would be automatically setup by gcc in caller > + * register Elf32_Addr *got __asm__ ("gp"); return *got; > + */ > +} > + > +/* Return the run-time load address of the shared object. */ > +static __always_inline Elf32_Addr elf_machine_load_address(void) > +{ > + /* To find the loadaddr we subtract the runtime addr of any symbol > + * say _dl_start from it's build-time addr. > + */ > + Elf32_Addr addr, tmp; > + __asm__ ( > + "ld %1, [pcl, _dl_start@gotpc] ;build addr of _dl_start \n" > + "add %0, pcl, _dl_start-.+(.&2) ;runtime addr of _dl_start \n" > + "sub %0, %0, %1 ;delta \n" > + : "=&r" (addr), "=r"(tmp) > + ); > + return addr; > +} > + > +static __always_inline void > +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, > + Elf32_Word relative_count) > +{ > + Elf32_Rel * rpnt = (void *) rel_addr; > + --rpnt; > + do { > + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); > + *reloc_addr += load_off; > + } while (--relative_count); > +} > diff --git a/ldso/ldso/arc/elfinterp.c b/ldso/ldso/arc/elfinterp.c > new file mode 100644 > index 000000000000..a3d741b65c4e > --- /dev/null > +++ b/ldso/ldso/arc/elfinterp.c > @@ -0,0 +1,279 @@ > +/* > + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) > + * > + * Lots of code copied from ../i386/elfinterp.c, so: > + * 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. > + * > + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. > + */ > +#include "ldso.h" > + > +#define ARC_PLT_SIZE 12 > + > +unsigned long > +_dl_linux_resolver(struct elf_resolve *tpnt, unsigned int plt_pc) > +{ > + ELF_RELOC *this_reloc, *rel_base; > + char *strtab, *symname, *new_addr; > + ElfW(Sym) *symtab; > + int symtab_index; > + unsigned int *got_addr; > + unsigned long plt_base; > + int plt_idx; > + > + /* start of .rela.plt */ > + rel_base = (ELF_RELOC *)(tpnt->dynamic_info[DT_JMPREL]); > + > + /* starts of .plt (addr of PLT0) */ > + plt_base = tpnt->dynamic_info[DT_PLTGOT]; > + > + /* > + * compute the idx of the yet-unresolved PLT entry in .plt > + * Same idx will be used to find the relo entry in .rela.plt > + */ > + plt_idx = (plt_pc - plt_base)/ARC_PLT_SIZE - 2; /* ignoring 2 dummy PLTs */ > + > + this_reloc = rel_base + plt_idx; > + > + symtab_index = ELF_R_SYM(this_reloc->r_info); > + symtab = (ElfW(Sym) *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); > + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); > + symname= strtab + symtab[symtab_index].st_name; > + > + /* relo-offset to fixup, shd be a .got entry */ > + got_addr = (unsigned int *)(this_reloc->r_offset + tpnt->loadaddr); > + > + /* Get the address of the GOT entry */ > + new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, > + ELF_RTYPE_CLASS_PLT, NULL); > + > + if (unlikely(!new_addr)) { > + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); > + _dl_exit(1); > + } > + > + > +#if defined __SUPPORT_LD_DEBUG__ > + if (_dl_debug_bindings) { > + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); > + if(_dl_debug_detail) > + _dl_dprintf(_dl_debug_file, "\n\tpatched %x ==> %pc @ %pl\n", > + *got_addr, new_addr, got_addr); > + } > + > + if (!_dl_debug_nofixups) > + *got_addr = (unsigned int)new_addr; > +#else > + /* Update the .got entry with the runtime address of symbol */ > + *got_addr = (unsigned int)new_addr; > +#endif > + > + /* > + * Return the new addres, where the asm trampoline will jump to > + * after re-setting up the orig args > + */ > + return (unsigned long) new_addr; > +} > + > + > +static int > +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope, > + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) > +{ > + int reloc_type; > + int symtab_index; > + char *symname; > + unsigned long *reloc_addr; > + unsigned long symbol_addr; > +#if defined __SUPPORT_LD_DEBUG__ > + unsigned long old_val = 0; > +#endif > + struct symbol_ref sym_ref; > + > + reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset); > + reloc_type = ELF_R_TYPE(rpnt->r_info); > + symtab_index = ELF_R_SYM(rpnt->r_info); > + symbol_addr = 0; > + > + sym_ref.sym = &symtab[symtab_index]; > + sym_ref.tpnt = NULL; > + > +#if defined __SUPPORT_LD_DEBUG__ > + if (reloc_addr) > + old_val = *reloc_addr; > +#endif > + > + if (symtab_index) { > + symname = strtab + symtab[symtab_index].st_name; > + symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, > + elf_machine_type_class(reloc_type), &sym_ref); > + > + /* > + * We want to allow undefined references to weak symbols, > + * this might have been intentional. We should not be linking > + * local symbols here, so all bases should be covered. > + */ > + > + if (unlikely(!symbol_addr > + && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { > + /* Non-fatal if called from dlopen, hence different ret code */ > + return 1; > + } > + } else if (reloc_type == R_ARC_RELATIVE ) { > + *reloc_addr += tpnt->loadaddr; > + goto log_entry; > + } > + > + switch (reloc_type) { > + case R_ARC_32: > + *reloc_addr += symbol_addr + rpnt->r_addend; > + break; > + case R_ARC_PC32: > + *reloc_addr += symbol_addr + rpnt->r_addend - (unsigned long) reloc_addr; > + break; > + case R_ARC_GLOB_DAT: > + case R_ARC_JMP_SLOT: > + *reloc_addr = symbol_addr; > + break; > + case R_ARC_COPY: > + _dl_memcpy((void *) reloc_addr,(void *) symbol_addr, > + symtab[symtab_index].st_size); > + break; > + default: > + return -1; > + } > + > +log_entry: > +#if defined __SUPPORT_LD_DEBUG__ > + if(_dl_debug_detail) missing space after if > + _dl_dprintf(_dl_debug_file,"\tpatched: %lx ==> %lx @ %pl: addend %x ", > + old_val, *reloc_addr, reloc_addr, rpnt->r_addend); > +#endif > + > + return 0; > +} > + > +static int > +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope, > + ELF_RELOC *rpnt) > +{ > + int reloc_type; > + unsigned long *reloc_addr; > +#if defined __SUPPORT_LD_DEBUG__ > + unsigned long old_val; > +#endif > + > + reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset); > + reloc_type = ELF_R_TYPE(rpnt->r_info); > + > +#if defined __SUPPORT_LD_DEBUG__ > + old_val = *reloc_addr; > +#endif > + > + switch (reloc_type) { > + case R_ARC_JMP_SLOT: > + *reloc_addr += tpnt->loadaddr; > + break; > + default: > + return -1; > + } > + > +#if defined __SUPPORT_LD_DEBUG__ > + if(_dl_debug_reloc && _dl_debug_detail) > + _dl_dprintf(_dl_debug_file, "\tpatched: %lx ==> %lx @ %pl\n", > + old_val, *reloc_addr, reloc_addr); > +#endif > + > + return 0; > +} > + > +#define ___DO_LAZY 1 > +#define ___DO_NOW 2 > + > +static int _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope, > + unsigned long rel_addr, unsigned long rel_size, int type) > +{ > + unsigned int i; > + char *strtab; > + ElfW(Sym) *symtab; > + ELF_RELOC *rpnt; > + int symtab_index; > + int res = 0; > + > + /* Now parse the relocation information */ > + rpnt = (ELF_RELOC *)(intptr_t) (rel_addr); > + rel_size = rel_size / sizeof(ELF_RELOC); > + > + symtab = (ElfW(Sym) *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); > + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); > + > + for (i = 0; i < rel_size; i++, rpnt++) { > + > + symtab_index = ELF_R_SYM(rpnt->r_info); > + > + debug_sym(symtab,strtab,symtab_index); > + debug_reloc(symtab,strtab,rpnt); > + > + /* constant propagation subsumes the 'if' */ > + if (type == ___DO_LAZY) > + res = _dl_do_lazy_reloc(tpnt, scope, rpnt); > + else > + res = _dl_do_reloc(tpnt, scope, rpnt, symtab, strtab); > + > + if (res != 0) > + break; > + } > + > + if (unlikely(res != 0)) { > + if (res < 0) { > + int reloc_type = ELF_R_TYPE(rpnt->r_info); > +#if defined __SUPPORT_LD_DEBUG__ > + _dl_dprintf(2, "can't handle reloc type %s\n ", > + _dl_reltypes(reloc_type)); > +#else > + _dl_dprintf(2, "can't handle reloc type %x\n", > + reloc_type); > +#endif > + _dl_exit(-res); > + } else { > + _dl_dprintf(2, "can't resolve symbol\n"); > + /* Fall thru to return res */ > + } > + } > + > + return res; > +} > + > +void > +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, > + unsigned long rel_addr, > + unsigned long rel_size) > +{ > + /* This func is called for processing .rela.plt of loaded module(s) > + * The relo entries handled are JMP_SLOT type for fixing up .got slots > + * for external function calls. > + * This function doesn't resolve the slots: that is done lazily at > + * runtime. The build linker (at least thats what happens for ARC) had > + * pre-init the .got slots to point to PLT0. All that is done here is > + * to fix them up to point to load value of PLT0 (as opposed to the > + * build value). > + * On ARC, the loadaddr of dyn exec is zero, thus elfaddr == loadaddr > + * Thus there is no point in adding "0" to values and un-necessarily > + * stir up the caches and TLB. > + * For lsdo processing busybox binary, this skips over 380 relo entries > + */ > + if (rpnt->dyn->loadaddr != 0) > + _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, ___DO_LAZY); > +} > + > +int > +_dl_parse_relocation_information(struct dyn_elf *rpnt, > + struct r_scope_elem *scope, > + unsigned long rel_addr, > + unsigned long rel_size) > +{ > + return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, ___DO_NOW); > +} > diff --git a/ldso/ldso/arc/resolve.S b/ldso/ldso/arc/resolve.S > new file mode 100644 > index 000000000000..891f66b97008 > --- /dev/null > +++ b/ldso/ldso/arc/resolve.S > @@ -0,0 +1,57 @@ > +/* > + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) > + * > + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. > + */ > + > +#include <sysdep.h> > +#include <sys/syscall.h> > + > +; Save the registers which resolver could possibly clobber > +; r0-r9: args to the function - symbol being resolved > +; r10-r12 are already clobbered by PLTn, PLT0 thus neednot be saved > + > +.macro SAVE_CALLER_SAVED > + push_s r0 > + push_s r1 > + push_s r2 > + push_s r3 > + st.a r4, [sp, -4] > + st.a r5, [sp, -4] > + st.a r6, [sp, -4] > + st.a r7, [sp, -4] > + st.a r8, [sp, -4] > + st.a r9, [sp, -4] > + push_s blink > +.endm > + > +.macro RESTORE_CALLER_SAVED_BUT_R0 > + ld.ab blink,[sp, 4] > + ld.ab r9, [sp, 4] > + ld.ab r8, [sp, 4] > + ld.ab r7, [sp, 4] > + ld.ab r6, [sp, 4] > + ld.ab r5, [sp, 4] > + ld.ab r4, [sp, 4] > + pop_s r3 > + pop_s r2 > + pop_s r1 > +.endm > + > +; Upon entry, PLTn, which led us here, sets up the following regs > +; r11 = Module info (tpnt pointer as expected by resolver) > +; r12 = PC of the PLTn itself - needed by resolver to find > +; corresponding .rela.plt entry > + > +ENTRY(_dl_linux_resolve) > + ; args to func being resolved, which resolver might clobber > + SAVE_CALLER_SAVED > + > + mov_s r1, r12 > + bl.d _dl_linux_resolver > + mov r0, r11 > + > + RESTORE_CALLER_SAVED_BUT_R0 > + j_s.d [r0] ; r0 has resolved function addr > + pop_s r0 ; restore first arg to resolved call > +END(_dl_linux_resolve) > -- > 1.8.1.2 >
diff --git a/ldso/ldso/arc/dl-debug.h b/ldso/ldso/arc/dl-debug.h new file mode 100644 index 000000000000..ff559f27fa31 --- /dev/null +++ b/ldso/ldso/arc/dl-debug.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ +static const char *_dl_reltypes_tab[] = +{ + "R_ARC_NONE", /* 0 */ + "R_ARC_8", + "R_ARC_16", + "R_ARC_24", + "R_ARC_32", + "R_ARC_B26", /* 5 */ + "R_ARC_B22_PCREL", + "R_ARC_H30", + "R_ARC_N8", + "R_ARC_N16", + "R_ARC_N24", /* 10 */ + "R_ARC_N32", + "R_ARC_SDA", + "R_ARC_SECTOFF", + "R_ARC_S21H_PCREL", + "R_ARC_S21W_PCREL", /* 15 */ + "R_ARC_S25H_PCREL", + "R_ARC_S25W_PCREL", + "R_ARC_SDA32", + "R_ARC_SDA_LDST", + "R_ARC_SDA_LDST1", /* 20 */ + "R_ARC_SDA_LDST2", + "R_ARC_SDA16_LD", + "R_ARC_SDA16_LD1", + "R_ARC_SDA16_LD2", + "R_ARC_S13_PCREL", /* 25 */ + "R_ARC_W", + "R_ARC_32_ME", + "R_ARC_N32_ME", + "R_ARC_SECTOFF_ME", + "R_ARC_SDA32_ME", /* 30 */ + "R_ARC_W_ME", + "R_ARC_H30_ME", + "R_ARC_SECTOFF_U8", + "R_ARC_SECTOFF_S9", + "R_AC_SECTOFF_U8", /* 35 */ + "R_AC_SECTOFF_U8_1", + "R_AC_SECTOFF_U8_2", + "R_AC_SECTOFF_S9", + "R_AC_SECTOFF_S9_1", + "R_AC_SECTOFF_S9_2", /* 40 */ + "R_ARC_SECTOFF_ME_1", + "R_ARC_SECTOFF_ME_2", + "R_ARC_SECTOFF_1", + "R_ARC_SECTOFF_2", + "", /* 45 */ + "", + "", + "", + "", + "R_ARC_PC32", /* 50 */ + "R_ARC_GOTPC32", + "R_ARC_PLT32", + "R_ARC_COPY", + "R_ARC_GLOB_DAT", + "R_ARC_JMP_SLOT", /* 55 */ + "R_ARC_RELATIVE", + "R_ARC_GOTOFF", + "R_ARC_GOTPC", + "R_ARC_GOT32", +}; diff --git a/ldso/ldso/arc/dl-startup.h b/ldso/ldso/arc/dl-startup.h new file mode 100644 index 000000000000..4a8d5d786b63 --- /dev/null +++ b/ldso/ldso/arc/dl-startup.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +/* + * vineetg: Refactoring/cleanup of loader entry point + * Removed 6 useless insns + * Joern Improved it even further: + * -better insn scheduling + * -no need for conditional code for _dl_skip_args + * -use of assembler .&2 expressions vs. @gotpc refs (avoids need for GP) + * + * What this code does: + * -ldso starts execution here when kernel returns from execve() + * -calls into generic ldso entry point _dl_start( ) + * -optionally adjusts argc for executable if exec passed as cmd + * -calls into app main with address of finaliser + */ +__asm__( + ".section .text \n" + ".align 4 \n" + ".global _start \n" + ".hidden _start \n" + ".type _start,@function \n" + + "_start: \n" + " ; ldso entry point, returns app entry point \n" + " bl.d _dl_start \n" + " mov_s r0, sp ; pass ptr to aux vector tbl \n" + + " ; If ldso ran as cmd with executable file nm as arg \n" + " ; as arg, skip the extra args calc by dl_start() \n" + " ld_s r1, [sp] ; orig argc from aux-vec Tbl \n" +#ifdef STAR_9000535888_FIXED + " ld r12, [pcl, _dl_skip_args-.+(.&2)] \n" +#else + " add r12, pcl, _dl_skip_args-.+(.&2) \n" + " ld r12, [r12] \n" +#endif + + " add r2, pcl, _dl_fini-.+(.&2) ; finalizer \n" + + " add2 sp, sp, r12 ; discard argv entries from stack\n" + " sub_s r1, r1, r12 ; adjusted argc, on stack \n" + " st_s r1, [sp] \n" + + " j_s.d [r0] ; app entry point \n" + " mov_s r0, r2 ; ptr to finalizer _dl_fini \n" + + ".size _start,.-_start \n" + ".previous \n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address if the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS + 1) + +/* + * Dynamic loader bootstrapping: + * Since we don't modify text at runtime, these can only be data relos + * (so safe to assume that they are word aligned). + * And also they HAVE to be RELATIVE relos only + * @RELP is the relo entry being processed + * @REL is the pointer to the address we are relocating. + * @SYMBOL is the symbol involved in the relocation + * @LOAD is the load address. + */ + +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ +do { \ + int type = ELF32_R_TYPE((RELP)->r_info); \ + if (likely(type == R_ARC_RELATIVE)) \ + *REL += (unsigned long) LOAD; \ + else \ + _dl_exit(1); \ +}while(0) + +/* + * This will go away once we have DT_RELACOUNT + */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +/* we dont need to spit out argc, argv etc for debugging */ +#define NO_EARLY_SEND_STDERR 1 diff --git a/ldso/ldso/arc/dl-syscalls.h b/ldso/ldso/arc/dl-syscalls.h new file mode 100644 index 000000000000..a0b5afc9ec78 --- /dev/null +++ b/ldso/ldso/arc/dl-syscalls.h @@ -0,0 +1,5 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h new file mode 100644 index 000000000000..dfde3323373b --- /dev/null +++ b/ldso/ldso/arc/dl-sysdep.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#include "elf.h" + +/* + * Define this if the system uses RELOCA. + */ +#define ELF_USES_RELOCA + +/* + * Dynamic Linking ABI for ARCompact ISA + * + * PLT + * -------------------------------- + * | ld r11, [pcl, off-to-GOT[1] | 0 (20 bytes) + * | | 4 + * plt0 | ld r10, [pcl, off-to-GOT[2] | 8 + * | | 12 + * | j [r10] | 16 + * -------------------------------- + * | Base address of GOT | 20 + * -------------------------------- + * | ld r12, [pcl, off-to-GOT[3] | 24 (12 bytes each) + * plt1 | | + * | j_s.d [r12] | 32 + * | mov_s r12, pcl | 34 + * -------------------------------- + * | | 36 + * ~ ~ + * ~ ~ + * | | + * -------------------------------- + * + * GOT + * -------------- + * | [0] | + * -------------- + * | [1] | Module info - setup by ldso + * -------------- + * | [2] | resolver entry point + * -------------- + * | [3] | + * | ... | Runtime address for function symbols + * | [f] | + * -------------- + * | [f+1] | + * | ... | Runtime address for data symbols + * | [last] | + * -------------- + */ + +/* + * Initialization sequence for a GOT. + * Caller elf_resolve() seeds @GOT_BASE from DT_PLTGOT - which essentially is + * pointer to first PLT entry. The actual GOT base is 5th word in PLT + * + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + unsigned long *__plt_base = (unsigned long *)GOT_BASE; \ + GOT_BASE = (unsigned long *)(__plt_base[5] + \ + (unsigned long)MODULE->loadaddr); \ + GOT_BASE[1] = (unsigned long) MODULE; \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_ARCOMPACT +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "ARC" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, + unsigned int plt_pc); + +extern unsigned __udivmodsi4(unsigned, unsigned) attribute_hidden; + +#define do_rem(result, n, base) ((result) = \ + \ + __builtin_constant_p (base) ? (n) % (unsigned) (base) : \ + __extension__ ({ \ + register unsigned r1 __asm__ ("r1") = (base); \ + \ + __asm("bl.d @__udivmodsi4` mov r0,%1" \ + : "=r" (r1) \ + : "r" (n), "r" (r1) \ + : "r0", "r2", "r3", "r4", "lp_count", "blink", "cc"); \ + \ + r1; \ + }) \ +) + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_ARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_ARC_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* + * Get the runtime address of GOT[0] + */ +static __always_inline Elf32_Addr elf_machine_dynamic(void) +{ + Elf32_Addr dyn; + + __asm__("ld %0,[pcl,_DYNAMIC@gotpc]\n\t" : "=r" (dyn)); + return dyn; + +/* + * Another way would have been to simply return GP, which due to some + * PIC reference would be automatically setup by gcc in caller + * register Elf32_Addr *got __asm__ ("gp"); return *got; + */ +} + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr elf_machine_load_address(void) +{ + /* To find the loadaddr we subtract the runtime addr of any symbol + * say _dl_start from it's build-time addr. + */ + Elf32_Addr addr, tmp; + __asm__ ( + "ld %1, [pcl, _dl_start@gotpc] ;build addr of _dl_start \n" + "add %0, pcl, _dl_start-.+(.&2) ;runtime addr of _dl_start \n" + "sub %0, %0, %1 ;delta \n" + : "=&r" (addr), "=r"(tmp) + ); + return addr; +} + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rel * rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + *reloc_addr += load_off; + } while (--relative_count); +} diff --git a/ldso/ldso/arc/elfinterp.c b/ldso/ldso/arc/elfinterp.c new file mode 100644 index 000000000000..a3d741b65c4e --- /dev/null +++ b/ldso/ldso/arc/elfinterp.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * Lots of code copied from ../i386/elfinterp.c, so: + * 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. + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ +#include "ldso.h" + +#define ARC_PLT_SIZE 12 + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, unsigned int plt_pc) +{ + ELF_RELOC *this_reloc, *rel_base; + char *strtab, *symname, *new_addr; + ElfW(Sym) *symtab; + int symtab_index; + unsigned int *got_addr; + unsigned long plt_base; + int plt_idx; + + /* start of .rela.plt */ + rel_base = (ELF_RELOC *)(tpnt->dynamic_info[DT_JMPREL]); + + /* starts of .plt (addr of PLT0) */ + plt_base = tpnt->dynamic_info[DT_PLTGOT]; + + /* + * compute the idx of the yet-unresolved PLT entry in .plt + * Same idx will be used to find the relo entry in .rela.plt + */ + plt_idx = (plt_pc - plt_base)/ARC_PLT_SIZE - 2; /* ignoring 2 dummy PLTs */ + + this_reloc = rel_base + plt_idx; + + symtab_index = ELF_R_SYM(this_reloc->r_info); + symtab = (ElfW(Sym) *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); + symname= strtab + symtab[symtab_index].st_name; + + /* relo-offset to fixup, shd be a .got entry */ + got_addr = (unsigned int *)(this_reloc->r_offset + tpnt->loadaddr); + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, + ELF_RTYPE_CLASS_PLT, NULL); + + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + + +#if defined __SUPPORT_LD_DEBUG__ + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if(_dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched %x ==> %pc @ %pl\n", + *got_addr, new_addr, got_addr); + } + + if (!_dl_debug_nofixups) + *got_addr = (unsigned int)new_addr; +#else + /* Update the .got entry with the runtime address of symbol */ + *got_addr = (unsigned int)new_addr; +#endif + + /* + * Return the new addres, where the asm trampoline will jump to + * after re-setting up the orig args + */ + return (unsigned long) new_addr; +} + + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined __SUPPORT_LD_DEBUG__ + unsigned long old_val = 0; +#endif + struct symbol_ref sym_ref; + + reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + symbol_addr = 0; + + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + +#if defined __SUPPORT_LD_DEBUG__ + if (reloc_addr) + old_val = *reloc_addr; +#endif + + if (symtab_index) { + symname = strtab + symtab[symtab_index].st_name; + symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + + /* + * We want to allow undefined references to weak symbols, + * this might have been intentional. We should not be linking + * local symbols here, so all bases should be covered. + */ + + if (unlikely(!symbol_addr + && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { + /* Non-fatal if called from dlopen, hence different ret code */ + return 1; + } + } else if (reloc_type == R_ARC_RELATIVE ) { + *reloc_addr += tpnt->loadaddr; + goto log_entry; + } + + switch (reloc_type) { + case R_ARC_32: + *reloc_addr += symbol_addr + rpnt->r_addend; + break; + case R_ARC_PC32: + *reloc_addr += symbol_addr + rpnt->r_addend - (unsigned long) reloc_addr; + break; + case R_ARC_GLOB_DAT: + case R_ARC_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_ARC_COPY: + _dl_memcpy((void *) reloc_addr,(void *) symbol_addr, + symtab[symtab_index].st_size); + break; + default: + return -1; + } + +log_entry: +#if defined __SUPPORT_LD_DEBUG__ + if(_dl_debug_detail) + _dl_dprintf(_dl_debug_file,"\tpatched: %lx ==> %lx @ %pl: addend %x ", + old_val, *reloc_addr, reloc_addr, rpnt->r_addend); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt) +{ + int reloc_type; + unsigned long *reloc_addr; +#if defined __SUPPORT_LD_DEBUG__ + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined __SUPPORT_LD_DEBUG__ + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_ARC_JMP_SLOT: + *reloc_addr += tpnt->loadaddr; + break; + default: + return -1; + } + +#if defined __SUPPORT_LD_DEBUG__ + if(_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %lx ==> %lx @ %pl\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +#define ___DO_LAZY 1 +#define ___DO_NOW 2 + +static int _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope, + unsigned long rel_addr, unsigned long rel_size, int type) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + int res = 0; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *)(intptr_t) (rel_addr); + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); + + for (i = 0; i < rel_size; i++, rpnt++) { + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + /* constant propagation subsumes the 'if' */ + if (type == ___DO_LAZY) + res = _dl_do_lazy_reloc(tpnt, scope, rpnt); + else + res = _dl_do_reloc(tpnt, scope, rpnt, symtab, strtab); + + if (res != 0) + break; + } + + if (unlikely(res != 0)) { + if (res < 0) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); +#if defined __SUPPORT_LD_DEBUG__ + _dl_dprintf(2, "can't handle reloc type %s\n ", + _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", + reloc_type); +#endif + _dl_exit(-res); + } else { + _dl_dprintf(2, "can't resolve symbol\n"); + /* Fall thru to return res */ + } + } + + return res; +} + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + /* This func is called for processing .rela.plt of loaded module(s) + * The relo entries handled are JMP_SLOT type for fixing up .got slots + * for external function calls. + * This function doesn't resolve the slots: that is done lazily at + * runtime. The build linker (at least thats what happens for ARC) had + * pre-init the .got slots to point to PLT0. All that is done here is + * to fix them up to point to load value of PLT0 (as opposed to the + * build value). + * On ARC, the loadaddr of dyn exec is zero, thus elfaddr == loadaddr + * Thus there is no point in adding "0" to values and un-necessarily + * stir up the caches and TLB. + * For lsdo processing busybox binary, this skips over 380 relo entries + */ + if (rpnt->dyn->loadaddr != 0) + _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, ___DO_LAZY); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + struct r_scope_elem *scope, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, ___DO_NOW); +} diff --git a/ldso/ldso/arc/resolve.S b/ldso/ldso/arc/resolve.S new file mode 100644 index 000000000000..891f66b97008 --- /dev/null +++ b/ldso/ldso/arc/resolve.S @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +#include <sysdep.h> +#include <sys/syscall.h> + +; Save the registers which resolver could possibly clobber +; r0-r9: args to the function - symbol being resolved +; r10-r12 are already clobbered by PLTn, PLT0 thus neednot be saved + +.macro SAVE_CALLER_SAVED + push_s r0 + push_s r1 + push_s r2 + push_s r3 + st.a r4, [sp, -4] + st.a r5, [sp, -4] + st.a r6, [sp, -4] + st.a r7, [sp, -4] + st.a r8, [sp, -4] + st.a r9, [sp, -4] + push_s blink +.endm + +.macro RESTORE_CALLER_SAVED_BUT_R0 + ld.ab blink,[sp, 4] + ld.ab r9, [sp, 4] + ld.ab r8, [sp, 4] + ld.ab r7, [sp, 4] + ld.ab r6, [sp, 4] + ld.ab r5, [sp, 4] + ld.ab r4, [sp, 4] + pop_s r3 + pop_s r2 + pop_s r1 +.endm + +; Upon entry, PLTn, which led us here, sets up the following regs +; r11 = Module info (tpnt pointer as expected by resolver) +; r12 = PC of the PLTn itself - needed by resolver to find +; corresponding .rela.plt entry + +ENTRY(_dl_linux_resolve) + ; args to func being resolved, which resolver might clobber + SAVE_CALLER_SAVED + + mov_s r1, r12 + bl.d _dl_linux_resolver + mov r0, r11 + + RESTORE_CALLER_SAVED_BUT_R0 + j_s.d [r0] ; r0 has resolved function addr + pop_s r0 ; restore first arg to resolved call +END(_dl_linux_resolve)
Signed-off-by: Vineet Gupta <vgupta@synopsys.com> --- ldso/ldso/arc/dl-debug.h | 68 +++++++++++ ldso/ldso/arc/dl-startup.h | 89 ++++++++++++++ ldso/ldso/arc/dl-syscalls.h | 5 + ldso/ldso/arc/dl-sysdep.h | 150 ++++++++++++++++++++++++ ldso/ldso/arc/elfinterp.c | 279 ++++++++++++++++++++++++++++++++++++++++++++ ldso/ldso/arc/resolve.S | 57 +++++++++ 6 files changed, 648 insertions(+) create mode 100644 ldso/ldso/arc/dl-debug.h create mode 100644 ldso/ldso/arc/dl-startup.h create mode 100644 ldso/ldso/arc/dl-syscalls.h create mode 100644 ldso/ldso/arc/dl-sysdep.h create mode 100644 ldso/ldso/arc/elfinterp.c create mode 100644 ldso/ldso/arc/resolve.S