summaryrefslogtreecommitdiff
path: root/ldso/ldso/mips
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-04-02 21:12:37 +0000
committerEric Andersen <andersen@codepoet.org>2002-04-02 21:12:37 +0000
commit96749a768287761528a05670560402a16f6839ac (patch)
treec53550a3ec7458f02da07d465c74bae3f752f499 /ldso/ldso/mips
parentabdb41c778c5892d51fe92879d383eb8ba000028 (diff)
Steven J. Hill's latest mips dynamic loader updates
Diffstat (limited to 'ldso/ldso/mips')
-rw-r--r--ldso/ldso/mips/README43
-rw-r--r--ldso/ldso/mips/boot1_arch.h5
-rw-r--r--ldso/ldso/mips/dl-startup.h5
-rw-r--r--ldso/ldso/mips/dl-syscalls.h30
-rw-r--r--ldso/ldso/mips/dl-sysdep.h92
-rw-r--r--ldso/ldso/mips/elfinterp.c49
-rw-r--r--ldso/ldso/mips/ld_syscalls.h30
-rw-r--r--ldso/ldso/mips/ld_sysdep.h92
8 files changed, 294 insertions, 52 deletions
diff --git a/ldso/ldso/mips/README b/ldso/ldso/mips/README
new file mode 100644
index 000000000..b54e25183
--- /dev/null
+++ b/ldso/ldso/mips/README
@@ -0,0 +1,43 @@
+Almost all of the code present in these source files was taken
+from GLIBC. In the descriptions below, all files mentioned are
+with respect to the top level GLIBC source directory accept for
+the code taken from the Linux kernel.
+
+boot1_arch.h
+------------
+Contains code to fix up the stack pointer so that the dynamic
+linker can find argc, argv and Auxillary Vector Table (AVT).
+The codes is taken from the function 'RTLD_START' in the
+file 'sysdeps/mips/dl-machine.h'.
+
+elfinterp.c
+-----------
+Contains '_dl_init_got' which initializes the GOT for the
+application being dynamically linked and loaded. The code is
+taken from the functions 'elf_machine_runtime_setup' and
+'elf_machine_got_rel' in the file 'sysdeps/mips/dl-machine.h'.
+
+ld_syscalls.h
+-------------
+Contains all the macro function prototypes for the system calls
+as well as the list of system calls supported. The macros were
+taken from the Linux kernel source 2.4.17 found in the file
+'include/asm-mips/unistd.h'.
+
+ld_sysdep.h
+-----------
+Contains bootstrap code for the dynamic linker, magic numbers
+for detecting MIPS target types and some macros. The macro
+function 'PERFORM_BOOTSTRAP_GOT' is used to relocate the dynamic
+linker's GOT so that function calls can be made. The code is
+taken from the function 'ELF_MACHINE_BEFORE_RTLD_RELOC' in the
+file 'sysdep/mips/dl-machine.h'. The other macro function
+'PERFORM_BOOTSTRAP_RELOC' is used to do the relocations for
+the dynamic loader. The code is taken from the function
+'elf_machine_rel' in the file 'sysdep/mips/dl-machine.h'.
+
+resolve.S
+---------
+Contains the low-level assembly code for the dynamic runtime
+resolver. The code is taken from the assembly code function
+'_dl_runtime_resolve' in the file 'sysdesp/mips/dl-machine.h'.
diff --git a/ldso/ldso/mips/boot1_arch.h b/ldso/ldso/mips/boot1_arch.h
index e86ff77cf..f439ee4bc 100644
--- a/ldso/ldso/mips/boot1_arch.h
+++ b/ldso/ldso/mips/boot1_arch.h
@@ -13,11 +13,8 @@ _dl_boot:
nop
0: .cpload $31
.set reorder
- # i386 ABI book says that the first entry of GOT holds
- # the address of the dynamic structure. Though MIPS ABI
- # doesn't say nothing about this, I emulate this here.
+ # Store offset of DYNAMIC section in first entry of GOT
la $4, _DYNAMIC
- # Subtract OFFSET_GP_GOT
sw $4, -0x7ff0($28)
move $4, $29
la $8, coff
diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
index e86ff77cf..f439ee4bc 100644
--- a/ldso/ldso/mips/dl-startup.h
+++ b/ldso/ldso/mips/dl-startup.h
@@ -13,11 +13,8 @@ _dl_boot:
nop
0: .cpload $31
.set reorder
- # i386 ABI book says that the first entry of GOT holds
- # the address of the dynamic structure. Though MIPS ABI
- # doesn't say nothing about this, I emulate this here.
+ # Store offset of DYNAMIC section in first entry of GOT
la $4, _DYNAMIC
- # Subtract OFFSET_GP_GOT
sw $4, -0x7ff0($28)
move $4, $29
la $8, coff
diff --git a/ldso/ldso/mips/dl-syscalls.h b/ldso/ldso/mips/dl-syscalls.h
index feb54d4cf..da17d63b9 100644
--- a/ldso/ldso/mips/dl-syscalls.h
+++ b/ldso/ldso/mips/dl-syscalls.h
@@ -142,4 +142,34 @@ type name(atype a, btype b, ctype c, dtype d) \
return (type) -1; \
}
+#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \
+{ \
+ register unsigned long __v0 asm("$2") = __NR_##name; \
+ register unsigned long __a0 asm("$4") = (unsigned long) a; \
+ register unsigned long __a1 asm("$5") = (unsigned long) b; \
+ register unsigned long __a2 asm("$6") = (unsigned long) c; \
+ register unsigned long __a3 asm("$7") = (unsigned long) d; \
+ \
+ __asm__ volatile ( \
+ ".set\tnoreorder\n\t" \
+ "lw\t$2, %6\n\t" \
+ "lw\t$8, %7\n\t" \
+ "subu\t$29, 32\n\t" \
+ "sw\t$2, 16($29)\n\t" \
+ "sw\t$8, 20($29)\n\t" \
+ "li\t$2, %5\t\t\t# " #name "\n\t" \
+ "syscall\n\t" \
+ "addiu\t$29, 32\n\t" \
+ ".set\treorder" \
+ : "=&r" (__v0), "+r" (__a3) \
+ : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \
+ "m" ((unsigned long)e), "m" ((unsigned long)f) \
+ : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \
+ \
+ if (__a3 == 0) \
+ return (type) __v0; \
+ return (type) -1; \
+}
+
#endif
diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h
index 24cbc3d04..8bc6aaccd 100644
--- a/ldso/ldso/mips/dl-sysdep.h
+++ b/ldso/ldso/mips/dl-sysdep.h
@@ -8,36 +8,82 @@
*/
#undef ELF_USES_RELOCA
+
/*
* 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)
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *) ARGS)
+
/*
- * Initialization sequence for a GOT.
+ * Initialization sequence for the application GOT.
*/
-#define INIT_GOT(GOT_BASE,MODULE) \
-{ \
- GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
- GOT_BASE[1] = (unsigned long) MODULE; \
-}
+#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE)
+
+
+/*
+ * Here is a macro to perform the GOT relocation. This is only
+ * used when bootstrapping the dynamic loader.
+ */
+#define PERFORM_BOOTSTRAP_GOT(got) \
+do { \
+ Elf32_Sym *sym; \
+ unsigned long i; \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+ i = 2; \
+ while (i < mips_local_gotno) \
+ got[i++] += load_addr; \
+ \
+ /* Handle global GOT entries */ \
+ got += mips_local_gotno; \
+ sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + \
+ load_addr) + mips_gotsym; \
+ i = mips_symtabno - mips_gotsym; \
+ \
+ while (i--) { \
+ if (sym->st_shndx == SHN_UNDEF || \
+ sym->st_shndx == SHN_COMMON) \
+ *got = load_addr + sym->st_value; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
+ *got != sym->st_value) \
+ *got += load_addr; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
+ if (sym->st_other == 0) \
+ *got += load_addr; \
+ } \
+ else \
+ *got = load_addr + sym->st_value; \
+ \
+ got++; \
+ sym++; \
+ } \
+} while (0)
+
/*
* Here is a macro to perform a relocation. This is only used when
- * bootstrapping the dynamic loader. RELP is the relocation that we
- * are performing, REL is the pointer to the address we are relocating.
- * SYMBOL is the symbol involved in the relocation, and LOAD is the
- * load address.
- *
- * !!!NOTE!!!
- *
- * For MIPS, we don't have any DT_JMPREL or DT_PLTRELSZ dynamic
- * entries, so this macro function is empty. The code contained
- * in elfinterp.c does the real relocation work.
+ * bootstrapping the dynamic loader.
*/
-#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) \
+ switch(ELF32_R_TYPE((RELP)->r_info)) { \
+ case R_MIPS_REL32: \
+ if (symtab_index) { \
+ if (symtab_index < mips_gotsym) \
+ *REL += SYMBOL + LOAD; \
+ } \
+ else { \
+ *REL += LOAD; \
+ } \
+ break; \
+ case R_MIPS_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("Aiieeee!"); \
+ _dl_exit(1); \
+ }
/*
@@ -45,19 +91,21 @@
* is done. This routine has to exit the current function, then
* call the _dl_elf_main function.
*/
-
#define START() return (void) _dl_elf_main;
-
/* Here we define the magic numbers that this dynamic loader should accept */
-
#define MAGIC1 EM_MIPS
#define MAGIC2 EM_MIPS_RS3_LE
+
+
/* Used for error messages */
#define ELF_TARGET "MIPS"
+
struct elf_resolve;
-unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
+ int reloc_entry);
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
#define do_rem(result, n, base) result = (n % base)
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
new file mode 100644
index 000000000..c38a7ffa2
--- /dev/null
+++ b/ldso/ldso/mips/elfinterp.c
@@ -0,0 +1,49 @@
+/* Run an ELF binary on a linux system.
+
+ Copyright (C) 1993, Eric Youngdale.
+ Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* 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);
+
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt)
+{
+ return;
+}
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ return 0;
+}
+
+int _dl_parse_relocation_information(struct elf_resolve *tpnt,
+ unsigned long rel_addr, unsigned long rel_size, int type)
+{
+ return 1;
+}
diff --git a/ldso/ldso/mips/ld_syscalls.h b/ldso/ldso/mips/ld_syscalls.h
index feb54d4cf..da17d63b9 100644
--- a/ldso/ldso/mips/ld_syscalls.h
+++ b/ldso/ldso/mips/ld_syscalls.h
@@ -142,4 +142,34 @@ type name(atype a, btype b, ctype c, dtype d) \
return (type) -1; \
}
+#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \
+{ \
+ register unsigned long __v0 asm("$2") = __NR_##name; \
+ register unsigned long __a0 asm("$4") = (unsigned long) a; \
+ register unsigned long __a1 asm("$5") = (unsigned long) b; \
+ register unsigned long __a2 asm("$6") = (unsigned long) c; \
+ register unsigned long __a3 asm("$7") = (unsigned long) d; \
+ \
+ __asm__ volatile ( \
+ ".set\tnoreorder\n\t" \
+ "lw\t$2, %6\n\t" \
+ "lw\t$8, %7\n\t" \
+ "subu\t$29, 32\n\t" \
+ "sw\t$2, 16($29)\n\t" \
+ "sw\t$8, 20($29)\n\t" \
+ "li\t$2, %5\t\t\t# " #name "\n\t" \
+ "syscall\n\t" \
+ "addiu\t$29, 32\n\t" \
+ ".set\treorder" \
+ : "=&r" (__v0), "+r" (__a3) \
+ : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \
+ "m" ((unsigned long)e), "m" ((unsigned long)f) \
+ : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \
+ \
+ if (__a3 == 0) \
+ return (type) __v0; \
+ return (type) -1; \
+}
+
#endif
diff --git a/ldso/ldso/mips/ld_sysdep.h b/ldso/ldso/mips/ld_sysdep.h
index 24cbc3d04..8bc6aaccd 100644
--- a/ldso/ldso/mips/ld_sysdep.h
+++ b/ldso/ldso/mips/ld_sysdep.h
@@ -8,36 +8,82 @@
*/
#undef ELF_USES_RELOCA
+
/*
* 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)
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *) ARGS)
+
/*
- * Initialization sequence for a GOT.
+ * Initialization sequence for the application GOT.
*/
-#define INIT_GOT(GOT_BASE,MODULE) \
-{ \
- GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
- GOT_BASE[1] = (unsigned long) MODULE; \
-}
+#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE)
+
+
+/*
+ * Here is a macro to perform the GOT relocation. This is only
+ * used when bootstrapping the dynamic loader.
+ */
+#define PERFORM_BOOTSTRAP_GOT(got) \
+do { \
+ Elf32_Sym *sym; \
+ unsigned long i; \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+ i = 2; \
+ while (i < mips_local_gotno) \
+ got[i++] += load_addr; \
+ \
+ /* Handle global GOT entries */ \
+ got += mips_local_gotno; \
+ sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + \
+ load_addr) + mips_gotsym; \
+ i = mips_symtabno - mips_gotsym; \
+ \
+ while (i--) { \
+ if (sym->st_shndx == SHN_UNDEF || \
+ sym->st_shndx == SHN_COMMON) \
+ *got = load_addr + sym->st_value; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
+ *got != sym->st_value) \
+ *got += load_addr; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
+ if (sym->st_other == 0) \
+ *got += load_addr; \
+ } \
+ else \
+ *got = load_addr + sym->st_value; \
+ \
+ got++; \
+ sym++; \
+ } \
+} while (0)
+
/*
* Here is a macro to perform a relocation. This is only used when
- * bootstrapping the dynamic loader. RELP is the relocation that we
- * are performing, REL is the pointer to the address we are relocating.
- * SYMBOL is the symbol involved in the relocation, and LOAD is the
- * load address.
- *
- * !!!NOTE!!!
- *
- * For MIPS, we don't have any DT_JMPREL or DT_PLTRELSZ dynamic
- * entries, so this macro function is empty. The code contained
- * in elfinterp.c does the real relocation work.
+ * bootstrapping the dynamic loader.
*/
-#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) \
+ switch(ELF32_R_TYPE((RELP)->r_info)) { \
+ case R_MIPS_REL32: \
+ if (symtab_index) { \
+ if (symtab_index < mips_gotsym) \
+ *REL += SYMBOL + LOAD; \
+ } \
+ else { \
+ *REL += LOAD; \
+ } \
+ break; \
+ case R_MIPS_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("Aiieeee!"); \
+ _dl_exit(1); \
+ }
/*
@@ -45,19 +91,21 @@
* is done. This routine has to exit the current function, then
* call the _dl_elf_main function.
*/
-
#define START() return (void) _dl_elf_main;
-
/* Here we define the magic numbers that this dynamic loader should accept */
-
#define MAGIC1 EM_MIPS
#define MAGIC2 EM_MIPS_RS3_LE
+
+
/* Used for error messages */
#define ELF_TARGET "MIPS"
+
struct elf_resolve;
-unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
+ int reloc_entry);
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
#define do_rem(result, n, base) result = (n % base)