elf32-sh.c

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

C
2,188
字号
/* Hitachi SH specific support for 32-bit ELF   Copyright 1996, 1997, 1998, 1999, 2000, 2001   Free Software Foundation, Inc.   Contributed 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.  */#include "bfd.h"#include "sysdep.h"#include "bfdlink.h"#include "libbfd.h"#include "elf-bfd.h"#include "elf/sh.h"static bfd_reloc_status_type sh_elf_reloc  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type sh_elf_ignore_reloc  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static reloc_howto_type *sh_elf_reloc_type_lookup  PARAMS ((bfd *, bfd_reloc_code_real_type));static void sh_elf_info_to_howto  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));static boolean sh_elf_set_private_flags  PARAMS ((bfd *, flagword));static boolean sh_elf_copy_private_data  PARAMS ((bfd *, bfd *));static boolean sh_elf_merge_private_data  PARAMS ((bfd *, bfd *));static boolean sh_elf_set_mach_from_flags  PARAMS ((bfd *));static boolean sh_elf_relax_section  PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));static boolean sh_elf_relax_delete_bytes  PARAMS ((bfd *, asection *, bfd_vma, int));static boolean sh_elf_align_loads  PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, boolean *));static boolean sh_elf_swap_insns  PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));static boolean sh_elf_relocate_section  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));static bfd_byte *sh_elf_get_relocated_section_contents  PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,	   bfd_byte *, boolean, asymbol **));static boolean sh_elf_check_relocs  PARAMS ((bfd *, struct bfd_link_info *, asection *,	   const Elf_Internal_Rela *));static struct bfd_hash_entry *sh_elf_link_hash_newfunc  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static struct bfd_link_hash_table *sh_elf_link_hash_table_create  PARAMS ((bfd *));static boolean sh_elf_adjust_dynamic_symbol  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));static boolean sh_elf_size_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean sh_elf_finish_dynamic_symbol  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,	   Elf_Internal_Sym *));static boolean sh_elf_finish_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));/* The name of the dynamic interpreter.  This is put in the .interp   section.  */#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"static reloc_howto_type sh_elf_howto_table[] ={  /* No relocation.  */  HOWTO (R_SH_NONE,		/* type */	 0,			/* rightshift */	 0,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_NONE",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false),		/* pcrel_offset */  /* 32 bit absolute relocation.  Setting partial_inplace to true and     src_mask to a non-zero value is similar to the COFF toolchain.  */  HOWTO (R_SH_DIR32,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 sh_elf_reloc,		/* special_function */	 "R_SH_DIR32",		/* name */	 true,			/* partial_inplace */	 0xffffffff,		/* src_mask */	 0xffffffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* 32 bit PC relative relocation.  */  HOWTO (R_SH_REL32,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_REL32",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xffffffff,		/* dst_mask */	 true),			/* pcrel_offset */  /* 8 bit PC relative branch divided by 2.  */  HOWTO (R_SH_DIR8WPN,		/* type */	 1,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_DIR8WPN",	/* name */	 true,			/* partial_inplace */	 0xff,			/* src_mask */	 0xff,			/* dst_mask */	 true),			/* pcrel_offset */  /* 12 bit PC relative branch divided by 2.  */  HOWTO (R_SH_IND12W,		/* type */	 1,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 12,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 sh_elf_reloc,		/* special_function */	 "R_SH_IND12W",		/* name */	 true,			/* partial_inplace */	 0xfff,			/* src_mask */	 0xfff,			/* dst_mask */	 true),			/* pcrel_offset */  /* 8 bit unsigned PC relative divided by 4.  */  HOWTO (R_SH_DIR8WPL,		/* type */	 2,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_DIR8WPL",	/* name */	 true,			/* partial_inplace */	 0xff,			/* src_mask */	 0xff,			/* dst_mask */	 true),			/* pcrel_offset */  /* 8 bit unsigned PC relative divided by 2.  */  HOWTO (R_SH_DIR8WPZ,		/* type */	 1,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_DIR8WPZ",	/* name */	 true,			/* partial_inplace */	 0xff,			/* src_mask */	 0xff,			/* dst_mask */	 true),			/* pcrel_offset */  /* 8 bit GBR relative.  FIXME: This only makes sense if we have some     special symbol for the GBR relative area, and that is not     implemented.  */  HOWTO (R_SH_DIR8BP,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_DIR8BP",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xff,			/* dst_mask */	 true),			/* pcrel_offset */  /* 8 bit GBR relative divided by 2.  FIXME: This only makes sense if     we have some special symbol for the GBR relative area, and that     is not implemented.  */  HOWTO (R_SH_DIR8W,		/* type */	 1,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_DIR8W",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xff,			/* dst_mask */	 true),			/* pcrel_offset */  /* 8 bit GBR relative divided by 4.  FIXME: This only makes sense if     we have some special symbol for the GBR relative area, and that     is not implemented.  */  HOWTO (R_SH_DIR8L,		/* type */	 2,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_DIR8L",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0xff,			/* dst_mask */	 true),			/* pcrel_offset */  EMPTY_HOWTO (10),  EMPTY_HOWTO (11),  EMPTY_HOWTO (12),  EMPTY_HOWTO (13),  EMPTY_HOWTO (14),  EMPTY_HOWTO (15),  EMPTY_HOWTO (16),  EMPTY_HOWTO (17),  EMPTY_HOWTO (18),  EMPTY_HOWTO (19),  EMPTY_HOWTO (20),  EMPTY_HOWTO (21),  EMPTY_HOWTO (22),  EMPTY_HOWTO (23),  EMPTY_HOWTO (24),  /* The remaining relocs are a GNU extension used for relaxing.  The     final pass of the linker never needs to do anything with any of     these relocs.  Any required operations are handled by the     relaxation code.  */  /* A 16 bit switch table entry.  This is generated for an expression     such as ``.word L1 - L2''.  The offset holds the difference     between the reloc address and L2.  */  HOWTO (R_SH_SWITCH16,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_SWITCH16",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* A 32 bit switch table entry.  This is generated for an expression     such as ``.long L1 - L2''.  The offset holds the difference     between the reloc address and L2.  */  HOWTO (R_SH_SWITCH32,		/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_SWITCH32",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* Indicates a .uses pseudo-op.  The compiler will generate .uses     pseudo-ops when it finds a function call which can be relaxed.     The offset field holds the PC relative offset to the instruction     which loads the register used in the function call.  */  HOWTO (R_SH_USES,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_USES",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* The assembler will generate this reloc for addresses referred to     by the register loads associated with USES relocs.  The offset     field holds the number of times the address is referenced in the     object file.  */  HOWTO (R_SH_COUNT,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_COUNT",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* Indicates an alignment statement.  The offset field is the power     of 2 to which subsequent portions of the object file must be     aligned.  */  HOWTO (R_SH_ALIGN,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_ALIGN",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* The assembler will generate this reloc before a block of     instructions.  A section should be processed as assumining it     contains data, unless this reloc is seen.  */  HOWTO (R_SH_CODE,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_CODE",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* The assembler will generate this reloc after a block of     instructions when it sees data that is not instructions.  */  HOWTO (R_SH_DATA,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_DATA",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* The assembler generates this reloc for each label within a block     of instructions.  This permits the linker to avoid swapping     instructions which are the targets of branches.  */  HOWTO (R_SH_LABEL,		/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_LABEL",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* An 8 bit switch table entry.  This is generated for an expression     such as ``.word L1 - L2''.  The offset holds the difference     between the reloc address and L2.  */  HOWTO (R_SH_SWITCH8,		/* type */	 0,			/* rightshift */	 0,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_unsigned, /* complain_on_overflow */	 sh_elf_ignore_reloc,	/* special_function */	 "R_SH_SWITCH8",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* GNU extension to record C++ vtable hierarchy */  HOWTO (R_SH_GNU_VTINHERIT, /* type */         0,                     /* rightshift */         2,                     /* size (0 = byte, 1 = short, 2 = long) */         0,                     /* bitsize */         false,                 /* pc_relative */         0,                     /* bitpos */         complain_overflow_dont, /* complain_on_overflow */         NULL,                  /* special_function */         "R_SH_GNU_VTINHERIT", /* name */         false,                 /* partial_inplace */         0,                     /* src_mask */         0,                     /* dst_mask */         false),                /* pcrel_offset */  /* GNU extension to record C++ vtable member usage */  HOWTO (R_SH_GNU_VTENTRY,     /* type */         0,                     /* rightshift */         2,                     /* size (0 = byte, 1 = short, 2 = long) */         0,                     /* bitsize */         false,                 /* pc_relative */         0,                     /* bitpos */         complain_overflow_dont, /* complain_on_overflow */         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */

⌨️ 快捷键说明

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