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