OSDN Git Service

microblaze mmu/elf/shared lib support
authorRyan Flux <ryan.flux@emsolutions.com.au>
Tue, 4 Oct 2011 00:50:49 +0000 (10:50 +1000)
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Thu, 6 Oct 2011 20:22:25 +0000 (22:22 +0200)
microblaze can either be with mmu or without
If with, use elf rather than flat, and support shared libs

Signed-off-by: Ryan Flux <ryan.flux@emsolutions.com.au>
Signed-off-by: Steve Bennett <steveb@workware.net.au>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
13 files changed:
extra/Configs/Config.microblaze
include/elf.h
ldso/include/dl-string.h
ldso/ldso/microblaze/dl-debug.h [new file with mode: 0644]
ldso/ldso/microblaze/dl-startup.h [new file with mode: 0644]
ldso/ldso/microblaze/dl-syscalls.h [new file with mode: 0644]
ldso/ldso/microblaze/dl-sysdep.h [new file with mode: 0644]
ldso/ldso/microblaze/elfinterp.c [new file with mode: 0644]
ldso/ldso/microblaze/resolve.S [new file with mode: 0644]
libc/sysdeps/linux/microblaze/bits/uClibc_page.h
libc/sysdeps/linux/microblaze/setjmp.S
libc/sysdeps/linux/microblaze/vfork.S
utils/ldd.c

index dbcf1d5..2dfd4a7 100644 (file)
@@ -6,8 +6,3 @@
 config TARGET_ARCH
        string
        default "microblaze"
-
-config FORCE_OPTIONS_FOR_ARCH
-       bool
-       default y
-       select ARCH_HAS_NO_MMU
index d71691e..ba3e804 100644 (file)
@@ -368,6 +368,14 @@ typedef struct
 /* V850 backend magic number.  Written in the absense of an ABI.  */
 #define EM_CYGNUS_V850 0x9080
 
+/* Xilinx Microblaze (unofficial). Note that there is now an official microblaze
+ * magic number, but all the toolchains currently in existence use the old number
+ */
+#define EM_MICROBLAZE_OLD   0xbaab
+
+/* Xilinx Microblaze (official) */
+#define EM_MICROBLAZE   189
+
 /* Legal values for e_version (version).  */
 
 #define EV_NONE                0               /* Invalid ELF version */
@@ -3108,6 +3116,31 @@ typedef Elf32_Addr Elf32_Conflict;
 
 #define DT_C6000_NUM    4
 
+/* microblaze specific relocs */
+#define R_MICROBLAZE_NONE 0
+#define R_MICROBLAZE_32 1
+#define R_MICROBLAZE_32_PCREL 2
+#define R_MICROBLAZE_64_PCREL 3
+#define R_MICROBLAZE_32_PCREL_LO 4
+#define R_MICROBLAZE_64 5
+#define R_MICROBLAZE_32_LO 6
+#define R_MICROBLAZE_SRO32 7
+#define R_MICROBLAZE_SRW32 8
+#define R_MICROBLAZE_64_NONE 9
+#define R_MICROBLAZE_32_SYM_OP_SYM 10
+#define R_MICROBLAZE_GNU_VTINHERIT 11
+#define R_MICROBLAZE_GNU_VTENTRY 12
+#define R_MICROBLAZE_GOTPC_64 13  /* PC-relative GOT offset */
+#define R_MICROBLAZE_GOT_64 14  /* GOT entry offset */
+#define R_MICROBLAZE_PLT_64 15  /* PLT offset (PC-relative  */
+#define R_MICROBLAZE_REL 16  /* adjust by program base */
+#define R_MICROBLAZE_JUMP_SLOT 17  /* create PLT entry */
+#define R_MICROBLAZE_GLOB_DAT 18  /* create GOT entry */
+#define R_MICROBLAZE_GOTOFF_64 19  /* offset relative to GOT */
+#define R_MICROBLAZE_GOTOFF_32 20  /* offset relative to GOT */
+#define R_MICROBLAZE_COPY 21  /* runtime copy */
+#define R_MICROBLAZE_NUM 22
+
 #ifdef __cplusplus
 }
 #endif
index 01ab50e..a7e2f47 100644 (file)
@@ -286,7 +286,7 @@ static __always_inline char * _dl_simple_ltoahex(char *local, unsigned long i)
  * This requires that load_addr must already be defined... */
 #if defined(mc68000)  || defined(__arm__) || defined(__thumb__) || \
     defined(__mips__) || defined(__sh__)  || defined(__powerpc__) || \
