elf64-alpha.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,160 行 · 第 1/5 页

C
2,160
字号
/* Alpha specific support for 64-bit ELF   Copyright 1996, 1997, 1998, 1999, 2000, 2001   Free Software Foundation, Inc.   Contributed by Richard Henderson <rth@tamu.edu>.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.  *//* We need a published ABI spec for this.  Until one comes out, don't   assume this'll remain unchanged forever.  */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "elf-bfd.h"#include "elf/alpha.h"#define ALPHAECOFF#define NO_COFF_RELOCS#define NO_COFF_SYMBOLS#define NO_COFF_LINENOS/* Get the ECOFF swapping routines.  Needed for the debug information.  */#include "coff/internal.h"#include "coff/sym.h"#include "coff/symconst.h"#include "coff/ecoff.h"#include "coff/alpha.h"#include "aout/ar.h"#include "libcoff.h"#include "libecoff.h"#define ECOFF_64#include "ecoffswap.h"static int alpha_elf_dynamic_symbol_p  PARAMS((struct elf_link_hash_entry *, struct bfd_link_info *));static struct bfd_hash_entry * elf64_alpha_link_hash_newfunc  PARAMS((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static struct bfd_link_hash_table * elf64_alpha_bfd_link_hash_table_create  PARAMS((bfd *));static bfd_reloc_status_type elf64_alpha_reloc_nil  PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type elf64_alpha_reloc_bad  PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type elf64_alpha_do_reloc_gpdisp  PARAMS((bfd *, bfd_vma, bfd_byte *, bfd_byte *));static bfd_reloc_status_type elf64_alpha_reloc_gpdisp  PARAMS((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static reloc_howto_type * elf64_alpha_bfd_reloc_type_lookup  PARAMS((bfd *, bfd_reloc_code_real_type));static void elf64_alpha_info_to_howto  PARAMS((bfd *, arelent *, Elf64_Internal_Rela *));static boolean elf64_alpha_mkobject  PARAMS((bfd *));static boolean elf64_alpha_object_p  PARAMS((bfd *));static boolean elf64_alpha_section_from_shdr  PARAMS((bfd *, Elf64_Internal_Shdr *, char *));static boolean elf64_alpha_fake_sections  PARAMS((bfd *, Elf64_Internal_Shdr *, asection *));static boolean elf64_alpha_create_got_section  PARAMS((bfd *, struct bfd_link_info *));static boolean elf64_alpha_create_dynamic_sections  PARAMS((bfd *, struct bfd_link_info *));static boolean elf64_alpha_read_ecoff_info  PARAMS((bfd *, asection *, struct ecoff_debug_info *));static boolean elf64_alpha_is_local_label_name  PARAMS((bfd *, const char *));static boolean elf64_alpha_find_nearest_line  PARAMS((bfd *, asection *, asymbol **, bfd_vma, const char **,	  const char **, unsigned int *));#if defined(__STDC__) || defined(ALMOST_STDC)struct alpha_elf_link_hash_entry;#endifstatic boolean elf64_alpha_output_extsym  PARAMS((struct alpha_elf_link_hash_entry *, PTR));static boolean elf64_alpha_can_merge_gots  PARAMS((bfd *, bfd *));static void elf64_alpha_merge_gots  PARAMS((bfd *, bfd *));static boolean elf64_alpha_calc_got_offsets_for_symbol  PARAMS ((struct alpha_elf_link_hash_entry *, PTR));static void elf64_alpha_calc_got_offsets PARAMS ((struct bfd_link_info *));static boolean elf64_alpha_size_got_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf64_alpha_always_size_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf64_alpha_calc_dynrel_sizes  PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));static boolean elf64_alpha_add_symbol_hook  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,	   const char **, flagword *, asection **, bfd_vma *));static boolean elf64_alpha_check_relocs  PARAMS((bfd *, struct bfd_link_info *, asection *sec,	  const Elf_Internal_Rela *));static boolean elf64_alpha_adjust_dynamic_symbol  PARAMS((struct bfd_link_info *, struct elf_link_hash_entry *));static boolean elf64_alpha_size_dynamic_sections  PARAMS((bfd *, struct bfd_link_info *));static boolean elf64_alpha_relocate_section  PARAMS((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,	  Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));static boolean elf64_alpha_finish_dynamic_symbol  PARAMS((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,	  Elf_Internal_Sym *));static boolean elf64_alpha_finish_dynamic_sections  PARAMS((bfd *, struct bfd_link_info *));static boolean elf64_alpha_final_link  PARAMS((bfd *, struct bfd_link_info *));static boolean elf64_alpha_merge_ind_symbols  PARAMS((struct alpha_elf_link_hash_entry *, PTR));static Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs  PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int));struct alpha_elf_link_hash_entry{  struct elf_link_hash_entry root;  /* External symbol information.  */  EXTR esym;  /* Cumulative flags for all the .got entries.  */  int flags;  /* Contexts (LITUSE) in which a literal was referenced.  */#define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01#define ALPHA_ELF_LINK_HASH_LU_MEM  0x02#define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04#define ALPHA_ELF_LINK_HASH_LU_FUNC 0x08  /* Used to implement multiple .got subsections.  */  struct alpha_elf_got_entry  {    struct alpha_elf_got_entry *next;    /* which .got subsection?  */    bfd *gotobj;    /* the addend in effect for this entry.  */    bfd_vma addend;    /* the .got offset for this entry.  */    int got_offset;    int flags;    /* An additional flag.  */#define ALPHA_ELF_GOT_ENTRY_RELOCS_DONE 0x10    int use_count;  } *got_entries;  /* used to count non-got, non-plt relocations for delayed sizing     of relocation sections.  */  struct alpha_elf_reloc_entry  {    struct alpha_elf_reloc_entry *next;    /* which .reloc section? */    asection *srel;    /* what kind of relocation? */    unsigned long rtype;    /* how many did we find?  */    unsigned long count;  } *reloc_entries;};/* Alpha ELF linker hash table.  */struct alpha_elf_link_hash_table{  struct elf_link_hash_table root;  /* The head of a list of .got subsections linked through     alpha_elf_tdata(abfd)->got_link_next.  */  bfd *got_list;};/* Look up an entry in a Alpha ELF linker hash table.  */#define alpha_elf_link_hash_lookup(table, string, create, copy, follow)	\  ((struct alpha_elf_link_hash_entry *)					\   elf_link_hash_lookup (&(table)->root, (string), (create),		\			 (copy), (follow)))/* Traverse a Alpha ELF linker hash table.  */#define alpha_elf_link_hash_traverse(table, func, info)			\  (elf_link_hash_traverse						\   (&(table)->root,							\    (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func),	\    (info)))/* Get the Alpha ELF linker hash table from a link_info structure.  */#define alpha_elf_hash_table(p) \  ((struct alpha_elf_link_hash_table *) ((p)->hash))/* Get the object's symbols as our own entry type.  */#define alpha_elf_sym_hashes(abfd) \  ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd))/* Should we do dynamic things to this symbol?  */static intalpha_elf_dynamic_symbol_p (h, info)     struct elf_link_hash_entry *h;     struct bfd_link_info *info;{  if (h == NULL)    return false;  while (h->root.type == bfd_link_hash_indirect	 || h->root.type == bfd_link_hash_warning)    h = (struct elf_link_hash_entry *) h->root.u.i.link;  if (h->dynindx == -1)    return false;  if (h->root.type == bfd_link_hash_undefweak      || h->root.type == bfd_link_hash_defweak)    return true;  switch (ELF_ST_VISIBILITY (h->other))    {    case STV_DEFAULT:      break;    case STV_HIDDEN:    case STV_INTERNAL:      return false;    case STV_PROTECTED:      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)        return false;      break;    }  if ((info->shared && !info->symbolic)      || ((h->elf_link_hash_flags	   & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))	  == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))    return true;  return false;}/* Create an entry in a Alpha ELF linker hash table.  */static struct bfd_hash_entry *elf64_alpha_link_hash_newfunc (entry, table, string)     struct bfd_hash_entry *entry;     struct bfd_hash_table *table;     const char *string;{  struct alpha_elf_link_hash_entry *ret =    (struct alpha_elf_link_hash_entry *) entry;  /* Allocate the structure if it has not already been allocated by a     subclass.  */  if (ret == (struct alpha_elf_link_hash_entry *) NULL)    ret = ((struct alpha_elf_link_hash_entry *)	   bfd_hash_allocate (table,			      sizeof (struct alpha_elf_link_hash_entry)));  if (ret == (struct alpha_elf_link_hash_entry *) NULL)    return (struct bfd_hash_entry *) ret;  /* Call the allocation method of the superclass.  */  ret = ((struct alpha_elf_link_hash_entry *)	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,				     table, string));  if (ret != (struct alpha_elf_link_hash_entry *) NULL)    {      /* Set local fields.  */      memset (&ret->esym, 0, sizeof (EXTR));      /* We use -2 as a marker to indicate that the information has	 not been set.  -1 means there is no associated ifd.  */      ret->esym.ifd = -2;      ret->flags = 0;      ret->got_entries = NULL;      ret->reloc_entries = NULL;    }  return (struct bfd_hash_entry *) ret;}/* Create a Alpha ELF linker hash table.  */static struct bfd_link_hash_table *elf64_alpha_bfd_link_hash_table_create (abfd)     bfd *abfd;{  struct alpha_elf_link_hash_table *ret;  ret = ((struct alpha_elf_link_hash_table *)	 bfd_zalloc (abfd, sizeof (struct alpha_elf_link_hash_table)));  if (ret == (struct alpha_elf_link_hash_table *) NULL)    return NULL;  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,				       elf64_alpha_link_hash_newfunc))    {      bfd_release (abfd, ret);      return NULL;    }  return &ret->root.root;}/* We have some private fields hanging off of the elf_tdata structure.  */struct alpha_elf_obj_tdata{  struct elf_obj_tdata root;  /* For every input file, these are the got entries for that object's     local symbols.  */  struct alpha_elf_got_entry ** local_got_entries;  /* For every input file, this is the object that owns the got that     this input file uses.  */  bfd *gotobj;  /* For every got, this is a linked list through the objects using this got */  bfd *in_got_link_next;  /* For every got, this is a link to the next got subsegment.  */  bfd *got_link_next;  /* For every got, this is the section.  */  asection *got;  /* For every got, this is it's total number of *entries*.  */  int total_got_entries;  /* For every got, this is the sum of the number of *entries* required     to hold all of the member object's local got.  */  int n_local_got_entries;};#define alpha_elf_tdata(abfd) \  ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any)static booleanelf64_alpha_mkobject (abfd)     bfd *abfd;{  abfd->tdata.any = bfd_zalloc (abfd, sizeof (struct alpha_elf_obj_tdata));  if (abfd->tdata.any == NULL)    return false;  return true;}static booleanelf64_alpha_object_p (abfd)     bfd *abfd;{  /* Allocate our special target data.  */  struct alpha_elf_obj_tdata *new_tdata;  new_tdata = bfd_zalloc (abfd, sizeof (struct alpha_elf_obj_tdata));  if (new_tdata == NULL)    return false;  new_tdata->root = *abfd->tdata.elf_obj_data;  abfd->tdata.any = new_tdata;  /* Set the right machine number for an Alpha ELF file.  */  return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);}/* In case we're on a 32-bit machine, construct a 64-bit "-1" value   from smaller values.  Start with zero, widen, *then* decrement.  */#define MINUS_ONE	(((bfd_vma)0) - 1)static reloc_howto_type elf64_alpha_howto_table[] ={  HOWTO (R_ALPHA_NONE,		/* type */	 0,			/* rightshift */	 0,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 elf64_alpha_reloc_nil,	/* special_function */	 "NONE",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* A 32 bit reference to a symbol.  */  HOWTO (R_ALPHA_REFLONG,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 0,			/* special_function */	 "REFLONG",		/* name */	 false,			/* partial_inplace */	 0xffffffff,		/* src_mask */	 0xffffffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* A 64 bit reference to a symbol.  */  HOWTO (R_ALPHA_REFQUAD,	/* type */	 0,			/* rightshift */	 4,			/* size (0 = byte, 1 = short, 2 = long) */	 64,			/* bitsize */

⌨️ 快捷键说明

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