elf32-hppa.c

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

C
2,142
字号
/* BFD back-end for HP PA-RISC ELF files.   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001   Free Software Foundation, Inc.   Original code by	Center for Software Science	Department of Computer Science	University of Utah   Largely rewritten by Alan Modra <alan@linuxcare.com.au>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 "elf/hppa.h"#include "libhppa.h"#include "elf32-hppa.h"#define ARCH_SIZE		32#include "elf-hppa.h"#include "elf32-hppa.h"/* In order to gain some understanding of code in this file without   knowing all the intricate details of the linker, note the   following:   Functions named elf32_hppa_* are called by external routines, other   functions are only called locally.  elf32_hppa_* functions appear   in this file more or less in the order in which they are called   from external routines.  eg. elf32_hppa_check_relocs is called   early in the link process, elf32_hppa_finish_dynamic_sections is   one of the last functions.  *//* We use two hash tables to hold information for linking PA ELF objects.   The first is the elf32_hppa_link_hash_table which is derived   from the standard ELF linker hash table.  We use this as a place to   attach other hash tables and static information.   The second is the stub hash table which is derived from the   base BFD hash table.  The stub hash table holds the information   necessary to build the linker stubs during a link.   There are a number of different stubs generated by the linker.   Long branch stub:   :		ldil LR'X,%r1   :		be,n RR'X(%sr4,%r1)   PIC long branch stub:   :		b,l .+8,%r1   :		addil LR'X - ($PIC_pcrel$0 - 4),%r1   :		be,n RR'X - ($PIC_pcrel$0 - 8)(%sr4,%r1)   Import stub to call shared library routine from normal object file   (single sub-space version)   :		addil LR'lt_ptr+ltoff,%dp	; get procedure entry point   :		ldw RR'lt_ptr+ltoff(%r1),%r21   :            bv %r0(%r21)   :		ldw RR'lt_ptr+ltoff+4(%r1),%r19	; get new dlt value.   Import stub to call shared library routine from shared library   (single sub-space version)   :		addil LR'ltoff,%r19		; get procedure entry point   :		ldw RR'ltoff(%r1),%r21   :            bv %r0(%r21)   :		ldw RR'ltoff+4(%r1),%r19	; get new dlt value.   Import stub to call shared library routine from normal object file   (multiple sub-space support)   :		addil LR'lt_ptr+ltoff,%dp	; get procedure entry point   :		ldw RR'lt_ptr+ltoff(%r1),%r21   :		ldw RR'lt_ptr+ltoff+4(%r1),%r19	; get new dlt value.   :		ldsid (%r21),%r1   :		mtsp %r1,%sr0   :		be 0(%sr0,%r21)			; branch to target   :		stw %rp,-24(%sp)		; save rp   Import stub to call shared library routine from shared library   (multiple sub-space support)   :		addil LR'ltoff,%r19		; get procedure entry point   :		ldw RR'ltoff(%r1),%r21   :		ldw RR'ltoff+4(%r1),%r19	; get new dlt value.   :		ldsid (%r21),%r1   :		mtsp %r1,%sr0   :		be 0(%sr0,%r21)			; branch to target   :		stw %rp,-24(%sp)		; save rp   Export stub to return from shared lib routine (multiple sub-space support)   One of these is created for each exported procedure in a shared   library (and stored in the shared lib).  Shared lib routines are   called via the first instruction in the export stub so that we can   do an inter-space return.  Not required for single sub-space.   :		bl,n X,%rp			; trap the return   :		nop   :		ldw -24(%sp),%rp		; restore the original rp   :		ldsid (%rp),%r1   :		mtsp %r1,%sr0   :		be,n 0(%sr0,%rp)		; inter-space return  */#define PLT_ENTRY_SIZE 8#define PLABEL_PLT_ENTRY_SIZE PLT_ENTRY_SIZE#define GOT_ENTRY_SIZE 4#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"static const bfd_byte plt_stub[] ={  0x0e, 0x80, 0x10, 0x96,  /* 1: ldw	0(%r20),%r22		*/  0xea, 0xc0, 0xc0, 0x00,  /*    bv	%r0(%r22)		*/  0x0e, 0x88, 0x10, 0x95,  /*    ldw	4(%r20),%r21		*/#define PLT_STUB_ENTRY (3*4)  0xea, 0x9f, 0x1f, 0xdd,  /*    b,l	1b,%r20			*/  0xd6, 0x80, 0x1c, 0x1e,  /*    depi	0,31,2,%r20		*/  0x00, 0xc0, 0xff, 0xee,  /* 9: .word	fixup_func		*/  0xde, 0xad, 0xbe, 0xef   /*    .word	fixup_ltp		*/};/* Section name for stubs is the associated section name plus this   string.  */#define STUB_SUFFIX ".stub"/* Setting the following non-zero makes all long branch stubs   generated during a shared link of the PIC variety.  This saves on   relocs, but costs one extra instruction per stub.  */#ifndef LONG_BRANCH_PIC_IN_SHLIB#define LONG_BRANCH_PIC_IN_SHLIB 1#endif/* Set this non-zero to use import stubs instead of long branch stubs   where a .plt entry exists for the symbol.  This is a fairly useless   option as import stubs are bigger than PIC long branch stubs.  */#ifndef LONG_BRANCH_VIA_PLT#define LONG_BRANCH_VIA_PLT 0#endif/* We don't need to copy any PC- or GP-relative dynamic relocs into a   shared object's dynamic section.  */#ifndef RELATIVE_DYNAMIC_RELOCS#define RELATIVE_DYNAMIC_RELOCS 0#endifenum elf32_hppa_stub_type {  hppa_stub_long_branch,  hppa_stub_long_branch_shared,  hppa_stub_import,  hppa_stub_import_shared,  hppa_stub_export,  hppa_stub_none};struct elf32_hppa_stub_hash_entry {  /* Base hash table entry structure.  */  struct bfd_hash_entry root;  /* The stub section.  */  asection *stub_sec;#if ! LONG_BRANCH_PIC_IN_SHLIB  /* It's associated reloc section.  */  asection *reloc_sec;#endif  /* Offset within stub_sec of the beginning of this stub.  */  bfd_vma stub_offset;  /* Given the symbol's value and its section we can determine its final     value when building the stubs (so the stub knows where to jump.  */  bfd_vma target_value;  asection *target_section;  enum elf32_hppa_stub_type stub_type;  /* The symbol table entry, if any, that this was derived from.  */  struct elf32_hppa_link_hash_entry *h;  /* Where this stub is being called from, or, in the case of combined     stub sections, the first input section in the group.  */  asection *id_sec;};struct elf32_hppa_link_hash_entry {  struct elf_link_hash_entry elf;  /* A pointer to the most recently used stub hash entry against this     symbol.  */  struct elf32_hppa_stub_hash_entry *stub_cache;#if ! LONG_BRANCH_PIC_IN_SHLIB  /* Used to track whether we have allocated space for a long branch     stub relocation for this symbol in the given section.  */  asection *stub_reloc_sec;#endif#if ! LONG_BRANCH_PIC_IN_SHLIB || RELATIVE_DYNAMIC_RELOCS  /* Used to count relocations for delayed sizing of relocation     sections.  */  struct elf32_hppa_dyn_reloc_entry {    /* Next relocation in the chain.  */    struct elf32_hppa_dyn_reloc_entry *next;    /* The section in dynobj.  */    asection *section;    /* Number of relocs copied in this section.  */    bfd_size_type count;  } *reloc_entries;#endif  /* Set during a static link if we detect a function is PIC.  */  unsigned int maybe_pic_call:1;  /* Set if the only reason we need a .plt entry is for a non-PIC to     PIC function call.  */  unsigned int pic_call:1;  /* Set if this symbol is used by a plabel reloc.  */  unsigned int plabel:1;  /* Set if this symbol is an init or fini function and thus should     use an absolute reloc.  */  unsigned int plt_abs:1;};struct elf32_hppa_link_hash_table {  /* The main hash table.  */  struct elf_link_hash_table root;  /* The stub hash table.  */  struct bfd_hash_table stub_hash_table;  /* Linker stub bfd.  */  bfd *stub_bfd;  /* Linker call-backs.  */  asection * (*add_stub_section) PARAMS ((const char *, asection *));  void (*layout_sections_again) PARAMS ((void));  /* Array to keep track of which stub sections have been created, and     information on stub grouping.  */  struct map_stub {    /* This is the section to which stubs in the group will be       attached.  */    asection *link_sec;    /* The stub section.  */    asection *stub_sec;#if ! LONG_BRANCH_PIC_IN_SHLIB    /* The stub section's reloc section.  */    asection *reloc_sec;#endif  } *stub_group;  /* Short-cuts to get to dynamic linker sections.  */  asection *sgot;  asection *srelgot;  asection *splt;  asection *srelplt;  asection *sdynbss;  asection *srelbss;  /* Used during a final link to store the base of the text and data     segments so that we can perform SEGREL relocations.  */  bfd_vma text_segment_base;  bfd_vma data_segment_base;  /* Whether we support multiple sub-spaces for shared libs.  */  unsigned int multi_subspace:1;  /* Flags set when PCREL12F and PCREL17F branches detected.  Used to     select suitable defaults for the stub group size.  */  unsigned int has_12bit_branch:1;  unsigned int has_17bit_branch:1;  /* Set if we need a .plt stub to support lazy dynamic linking.  */  unsigned int need_plt_stub:1;};/* Various hash macros and functions.  */#define hppa_link_hash_table(p) \  ((struct elf32_hppa_link_hash_table *) ((p)->hash))#define hppa_stub_hash_lookup(table, string, create, copy) \  ((struct elf32_hppa_stub_hash_entry *) \   bfd_hash_lookup ((table), (string), (create), (copy)))static struct bfd_hash_entry *stub_hash_newfunc  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static struct bfd_hash_entry *hppa_link_hash_newfunc  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static struct bfd_link_hash_table *elf32_hppa_link_hash_table_create  PARAMS ((bfd *));/* Stub handling functions.  */static char *hppa_stub_name  PARAMS ((const asection *, const asection *,	   const struct elf32_hppa_link_hash_entry *,	   const Elf_Internal_Rela *));static struct elf32_hppa_stub_hash_entry *hppa_get_stub_entry  PARAMS ((const asection *, const asection *,	   struct elf32_hppa_link_hash_entry *,	   const Elf_Internal_Rela *,	   struct elf32_hppa_link_hash_table *));static struct elf32_hppa_stub_hash_entry *hppa_add_stub  PARAMS ((const char *, asection *, struct elf32_hppa_link_hash_table *));static enum elf32_hppa_stub_type hppa_type_of_stub  PARAMS ((asection *, const Elf_Internal_Rela *,	   struct elf32_hppa_link_hash_entry *, bfd_vma));static boolean hppa_build_one_stub  PARAMS ((struct bfd_hash_entry *, PTR));static boolean hppa_size_one_stub  PARAMS ((struct bfd_hash_entry *, PTR));/* BFD and elf backend functions.  */static boolean elf32_hppa_object_p PARAMS ((bfd *));static boolean elf32_hppa_add_symbol_hook  PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,	   const char **, flagword *, asection **, bfd_vma *));static boolean elf32_hppa_create_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf32_hppa_check_relocs  PARAMS ((bfd *, struct bfd_link_info *,	   asection *, const Elf_Internal_Rela *));static asection *elf32_hppa_gc_mark_hook  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,	   struct elf_link_hash_entry *, Elf_Internal_Sym *));static boolean elf32_hppa_gc_sweep_hook  PARAMS ((bfd *, struct bfd_link_info *,	   asection *, const Elf_Internal_Rela *));static void elf32_hppa_hide_symbol  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));static boolean elf32_hppa_adjust_dynamic_symbol  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));static boolean hppa_handle_PIC_calls  PARAMS ((struct elf_link_hash_entry *, PTR));static boolean allocate_plt_and_got  PARAMS ((struct elf_link_hash_entry *, PTR));#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \     || RELATIVE_DYNAMIC_RELOCS)static boolean hppa_discard_copies  PARAMS ((struct elf_link_hash_entry *, PTR));#endifstatic boolean clobber_millicode_symbols  PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *));static boolean elf32_hppa_size_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf32_hppa_final_link  PARAMS ((bfd *, struct bfd_link_info *));static void hppa_record_segment_addr  PARAMS ((bfd *, asection *, PTR));static bfd_reloc_status_type final_link_relocate  PARAMS ((asection *, bfd_byte *, const Elf_Internal_Rela *,	   bfd_vma, struct elf32_hppa_link_hash_table *, asection *,	   struct elf32_hppa_link_hash_entry *));static boolean elf32_hppa_relocate_section  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,	   bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));static int hppa_unwind_entry_compare  PARAMS ((const PTR, const PTR));static boolean elf32_hppa_finish_dynamic_symbol  PARAMS ((bfd *, struct bfd_link_info *,	   struct elf_link_hash_entry *, Elf_Internal_Sym *));static boolean elf32_hppa_finish_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static void elf32_hppa_post_process_headers  PARAMS ((bfd *, struct bfd_link_info *));static int elf32_hppa_elf_get_symbol_type  PARAMS ((Elf_Internal_Sym *, int));/* Assorted hash table functions.  *//* Initialize an entry in the stub hash table.  */static struct bfd_hash_entry *stub_hash_newfunc (entry, table, string)     struct bfd_hash_entry *entry;     struct bfd_hash_table *table;     const char *string;{  struct elf32_hppa_stub_hash_entry *ret;  ret = (struct elf32_hppa_stub_hash_entry *) entry;  /* Allocate the structure if it has not already been allocated by a

⌨️ 快捷键说明

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