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