elfxx-ia64.c

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

C
2,106
字号
/* IA-64 support for 64-bit ELF   Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>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 "opcode/ia64.h"#include "elf/ia64.h"/* * THE RULES for all the stuff the linker creates -- * * GOT		Entries created in response to LTOFF or LTOFF_FPTR *		relocations.  Dynamic relocs created for dynamic *		symbols in an application; REL relocs for locals *		in a shared library. * * FPTR		The canonical function descriptor.  Created for local *		symbols in applications.  Descriptors for dynamic symbols *		and local symbols in shared libraries are created by *		ld.so.  Thus there are no dynamic relocs against these *		objects.  The FPTR relocs for such _are_ passed through *		to the dynamic relocation tables. * * FULL_PLT	Created for a PCREL21B relocation against a dynamic symbol. *		Requires the creation of a PLTOFF entry.  This does not *		require any dynamic relocations. * * PLTOFF	Created by PLTOFF relocations.  For local symbols, this *		is an alternate function descriptor, and in shared libraries *		requires two REL relocations.  Note that this cannot be *		transformed into an FPTR relocation, since it must be in *		range of the GP.  For dynamic symbols, this is a function *		descriptor for a MIN_PLT entry, and requires one IPLT reloc. * * MIN_PLT	Created by PLTOFF entries against dynamic symbols.  This *		does not reqire dynamic relocations. */#define USE_RELA		/* we want RELA relocs, not REL */#define NELEMS(a)	((int) (sizeof (a) / sizeof ((a)[0])))typedef struct bfd_hash_entry *(*new_hash_entry_func)  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));/* In dynamically (linker-) created sections, we generally need to keep track   of the place a symbol or expression got allocated to. This is done via hash   tables that store entries of the following type.  */struct elfNN_ia64_dyn_sym_info{  /* The addend for which this entry is relevant.  */  bfd_vma addend;  /* Next addend in the list.  */  struct elfNN_ia64_dyn_sym_info *next;  bfd_vma got_offset;  bfd_vma fptr_offset;  bfd_vma pltoff_offset;  bfd_vma plt_offset;  bfd_vma plt2_offset;  /* The symbol table entry, if any, that this was derrived from.  */  struct elf_link_hash_entry *h;  /* Used to count non-got, non-plt relocations for delayed sizing     of relocation sections.  */  struct elfNN_ia64_dyn_reloc_entry  {    struct elfNN_ia64_dyn_reloc_entry *next;    asection *srel;    int type;    int count;  } *reloc_entries;  /* True when the section contents have been updated.  */  unsigned got_done : 1;  unsigned fptr_done : 1;  unsigned pltoff_done : 1;  /* True for the different kinds of linker data we want created.  */  unsigned want_got : 1;  unsigned want_fptr : 1;  unsigned want_ltoff_fptr : 1;  unsigned want_plt : 1;  unsigned want_plt2 : 1;  unsigned want_pltoff : 1;};struct elfNN_ia64_local_hash_entry{  struct bfd_hash_entry root;  struct elfNN_ia64_dyn_sym_info *info;};struct elfNN_ia64_local_hash_table{  struct bfd_hash_table root;  /* No additional fields for now.  */};struct elfNN_ia64_link_hash_entry{  struct elf_link_hash_entry root;  struct elfNN_ia64_dyn_sym_info *info;};struct elfNN_ia64_link_hash_table{  /* The main hash table */  struct elf_link_hash_table root;  asection *got_sec;		/* the linkage table section (or NULL) */  asection *rel_got_sec;	/* dynamic relocation section for same */  asection *fptr_sec;		/* function descriptor table (or NULL) */  asection *plt_sec;		/* the primary plt section (or NULL) */  asection *pltoff_sec;		/* private descriptors for plt (or NULL) */  asection *rel_pltoff_sec;	/* dynamic relocation section for same */  bfd_size_type minplt_entries;	/* number of minplt entries */  struct elfNN_ia64_local_hash_table loc_hash_table;};#define elfNN_ia64_hash_table(p) \  ((struct elfNN_ia64_link_hash_table *) ((p)->hash))static bfd_reloc_status_type elfNN_ia64_reloc  PARAMS ((bfd *abfd, arelent *reloc, asymbol *sym, PTR data,	   asection *input_section, bfd *output_bfd, char **error_message));static reloc_howto_type * lookup_howto  PARAMS ((unsigned int rtype));static reloc_howto_type *elfNN_ia64_reloc_type_lookup  PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code));static void elfNN_ia64_info_to_howto  PARAMS ((bfd *abfd, arelent *bfd_reloc, ElfNN_Internal_Rela *elf_reloc));static boolean elfNN_ia64_relax_section  PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,	  boolean *again));static boolean is_unwind_section_name  PARAMS ((const char *));static boolean elfNN_ia64_section_from_shdr  PARAMS ((bfd *, ElfNN_Internal_Shdr *, char *));static boolean elfNN_ia64_fake_sections  PARAMS ((bfd *abfd, ElfNN_Internal_Shdr *hdr, asection *sec));static void elfNN_ia64_final_write_processing  PARAMS ((bfd *abfd, boolean linker));static boolean elfNN_ia64_add_symbol_hook  PARAMS ((bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Sym *sym,	   const char **namep, flagword *flagsp, asection **secp,	   bfd_vma *valp));static int elfNN_ia64_additional_program_headers  PARAMS ((bfd *abfd));static boolean elfNN_ia64_is_local_label_name  PARAMS ((bfd *abfd, const char *name));static boolean elfNN_ia64_dynamic_symbol_p  PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info));static boolean elfNN_ia64_local_hash_table_init  PARAMS ((struct elfNN_ia64_local_hash_table *ht, bfd *abfd,	   new_hash_entry_func new));static struct bfd_hash_entry *elfNN_ia64_new_loc_hash_entry  PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,	   const char *string));static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry  PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,	   const char *string));static struct bfd_link_hash_table *elfNN_ia64_hash_table_create  PARAMS ((bfd *abfd));static struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup  PARAMS ((struct elfNN_ia64_local_hash_table *table, const char *string,	   boolean create, boolean copy));static void elfNN_ia64_dyn_sym_traverse  PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,	   boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),	   PTR info));static boolean elfNN_ia64_create_dynamic_sections  PARAMS ((bfd *abfd, struct bfd_link_info *info));static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info  PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,	   struct elf_link_hash_entry *h,	   bfd *abfd, const Elf_Internal_Rela *rel, boolean create));static asection *get_got  PARAMS ((bfd *abfd, struct bfd_link_info *info,	   struct elfNN_ia64_link_hash_table *ia64_info));static asection *get_fptr  PARAMS ((bfd *abfd, struct bfd_link_info *info,	   struct elfNN_ia64_link_hash_table *ia64_info));static asection *get_pltoff  PARAMS ((bfd *abfd, struct bfd_link_info *info,	   struct elfNN_ia64_link_hash_table *ia64_info));static asection *get_reloc_section  PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info,	   asection *sec, boolean create));static boolean count_dyn_reloc  PARAMS ((bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i,	   asection *srel, int type));static boolean elfNN_ia64_check_relocs  PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,	   const Elf_Internal_Rela *relocs));static boolean elfNN_ia64_adjust_dynamic_symbol  PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));static unsigned long global_sym_index  PARAMS ((struct elf_link_hash_entry *h));static boolean allocate_fptr  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));static boolean allocate_global_data_got  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));static boolean allocate_global_fptr_got  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));static boolean allocate_local_got  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));static boolean allocate_pltoff_entries  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));static boolean allocate_plt_entries  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));static boolean allocate_plt2_entries  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));static boolean allocate_dynrel_entries  PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));static boolean elfNN_ia64_size_dynamic_sections  PARAMS ((bfd *output_bfd, struct bfd_link_info *info));static bfd_reloc_status_type elfNN_ia64_install_value  PARAMS ((bfd *abfd, bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));static void elfNN_ia64_install_dyn_reloc  PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,	   asection *srel, bfd_vma offset, unsigned int type,	   long dynindx, bfd_vma addend));static bfd_vma set_got_entry  PARAMS ((bfd *abfd, struct bfd_link_info *info,	   struct elfNN_ia64_dyn_sym_info *dyn_i, long dynindx,	   bfd_vma addend, bfd_vma value, unsigned int dyn_r_type));static bfd_vma set_fptr_entry  PARAMS ((bfd *abfd, struct bfd_link_info *info,	   struct elfNN_ia64_dyn_sym_info *dyn_i,	   bfd_vma value));static bfd_vma set_pltoff_entry  PARAMS ((bfd *abfd, struct bfd_link_info *info,	   struct elfNN_ia64_dyn_sym_info *dyn_i,	   bfd_vma value, boolean));static boolean elfNN_ia64_final_link  PARAMS ((bfd *abfd, struct bfd_link_info *info));static boolean elfNN_ia64_relocate_section  PARAMS ((bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd,	   asection *input_section, bfd_byte *contents,	   Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms,	   asection **local_sections));static boolean elfNN_ia64_finish_dynamic_symbol  PARAMS ((bfd *output_bfd, struct bfd_link_info *info,	   struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));static boolean elfNN_ia64_finish_dynamic_sections  PARAMS ((bfd *abfd, struct bfd_link_info *info));static boolean elfNN_ia64_set_private_flags  PARAMS ((bfd *abfd, flagword flags));static boolean elfNN_ia64_copy_private_bfd_data  PARAMS ((bfd *ibfd, bfd *obfd));static boolean elfNN_ia64_merge_private_bfd_data  PARAMS ((bfd *ibfd, bfd *obfd));static boolean elfNN_ia64_print_private_bfd_data  PARAMS ((bfd *abfd, PTR ptr));/* ia64-specific relocation *//* Perform a relocation.  Not much to do here as all the hard work is   done in elfNN_ia64_final_link_relocate.  */static bfd_reloc_status_typeelfNN_ia64_reloc (abfd, reloc, sym, data, input_section,		  output_bfd, error_message)     bfd *abfd ATTRIBUTE_UNUSED;     arelent *reloc;     asymbol *sym ATTRIBUTE_UNUSED;     PTR data ATTRIBUTE_UNUSED;     asection *input_section;     bfd *output_bfd;     char **error_message;{  if (output_bfd)    {      reloc->address += input_section->output_offset;      return bfd_reloc_ok;    }  *error_message = "Unsupported call to elfNN_ia64_reloc";  return bfd_reloc_notsupported;}#define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN)			\  HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed,	\	 elfNN_ia64_reloc, NAME, false, 0, 0, IN)/* This table has to be sorted according to increasing number of the   TYPE field.  */static reloc_howto_type ia64_howto_table[] =  {    IA64_HOWTO (R_IA64_NONE,	    "NONE",	   0, false, true),    IA64_HOWTO (R_IA64_IMM14,	    "IMM14",	   0, false, true),    IA64_HOWTO (R_IA64_IMM22,	    "IMM22",	   0, false, true),    IA64_HOWTO (R_IA64_IMM64,	    "IMM64",	   0, false, true),    IA64_HOWTO (R_IA64_DIR32MSB,    "DIR32MSB",	   2, false, true),    IA64_HOWTO (R_IA64_DIR32LSB,    "DIR32LSB",	   2, false, true),    IA64_HOWTO (R_IA64_DIR64MSB,    "DIR64MSB",	   4, false, true),    IA64_HOWTO (R_IA64_DIR64LSB,    "DIR64LSB",	   4, false, true),    IA64_HOWTO (R_IA64_GPREL22,	    "GPREL22",	   0, false, true),    IA64_HOWTO (R_IA64_GPREL64I,    "GPREL64I",	   0, false, true),    IA64_HOWTO (R_IA64_GPREL32MSB,  "GPREL32MSB",  2, false, true),    IA64_HOWTO (R_IA64_GPREL32LSB,  "GPREL32LSB",  2, false, true),    IA64_HOWTO (R_IA64_GPREL64MSB,  "GPREL64MSB",  4, false, true),    IA64_HOWTO (R_IA64_GPREL64LSB,  "GPREL64LSB",  4, false, true),    IA64_HOWTO (R_IA64_LTOFF22,	    "LTOFF22",	   0, false, true),    IA64_HOWTO (R_IA64_LTOFF64I,    "LTOFF64I",	   0, false, true),    IA64_HOWTO (R_IA64_PLTOFF22,    "PLTOFF22",	   0, false, true),    IA64_HOWTO (R_IA64_PLTOFF64I,   "PLTOFF64I",   0, false, true),    IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, false, true),    IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, false, true),    IA64_HOWTO (R_IA64_FPTR64I,	    "FPTR64I",	   0, false, true),    IA64_HOWTO (R_IA64_FPTR32MSB,   "FPTR32MSB",   2, false, true),    IA64_HOWTO (R_IA64_FPTR32LSB,   "FPTR32LSB",   2, false, true),    IA64_HOWTO (R_IA64_FPTR64MSB,   "FPTR64MSB",   4, false, true),    IA64_HOWTO (R_IA64_FPTR64LSB,   "FPTR64LSB",   4, false, true),    IA64_HOWTO (R_IA64_PCREL60B,    "PCREL60B",	   0, true, true),    IA64_HOWTO (R_IA64_PCREL21B,    "PCREL21B",	   0, true, true),    IA64_HOWTO (R_IA64_PCREL21M,    "PCREL21M",	   0, true, true),    IA64_HOWTO (R_IA64_PCREL21F,    "PCREL21F",	   0, true, true),    IA64_HOWTO (R_IA64_PCREL32MSB,  "PCREL32MSB",  2, true, true),    IA64_HOWTO (R_IA64_PCREL32LSB,  "PCREL32LSB",  2, true, true),    IA64_HOWTO (R_IA64_PCREL64MSB,  "PCREL64MSB",  4, true, true),    IA64_HOWTO (R_IA64_PCREL64LSB,  "PCREL64LSB",  4, true, true),    IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, false, true),    IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, false, true),    IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, false, true),    IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, false, true),    IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, false, true),    IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, false, true),    IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, false, true),    IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, false, true),    IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, false, true),    IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, false, true),    IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, false, true),    IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, false, true),    IA64_HOWTO (R_IA64_REL32MSB,    "REL32MSB",	   2, false, true),    IA64_HOWTO (R_IA64_REL32LSB,    "REL32LSB",	   2, false, true),    IA64_HOWTO (R_IA64_REL64MSB,    "REL64MSB",	   4, false, true),    IA64_HOWTO (R_IA64_REL64LSB,    "REL64LSB",	   4, false, true),    IA64_HOWTO (R_IA64_LTV32MSB,    "LTV32MSB",	   2, false, true),    IA64_HOWTO (R_IA64_LTV32LSB,    "LTV32LSB",	   2, false, true),    IA64_HOWTO (R_IA64_LTV64MSB,    "LTV64MSB",	   4, false, true),    IA64_HOWTO (R_IA64_LTV64LSB,    "LTV64LSB",	   4, false, true),    IA64_HOWTO (R_IA64_PCREL21BI,   "PCREL21BI",   0, true, true),    IA64_HOWTO (R_IA64_PCREL22,     "PCREL22",     0, true, true),    IA64_HOWTO (R_IA64_PCREL64I,    "PCREL64I",    0, true, true),    IA64_HOWTO (R_IA64_IPLTMSB,	    "IPLTMSB",	   4, false, true),    IA64_HOWTO (R_IA64_IPLTLSB,	    "IPLTLSB",	   4, false, true),    IA64_HOWTO (R_IA64_COPY,	    "COPY",	   4, false, true),    IA64_HOWTO (R_IA64_LTOFF22X,    "LTOFF22X",	   0, false, true),    IA64_HOWTO (R_IA64_LDXMOV,	    "LDXMOV",	   0, false, true),    IA64_HOWTO (R_IA64_TPREL22,	    "TPREL22",	   0, false, false),    IA64_HOWTO (R_IA64_TPREL64MSB,  "TPREL64MSB",  8, false, false),    IA64_HOWTO (R_IA64_TPREL64LSB,  "TPREL64LSB",  8, false, false),    IA64_HOWTO (R_IA64_LTOFF_TP22,  "LTOFF_TP22",  0, false, false),  };static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];/* Given a BFD reloc type, return the matching HOWTO structure.  */static reloc_howto_type*lookup_howto (rtype)     unsigned int rtype;{  static int inited = 0;  int i;  if (!inited)    {      inited = 1;      memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index));      for (i = 0; i < NELEMS (ia64_howto_table); ++i)	elf_code_to_howto_index[ia64_howto_table[i].type] = i;    }  BFD_ASSERT (rtype <= R_IA64_MAX_RELOC_CODE);  i = elf_code_to_howto_index[rtype];  if (i >= NELEMS (ia64_howto_table))    return 0;  return ia64_howto_table + i;}static reloc_howto_type*elfNN_ia64_reloc_type_lookup (abfd, bfd_code)

⌨️ 快捷键说明

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