-    defined(__avr32__) || defined(__xtensa__) || defined(__sparc__)
+    defined(__avr32__) || defined(__xtensa__) || defined(__sparc__) || defined(__microblaze__)
 # define CONSTANT_STRING_GOT_FIXUP(X) \
        if ((X) < (const char *) load_addr) (X) += load_addr
 # define NO_EARLY_SEND_STDERR
diff --git a/ldso/ldso/microblaze/dl-debug.h b/ldso/ldso/microblaze/dl-debug.h
new file mode 100644 (file)
index 0000000..6fd7bd5
--- /dev/null
@@ -0,0 +1,54 @@
+/* vi: set sw=4 ts=4: */
+/* microblaze shared library loader suppport
+ *
+ * Copyright (C) 2011 Ryan Flux
+ *
+ * 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_MICROBLAZE_NONE",
+               "R_MICROBLAZE_32",
+               "R_MICROBLAZE_32_PCREL",
+               "R_MICROBLAZE_64_PCREL",
+               "R_MICROBLAZE_32_PCREL_LO",
+               "R_MICROBLAZE_64",
+               "R_MICROBLAZE_32_LO",
+               "R_MICROBLAZE_SRO32",
+               "R_MICROBLAZE_SRW32",
+               "R_MICROBLAZE_64_NONE",
+               "R_MICROBLAZE_32_SYM_OP_SYM",
+               "R_MICROBLAZE_GNU_VTINHERIT",
+               "R_MICROBLAZE_GNU_VTENTRY",
+               "R_MICROBLAZE_GOTPC_64",
+               "R_MICROBLAZE_GOT_64",
+               "R_MICROBLAZE_PLT_64",
+               "R_MICROBLAZE_REL",
+               "R_MICROBLAZE_JUMP_SLOT",
+               "R_MICROBLAZE_GLOB_DAT",
+               "R_MICROBLAZE_GOTOFF_64",
+               "R_MICROBLAZE_GOTOFF_32",
+               "R_MICROBLAZE_COPY",
+       };
diff --git a/ldso/ldso/microblaze/dl-startup.h b/ldso/ldso/microblaze/dl-startup.h
new file mode 100644 (file)
index 0000000..0d3f3bf
--- /dev/null
@@ -0,0 +1,102 @@
+/* Startup code for the microblaze 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.  */
+
+__asm__ ("\
+       .text\n\
+       .globl _start\n\
+       .type _start,@function\n\
+_start:\n\
+       addk  r5,r0,r1\n\
+       addk  r3,r0,r0\n\
+1:\n\
+       addik r5,r5,4\n\
+       lw    r4,r5,r0\n\
+       bneid r4,1b\n\
+       addik r3,r3,1\n\
+       addik r3,r3,-1\n\
+       addk  r5,r0,r1\n\
+       sw    r3,r5,r0\n\
+       addik r1,r1,-24\n\
+       sw    r15,r1,r0\n\
+       brlid r15,_dl_start\n\
+       nop\n\
+       /* FALLTHRU */\n\
+\n\
+       .globl _dl_start_user\n\
+       .type _dl_start_user,@function\n\
+_dl_start_user:\n\
+       mfs   r20,rpc\n\
+       addik r20,r20,_GLOBAL_OFFSET_TABLE_+8\n\
+       lwi   r4,r20,_dl_skip_args@GOTOFF\n\
+       lwi   r5,r1,24\n\
+       rsubk r5,r4,r5\n\
+       addk  r4,r4,r4\n\
+       addk  r4,r4,r4\n\
+       addk  r1,r1,r4\n\
+       swi   r5,r1,24\n\
+       swi   r3,r1,20\n\
+       addk  r6,r5,r0\n\
+       addk  r5,r5,r5\n\
+       addk  r5,r5,r5\n\
+       addik r7,r1,28\n\
+       addk  r8,r7,r5\n\
+       addik r8,r8,4\n\
+       lwi   r5,r1,24\n\
+       lwi   r3,r1,20\n\
+       addk  r4,r5,r5\n\
+       addk  r4,r4,r4\n\
+       addik r6,r1,28\n\
+       addk  r7,r6,r4\n\
+       addik r7,r7,4\n\
+       addik r15,r20,_dl_fini@GOTOFF\n\
+       addik r15,r15,-8\n\
+       brad  r3\n\
+       addik r1,r1,24\n\
+       nop\n\
+       .size _dl_start_user, . - _dl_start_user\n\
+       .previous");
+
+/*
+ * 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 (ELF32_R_TYPE(rpnt->r_info))
+       {
+               case R_MICROBLAZE_REL:
+
+                       *reloc_addr = load_addr + rpnt->r_addend;
+                       break;
+
+               default:
+                       _dl_exit(1);
+                       break;
+
+       }
+
+}
diff --git a/ldso/ldso/microblaze/dl-syscalls.h b/ldso/ldso/microblaze/dl-syscalls.h
new file mode 100644 (file)
index 0000000..996bb87
--- /dev/null
@@ -0,0 +1,6 @@
+/* We can't use the real errno in ldso, since it has not yet
+ * been dynamicly linked in yet. */
+#include "sys/syscall.h"
+extern int _dl_errno;
+#undef __set_errno
+#define __set_errno(X) {(_dl_errno) = (X);}
diff --git a/ldso/ldso/microblaze/dl-sysdep.h b/ldso/ldso/microblaze/dl-sysdep.h
new file mode 100644 (file)
index 0000000..1f89673
--- /dev/null
@@ -0,0 +1,85 @@
+/* elf reloc code for the microblaze 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 <elf.h>
+
+
+/* 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_MICROBLAZE_OLD
+#undef  MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "microblaze"
+
+#define elf_machine_type_class(type) \
+  (((type) == R_MICROBLAZE_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT \
+   | ((type) == R_MICROBLAZE_COPY) * ELF_RTYPE_CLASS_COPY)
+
+/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
+   first element of the GOT.  This must be inlined in a function which
+   uses global data.  */
+static inline Elf32_Addr
+elf_machine_dynamic (void)
+{
+  Elf32_Addr got_entry_0;
+  __asm__ __volatile__(
+    "lwi %0,r20,0"
+    :"=r"(got_entry_0)
+    );
+  return got_entry_0;
+}
+
+
+/* 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;
+  __asm__ __volatile__ (
+    "addik %0,r20,_DYNAMIC@GOTOFF"
+    : "=r"(dyn)
+    );
+  return dyn - elf_machine_dynamic ();
+}
+
+
+
+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;
+       do {
+               Elf32_Addr *const reloc_addr = (void *) (load_off + (rpnt)->r_offset);
+
+               *reloc_addr += load_off;
+       } while (--relative_count);
+}
diff --git a/ldso/ldso/microblaze/elfinterp.c b/ldso/ldso/microblaze/elfinterp.c
new file mode 100644 (file)
index 0000000..1f6aeff
--- /dev/null
@@ -0,0 +1,330 @@
+/* vi: set sw=4 ts=4: */
+/* microblaze 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'\n", _dl_progname, symname);
+               _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
+
+       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 = *reloc_addr;
+       } else {
+               old_val = 0;
+       }
+#endif
+
+       switch (reloc_type) {
+               case R_MICROBLAZE_NONE:
+               case R_MICROBLAZE_64_NONE:
+                       break;
+
+               case R_MICROBLAZE_64:
+                       *reloc_addr = symbol_addr + rpnt->r_addend;
+                       break;
+
+               case R_MICROBLAZE_32:
+               case R_MICROBLAZE_32_LO:
+                       *reloc_addr = symbol_addr + rpnt->r_addend;
+                       break;
+
+               case R_MICROBLAZE_32_PCREL:
+               case R_MICROBLAZE_32_PCREL_LO:
+               case R_MICROBLAZE_64_PCREL:
+               case R_MICROBLAZE_SRO32:
+               case R_MICROBLAZE_SRW32:
+                       *reloc_addr = symbol_addr + rpnt->r_addend;
+                       break;
+
+               case R_MICROBLAZE_GLOB_DAT:
+               case R_MICROBLAZE_JUMP_SLOT:
+                       *reloc_addr = symbol_addr + rpnt->r_addend;
+                       break;
+/* Handled by elf_machine_relative */
+               case R_MICROBLAZE_REL:
+                       *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
+                       break;
+
+               case R_MICROBLAZE_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, *reloc_addr, 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_MICROBLAZE_NONE:
+                       break;
+               case R_MICROBLAZE_JUMP_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/microblaze/resolve.S b/ldso/ldso/microblaze/resolve.S
new file mode 100644 (file)
index 0000000..8ad94fe
--- /dev/null
@@ -0,0 +1,52 @@
+
+/* This code is used in dl-runtime.c to call the `fixup' function
+   and then redirect to the address it returns. */
+/* We assume that R3 contain relocation offset and R4 contains
+   link_map (_DYNAMIC). This must be consistent with the JUMP_SLOT
+   layout generated by binutils. */
+
+/* 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.  */
+
+.text
+.align 4
+.globl _dl_linux_resolver
+.globl _dl_linux_resolve
+.type  _dl_linux_resolve,@function
+
+_dl_linux_resolve:
+    addik r1,r1,-40
+    swi   r5,r1,12
+    swi   r6,r1,16
+    swi   r7,r1,20
+    swi   r8,r1,24
+    swi   r9,r1,28
+    swi   r10,r1,32
+    swi   r15,r1,0
+    addk r5,r0,r4
+    brlid r15, _dl_linux_resolver
+    addk r6,r0,r3; /* delay slot */
+    lwi   r10,r1,32
+    lwi   r9,r1,28
+    lwi   r8,r1,24
+    lwi   r7,r1,20
+    lwi   r6,r1,16
+    lwi   r5,r1,12
+    lwi   r15,r1,0
+    brad  r3
+    addik r1,r1,40; /* delay slot */
+    .size _dl_linux_resolve, . - _dl_linux_resolve
index 8fc81ae..41b0422 100644 (file)
@@ -31,7 +31,9 @@
 #elif defined(CONFIG_MICROBLAZE_4K_PAGES)
 #define PAGE_SHIFT             12
 #else
