From 96749a768287761528a05670560402a16f6839ac Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Tue, 2 Apr 2002 21:12:37 +0000 Subject: Steven J. Hill's latest mips dynamic loader updates --- Makefile | 9 +++-- ldso/ldso/dl-elf.c | 7 ++-- ldso/ldso/ld_string.h | 2 +- ldso/ldso/ld_syscall.h | 4 +- ldso/ldso/ldso.c | 46 +++++++++++++++++----- ldso/ldso/mips/README | 43 +++++++++++++++++++++ ldso/ldso/mips/boot1_arch.h | 5 +-- ldso/ldso/mips/dl-startup.h | 5 +-- ldso/ldso/mips/dl-syscalls.h | 30 +++++++++++++++ ldso/ldso/mips/dl-sysdep.h | 92 +++++++++++++++++++++++++++++++++----------- ldso/ldso/mips/elfinterp.c | 49 +++++++++++++++++++++++ ldso/ldso/mips/ld_syscalls.h | 30 +++++++++++++++ ldso/ldso/mips/ld_sysdep.h | 92 +++++++++++++++++++++++++++++++++----------- ldso/ldso/readelflib1.c | 7 ++-- 14 files changed, 346 insertions(+), 75 deletions(-) create mode 100644 ldso/ldso/mips/README create mode 100644 ldso/ldso/mips/elfinterp.c diff --git a/Makefile b/Makefile index ac6b27bc0..0455a2ac9 100644 --- a/Makefile +++ b/Makefile @@ -332,16 +332,17 @@ finished2: distclean clean: @rm -rf tmp lib include/bits libc/tmp _install - - find include -type l -exec rm -f {} \; - - find . \( -name \*.o -o -name \*.a -o -name \*.so -o -name core -o -name .\#\* \) -exec rm -f {} \; $(MAKE) -C test clean $(MAKE) -C ldso clean $(MAKE) -C libc/misc clean $(MAKE) -C libc/unistd clean $(MAKE) -C libc/sysdeps/linux/common clean - $(MAKE) -C libc/sysdeps/linux/$(TARGET_ARCH) clean $(MAKE) -C extra/gcc-uClibc clean - find . -name mipsel -exec rm -rf {} \; + @if [ -d libc/sysdeps/linux/$(TARGET_ARCH) ]; then \ + $(MAKE) -C libc/sysdeps/linux/$(TARGET_ARCH) clean; \ + fi; + - find . \( -name \*.o -o -name \*.a -o -name \*.so -o -name core -o -name .\#\* \) -exec rm -f {} \; + - find -type l -exec rm -f {} \; dist release: distclean cd ..; \ diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index d565b9290..913ac8778 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -308,7 +308,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, int flags; char header[4096]; unsigned long dynamic_info[24]; - int *lpnt; + unsigned long *lpnt; unsigned long libaddr; unsigned long minvma = 0xffffffff, maxvma = 0; @@ -553,10 +553,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, * resolved. */ - lpnt = (int *) dynamic_info[DT_PLTGOT]; + lpnt = (unsigned long *) dynamic_info[DT_PLTGOT]; if (lpnt) { - lpnt = (int *) (dynamic_info[DT_PLTGOT] + ((int) libaddr)); + lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] + + ((int) libaddr)); INIT_GOT(lpnt, tpnt); }; diff --git a/ldso/ldso/ld_string.h b/ldso/ldso/ld_string.h index d872a6f13..736836d9b 100644 --- a/ldso/ldso/ld_string.h +++ b/ldso/ldso/ld_string.h @@ -221,7 +221,7 @@ static inline char *_dl_simple_ltoahex(char * local, unsigned long i) } -#if defined mc68000 || defined __arm__ +#if defined mc68000 || defined __arm__ || defined __mips__ /* On some arches constant strings are referenced through the GOT. */ /* XXX Requires load_addr to be defined. */ #define SEND_STDERR(X) \ diff --git a/ldso/ldso/ld_syscall.h b/ldso/ldso/ld_syscall.h index ba94d7598..db7447f67 100644 --- a/ldso/ldso/ld_syscall.h +++ b/ldso/ldso/ld_syscall.h @@ -51,8 +51,8 @@ static inline _syscall1(void, _dl_exit, int, status); static inline _syscall1(int, _dl_close, int, fd); -#ifdef __powerpc__ -/* PowerPC has a different calling convention for mmap(). */ +#if defined(__powerpc) || defined(__mips__) +/* PowerPC and MIPS have a different calling convention for mmap(). */ #define __NR__dl_mmap __NR_mmap static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length, int, prot, int, flags, int, fd, off_t, offset); diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 456205adc..3a479caf5 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -20,11 +20,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* Enable this to turn on debugging noise */ -//#define DL_DEBUG - -/* Enable mprotect protection munging. ARM Linux needs this it seems, - * so leave this enabled by default */ +/* Enable mprotect protection munging. ARM and MIPS Linux needs this + * it seems, so leave this enabled by default */ #define DO_MPROTECT_HACKS // Support a list of library preloads in /etc/ld.so.preload @@ -209,10 +206,16 @@ DL_BOOT(unsigned long args) Elf32_auxv_t auxvt[AT_EGID + 1]; unsigned char *malloc_buffer, *mmap_zero; Elf32_Dyn *dpnt; + Elf32_Dyn *dpnt_debug = NULL; unsigned long *hash_addr; struct r_debug *debug_addr; int indx; int status; +#if defined(__mips__) + unsigned long mips_gotsym = 0; + unsigned long mips_local_gotno = 0; + unsigned long mips_symtabno = 0; +#endif /* WARNING! -- we cannot make _any_ funtion calls until we have @@ -223,7 +226,7 @@ DL_BOOT(unsigned long args) /* First obtain the information on the stack that tells us more about what binary is loaded, where it is loaded, etc, etc */ GET_ARGV(aux_dat, args); -#if defined(__arm__) || defined(__mips__) +#if defined (__arm__) || defined (__mips__) aux_dat += 1; #endif argc = *(aux_dat - 1); @@ -267,7 +270,7 @@ DL_BOOT(unsigned long args) _dl_exit(0); } #ifdef DL_DEBUG - SEND_STDERR("ELF header ="); + SEND_STDERR("ELF header="); SEND_ADDRESS_STDERR(load_addr, 1); #endif @@ -287,7 +290,7 @@ DL_BOOT(unsigned long args) #elif defined(__powerpc__) __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got)); #elif defined(__mips__) - __asm__("\tmove %0, $28\n\t":"=r"(got)); + __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got)); #else /* Do things the slow way in C */ { @@ -334,7 +337,7 @@ DL_BOOT(unsigned long args) _dl_exit(0); found_got: - got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc + + got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc + (char *) header); } #endif @@ -376,6 +379,14 @@ DL_BOOT(unsigned long args) tpnt->dynamic_info[DT_TEXTREL] = 1; } } +#if defined(__mips__) + if (dpnt->d_tag == DT_MIPS_GOTSYM) + mips_gotsym = (unsigned long) dpnt->d_un.d_val; + if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) + mips_local_gotno = (unsigned long) dpnt->d_un.d_val; + if (dpnt->d_tag == DT_MIPS_SYMTABNO) + mips_symtabno = (unsigned long) dpnt->d_un.d_val; +#endif dpnt++; } @@ -394,7 +405,11 @@ DL_BOOT(unsigned long args) } app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val; if (dpnt->d_tag == DT_DEBUG) +#ifndef DO_MPROTECT_HACKS dpnt->d_un.d_val = (unsigned long) debug_addr; +#else + dpnt_debug = dpnt; +#endif if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT) app_tpnt->dynamic_info[DT_TEXTREL] = 1; dpnt++; @@ -446,6 +461,16 @@ DL_BOOT(unsigned long args) } } } + + /* Now we can store the debug structure address */ + dpnt_debug->d_un.d_val = (unsigned long) debug_addr; +#endif + + + /* For MIPS, we have to do special stuff to the GOT before we do + any relocations. */ +#if defined(__mips__) + PERFORM_BOOTSTRAP_GOT(got); #endif @@ -454,6 +479,7 @@ DL_BOOT(unsigned long args) #ifdef DL_DEBUG SEND_STDERR("About to do library loader relocations.\n"); #endif + goof = 0; for (indx = 0; indx < 2; indx++) { int i; @@ -476,7 +502,6 @@ DL_BOOT(unsigned long args) dynamic_info[DT_RELSZ]); #endif - if (!rel_addr) continue; @@ -499,6 +524,7 @@ DL_BOOT(unsigned long args) if (!_dl_symbol(strtab + symtab[symtab_index].st_name)) continue; symbol_addr = load_addr + symtab[symtab_index].st_value; + SEND_NUMBER_STDERR(symbol_addr,1); if (!symbol_addr) { /* This will segfault - you cannot call a function until 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) diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c index d565b9290..913ac8778 100644 --- a/ldso/ldso/readelflib1.c +++ b/ldso/ldso/readelflib1.c @@ -308,7 +308,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, int flags; char header[4096]; unsigned long dynamic_info[24]; - int *lpnt; + unsigned long *lpnt; unsigned long libaddr; unsigned long minvma = 0xffffffff, maxvma = 0; @@ -553,10 +553,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, * resolved. */ - lpnt = (int *) dynamic_info[DT_PLTGOT]; + lpnt = (unsigned long *) dynamic_info[DT_PLTGOT]; if (lpnt) { - lpnt = (int *) (dynamic_info[DT_PLTGOT] + ((int) libaddr)); + lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] + + ((int) libaddr)); INIT_GOT(lpnt, tpnt); }; -- cgit v1.2.3