From 4d8e5484afb4978f672a8568ddd12e628fb02724 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Thu, 8 Oct 2015 20:28:39 +0200 Subject: add new architecture support for or1k Information about Openrisc: http://opencores.org/or1k/Main_Page Integrated from: https://github.com/openrisc/uClibc-or1k --- ldso/ldso/or1k/dl-debug.h | 53 +++++++ ldso/ldso/or1k/dl-startup.h | 106 ++++++++++++++ ldso/ldso/or1k/dl-syscalls.h | 1 + ldso/ldso/or1k/dl-sysdep.h | 105 ++++++++++++++ ldso/ldso/or1k/elfinterp.c | 333 +++++++++++++++++++++++++++++++++++++++++++ ldso/ldso/or1k/resolve.S | 54 +++++++ 6 files changed, 652 insertions(+) create mode 100644 ldso/ldso/or1k/dl-debug.h create mode 100644 ldso/ldso/or1k/dl-startup.h create mode 100644 ldso/ldso/or1k/dl-syscalls.h create mode 100644 ldso/ldso/or1k/dl-sysdep.h create mode 100644 ldso/ldso/or1k/elfinterp.c create mode 100644 ldso/ldso/or1k/resolve.S (limited to 'ldso') diff --git a/ldso/ldso/or1k/dl-debug.h b/ldso/ldso/or1k/dl-debug.h new file mode 100644 index 000000000..d925577cd --- /dev/null +++ b/ldso/ldso/or1k/dl-debug.h @@ -0,0 +1,53 @@ +/* OpenRISC 1000 shared library loader suppport + * + * Copyright (C) 2012 Stefan Kristansson + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char * const _dl_reltypes_tab[] = + { + "R_OR1K_NONE", + "R_OR1K_32", + "R_OR1K_16", + "R_OR1K_8", + "R_OR1K_LO_16_IN_INSN", + "R_OR1K_HI_16_IN_INSN", + "R_OR1K_INSN_REL_26", + "R_OR1K_GNU_VTENTRY", + "R_OR1K_GNU_VTINHERIT", + "R_OR1K_32_PCREL", + "R_OR1K_16_PCREL", + "R_OR1K_8_PCREL", + "R_OR1K_GOTPC_HI16", + "R_OR1K_GOTPC_LO16", + "R_OR1K_GOT16", + "R_OR1K_PLT26", + "R_OR1K_GOTOFF_HI16", + "R_OR1K_GOTOFF_LO16", + "R_OR1K_COPY", + "R_OR1K_GLOB_DAT", + "R_OR1K_JMP_SLOT", + "R_OR1K_RELATIVE", + }; diff --git a/ldso/ldso/or1k/dl-startup.h b/ldso/ldso/or1k/dl-startup.h new file mode 100644 index 000000000..3c99bcd5c --- /dev/null +++ b/ldso/ldso/or1k/dl-startup.h @@ -0,0 +1,106 @@ +/* Startup code for the OpenRISC 1000 platform, + based on microblaze implementation */ +/* + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +__asm__ ("\ + .text\n\ + .globl _start\n\ + .type _start,@function\n\ + .hidden _start\n\ +_start:\n\ + l.ori r3, r9, 0\n\ + l.ori r3, r1, 0\n\ + l.movhi r11, 0\n\ +1:\n\ + l.addi r3, r3, 4\n\ + l.lwz r12, 0(r3)\n\ + l.sfnei r12, 0\n\ + l.addi r11, r11, 1\n\ + l.bf 1b\n\ + l.nop\n\ + l.ori r3, r11, 0\n\ + l.ori r3, r1, 0\n\ + l.addi r11, r11, -1\n\ + /* store argument counter to stack */\n\ + l.sw 0(r3), r11\n\ + l.addi r1, r1, -24\n\ + l.sw 0(r1), r9\n\ +\n\ + l.jal .LPC0\n\ +#ifndef __OR1K_NODELAY__\n\ + l.nop\n\ +#endif\n\ + /* Load the PIC register */\n\ +.LPC0:\n\ + l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_+(.-.LPC0))\n\ + l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+(.-.LPC0))\n\ + l.add r16, r16, r9\n\ +\n\ + l.jal _dl_start\n\ + l.nop\n\ + /* FALLTHRU */\n\ +\n\ + .globl _dl_start_user\n\ + .type _dl_start_user,@function\n\ +_dl_start_user:\n\ + l.movhi r12, gotoffhi(_dl_skip_args)\n\ + l.ori r12, r12, gotofflo(_dl_skip_args)\n\ + l.add r12, r12, r16\n\ + l.lwz r12, 0(r12)\n\ + l.lwz r3, 24(r1)\n\ +\n\ + l.movhi r9, gotoffhi(_dl_fini)\n\ + l.ori r9, r9, gotofflo(_dl_fini)\n\ + l.add r9, r9, r16\n\ +\n\ + l.addi r9, r9, -8\n\ + l.addi r1, r1, 24\n\ + l.jr r11\n\ + l.nop\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of 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) + +/* The ld.so library requires relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, + attribute_unused Elf32_Sym *symtab) +{ + + switch (ELF_R_TYPE(rpnt->r_info)) + { + case R_OR1K_RELATIVE: + + *reloc_addr = load_addr + rpnt->r_addend; + break; + + default: + _dl_exit(1); + break; + + } + +} diff --git a/ldso/ldso/or1k/dl-syscalls.h b/ldso/ldso/or1k/dl-syscalls.h new file mode 100644 index 000000000..f40c4fd31 --- /dev/null +++ b/ldso/ldso/or1k/dl-syscalls.h @@ -0,0 +1 @@ +/* stub for arch-specific syscall issues */ diff --git a/ldso/ldso/or1k/dl-sysdep.h b/ldso/ldso/or1k/dl-sysdep.h new file mode 100644 index 000000000..21ca028c8 --- /dev/null +++ b/ldso/ldso/or1k/dl-sysdep.h @@ -0,0 +1,105 @@ +/* elf reloc code for the or1k platform, based on glibc 2.3.6, dl-machine.h */ + +/* + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Use reloca */ +#define ELF_USES_RELOCA + +#include + + +/* Initialise the GOT */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ + +#define MAGIC1 EM_OR1K +#undef MAGIC2 +/* Used for error messages */ +#define ELF_TARGET "or1k" + +#define elf_machine_type_class(type) \ + (((type) == R_OR1K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT \ + | ((type) == R_OR1K_COPY) * ELF_RTYPE_CLASS_COPY) + +static inline Elf32_Addr * +or1k_get_got (void) +{ + Elf32_Addr *got; + Elf32_Addr linkreg; + __asm__("l.ori %0, r9, 0\n" + "l.jal .LPC1\n" +#ifndef __OR1K_NODELAY__ + "l.nop\n" +#endif + ".LPC1:\n" + "l.movhi %1, gotpchi(_GLOBAL_OFFSET_TABLE_+(.-.LPC1))\n" + "l.ori %1, %1, gotpclo(_GLOBAL_OFFSET_TABLE_+(.-.LPC1))\n" + "l.add %1, %1, r9\n" + "l.ori r9, %0, 0\n" + : "=r" (linkreg), "=r" (got)); + return got; +} + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. */ +static inline Elf32_Addr +elf_machine_dynamic (void) +{ + Elf32_Addr *got = or1k_get_got(); + return *got; +} + + +/* Return the run-time load address of the shared object. */ +static inline Elf32_Addr +elf_machine_load_address (void) +{ + /* Compute the difference between the runtime address of _DYNAMIC as seen + by a GOTOFF reference, and the link-time address found in the special + unrelocated first GOT entry. */ + Elf32_Addr dyn; + Elf32_Addr *got = or1k_get_got(); + + __asm__ __volatile__ ( + "l.movhi %0, gotoffhi(_DYNAMIC);" + "l.ori %0, %0, gotofflo(_DYNAMIC);" + "l.add %0, %0, %1;" + : "=r"(dyn), "=r"(got) + ); + return dyn - *got; +} + + + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * 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/or1k/elfinterp.c b/ldso/ldso/or1k/elfinterp.c new file mode 100644 index 000000000..928e95ba1 --- /dev/null +++ b/ldso/ldso/or1k/elfinterp.c @@ -0,0 +1,333 @@ +/* vi: set sw=4 ts=4: */ +/* OpenRISC 1000 ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* 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' in lib '%s'.\n", + _dl_progname, symname, tpnt->libname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) +#endif + *got_addr = new_addr; + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#if defined (__SUPPORT_LD_DEBUG__) + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +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; +#if defined USE_TLS && USE_TLS + struct elf_resolve *tls_tpnt; +#endif + struct symbol_ref sym_ref; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + struct unaligned { + Elf32_Addr x; + } __attribute__ ((packed, may_alias)); + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symbol_addr = 0; + symname = strtab + sym_ref.sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_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_TYPE(sym_ref.sym->st_info) != STT_TLS) + && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) { + /* This may be non-fatal if called from dlopen. */ + return 1; + } +#if defined USE_TLS && USE_TLS + tls_tpnt = sym_ref.tpnt; +#endif + } else { + /* Relocs against STN_UNDEF are usually treated as using a + * symbol value of zero, and using the module containing the + * reloc itself. */ + symbol_addr = sym_ref.sym->st_value; +#if defined USE_TLS && USE_TLS + tls_tpnt = tpnt; +#endif + } + + +#if defined (__SUPPORT_LD_DEBUG__) + if (reloc_addr) { + old_val = ((struct unaligned *)reloc_addr)->x; + } else { + old_val = 0; + } +#endif + + switch (reloc_type) { + case R_OR1K_NONE: + break; + + case R_OR1K_8: + case R_OR1K_16: + case R_OR1K_32: + /* Support relocations on mis-aligned offsets. */ + ((struct unaligned *)reloc_addr)->x = symbol_addr + + rpnt->r_addend; + break; + + case R_OR1K_8_PCREL: + case R_OR1K_16_PCREL: + case R_OR1K_32_PCREL: + case R_OR1K_INSN_REL_26: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + + case R_OR1K_GLOB_DAT: + case R_OR1K_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; +/* Handled by elf_machine_relative */ + case R_OR1K_RELATIVE: + *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + break; + + case R_OR1K_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym_ref.sym->st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + sym_ref.sym->st_size); + } +#if defined (__SUPPORT_LD_DEBUG__) + else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); +#endif + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, ((struct unaligned *)reloc_addr)->x, + reloc_addr); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(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_OR1K_NONE: + break; + case R_OR1K_JMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\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) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +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, _dl_do_reloc); +} diff --git a/ldso/ldso/or1k/resolve.S b/ldso/ldso/or1k/resolve.S new file mode 100644 index 000000000..4a156d529 --- /dev/null +++ b/ldso/ldso/or1k/resolve.S @@ -0,0 +1,54 @@ +/* This code is used in dl-runtime.c to call the `fixup' function + and then redirect to the address it returns. */ +/* We assume that R11 contain relocation offset and R12 contains + link_map (_DYNAMIC). This must be consistent with the JUMP_SLOT + layout generated by binutils. */ + +/* Based on microblaze implementation */ +/* + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +.text +.align 4 +.globl _dl_linux_resolver +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function + +_dl_linux_resolve: + l.addi r1, r1, -32 + l.sw 0(r1), r9 + /* save function arguments */ + l.sw 8(r1), r3 + l.sw 12(r1), r4 + l.sw 16(r1), r5 + l.sw 20(r1), r6 + l.sw 24(r1), r7 + l.sw 28(r1), r8 + l.ori r3, r12, 0 + l.ori r4, r11, 0 + l.jal _dl_linux_resolver + l.nop + l.lwz r8, 28(r1) + l.lwz r7, 24(r1) + l.lwz r6, 20(r1) + l.lwz r5, 16(r1) + l.lwz r4, 12(r1) + l.lwz r3, 8(r1) + l.lwz r9, 0(r1) + l.addi r1, r1, 32 + l.jr r11 + l.nop + .size _dl_linux_resolve, . - _dl_linux_resolve -- cgit v1.2.3