mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-11-03 20:53:13 +03:00 
			
		
		
		
	* sysdeps/mips/atomicity.h: Remove unused file. * sysdeps/mips/dl-machine.h (elf_machine_rel): Add TLS relocations. * sysdeps/mips/dl-tls.h: New file. * sysdeps/mips/libc-tls.c: New file. * sysdeps/mips/tls-macros.h: New file. * sysdeps/mips/bits/atomic.h: New file. * sysdeps/mips/bits/setjmp.h: Protect against multiple inclusion. * sysdeps/mips/elf/configure.in: New file. * sysdeps/mips/elf/configure: Generated. * sysdeps/mips/sys/asm.h: New file. * sysdeps/unix/sysv/linux/mips/vfork.S: New file. * sysdeps/unix/sysv/linux/mips/clone.S: Add NPTL and five-argument clone support. * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h (INTERNAL_SYSCALL_NCS): New. (INTERNAL_SYSCALL): Update for non-constant support. (internal_syscall0): Likewise. (internal_syscall1): Likewise. (internal_syscall2): Likewise. (internal_syscall3): Likewise. (internal_syscall4): Likewise. (internal_syscall5): Likewise. (internal_syscall6): Likewise. (internal_syscall7): Likewise. * sysdeps/unix/sysv/linux/mips/bits/siginfo.h (SIGEV_THREAD): Update to match the kernel. (SIGEV_CALLBACK): Likewise. (SIGEV_THREAD_ID): Likewise. 2005-03-28 Daniel Jacobowitz <dan@codesourcery.com>
		
			
				
	
	
		
			273 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* PLT trampoline.  MIPS version.
 | 
						|
   Copyright (C) 1996-2001, 2002, 2003, 2004, 2005
 | 
						|
   Free Software Foundation, Inc.
 | 
						|
   This file is part of the GNU C Library.
 | 
						|
   Contributed by Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>.
 | 
						|
 | 
						|
   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.  */
 | 
						|
 | 
						|
/*  FIXME: Profiling of shared libraries is not implemented yet.  */
 | 
						|
 | 
						|
#include <sysdep.h>
 | 
						|
#include <link.h>
 | 
						|
#include <elf.h>
 | 
						|
#include <ldsodefs.h>
 | 
						|
#include <dl-machine.h>
 | 
						|
 | 
						|
/* Get link map for callers object containing STUB_PC.  */
 | 
						|
static inline struct link_map *
 | 
						|
elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc)
 | 
						|
{
 | 
						|
  extern int _dl_mips_gnu_objects;
 | 
						|
 | 
						|
  /* got[1] is reserved to keep its link map address for the shared
 | 
						|
     object generated by the gnu linker.  If all are such objects, we
 | 
						|
     can find the link map from current GPREG simply.  If not so, get
 | 
						|
     the link map for caller's object containing STUB_PC.  */
 | 
						|
 | 
						|
  if (_dl_mips_gnu_objects)
 | 
						|
    {
 | 
						|
      ElfW(Addr) *got = elf_mips_got_from_gpreg (gpreg);
 | 
						|
      ElfW(Word) g1;
 | 
						|
 | 
						|
      g1 = ((ElfW(Word) *) got)[1];
 | 
						|
 | 
						|
      if ((g1 & ELF_MIPS_GNU_GOT1_MASK) != 0)
 | 
						|
	{
 | 
						|
	  struct link_map *l =
 | 
						|
	    (struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK);
 | 
						|
	  ElfW(Addr) base, limit;
 | 
						|
	  const ElfW(Phdr) *p = l->l_phdr;
 | 
						|
	  ElfW(Half) this, nent = l->l_phnum;
 | 
						|
 | 
						|
	  /* For the common case of a stub being called from the containing
 | 
						|
	     object, STUB_PC will point to somewhere within the object that
 | 
						|
	     is described by the link map fetched via got[1].  Otherwise we
 | 
						|
	     have to scan all maps.  */
 | 
						|
	  for (this = 0; this < nent; this++)
 | 
						|
	    {
 | 
						|
	      if (p[this].p_type == PT_LOAD)
 | 
						|
		{
 | 
						|
		  base = p[this].p_vaddr + l->l_addr;
 | 
						|
		  limit = base + p[this].p_memsz;
 | 
						|
		  if (stub_pc >= base && stub_pc < limit)
 | 
						|
		    return l;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    struct link_map *l;
 | 
						|
    Lmid_t nsid;
 | 
						|
 | 
						|
    for (nsid = 0; nsid < DL_NNS; ++nsid)
 | 
						|
      for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
 | 
						|
	{
 | 
						|
	  ElfW(Addr) base, limit;
 | 
						|
	  const ElfW(Phdr) *p = l->l_phdr;
 | 
						|
	  ElfW(Half) this, nent = l->l_phnum;
 | 
						|
 | 
						|
	  for (this = 0; this < nent; ++this)
 | 
						|
	    {
 | 
						|
	      if (p[this].p_type == PT_LOAD)
 | 
						|
		{
 | 
						|
		  base = p[this].p_vaddr + l->l_addr;
 | 
						|
		  limit = base + p[this].p_memsz;
 | 
						|
		  if (stub_pc >= base && stub_pc < limit)
 | 
						|
		    return l;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
  _dl_signal_error (0, NULL, NULL, "cannot find runtime link map");
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/* Define mips specific runtime resolver. The function __dl_runtime_resolve
 | 
						|
   is called from assembler function _dl_runtime_resolve which converts
 | 
						|
   special argument registers t7 ($15) and t8 ($24):
 | 
						|
     t7  address to return to the caller of the function
 | 
						|
     t8  index for this function symbol in .dynsym
 | 
						|
   to usual c arguments.
 | 
						|
 | 
						|
   Other architectures call fixup from dl-runtime.c in
 | 
						|
   _dl_runtime_resolve.  MIPS instead calls __dl_runtime_resolve.  We
 | 
						|
   have to use our own version because of the way the got section is
 | 
						|
   treated on MIPS (we've also got ELF_MACHINE_PLT defined).  */
 | 
						|
 | 
						|
/* The flag _dl_mips_gnu_objects is set if all dynamic objects are
 | 
						|
   generated by the gnu linker. */
 | 
						|
int _dl_mips_gnu_objects = 1;
 | 
						|
 | 
						|
#define VERSYMIDX(sym)  (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
 | 
						|
 | 
						|
/* This is called from assembly stubs below which the compiler can't see.  */
 | 
						|
static ElfW(Addr)
 | 
						|
__dl_runtime_resolve (ElfW(Word), ElfW(Word), ElfW(Addr), ElfW(Addr))
 | 
						|
		  __attribute_used__;
 | 
						|
 | 
						|
static ElfW(Addr)
 | 
						|
__dl_runtime_resolve (ElfW(Word) sym_index,
 | 
						|
		      ElfW(Word) return_address,
 | 
						|
		      ElfW(Addr) old_gpreg,
 | 
						|
		      ElfW(Addr) stub_pc)
 | 
						|
{
 | 
						|
  struct link_map *l = elf_machine_runtime_link_map (old_gpreg, stub_pc);
 | 
						|
  const ElfW(Sym) *const symtab
 | 
						|
    = (const ElfW(Sym) *) D_PTR (l, l_info[DT_SYMTAB]);
 | 
						|
  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
 | 
						|
  ElfW(Addr) *got
 | 
						|
    = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
 | 
						|
  const ElfW(Word) local_gotno
 | 
						|
    = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val;
 | 
						|
  const ElfW(Word) gotsym
 | 
						|
    = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val;
 | 
						|
  const ElfW(Sym) *sym = &symtab[sym_index];
 | 
						|
  struct link_map *sym_map;
 | 
						|
  ElfW(Addr) value;
 | 
						|
 | 
						|
  /* FIXME: The symbol versioning stuff is not tested yet.  */
 | 
						|
  if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
 | 
						|
    {
 | 
						|
      switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
 | 
						|
	{
 | 
						|
	default:
 | 
						|
	  {
 | 
						|
	    const ElfW(Half) *vernum =
 | 
						|
	      (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
 | 
						|
	    ElfW(Half) ndx = vernum[sym_index] & 0x7fff;
 | 
						|
	    const struct r_found_version *version = &l->l_versions[ndx];
 | 
						|
 | 
						|
	    if (version->hash != 0)
 | 
						|
	      {
 | 
						|
		sym_map = _dl_lookup_symbol_x (strtab + sym->st_name, l,
 | 
						|
					       &sym, l->l_scope, version,
 | 
						|
					       ELF_RTYPE_CLASS_PLT, 0, 0);
 | 
						|
		break;
 | 
						|
	      }
 | 
						|
	    /* Fall through.  */
 | 
						|
	  }
 | 
						|
	case 0:
 | 
						|
	  sym_map = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
 | 
						|
					 l->l_scope, 0, ELF_RTYPE_CLASS_PLT,
 | 
						|
					 DL_LOOKUP_ADD_DEPENDENCY, 0);
 | 
						|
	}
 | 
						|
 | 
						|
      /* Currently value contains the base load address of the object
 | 
						|
	 that defines sym.  Now add in the symbol offset.  */
 | 
						|
      value = (sym ? sym_map->l_addr + sym->st_value : 0);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    /* We already found the symbol.  The module (and therefore its load
 | 
						|
       address) is also known.  */
 | 
						|
    value = l->l_addr + sym->st_value;
 | 
						|
 | 
						|
  /* Apply the relocation with that value.  */
 | 
						|
  *(got + local_gotno + sym_index - gotsym) = value;
 | 
						|
 | 
						|
  return value;
 | 
						|
}
 | 
						|
 | 
						|
#if _MIPS_SIM == _ABIO32
 | 
						|
#define ELF_DL_FRAME_SIZE 40
 | 
						|
 | 
						|
#define ELF_DL_SAVE_ARG_REGS "\
 | 
						|
	sw	$15, 36($29)\n						      \
 | 
						|
	sw	$4, 16($29)\n						      \
 | 
						|
	sw	$5, 20($29)\n						      \
 | 
						|
	sw	$6, 24($29)\n						      \
 | 
						|
	sw	$7, 28($29)\n						      \
 | 
						|
"
 | 
						|
 | 
						|
#define ELF_DL_RESTORE_ARG_REGS "\
 | 
						|
	lw	$31, 36($29)\n						      \
 | 
						|
	lw	$4, 16($29)\n						      \
 | 
						|
	lw	$5, 20($29)\n						      \
 | 
						|
	lw	$6, 24($29)\n						      \
 | 
						|
	lw	$7, 28($29)\n						      \
 | 
						|
"
 | 
						|
 | 
						|
#define IFABIO32(X) X
 | 
						|
 | 
						|
#else /* _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 */
 | 
						|
 | 
						|
#define ELF_DL_FRAME_SIZE 80
 | 
						|
 | 
						|
#define ELF_DL_SAVE_ARG_REGS "\
 | 
						|
	sd	$15, 72($29)\n						      \
 | 
						|
	sd	$4, 8($29)\n						      \
 | 
						|
	sd	$5, 16($29)\n						      \
 | 
						|
	sd	$6, 24($29)\n						      \
 | 
						|
	sd	$7, 32($29)\n						      \
 | 
						|
	sd	$8, 40($29)\n						      \
 | 
						|
	sd	$9, 48($29)\n						      \
 | 
						|
	sd	$10, 56($29)\n						      \
 | 
						|
	sd	$11, 64($29)\n						      \
 | 
						|
"
 | 
						|
 | 
						|
#define ELF_DL_RESTORE_ARG_REGS "\
 | 
						|
	ld	$31, 72($29)\n						      \
 | 
						|
	ld	$4, 8($29)\n						      \
 | 
						|
	ld	$5, 16($29)\n						      \
 | 
						|
	ld	$6, 24($29)\n						      \
 | 
						|
	ld	$7, 32($29)\n						      \
 | 
						|
	ld	$8, 40($29)\n						      \
 | 
						|
	ld	$9, 48($29)\n						      \
 | 
						|
	ld	$10, 56($29)\n						      \
 | 
						|
	ld	$11, 64($29)\n						      \
 | 
						|
"
 | 
						|
 | 
						|
#define IFABIO32(X)
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
asm ("\n\
 | 
						|
	.text\n\
 | 
						|
	.align	2\n\
 | 
						|
	.globl	_dl_runtime_resolve\n\
 | 
						|
	.type	_dl_runtime_resolve,@function\n\
 | 
						|
	.ent	_dl_runtime_resolve\n\
 | 
						|
_dl_runtime_resolve:\n\
 | 
						|
	.frame	$29, " STRINGXP(ELF_DL_FRAME_SIZE) ", $31\n\
 | 
						|
	.set noreorder\n\
 | 
						|
	# Save GP.\n\
 | 
						|
	move	$3, $28\n\
 | 
						|
	# Save arguments and sp value in stack.\n\
 | 
						|
	" STRINGXP(PTR_SUBIU) "  $29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n\
 | 
						|
	# Modify t9 ($25) so as to point .cpload instruction.\n\
 | 
						|
	" IFABIO32(STRINGXP(PTR_ADDIU) "	$25, 12\n") "\
 | 
						|
	# Compute GP.\n\
 | 
						|
	" STRINGXP(SETUP_GP) "\n\
 | 
						|
	" STRINGXV(SETUP_GP64 (0, _dl_runtime_resolve)) "\n\
 | 
						|
	.set reorder\n\
 | 
						|
	# Save slot call pc.\n\
 | 
						|
	move	$2, $31\n\
 | 
						|
	" IFABIO32(STRINGXP(CPRESTORE(32))) "\n\
 | 
						|
	" ELF_DL_SAVE_ARG_REGS "\
 | 
						|
	move	$4, $24\n\
 | 
						|
	move	$5, $15\n\
 | 
						|
	move	$6, $3\n\
 | 
						|
	move	$7, $2\n\
 | 
						|
	jal	__dl_runtime_resolve\n\
 | 
						|
	" ELF_DL_RESTORE_ARG_REGS "\
 | 
						|
	" STRINGXP(RESTORE_GP64) "\n\
 | 
						|
	" STRINGXP(PTR_ADDIU) "	$29, " STRINGXP(ELF_DL_FRAME_SIZE) "\n\
 | 
						|
	move	$25, $2\n\
 | 
						|
	jr	$25\n\
 | 
						|
	.end	_dl_runtime_resolve\n\
 | 
						|
	.previous\n\
 | 
						|
");
 |