elf32-ppc.c

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

C
1,931
字号
/* PowerPC-specific support for 32-bit ELF   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001   Free Software Foundation, Inc.   Written by Ian Lance Taylor, Cygnus Support.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.  *//* This file is based on a preliminary PowerPC ELF ABI.  The   information may not match the final PowerPC ELF ABI.  It includes   suggestions from the in-progress Embedded PowerPC ABI, and that   information may also not match.  */#include "bfd.h"#include "sysdep.h"#include "bfdlink.h"#include "libbfd.h"#include "elf-bfd.h"#include "elf/ppc.h"#define USE_RELA		/* we want RELA relocations, not REL */static reloc_howto_type *ppc_elf_reloc_type_lookup  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));static void ppc_elf_info_to_howto  PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rela *dst));static void ppc_elf_howto_init PARAMS ((void));static bfd_reloc_status_type ppc_elf_addr16_ha_reloc  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static boolean ppc_elf_set_private_flags PARAMS ((bfd *, flagword));static boolean ppc_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));static boolean ppc_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));static int ppc_elf_additional_program_headers PARAMS ((bfd *));static boolean ppc_elf_modify_segment_map PARAMS ((bfd *));static boolean ppc_elf_create_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean ppc_elf_section_from_shdr PARAMS ((bfd *,						  Elf32_Internal_Shdr *,						  char *));static boolean ppc_elf_fake_sections  PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));static elf_linker_section_t *ppc_elf_create_linker_section  PARAMS ((bfd *abfd,	   struct bfd_link_info *info,	   enum elf_linker_section_enum));static boolean ppc_elf_check_relocs PARAMS ((bfd *,					     struct bfd_link_info *,					     asection *,					     const Elf_Internal_Rela *));static asection * ppc_elf_gc_mark_hook PARAMS ((bfd *abfd,						struct bfd_link_info *info,						Elf_Internal_Rela *rel,						struct elf_link_hash_entry *h,						Elf_Internal_Sym *sym));static boolean ppc_elf_gc_sweep_hook PARAMS ((bfd *abfd,					      struct bfd_link_info *info,					      asection *sec,					      const Elf_Internal_Rela *relocs));static boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *,						      struct elf_link_hash_entry *));static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));static boolean ppc_elf_relocate_section PARAMS ((bfd *,						 struct bfd_link_info *info,						 bfd *,						 asection *,						 bfd_byte *,						 Elf_Internal_Rela *relocs,						 Elf_Internal_Sym *local_syms,						 asection **));static boolean ppc_elf_add_symbol_hook  PARAMS ((bfd *,						 struct bfd_link_info *,						 const Elf_Internal_Sym *,						 const char **,						 flagword *,						 asection **,						 bfd_vma *));static boolean ppc_elf_finish_dynamic_symbol PARAMS ((bfd *,						      struct bfd_link_info *,						      struct elf_link_hash_entry *,						      Elf_Internal_Sym *));static boolean ppc_elf_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));#define BRANCH_PREDICT_BIT 0x200000		/* branch prediction bit for branch taken relocs */#define RA_REGISTER_MASK 0x001f0000		/* mask to set RA in memory instructions */#define RA_REGISTER_SHIFT 16			/* value to shift register by to insert RA *//* The name of the dynamic interpreter.  This is put in the .interp   section.  */#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"/* The size in bytes of an entry in the procedure linkage table.  */#define PLT_ENTRY_SIZE 12/* The initial size of the plt reserved for the dynamic linker.  */#define PLT_INITIAL_ENTRY_SIZE 72/* The size of the gap between entries in the PLT.  */#define PLT_SLOT_SIZE 8/* The number of single-slot PLT entries (the rest use two slots).  */#define PLT_NUM_SINGLE_ENTRIES 8192/* Will references to this symbol always reference the symbol   in this object?  */#define SYMBOL_REFERENCES_LOCAL(INFO, H)				\  ((! INFO->shared							\    || INFO->symbolic							\    || H->dynindx == -1							\    || ELF_ST_VISIBILITY (H->other) == STV_INTERNAL			\    || ELF_ST_VISIBILITY (H->other) == STV_HIDDEN)			\   && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)/* Will _calls_ to this symbol always call the version in this object?  */#define SYMBOL_CALLS_LOCAL(INFO, H)				\  ((! INFO->shared							\    || INFO->symbolic							\    || H->dynindx == -1							\    || ELF_ST_VISIBILITY (H->other) != STV_DEFAULT)			\   && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)static reloc_howto_type *ppc_elf_howto_table[(int) R_PPC_max];static reloc_howto_type ppc_elf_howto_raw[] = {  /* This reloc does nothing.  */  HOWTO (R_PPC_NONE,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_NONE",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false),		/* pcrel_offset */  /* A standard 32 bit relocation.  */  HOWTO (R_PPC_ADDR32,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_ADDR32",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xffffffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* An absolute 26 bit branch; the lower two bits must be zero.     FIXME: we don't check that, we just clear them.  */  HOWTO (R_PPC_ADDR24,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 26,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_ADDR24",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0x3fffffc,		/* dst_mask */	 false),		/* pcrel_offset */  /* A standard 16 bit relocation.  */  HOWTO (R_PPC_ADDR16,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_ADDR16",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* A 16 bit relocation without overflow.  */  HOWTO (R_PPC_ADDR16_LO,	/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont,/* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_ADDR16_LO",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* The high order 16 bits of an address.  */  HOWTO (R_PPC_ADDR16_HI,	/* type */	 16,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_ADDR16_HI",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* The high order 16 bits of an address, plus 1 if the contents of     the low 16 bits, treated as a signed number, is negative.  */  HOWTO (R_PPC_ADDR16_HA,	/* type */	 16,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 ppc_elf_addr16_ha_reloc, /* special_function */	 "R_PPC_ADDR16_HA",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* An absolute 16 bit branch; the lower two bits must be zero.     FIXME: we don't check that, we just clear them.  */  HOWTO (R_PPC_ADDR14,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_ADDR14",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xfffc,		/* dst_mask */	 false),		/* pcrel_offset */  /* An absolute 16 bit branch, for which bit 10 should be set to     indicate that the branch is expected to be taken.	The lower two     bits must be zero.  */  HOWTO (R_PPC_ADDR14_BRTAKEN,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_ADDR14_BRTAKEN",/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xfffc,		/* dst_mask */	 false),		/* pcrel_offset */  /* An absolute 16 bit branch, for which bit 10 should be set to     indicate that the branch is not expected to be taken.  The lower     two bits must be zero.  */  HOWTO (R_PPC_ADDR14_BRNTAKEN, /* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_ADDR14_BRNTAKEN",/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xfffc,		/* dst_mask */	 false),		/* pcrel_offset */  /* A relative 26 bit branch; the lower two bits must be zero.  */  HOWTO (R_PPC_REL24,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 26,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_REL24",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0x3fffffc,		/* dst_mask */	 true),			/* pcrel_offset */  /* A relative 16 bit branch; the lower two bits must be zero.  */  HOWTO (R_PPC_REL14,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_REL14",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xfffc,		/* dst_mask */	 true),			/* pcrel_offset */  /* A relative 16 bit branch.  Bit 10 should be set to indicate that     the branch is expected to be taken.  The lower two bits must be     zero.  */  HOWTO (R_PPC_REL14_BRTAKEN,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_REL14_BRTAKEN",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xfffc,		/* dst_mask */	 true),			/* pcrel_offset */  /* A relative 16 bit branch.  Bit 10 should be set to indicate that     the branch is not expected to be taken.  The lower two bits must     be zero.  */  HOWTO (R_PPC_REL14_BRNTAKEN,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_REL14_BRNTAKEN",/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xfffc,		/* dst_mask */	 true),			/* pcrel_offset */  /* Like R_PPC_ADDR16, but referring to the GOT table entry for the     symbol.  */  HOWTO (R_PPC_GOT16,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 bfd_elf_generic_reloc,	/* special_function */	 "R_PPC_GOT16",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for     the symbol.  */  HOWTO (R_PPC_GOT16_LO,	/* type */

⌨️ 快捷键说明

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