+#if !defined(CONFIG_MMU)
 #warning Missing CONFIG_MICROBLAZE_nnK_PAGES, assuming 4K
+#endif
 #define PAGE_SHIFT             12
 #endif
 
index 7acb9ea..d01c745 100644 (file)
  * directory of this archive for more details.
  *
  * Written by Miles Bader <miles@gnu.org>
- */
+ *
+ * PIC code based on glibc 2.3.6 */
+
+/*
+   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.  */
 
 #define _SETJMP_H
 #define _ASM
        .globl C_SYMBOL_NAME(setjmp)
        .align 4
 C_SYMBOL_NAME(setjmp):
+#ifdef __PIC__
+       brid    1f
+#else
        braid   C_SYMBOL_NAME(__sigsetjmp)
+#endif
        addi    r6, r0, 1                       /* Save the signal mask.  */
 
        .globl C_SYMBOL_NAME(_setjmp)
@@ -31,6 +52,7 @@ C_SYMBOL_NAME(_setjmp):
 
        .globl C_SYMBOL_NAME(__sigsetjmp)
 C_SYMBOL_NAME(__sigsetjmp):
+1:
        /* Save registers relative to r5 (arg0)*/
        swi     r1, r5, 0                       /* stack pointer */
        swi     r15, r5, 4                      /* link register */
