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 + -
显示快捷键?