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