⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dl-machine.h

📁 Glibc 2.3.2源代码(解压后有100多M)
💻 H
📖 第 1 页 / 共 2 页
字号:
/* Machine-dependent ELF dynamic relocation inline functions.  Sparc64 version.   Copyright (C) 1997,1998,1999,2000,2001,2002 Free Software Foundation, Inc.   This file is part of the GNU C Library.   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 ELF_MACHINE_NAME "sparc64"#include <string.h>#include <sys/param.h>#include <ldsodefs.h>#include <sysdep.h>#ifndef VALIDX# define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \		      + DT_EXTRANUM + DT_VALTAGIDX (tag))#endif#define ELF64_R_TYPE_ID(info)	((info) & 0xff)#define ELF64_R_TYPE_DATA(info) ((info) >> 8)/* Return nonzero iff ELF header is compatible with the running host.  */static inline intelf_machine_matches_host (const Elf64_Ehdr *ehdr){  return ehdr->e_machine == EM_SPARCV9;}/* We have to do this because elf_machine_{dynamic,load_address} can be   invoked from functions that have no GOT references, and thus the compiler   has no obligation to load the PIC register.  */#define LOAD_PIC_REG(PIC_REG)	\do {	Elf64_Addr tmp;		\	__asm("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \	      "rd %%pc, %0\n\t" \	      "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \	      "add %0, %1, %0" \	      : "=r" (PIC_REG), "=r" (tmp)); \} while (0)/* 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 Elf64_Addrelf_machine_dynamic (void){  register Elf64_Addr *elf_pic_register __asm__("%l7");  LOAD_PIC_REG (elf_pic_register);  return *elf_pic_register;}/* Return the run-time load address of the shared object.  */static inline Elf64_Addrelf_machine_load_address (void){  register Elf32_Addr *pc __asm ("%o7");  register Elf64_Addr *got __asm ("%l7");  __asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"         "call 1f\n\t"         " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"         "call _DYNAMIC\n\t"         "call _GLOBAL_OFFSET_TABLE_\n"         "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got));  /* got is now l_addr + _GLOBAL_OFFSET_TABLE_     *got is _DYNAMIC     pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8     pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12  */  return (Elf64_Addr) got - *got + (Elf32_Sword) ((pc[2] - pc[3]) * 4) - 4;}/* We have 4 cases to handle.  And we code different code sequences   for each one.  I love V9 code models...  */static inline voidsparc64_fixup_plt (struct link_map *map, const Elf64_Rela *reloc,		   Elf64_Addr *reloc_addr, Elf64_Addr value,		   Elf64_Addr high, int t){  unsigned int *insns = (unsigned int *) reloc_addr;  Elf64_Addr plt_vaddr = (Elf64_Addr) reloc_addr;  Elf64_Sxword disp = value - plt_vaddr;  /* Now move plt_vaddr up to the call instruction.  */  plt_vaddr += ((t + 1) * 4);  /* PLT entries .PLT32768 and above look always the same.  */  if (__builtin_expect (high, 0) != 0)    {      *reloc_addr = value - map->l_addr;    }  /* Near destination.  */  else if (disp >= -0x800000 && disp < 0x800000)    {      /* As this is just one instruction, it is thread safe and so	 we can avoid the unnecessary sethi FOO, %g1.	 b,a target  */      insns[0] = 0x30800000 | ((disp >> 2) & 0x3fffff);      __asm __volatile ("flush %0" : : "r" (insns));    }  /* 32-bit Sparc style, the target is in the lower 32-bits of     address space.  */  else if (insns += t, (value >> 32) == 0)    {      /* sethi	%hi(target), %g1	 jmpl	%g1 + %lo(target), %g0  */      insns[1] = 0x81c06000 | (value & 0x3ff);      __asm __volatile ("flush %0 + 4" : : "r" (insns));      insns[0] = 0x03000000 | ((unsigned int)(value >> 10));      __asm __volatile ("flush %0" : : "r" (insns));    }  /* We can also get somewhat simple sequences if the distance between     the target and the PLT entry is within +/- 2GB.  */  else if ((plt_vaddr > value	    && ((plt_vaddr - value) >> 31) == 0)	   || (value > plt_vaddr	       && ((value - plt_vaddr) >> 31) == 0))    {      unsigned int displacement;      if (plt_vaddr > value)	displacement = (0 - (plt_vaddr - value));      else	displacement = value - plt_vaddr;      /* mov	%o7, %g1	 call	displacement	  mov	%g1, %o7  */      insns[2] = 0x9e100001;      __asm __volatile ("flush %0 + 8" : : "r" (insns));      insns[1] = 0x40000000 | (displacement >> 2);      __asm __volatile ("flush %0 + 4" : : "r" (insns));      insns[0] = 0x8210000f;      __asm __volatile ("flush %0" : : "r" (insns));    }  /* Worst case, ho hum...  */  else    {      unsigned int high32 = (value >> 32);      unsigned int low32 = (unsigned int) value;      /* ??? Some tricks can be stolen from the sparc64 egcs backend	     constant formation code I wrote.  -DaveM  */      if (__builtin_expect (high32 & 0x3ff, 0))	{	  /* sethi	%hh(value), %g1	     sethi	%lm(value), %g5	     or		%g1, %hm(value), %g1	     or		%g5, %lo(value), %g5	     sllx	%g1, 32, %g1	     jmpl	%g1 + %g5, %g0	      nop  */	  insns[5] = 0x81c04005;	  __asm __volatile ("flush %0 + 20" : : "r" (insns));	  insns[4] = 0x83287020;	  __asm __volatile ("flush %0 + 16" : : "r" (insns));	  insns[3] = 0x8a116000 | (low32 & 0x3ff);	  __asm __volatile ("flush %0 + 12" : : "r" (insns));	  insns[2] = 0x82106000 | (high32 & 0x3ff);	}      else	{	  /* sethi	%hh(value), %g1	     sethi	%lm(value), %g5	     sllx	%g1, 32, %g1	     or		%g5, %lo(value), %g5	     jmpl	%g1 + %g5, %g0	      nop  */	  insns[4] = 0x81c04005;	  __asm __volatile ("flush %0 + 16" : : "r" (insns));	  insns[3] = 0x8a116000 | (low32 & 0x3ff);	  __asm __volatile ("flush %0 + 12" : : "r" (insns));	  insns[2] = 0x83287020;	}      __asm __volatile ("flush %0 + 8" : : "r" (insns));      insns[1] = 0x0b000000 | (low32 >> 10);      __asm __volatile ("flush %0 + 4" : : "r" (insns));      insns[0] = 0x03000000 | (high32 >> 10);      __asm __volatile ("flush %0" : : "r" (insns));    }}static inline Elf64_Addrelf_machine_fixup_plt (struct link_map *map, lookup_t t,		       const Elf64_Rela *reloc,		       Elf64_Addr *reloc_addr, Elf64_Addr value){  sparc64_fixup_plt (map, reloc, reloc_addr, value + reloc->r_addend,		     reloc->r_addend, 1);  return value;}/* Return the final value of a plt relocation.  */static inline Elf64_Addrelf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,		       Elf64_Addr value){  /* Don't add addend here, but in elf_machine_fixup_plt instead.     value + reloc->r_addend is the value which should actually be     stored into .plt data slot.  */  return value;}#ifdef RESOLVE/* Perform the relocation specified by RELOC and SYM (which is fully resolved).   MAP is the object containing the reloc.  */static inline voidelf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,		  const Elf64_Sym *sym, const struct r_found_version *version,		  Elf64_Addr *const reloc_addr){  const unsigned long int r_type = ELF64_R_TYPE_ID (reloc->r_info);#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC  if (__builtin_expect (r_type == R_SPARC_RELATIVE, 0))    *reloc_addr = map->l_addr + reloc->r_addend;# ifndef RTLD_BOOTSTRAP  else if (r_type == R_SPARC_NONE) /* Who is Wilbur? */    return;# endif  else#endif    {#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP      const Elf64_Sym *const refsym = sym;#endif      Elf64_Addr value;#ifndef RESOLVE_CONFLICT_FIND_MAP      if (sym->st_shndx != SHN_UNDEF &&	  ELF64_ST_BIND (sym->st_info) == STB_LOCAL)	value = map->l_addr;      else	{	  value = RESOLVE (&sym, version, r_type);	  if (sym)	    value += sym->st_value;	}#else      value = 0;#endif      value += reloc->r_addend;	/* Assume copy relocs have zero addend.  */      switch (r_type)	{#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP	case R_SPARC_COPY:	  if (sym == NULL)	    /* This can happen in trace mode if an object could not be	       found.  */	    break;	  if (sym->st_size > refsym->st_size	      || (GL(dl_verbose) && sym->st_size < refsym->st_size))	    {	      const char *strtab;	      strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);	      _dl_error_printf ("\%s: Symbol `%s' has different size in shared object, consider re-linking\n",				rtld_progname ?: "<program name unknown>",				strtab + refsym->st_name);	    }	  memcpy (reloc_addr, (void *) value, MIN (sym->st_size,						   refsym->st_size));	  break;#endif	case R_SPARC_64:	case R_SPARC_GLOB_DAT:	  *reloc_addr = value;	  break;#ifndef RTLD_BOOTSTRAP	case R_SPARC_8:	  *(char *) reloc_addr = value;	  break;	case R_SPARC_16:	  *(short *) reloc_addr = value;	  break;	case R_SPARC_32:	  *(unsigned int *) reloc_addr = value;	  break;	case R_SPARC_DISP8:	  *(char *) reloc_addr = (value - (Elf64_Addr) reloc_addr);	  break;	case R_SPARC_DISP16:	  *(short *) reloc_addr = (value - (Elf64_Addr) reloc_addr);	  break;	case R_SPARC_DISP32:	  *(unsigned int *) reloc_addr = (value - (Elf64_Addr) reloc_addr);	  break;	case R_SPARC_WDISP30:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & 0xc0000000) |	     ((value - (Elf64_Addr) reloc_addr) >> 2));	  break;	/* MEDLOW code model relocs */	case R_SPARC_LO10:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & ~0x3ff) |	     (value & 0x3ff));	  break;	case R_SPARC_HI22:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & 0xffc00000) |	     (value >> 10));	  break;	case R_SPARC_OLO10:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & ~0x1fff) |	     (((value & 0x3ff) + ELF64_R_TYPE_DATA (reloc->r_info)) & 0x1fff));	  break;	/* MEDMID code model relocs */	case R_SPARC_H44:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & 0xffc00000) |	     (value >> 22));	  break;	case R_SPARC_M44:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & ~0x3ff) |	     ((value >> 12) & 0x3ff));	  break;	case R_SPARC_L44:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & ~0xfff) |	     (value & 0xfff));	  break;	/* MEDANY code model relocs */	case R_SPARC_HH22:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & 0xffc00000) |	     (value >> 42));	  break;	case R_SPARC_HM10:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & ~0x3ff) |	     ((value >> 32) & 0x3ff));	  break;	case R_SPARC_LM22:	  *(unsigned int *) reloc_addr =	    ((*(unsigned int *)reloc_addr & 0xffc00000) |	     ((value >> 10) & 0x003fffff));	  break;#endif	case R_SPARC_JMP_SLOT:#ifdef RESOLVE_CONFLICT_FIND_MAP	  /* R_SPARC_JMP_SLOT conflicts against .plt[32768+]	     relocs should be turned into R_SPARC_64 relocs

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -