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

📄 elf64-x86-64.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
/* X86-64 specific support for 64-bit ELF   Copyright 2000, 2001 Free Software Foundation, Inc.   Contributed by Jan Hubicka <jh@suse.cz>.This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "elf-bfd.h"#include "elf/x86-64.h"/* We use only the RELA entries.  */#define USE_RELA/* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */#define MINUS_ONE (~ (bfd_vma) 0)/* The relocation "howto" table.  Order of fields:   type, size, bitsize, pc_relative, complain_on_overflow,   special_function, name, partial_inplace, src_mask, dst_pack, pcrel_offset.  */static reloc_howto_type x86_64_elf_howto_table[] ={  HOWTO(R_X86_64_NONE, 0, 0, 0, false, 0, complain_overflow_dont,	bfd_elf_generic_reloc, "R_X86_64_NONE",	false, 0x00000000, 0x00000000,	false),  HOWTO(R_X86_64_64, 0, 4, 64, false, 0, complain_overflow_bitfield,	bfd_elf_generic_reloc, "R_X86_64_64", false, MINUS_ONE, MINUS_ONE,	false),  HOWTO(R_X86_64_PC32, 0, 4, 32, true, 0, complain_overflow_signed,	bfd_elf_generic_reloc, "R_X86_64_PC32", false, 0xffffffff, 0xffffffff,	true),  HOWTO(R_X86_64_GOT32, 0, 4, 32, false, 0, complain_overflow_signed,	bfd_elf_generic_reloc, "R_X86_64_GOT32", false, 0xffffffff, 0xffffffff,	false),  HOWTO(R_X86_64_PLT32, 0, 4, 32, true, 0, complain_overflow_signed,	bfd_elf_generic_reloc, "R_X86_64_PLT32", false, 0xffffffff, 0xffffffff,	true),  HOWTO(R_X86_64_COPY, 0, 4, 32, false, 0, complain_overflow_bitfield,	bfd_elf_generic_reloc, "R_X86_64_COPY", false, 0xffffffff, 0xffffffff,	false),  HOWTO(R_X86_64_GLOB_DAT, 0, 4, 64, false, 0, complain_overflow_bitfield,	bfd_elf_generic_reloc, "R_X86_64_GLOB_DAT", false, MINUS_ONE,	MINUS_ONE, false),  HOWTO(R_X86_64_JUMP_SLOT, 0, 4, 64, false, 0, complain_overflow_bitfield,	bfd_elf_generic_reloc, "R_X86_64_JUMP_SLOT", false, MINUS_ONE,	MINUS_ONE, false),  HOWTO(R_X86_64_RELATIVE, 0, 4, 64, false, 0, complain_overflow_bitfield,	bfd_elf_generic_reloc, "R_X86_64_RELATIVE", false, MINUS_ONE,	MINUS_ONE, false),  HOWTO(R_X86_64_GOTPCREL, 0, 4, 32, true,0 , complain_overflow_signed,	bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", false, 0xffffffff,	0xffffffff, true),  HOWTO(R_X86_64_32, 0, 4, 32, false, 0, complain_overflow_unsigned,	bfd_elf_generic_reloc, "R_X86_64_32", false, 0xffffffff, 0xffffffff,	false),  HOWTO(R_X86_64_32S, 0, 4, 32, false, 0, complain_overflow_signed,	bfd_elf_generic_reloc, "R_X86_64_32S", false, 0xffffffff, 0xffffffff,	false),  HOWTO(R_X86_64_16, 0, 1, 16, false, 0, complain_overflow_bitfield,	bfd_elf_generic_reloc, "R_X86_64_16", false, 0xffff, 0xffff, false),  HOWTO(R_X86_64_PC16,0, 1, 16, true, 0, complain_overflow_bitfield,	bfd_elf_generic_reloc, "R_X86_64_PC16", false, 0xffff, 0xffff, true),  HOWTO(R_X86_64_8, 0, 0, 8, false, 0, complain_overflow_signed,	bfd_elf_generic_reloc, "R_X86_64_8", false, 0xff, 0xff, false),  HOWTO(R_X86_64_PC8, 0, 0, 8, true, 0, complain_overflow_signed,	bfd_elf_generic_reloc, "R_X86_64_PC8", false, 0xff, 0xff, true)};/* Map BFD relocs to the x86_64 elf relocs.  */struct elf_reloc_map{  bfd_reloc_code_real_type bfd_reloc_val;  unsigned char elf_reloc_val;};static CONST struct elf_reloc_map x86_64_reloc_map[] ={  { BFD_RELOC_NONE,		R_X86_64_NONE, },  { BFD_RELOC_64,		R_X86_64_64,   },  { BFD_RELOC_32_PCREL,		R_X86_64_PC32, },  { BFD_RELOC_X86_64_GOT32,	R_X86_64_GOT32,},  { BFD_RELOC_X86_64_PLT32,	R_X86_64_PLT32,},  { BFD_RELOC_X86_64_COPY,	R_X86_64_COPY, },  { BFD_RELOC_X86_64_GLOB_DAT,	R_X86_64_GLOB_DAT, },  { BFD_RELOC_X86_64_JUMP_SLOT, R_X86_64_JUMP_SLOT, },  { BFD_RELOC_X86_64_RELATIVE,	R_X86_64_RELATIVE, },  { BFD_RELOC_X86_64_GOTPCREL,	R_X86_64_GOTPCREL, },  { BFD_RELOC_32,		R_X86_64_32, },  { BFD_RELOC_X86_64_32S,	R_X86_64_32S, },  { BFD_RELOC_16,		R_X86_64_16, },  { BFD_RELOC_16_PCREL,		R_X86_64_PC16, },  { BFD_RELOC_8,		R_X86_64_8, },  { BFD_RELOC_8_PCREL,		R_X86_64_PC8, },};static reloc_howto_type *elf64_x86_64_reloc_type_lookup  PARAMS ((bfd *, bfd_reloc_code_real_type));static void elf64_x86_64_info_to_howto  PARAMS ((bfd *, arelent *, Elf64_Internal_Rela *));static struct bfd_link_hash_table *elf64_x86_64_link_hash_table_create  PARAMS ((bfd *));static struct bfd_hash_entry *elf64_x86_64_link_hash_newfunc  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static boolean elf64_x86_64_adjust_dynamic_symbol  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));static boolean elf64_x86_64_size_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf64_x86_64_relocate_section  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,	 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));static boolean elf64_x86_64_finish_dynamic_symbol  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,	   Elf_Internal_Sym *sym));static boolean elf64_x86_64_finish_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));/* Given a BFD reloc type, return a HOWTO structure.  */static reloc_howto_type *elf64_x86_64_reloc_type_lookup (abfd, code)     bfd *abfd ATTRIBUTE_UNUSED;     bfd_reloc_code_real_type code;{  unsigned int i;  for (i = 0; i < sizeof (x86_64_reloc_map) / sizeof (struct elf_reloc_map);       i++)    {      if (x86_64_reloc_map[i].bfd_reloc_val == code)	return &x86_64_elf_howto_table[(int)				       x86_64_reloc_map[i].elf_reloc_val];    }  return 0;}/* Given an x86_64 ELF reloc type, fill in an arelent structure.  */static voidelf64_x86_64_info_to_howto (abfd, cache_ptr, dst)     bfd *abfd ATTRIBUTE_UNUSED;     arelent *cache_ptr;     Elf64_Internal_Rela *dst;{  unsigned r_type;  r_type = ELF64_R_TYPE (dst->r_info);  BFD_ASSERT (r_type < (unsigned int) R_X86_64_max);  cache_ptr->howto = &x86_64_elf_howto_table[r_type];  BFD_ASSERT (r_type == cache_ptr->howto->type);}/* Functions for the x86-64 ELF linker.	 *//* The name of the dynamic interpreter.	 This is put in the .interp   section.  */#define ELF_DYNAMIC_INTERPRETER "/lib/ld64.so.1"/* The size in bytes of an entry in the global offset table.  */#define GOT_ENTRY_SIZE 8/* The size in bytes of an entry in the procedure linkage table.  */#define PLT_ENTRY_SIZE 16/* The first entry in a procedure linkage table looks like this.  See the   SVR4 ABI i386 supplement and the x86-64 ABI to see how this works.  */static const bfd_byte elf64_x86_64_plt0_entry[PLT_ENTRY_SIZE] ={  0xff, 0x35, 8, 0, 0, 0,	/* pushq GOT+8(%rip)  */  0xff, 0x25, 16, 0, 0, 0,	/* jmpq *GOT+16(%rip) */  0x90, 0x90, 0x90, 0x90	/* pad out to 16 bytes with nops.  */};/* Subsequent entries in a procedure linkage table look like this.  */static const bfd_byte elf64_x86_64_plt_entry[PLT_ENTRY_SIZE] ={  0xff, 0x25,	/* jmpq *name@GOTPC(%rip) */  0, 0, 0, 0,	/* replaced with offset to this symbol in .got.	 */  0x68,		/* pushq immediate */  0, 0, 0, 0,	/* replaced with index into relocation table.  */  0xe9,		/* jmp relative */  0, 0, 0, 0	/* replaced with offset to start of .plt0.  */};/* The x86-64 linker needs to keep track of the number of relocs that   it decides to copy in check_relocs for each symbol.	This is so   that it can discard PC relative relocs if it doesn't need them when   linking with -Bsymbolic.  We store the information in a field   extending the regular ELF linker hash table.	 *//* This structure keeps track of the number of PC relative relocs we   have copied for a given symbol.  */struct elf64_x86_64_pcrel_relocs_copied{  /* Next section.  */  struct elf64_x86_64_pcrel_relocs_copied *next;  /* A section in dynobj.  */  asection *section;  /* Number of relocs copied in this section.  */  bfd_size_type count;};/* x86-64 ELF linker hash entry.  */struct elf64_x86_64_link_hash_entry{  struct elf_link_hash_entry root;  /* Number of PC relative relocs copied for this symbol.  */  struct elf64_x86_64_pcrel_relocs_copied *pcrel_relocs_copied;};/* x86-64  ELF linker hash table.  */struct elf64_x86_64_link_hash_table{  struct elf_link_hash_table root;};/* Declare this now that the above structures are defined.  */static boolean elf64_x86_64_discard_copies  PARAMS ((struct elf64_x86_64_link_hash_entry *, PTR));/* Traverse an x86-64 ELF linker hash table.  */#define elf64_x86_64_link_hash_traverse(table, func, info)		\  (elf_link_hash_traverse						\   (&(table)->root,							\    (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func),	\    (info)))/* Get the x86-64 ELF linker hash table from a link_info structure.  */#define elf64_x86_64_hash_table(p) \  ((struct elf64_x86_64_link_hash_table *) ((p)->hash))/* Create an entry in an x86-64 ELF linker hash table.	*/static struct bfd_hash_entry *elf64_x86_64_link_hash_newfunc (entry, table, string)     struct bfd_hash_entry *entry;     struct bfd_hash_table *table;     const char *string;{  struct elf64_x86_64_link_hash_entry *ret =    (struct elf64_x86_64_link_hash_entry *) entry;  /* Allocate the structure if it has not already been allocated by a     subclass.	*/  if (ret == (struct elf64_x86_64_link_hash_entry *) NULL)    ret = ((struct elf64_x86_64_link_hash_entry *)	   bfd_hash_allocate (table,			      sizeof (struct elf64_x86_64_link_hash_entry)));  if (ret == (struct elf64_x86_64_link_hash_entry *) NULL)    return (struct bfd_hash_entry *) ret;  /* Call the allocation method of the superclass.  */  ret = ((struct elf64_x86_64_link_hash_entry *)	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,				     table, string));  if (ret != (struct elf64_x86_64_link_hash_entry *) NULL)    {      ret->pcrel_relocs_copied = NULL;    }  return (struct bfd_hash_entry *) ret;}/* Create an X86-64 ELF linker hash table.  */static struct bfd_link_hash_table *elf64_x86_64_link_hash_table_create (abfd)     bfd *abfd;{  struct elf64_x86_64_link_hash_table *ret;  ret = ((struct elf64_x86_64_link_hash_table *)	 bfd_alloc (abfd, sizeof (struct elf64_x86_64_link_hash_table)));  if (ret == (struct elf64_x86_64_link_hash_table *) NULL)    return NULL;  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,				       elf64_x86_64_link_hash_newfunc))    {      bfd_release (abfd, ret);      return NULL;    }  return &ret->root.root;}booleanelf64_x86_64_elf_object_p (abfd)     bfd *abfd;{  /* Set the right machine number for an x86-64 elf64 file.  */  bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);  return true;}/* Look through the relocs for a section during the first phase, and   allocate space in the global offset table or procedure linkage   table.  */static booleanelf64_x86_64_check_relocs (abfd, info, sec, relocs)     bfd *abfd;     struct bfd_link_info *info;     asection *sec;     const Elf_Internal_Rela *relocs;{  bfd *dynobj;  Elf_Internal_Shdr *symtab_hdr;  struct elf_link_hash_entry **sym_hashes;  bfd_signed_vma *local_got_refcounts;  const Elf_Internal_Rela *rel;  const Elf_Internal_Rela *rel_end;  asection *sgot;  asection *srelgot;  asection *sreloc;  if (info->relocateable)    return true;  dynobj = elf_hash_table (info)->dynobj;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  sym_hashes = elf_sym_hashes (abfd);  local_got_refcounts = elf_local_got_refcounts (abfd);  sgot = srelgot = sreloc = NULL;  rel_end = relocs + sec->reloc_count;  for (rel = relocs; rel < rel_end; rel++)    {      unsigned long r_symndx;      struct elf_link_hash_entry *h;      r_symndx = ELF64_R_SYM (rel->r_info);      if (r_symndx < symtab_hdr->sh_info)	h = NULL;      else	h = sym_hashes[r_symndx - symtab_hdr->sh_info];      /* Some relocs require a global offset table.  */      if (dynobj == NULL)	{	  switch (ELF64_R_TYPE (rel->r_info))	    {	    case R_X86_64_GOT32:	    case R_X86_64_GOTPCREL:	      elf_hash_table (info)->dynobj = dynobj = abfd;	      if (! _bfd_elf_create_got_section (dynobj, info))		return false;	      break;	    }	}      switch (ELF64_R_TYPE (rel->r_info))	{	case R_X86_64_GOTPCREL:	case R_X86_64_GOT32:	  /* This symbol requires a global offset table entry.	*/	  if (sgot == NULL)	    {	      sgot = bfd_get_section_by_name (dynobj, ".got");	      BFD_ASSERT (sgot != NULL);	    }	  if (srelgot == NULL && (h != NULL || info->shared))	    {	      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");	      if (srelgot == NULL)		{		  srelgot = bfd_make_section (dynobj, ".rela.got");		  if (srelgot == NULL		      || ! bfd_set_section_flags (dynobj, srelgot,						  (SEC_ALLOC						   | SEC_LOAD						   | SEC_HAS_CONTENTS						   | SEC_IN_MEMORY						   | SEC_LINKER_CREATED						   | SEC_READONLY))		      || ! bfd_set_section_alignment (dynobj, srelgot, 3))		    return false;		}	    }	  if (h != NULL)	    {	      if (h->got.refcount == -1)		{		  h->got.refcount = 1;		  /* Make sure this symbol is output as a dynamic symbol.  */		  if (h->dynindx == -1)		    {		      if (! bfd_elf64_link_record_dynamic_symbol (info, h))			return false;		    }		  sgot->_raw_size += GOT_ENTRY_SIZE;		  srelgot->_raw_size += sizeof (Elf64_External_Rela);		}	      else		h->got.refcount += 1;	    }	  else	    {	      /* This is a global offset table entry for a local symbol.  */	      if (local_got_refcounts == NULL)		{		  size_t size;		  size = symtab_hdr->sh_info * sizeof (bfd_signed_vma);		  local_got_refcounts = ((bfd_signed_vma *)					 bfd_alloc (abfd, size));		  if (local_got_refcounts == NULL)		    return false;		  elf_local_got_refcounts (abfd) = local_got_refcounts;		  memset (local_got_refcounts, -1, size);		}	      if (local_got_refcounts[r_symndx] == -1)		{		  local_got_refcounts[r_symndx] = 1;		  sgot->_raw_size += GOT_ENTRY_SIZE;		  if (info->shared)		    {		      /* If we are generating a shared object, we need to			 output a R_X86_64_RELATIVE reloc so that the dynamic			 linker can adjust this GOT entry.  */		      srelgot->_raw_size += sizeof (Elf64_External_Rela);		    }		}	      else		local_got_refcounts[r_symndx] += 1;	    }	  break;	case R_X86_64_PLT32:	  /* This symbol requires a procedure linkage table entry.  We	     actually build the entry in adjust_dynamic_symbol,	     because this might be a case of linking PIC code which is	     never referenced by a dynamic object, in which case we	     don't need to generate a procedure linkage table entry	     after all.	 */	  /* If this is a local symbol, we resolve it directly without	     creating a procedure linkage table entry.	*/	  if (h == NULL)	    continue;	  h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;	  if (h->plt.refcount == -1)	    h->plt.refcount = 1;	  else	    h->plt.refcount += 1;	  break;	case R_X86_64_8:	case R_X86_64_16:	case R_X86_64_32:

⌨️ 快捷键说明

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