[PATCH 3/6] ldso: Add ARC support
Bernhard Reutner-Fischer
rep.dot.nop at gmail.com
Tue Nov 12 14:04:08 UTC 2013
On Fri, Nov 01, 2013 at 04:25:04PM +0530, Vineet Gupta wrote:
>Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
>---
> ldso/ldso/arc/dl-debug.h | 68 +++++++++++
> ldso/ldso/arc/dl-startup.h | 88 ++++++++++++++
> ldso/ldso/arc/dl-syscalls.h | 8 ++
> ldso/ldso/arc/dl-sysdep.h | 156 ++++++++++++++++++++++++
> ldso/ldso/arc/elfinterp.c | 284 ++++++++++++++++++++++++++++++++++++++++++++
> ldso/ldso/arc/resolve.S | 59 +++++++++
> 6 files changed, 663 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..93ce1e6c729d
>--- /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, see the file COPYING.LIB in this tarball.
>+ */
I take it you double-checked the table below against the defines in
include/elf.h
>+static const char *_dl_reltypes_tab[] =
>+{
>+};
>diff --git a/ldso/ldso/arc/dl-startup.h b/ldso/ldso/arc/dl-startup.h
>new file mode 100644
>index 000000000000..0d7d44abf2fa
>--- /dev/null
>+++ b/ldso/ldso/arc/dl-startup.h
>@@ -0,0 +1,88 @@
>+/*
>+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>+ *
>+ * Licensed under the LGPL v2.1, 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"
>+ ".balign 4 \n"
>+ ".global _start \n"
.hidden _start ?
>+ ".type _start, at 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..1ab7b552a217
>--- /dev/null
>+++ b/ldso/ldso/arc/dl-syscalls.h
>@@ -0,0 +1,8 @@
>+/*
>+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>+ *
>+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
>+ */
>+
>+#include "sys/syscall.h"
>+#include <bits/uClibc_page.h>
Sounds like it could go with the stub only?
>diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h
>new file mode 100644
>index 000000000000..642f020f42e1
>--- /dev/null
>+++ b/ldso/ldso/arc/dl-sysdep.h
>@@ -0,0 +1,156 @@
>+/*
>+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>+ *
>+ * Licensed under the LGPL v2.1, 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
table layout seems to be broken here
>+ * | | 12
>+ * | j [r10] | 16
>+ * --------------------------------
>+ * | Base address of GOT | 20
>+ * --------------------------------
>+ * | ld r12, [pcl, off-to-GOT[3] | 24 (12 bytes each)
>+ * plt1 | |
.. and here.
>+ * | 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; \
>+ if(MODULE->libtype != program_interpreter) \
you sure you need the above?
>+ 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 ((visibility("hidden")));
yuck ;)
And please use __foo__ throughout, for attribute, inline.
>+
>+#define do_rem(result, n, base) ((result) = \
>+ \
>+ __builtin_constant_p (base) ? (n) % (unsigned) (base) : \
I'd prefer if you marked that as (__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 inline Elf32_Addr elf_machine_dynamic (void) attribute_unused;
>+static inline Elf32_Addr
Perhaps you want __always_inline and in similar spots?
>+elf_machine_dynamic (void)
>+{
>+ Elf32_Addr dyn;
>+
>+ __asm__("ld %0,[pcl,_DYNAMIC at 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 inline Elf32_Addr elf_machine_load_address (void) attribute_unused;
>+static 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 at 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 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..ee6496659a3a
>--- /dev/null
>+++ b/ldso/ldso/arc/elfinterp.c
>@@ -0,0 +1,284 @@
>+/*
>+ * 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, see the file COPYING.LIB in this tarball.
>+ */
>+#include "ldso.h"
>+
>+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
>+ */
whitespace damage above
>+ plt_idx = (plt_pc - plt_base)/0xc - 2; /* ignoring 2 dummy PLTs */
magic 12 ?
>+
>+ 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__)
please remove braces
>+ 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_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
>+ ELF_RELOC *rpnt);
>+
>+static int
>+_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
>+ ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab);
Please restructure so you don't need these forward declarations.
Also, it would be nice if you could switch to using a function pointer
for the real handler, see all other arches.
>+
>+#define ___DO_LAZY 1
>+#define ___DO_NOW 2
>+
>+static int __attribute__((always_inline))
>+_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;
>+}
>+
>+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;
>+}
>+
>+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..8609b339effa
>--- /dev/null
>+++ b/ldso/ldso/arc/resolve.S
>@@ -0,0 +1,59 @@
>+/*
>+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>+ *
>+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
>+ */
>+
>+#define __ASSEMBLY__
please remove that define.
>+
>+#include <bits/asm.h>
Can you instead of asm.h use ENTRY and PLTJMP et al from sysdep.h please?
Everywhere.
>+#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
>+ENDFUNC(_dl_linux_resolve)
>--
>1.8.1.2
>
>_______________________________________________
>uClibc mailing list
>uClibc at uclibc.org
>http://lists.busybox.net/mailman/listinfo/uclibc
More information about the uClibc
mailing list