elf64-hppa.c

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

C
2,237
字号
/* Support for HPPA 64-bit ELF   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.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 "alloca-conf.h"#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "elf-bfd.h"#include "elf/hppa.h"#include "libhppa.h"#include "elf64-hppa.h"#define ARCH_SIZE	       64#define PLT_ENTRY_SIZE 0x10#define DLT_ENTRY_SIZE 0x8#define OPD_ENTRY_SIZE 0x20#define ELF_DYNAMIC_INTERPRETER "/usr/lib/pa20_64/dld.sl"/* The stub is supposed to load the target address and target's DP   value out of the PLT, then do an external branch to the target   address.   LDD PLTOFF(%r27),%r1   BVE (%r1)   LDD PLTOFF+8(%r27),%r27   Note that we must use the LDD with a 14 bit displacement, not the one   with a 5 bit displacement.  */static char plt_stub[] = {0x53, 0x61, 0x00, 0x00, 0xe8, 0x20, 0xd0, 0x00,			  0x53, 0x7b, 0x00, 0x00 };struct elf64_hppa_dyn_hash_entry{  struct bfd_hash_entry root;  /* Offsets for this symbol in various linker sections.  */  bfd_vma dlt_offset;  bfd_vma plt_offset;  bfd_vma opd_offset;  bfd_vma stub_offset;  /* The symbol table entry, if any, that this was derived from.  */  struct elf_link_hash_entry *h;  /* The index of the (possibly local) symbol in the input bfd and its     associated BFD.  Needed so that we can have relocs against local     symbols in shared libraries.  */  unsigned long sym_indx;  bfd *owner;  /* Dynamic symbols may need to have two different values.  One for     the dynamic symbol table, one for the normal symbol table.     In such cases we store the symbol's real value and section     index here so we can restore the real value before we write     the normal symbol table.  */  bfd_vma st_value;  int st_shndx;  /* Used to count non-got, non-plt relocations for delayed sizing     of relocation sections.  */  struct elf64_hppa_dyn_reloc_entry  {    /* Next relocation in the chain.  */    struct elf64_hppa_dyn_reloc_entry *next;    /* The type of the relocation.  */    int type;    /* The input section of the relocation.  */    asection *sec;    /* The index of the section symbol for the input section of       the relocation.  Only needed when building shared libraries.  */    int sec_symndx;    /* The offset within the input section of the relocation.  */    bfd_vma offset;    /* The addend for the relocation.  */    bfd_vma addend;  } *reloc_entries;  /* Nonzero if this symbol needs an entry in one of the linker     sections.  */  unsigned want_dlt;  unsigned want_plt;  unsigned want_opd;  unsigned want_stub;};struct elf64_hppa_dyn_hash_table{  struct bfd_hash_table root;};struct elf64_hppa_link_hash_table{  struct elf_link_hash_table root;  /* Shortcuts to get to the various linker defined sections.  */  asection *dlt_sec;  asection *dlt_rel_sec;  asection *plt_sec;  asection *plt_rel_sec;  asection *opd_sec;  asection *opd_rel_sec;  asection *other_rel_sec;  /* Offset of __gp within .plt section.  When the PLT gets large we want     to slide __gp into the PLT section so that we can continue to use     single DP relative instructions to load values out of the PLT.  */  bfd_vma gp_offset;  /* Note this is not strictly correct.  We should create a stub section for     each input section with calls.  The stub section should be placed before     the section with the call.  */  asection *stub_sec;  bfd_vma text_segment_base;  bfd_vma data_segment_base;  struct elf64_hppa_dyn_hash_table dyn_hash_table;  /* We build tables to map from an input section back to its     symbol index.  This is the BFD for which we currently have     a map.  */  bfd *section_syms_bfd;  /* Array of symbol numbers for each input section attached to the     current BFD.  */  int *section_syms;};#define elf64_hppa_hash_table(p) \  ((struct elf64_hppa_link_hash_table *) ((p)->hash))typedef struct bfd_hash_entry *(*new_hash_entry_func)  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static boolean elf64_hppa_dyn_hash_table_init  PARAMS ((struct elf64_hppa_dyn_hash_table *ht, bfd *abfd,	   new_hash_entry_func new));static struct bfd_hash_entry *elf64_hppa_new_dyn_hash_entry  PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,	   const char *string));static struct bfd_link_hash_table *elf64_hppa_hash_table_create  PARAMS ((bfd *abfd));static struct elf64_hppa_dyn_hash_entry *elf64_hppa_dyn_hash_lookup  PARAMS ((struct elf64_hppa_dyn_hash_table *table, const char *string,	   boolean create, boolean copy));static void elf64_hppa_dyn_hash_traverse  PARAMS ((struct elf64_hppa_dyn_hash_table *table,	   boolean (*func) (struct elf64_hppa_dyn_hash_entry *, PTR),	   PTR info));static const char *get_dyn_name  PARAMS ((asection *, struct elf_link_hash_entry *,	   const Elf_Internal_Rela *, char **, size_t *));/* This must follow the definitions of the various derived linker   hash tables and shared functions.  */#include "elf-hppa.h"static boolean elf64_hppa_object_p  PARAMS ((bfd *));static boolean elf64_hppa_section_from_shdr  PARAMS ((bfd *, Elf64_Internal_Shdr *, char *));static void elf64_hppa_post_process_headers  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf64_hppa_create_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf64_hppa_adjust_dynamic_symbol  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));static boolean elf64_hppa_size_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf64_hppa_finish_dynamic_symbol  PARAMS ((bfd *, struct bfd_link_info *,	   struct elf_link_hash_entry *, Elf_Internal_Sym *));static boolean elf64_hppa_finish_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf64_hppa_check_relocs  PARAMS ((bfd *, struct bfd_link_info *,	   asection *, const Elf_Internal_Rela *));static boolean elf64_hppa_dynamic_symbol_p  PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));static boolean elf64_hppa_mark_exported_functions  PARAMS ((struct elf_link_hash_entry *, PTR));static boolean elf64_hppa_finalize_opd  PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));static boolean elf64_hppa_finalize_dlt  PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));static boolean allocate_global_data_dlt  PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));static boolean allocate_global_data_plt  PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));static boolean allocate_global_data_stub  PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));static boolean allocate_global_data_opd  PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));static boolean get_reloc_section  PARAMS ((bfd *, struct elf64_hppa_link_hash_table *, asection *));static boolean count_dyn_reloc  PARAMS ((bfd *, struct elf64_hppa_dyn_hash_entry *,	   int, asection *, int, bfd_vma, bfd_vma));static boolean allocate_dynrel_entries  PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));static boolean elf64_hppa_finalize_dynreloc  PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));static boolean get_opd  PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));static boolean get_plt  PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));static boolean get_dlt  PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));static boolean get_stub  PARAMS ((bfd *, struct bfd_link_info *, struct elf64_hppa_link_hash_table *));static int elf64_hppa_elf_get_symbol_type  PARAMS ((Elf_Internal_Sym *, int));static booleanelf64_hppa_dyn_hash_table_init (ht, abfd, new)     struct elf64_hppa_dyn_hash_table *ht;     bfd *abfd ATTRIBUTE_UNUSED;     new_hash_entry_func new;{  memset (ht, 0, sizeof (*ht));  return bfd_hash_table_init (&ht->root, new);}static struct bfd_hash_entry*elf64_hppa_new_dyn_hash_entry (entry, table, string)     struct bfd_hash_entry *entry;     struct bfd_hash_table *table;     const char *string;{  struct elf64_hppa_dyn_hash_entry *ret;  ret = (struct elf64_hppa_dyn_hash_entry *) entry;  /* Allocate the structure if it has not already been allocated by a     subclass.  */  if (!ret)    ret = bfd_hash_allocate (table, sizeof (*ret));  if (!ret)    return 0;  /* Initialize our local data.  All zeros, and definitely easier     than setting 8 bit fields.  */  memset (ret, 0, sizeof (*ret));  /* Call the allocation method of the superclass.  */  ret = ((struct elf64_hppa_dyn_hash_entry *)	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));  return &ret->root;}/* Create the derived linker hash table.  The PA64 ELF port uses this   derived hash table to keep information specific to the PA ElF   linker (without using static variables).  */static struct bfd_link_hash_table*elf64_hppa_hash_table_create (abfd)     bfd *abfd;{  struct elf64_hppa_link_hash_table *ret;  ret = bfd_zalloc (abfd, sizeof (*ret));  if (!ret)    return 0;  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,				      _bfd_elf_link_hash_newfunc))    {      bfd_release (abfd, ret);      return 0;    }  if (!elf64_hppa_dyn_hash_table_init (&ret->dyn_hash_table, abfd,				       elf64_hppa_new_dyn_hash_entry))    return 0;  return &ret->root.root;}/* Look up an entry in a PA64 ELF linker hash table.  */static struct elf64_hppa_dyn_hash_entry *elf64_hppa_dyn_hash_lookup(table, string, create, copy)     struct elf64_hppa_dyn_hash_table *table;     const char *string;     boolean create, copy;{  return ((struct elf64_hppa_dyn_hash_entry *)	  bfd_hash_lookup (&table->root, string, create, copy));}/* Traverse a PA64 ELF linker hash table.  */static voidelf64_hppa_dyn_hash_traverse (table, func, info)     struct elf64_hppa_dyn_hash_table *table;     boolean (*func) PARAMS ((struct elf64_hppa_dyn_hash_entry *, PTR));     PTR info;{  (bfd_hash_traverse   (&table->root,    (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) func,    info));}/* Return nonzero if ABFD represents a PA2.0 ELF64 file.   Additionally we set the default architecture and machine.  */static booleanelf64_hppa_object_p (abfd)     bfd *abfd;{  Elf_Internal_Ehdr * i_ehdrp;  unsigned int flags;  i_ehdrp = elf_elfheader (abfd);  if (strcmp (bfd_get_target (abfd), "elf64-hppa-linux") == 0)    {      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX)	return false;    }  else    {      if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)	return false;    }  flags = i_ehdrp->e_flags;  switch (flags & (EF_PARISC_ARCH | EF_PARISC_WIDE))    {    case EFA_PARISC_1_0:      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 10);    case EFA_PARISC_1_1:      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 11);    case EFA_PARISC_2_0:      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 20);    case EFA_PARISC_2_0 | EF_PARISC_WIDE:      return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);    }  /* Don't be fussy.  */  return true;}/* Given section type (hdr->sh_type), return a boolean indicating   whether or not the section is an elf64-hppa specific section.  */static booleanelf64_hppa_section_from_shdr (abfd, hdr, name)     bfd *abfd;     Elf64_Internal_Shdr *hdr;     char *name;{  asection *newsect;  switch (hdr->sh_type)    {    case SHT_PARISC_EXT:      if (strcmp (name, ".PARISC.archext") != 0)	return false;      break;    case SHT_PARISC_UNWIND:      if (strcmp (name, ".PARISC.unwind") != 0)	return false;      break;    case SHT_PARISC_DOC:    case SHT_PARISC_ANNOT:    default:      return false;    }  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))    return false;  newsect = hdr->bfd_section;  return true;}/* Construct a string for use in the elf64_hppa_dyn_hash_table.  The   name describes what was once potentially anonymous memory.  We   allocate memory as necessary, possibly reusing PBUF/PLEN.  */static const char *get_dyn_name (sec, h, rel, pbuf, plen)     asection *sec;     struct elf_link_hash_entry *h;     const Elf_Internal_Rela *rel;     char **pbuf;     size_t *plen;{  size_t nlen, tlen;  char *buf;  size_t len;  if (h && rel->r_addend == 0)    return h->root.root.string;  if (h)    nlen = strlen (h->root.root.string);  else    nlen = 8 + 1 + sizeof (rel->r_info) * 2 - 8;  tlen = nlen + 1 + sizeof (rel->r_addend) * 2 + 1;

⌨️ 快捷键说明

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