From f9e3d5ffc0472279dde8589fa52e2dfb7e78de03 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Tue, 19 Mar 2002 17:05:51 +0000 Subject: Initial mips ldso porting effort from Steven J. Hill. Not yet complete, but off to a fine start. --- ldso/ldso/mips/dl-syscalls.h | 137 +++++++++++++++++++++++++++++++++++++++++++ ldso/ldso/mips/dl-sysdep.h | 63 ++++++++++++++++++++ ldso/ldso/mips/ld_syscalls.h | 137 +++++++++++++++++++++++++++++++++++++++++++ ldso/ldso/mips/ld_sysdep.h | 63 ++++++++++++++++++++ ldso/ldso/mips/resolve.S | 48 +++++++++++++++ 5 files changed, 448 insertions(+) create mode 100644 ldso/ldso/mips/dl-syscalls.h create mode 100644 ldso/ldso/mips/dl-sysdep.h create mode 100644 ldso/ldso/mips/ld_syscalls.h create mode 100644 ldso/ldso/mips/ld_sysdep.h create mode 100644 ldso/ldso/mips/resolve.S diff --git a/ldso/ldso/mips/dl-syscalls.h b/ldso/ldso/mips/dl-syscalls.h new file mode 100644 index 000000000..2327219df --- /dev/null +++ b/ldso/ldso/mips/dl-syscalls.h @@ -0,0 +1,137 @@ +/* + * This file contains the system call macros and syscall + * numbers used by the shared library loader. Taken from + * Linux/MIPS 2.4.17 version kernel. + */ + +#define __NR_SYSCALL_BASE 4000 + +#define __NR_exit (__NR_SYSCALL_BASE + 1) +#define __NR_read (__NR_SYSCALL_BASE + 3) +#define __NR_write (__NR_SYSCALL_BASE + 4) +#define __NR_open (__NR_SYSCALL_BASE + 5) +#define __NR_close (__NR_SYSCALL_BASE + 6) +#define __NR_getuid (__NR_SYSCALL_BASE + 24) +#define __NR_getgid (__NR_SYSCALL_BASE + 47) +#define __NR_geteuid (__NR_SYSCALL_BASE + 49) +#define __NR_getegid (__NR_SYSCALL_BASE + 50) +#define __NR_readlink (__NR_SYSCALL_BASE + 85) +#define __NR_mmap (__NR_SYSCALL_BASE + 90) +#define __NR_munmap (__NR_SYSCALL_BASE + 91) +#define __NR_stat (__NR_SYSCALL_BASE + 106) +#define __NR_mprotect (__NR_SYSCALL_BASE + 125) + +/* Here are the macros which define how this platform makes + * system calls. This particular variant does _not_ set + * errno (note how it is disabled in __syscall_return) since + * these will get called before the errno symbol is dynamicly + * linked. */ + +#define _syscall0(type,name) \ +type name(void) \ +{ \ + register unsigned long __v0 asm("$2") = __NR_##name; \ + register unsigned long __a3 asm("$7"); \ + \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "li\t$2, %2\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "=r" (__a3) \ + : "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return -1; \ +} + +#define _syscall1(type,name,atype,a) \ +type name(atype a) \ +{ \ + register unsigned long __v0 asm("$2") = __NR_##name; \ + register unsigned long __a0 asm("$4") = (unsigned long) a; \ + register unsigned long __a3 asm("$7"); \ + \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "li\t$2, %3\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "=r" (__a3) \ + : "r" (__a0), "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return (type) -1; \ +} + +#define _syscall2(type,name,atype,a,btype,b) \ +type name(atype a, btype b) \ +{ \ + 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 __a3 asm("$7"); \ + \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "li\t$2, %4\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "=r" (__a3) \ + : "r" (__a0), "r" (__a1), "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return (type) -1; \ +} + +#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ +type name(atype a, btype b, ctype c) \ +{ \ + 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"); \ + \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "li\t$2, %5\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "=r" (__a3) \ + : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return (type) -1; \ +} + +#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \ +type name(atype a, btype b, ctype c, dtype d) \ +{ \ + 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" \ + "li\t$2, %5\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "+r" (__a3) \ + : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return (type) -1; \ +} diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h new file mode 100644 index 000000000..24cbc3d04 --- /dev/null +++ b/ldso/ldso/mips/dl-sysdep.h @@ -0,0 +1,63 @@ +/* + * Various assmbly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* + * Define this if the system uses RELOCA. + */ +#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) + +/* + * Initialization sequence for a GOT. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +/* + * 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. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) + + +/* + * Transfer control to the user's application, once the dynamic loader + * 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); + +#define do_rem(result, n, base) result = (n % base) diff --git a/ldso/ldso/mips/ld_syscalls.h b/ldso/ldso/mips/ld_syscalls.h new file mode 100644 index 000000000..2327219df --- /dev/null +++ b/ldso/ldso/mips/ld_syscalls.h @@ -0,0 +1,137 @@ +/* + * This file contains the system call macros and syscall + * numbers used by the shared library loader. Taken from + * Linux/MIPS 2.4.17 version kernel. + */ + +#define __NR_SYSCALL_BASE 4000 + +#define __NR_exit (__NR_SYSCALL_BASE + 1) +#define __NR_read (__NR_SYSCALL_BASE + 3) +#define __NR_write (__NR_SYSCALL_BASE + 4) +#define __NR_open (__NR_SYSCALL_BASE + 5) +#define __NR_close (__NR_SYSCALL_BASE + 6) +#define __NR_getuid (__NR_SYSCALL_BASE + 24) +#define __NR_getgid (__NR_SYSCALL_BASE + 47) +#define __NR_geteuid (__NR_SYSCALL_BASE + 49) +#define __NR_getegid (__NR_SYSCALL_BASE + 50) +#define __NR_readlink (__NR_SYSCALL_BASE + 85) +#define __NR_mmap (__NR_SYSCALL_BASE + 90) +#define __NR_munmap (__NR_SYSCALL_BASE + 91) +#define __NR_stat (__NR_SYSCALL_BASE + 106) +#define __NR_mprotect (__NR_SYSCALL_BASE + 125) + +/* Here are the macros which define how this platform makes + * system calls. This particular variant does _not_ set + * errno (note how it is disabled in __syscall_return) since + * these will get called before the errno symbol is dynamicly + * linked. */ + +#define _syscall0(type,name) \ +type name(void) \ +{ \ + register unsigned long __v0 asm("$2") = __NR_##name; \ + register unsigned long __a3 asm("$7"); \ + \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "li\t$2, %2\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "=r" (__a3) \ + : "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return -1; \ +} + +#define _syscall1(type,name,atype,a) \ +type name(atype a) \ +{ \ + register unsigned long __v0 asm("$2") = __NR_##name; \ + register unsigned long __a0 asm("$4") = (unsigned long) a; \ + register unsigned long __a3 asm("$7"); \ + \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "li\t$2, %3\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "=r" (__a3) \ + : "r" (__a0), "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return (type) -1; \ +} + +#define _syscall2(type,name,atype,a,btype,b) \ +type name(atype a, btype b) \ +{ \ + 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 __a3 asm("$7"); \ + \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "li\t$2, %4\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "=r" (__a3) \ + : "r" (__a0), "r" (__a1), "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return (type) -1; \ +} + +#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ +type name(atype a, btype b, ctype c) \ +{ \ + 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"); \ + \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "li\t$2, %5\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "=r" (__a3) \ + : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return (type) -1; \ +} + +#define _syscall4(type,name,atype,a,btype,b,ctype,c,dtype,d) \ +type name(atype a, btype b, ctype c, dtype d) \ +{ \ + 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" \ + "li\t$2, %5\t\t\t# " #name "\n\t" \ + "syscall\n\t" \ + ".set\treorder" \ + : "=&r" (__v0), "+r" (__a3) \ + : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name) \ + : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \ + \ + if (__a3 == 0) \ + return (type) __v0; \ + return (type) -1; \ +} diff --git a/ldso/ldso/mips/ld_sysdep.h b/ldso/ldso/mips/ld_sysdep.h new file mode 100644 index 000000000..24cbc3d04 --- /dev/null +++ b/ldso/ldso/mips/ld_sysdep.h @@ -0,0 +1,63 @@ +/* + * Various assmbly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* + * Define this if the system uses RELOCA. + */ +#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) + +/* + * Initialization sequence for a GOT. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +/* + * 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. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) + + +/* + * Transfer control to the user's application, once the dynamic loader + * 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); + +#define do_rem(result, n, base) result = (n % base) diff --git a/ldso/ldso/mips/resolve.S b/ldso/ldso/mips/resolve.S new file mode 100644 index 000000000..b160b1cfb --- /dev/null +++ b/ldso/ldso/mips/resolve.S @@ -0,0 +1,48 @@ +/* + * Linux dynamic resolving code for MIPS. Fixes up the GOT entry as + * indicated in register t8 and jumps to the resolved address. Shamelessly + * ripped from 'sysdeps/mips/dl-machine.h' in glibc-2.2.5. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING.LIB" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996-2001 Kazumoto Kojima + * Copyright (C) 2002 Steven J. Hill + * + */ +.text +.align 2 +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function +.ent _dl_linux_resolve +_dl_linux_resolve: + .frame $29, 40, $31 + .set noreorder + move $3, $28 # Save GP + addu $25, 8 # t9 ($25) now points at .cpload instruction + .cpload $25 # Compute GP + .set reorder + move $2, $31 # Save slot call pc + subu $29, 40 # Save arguments and sp value in stack + .cprestore 32 + sw $15, 36($29) + sw $4, 16($29) + sw $5, 20($29) + sw $6, 24($29) + sw $7, 28($29) + move $4, $24 + move $5, $15 + move $6, $3 + move $7, $2 + jal _dl_linux_resolver + lw $31, 36($29) + lw $4, 16($29) + lw $5, 20($29) + lw $6, 24($29) + lw $7, 28($29) + addu $29, 40 + move $25, $2 + jr $25 +.size _dl_linux_resolve,.-_dl_linux_resolve +.end _dl_linux_resolve -- cgit v1.2.3