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