OSDN Git Service

ldso: Add ARC support
authorVineet Gupta <vgupta@synopsys.com>
Fri, 13 Dec 2013 09:19:22 +0000 (14:49 +0530)
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Fri, 20 Dec 2013 13:38:23 +0000 (14:38 +0100)
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
ldso/ldso/arc/dl-debug.h [new file with mode: 0644]
ldso/ldso/arc/dl-startup.h [new file with mode: 0644]
ldso/ldso/arc/dl-syscalls.h [new file with mode: 0644]
ldso/ldso/arc/dl-sysdep.h [new file with mode: 0644]
ldso/ldso/arc/elfinterp.c [new file with mode: 0644]
ldso/ldso/arc/resolve.S [new file with mode: 0644]

diff --git a/ldso/ldso/arc/dl-debug.h b/ldso/ldso/arc/dl-debug.h
new file mode 100644 (file)
index 0000000..ff559f2
--- /dev/null
@@ -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 (file)
index 0000000..4a8d5d7
--- /dev/null
@@ -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 (file)
index 0000000..a0b5afc
--- /dev/null
@@ -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 (file)
index 0000000..dfde332
--- /dev/null
@@ -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 (file)
index 0000000..a3d741b
--- /dev/null
@@ -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 (file)
index 0000000..891f66b
--- /dev/null
@@ -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)