@@ -52,5 +74,13 @@ C_SYMBOL_NAME(__sigsetjmp):
        swi     r31, r5, 68
 
        /* Make a tail call to __sigjmp_save; it takes the same args.  */
+#ifdef __PIC__
+       mfs   r12,rpc
+       addik r12,r12,_GLOBAL_OFFSET_TABLE_+8
+       lwi   r12,r12,__sigjmp_save@GOT
+       brad  r12
+       nop
+#else
        braid   C_SYMBOL_NAME(__sigjmp_save)
        nop
+#endif
index c4b4dbf..57db5e5 100644 (file)
@@ -36,7 +36,14 @@ __vfork:
        blti    r4, 1f                  /* is r3 < -125? */
        bri     2f                      /* normal return */
 1:     sub     r3, r3, r0              /* r3 = -r3 */
+#ifdef __PIC__
+       mfs     r3,rpc
+       addik   r3,r3,_GLOBAL_OFFSET_TABLE_+8
+       lwi     r3,r3,C_SYMBOL_NAME(errno)@GOT
+       sw      r3, r0, r3
+#else
        swi     r3, r0, C_SYMBOL_NAME(errno);
+#endif
                                        /* state restore etc */
 2:     rtsd    r15, 8                  /* error return */
        nop
index 904075c..6d08efd 100644 (file)
 #define ELFCLASSM      ELFCLASS64
 #endif
 
+#if defined(__microblaze__)
+#define MATCH_MACHINE(x) (x == EM_MICROBLAZE_OLD)
+#define ELFCLASSM      ELFCLASS32
+#endif
+
 #ifndef MATCH_MACHINE
 # ifdef __linux__
 #  include <asm/elf.h>