elf32-fr30.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 813 行 · 第 1/2 页
C
813 行
/* FR30-specific support for 32-bit ELF. Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.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/fr30.h"/* Forward declarations. */static bfd_reloc_status_type fr30_elf_i20_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type fr30_elf_i32_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static reloc_howto_type * fr30_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));static void fr30_info_to_howto_rela PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));static boolean fr30_elf_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));static bfd_reloc_status_type fr30_final_link_relocate PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma));static boolean fr30_elf_gc_sweep_hook PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));static asection * fr30_elf_gc_mark_hook PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));static reloc_howto_type fr30_elf_howto_table [] ={ /* This reloc does nothing. */ HOWTO (R_FR30_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_FR30_NONE", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */ /* An 8 bit absolute relocation. */ HOWTO (R_FR30_8, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 4, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_FR30_8", /* name */ true, /* partial_inplace */ 0x0000, /* src_mask */ 0x0ff0, /* dst_mask */ false), /* pcrel_offset */ /* A 20 bit absolute relocation. */ HOWTO (R_FR30_20, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 20, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ fr30_elf_i20_reloc, /* special_function */ "R_FR30_20", /* name */ true, /* partial_inplace */ 0x00000000, /* src_mask */ 0x00f0ffff, /* dst_mask */ false), /* pcrel_offset */ /* A 32 bit absolute relocation. */ HOWTO (R_FR30_32, /* 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_FR30_32", /* name */ true, /* partial_inplace */ 0x00000000, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ /* A 32 bit into 48 bits absolute relocation. */ HOWTO (R_FR30_48, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ fr30_elf_i32_reloc, /* special_function */ "R_FR30_48", /* name */ true, /* partial_inplace */ 0x00000000, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ /* A 6 bit absolute relocation. */ HOWTO (R_FR30_6_IN_4, /* type */ 2, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 6, /* bitsize */ false, /* pc_relative */ 4, /* bitpos */ complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_FR30_6_IN_4", /* name */ true, /* partial_inplace */ 0x0000, /* src_mask */ 0x00f0, /* dst_mask */ false), /* pcrel_offset */ /* An 8 bit absolute relocation. */ HOWTO (R_FR30_8_IN_8, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 4, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc,/* special_function */ "R_FR30_8_IN_8", /* name */ true, /* partial_inplace */ 0x0000, /* src_mask */ 0x0ff0, /* dst_mask */ false), /* pcrel_offset */ /* A 9 bit absolute relocation. */ HOWTO (R_FR30_9_IN_8, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 9, /* bitsize */ false, /* pc_relative */ 4, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc,/* special_function */ "R_FR30_9_IN_8", /* name */ true, /* partial_inplace */ 0x0000, /* src_mask */ 0x0ff0, /* dst_mask */ false), /* pcrel_offset */ /* A 10 bit absolute relocation. */ HOWTO (R_FR30_10_IN_8, /* type */ 2, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 10, /* bitsize */ false, /* pc_relative */ 4, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc,/* special_function */ "R_FR30_10_IN_8", /* name */ true, /* partial_inplace */ 0x0000, /* src_mask */ 0x0ff0, /* dst_mask */ false), /* pcrel_offset */ /* A PC relative 9 bit relocation, right shifted by 1. */ HOWTO (R_FR30_9_PCREL, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 9, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_FR30_9_PCREL", /* name */ false, /* partial_inplace */ 0x0000, /* src_mask */ 0x00ff, /* dst_mask */ false), /* pcrel_offset */ /* A PC relative 12 bit relocation, right shifted by 1. */ HOWTO (R_FR30_12_PCREL, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_FR30_12_PCREL", /* name */ false, /* partial_inplace */ 0x0000, /* src_mask */ 0x07ff, /* dst_mask */ false), /* pcrel_offset */ /* GNU extension to record C++ vtable hierarchy */ HOWTO (R_FR30_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_FR30_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_FR30_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 */ "R_FR30_GNU_VTENTRY", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */};/* Utility to actually perform an R_FR30_20 reloc. */static bfd_reloc_status_typefr30_elf_i20_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd * abfd; arelent * reloc_entry; asymbol * symbol; PTR data; asection * input_section; bfd * output_bfd; char ** error_message ATTRIBUTE_UNUSED;{ bfd_vma relocation; unsigned long x; /* This part is from bfd_elf_generic_reloc. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 && (! reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } if (output_bfd != NULL) /* FIXME: See bfd_perform_relocation. Is this right? */ return bfd_reloc_ok; relocation = symbol->value + symbol->section->output_section->vma + symbol->section->output_offset + reloc_entry->addend; if (relocation > (((bfd_vma) 1 << 20) - 1)) return bfd_reloc_overflow; x = bfd_get_32 (abfd, (char *) data + reloc_entry->address); x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4); bfd_put_32 (abfd, x, (char *) data + reloc_entry->address); return bfd_reloc_ok;}/* Utility to actually perform a R_FR30_48 reloc. */static bfd_reloc_status_typefr30_elf_i32_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd * abfd; arelent * reloc_entry; asymbol * symbol; PTR data; asection * input_section; bfd * output_bfd; char ** error_message ATTRIBUTE_UNUSED;{ bfd_vma relocation; /* This part is from bfd_elf_generic_reloc. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 && (! reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } if (output_bfd != NULL) /* FIXME: See bfd_perform_relocation. Is this right? */ return bfd_reloc_ok; relocation = symbol->value + symbol->section->output_section->vma + symbol->section->output_offset + reloc_entry->addend; bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2); return bfd_reloc_ok;}/* Map BFD reloc types to FR30 ELF reloc types. */struct fr30_reloc_map{ bfd_reloc_code_real_type bfd_reloc_val; unsigned int fr30_reloc_val;};static const struct fr30_reloc_map fr30_reloc_map [] ={ { BFD_RELOC_NONE, R_FR30_NONE }, { BFD_RELOC_8, R_FR30_8 }, { BFD_RELOC_FR30_20, R_FR30_20 }, { BFD_RELOC_32, R_FR30_32 }, { BFD_RELOC_FR30_48, R_FR30_48 }, { BFD_RELOC_FR30_6_IN_4, R_FR30_6_IN_4 }, { BFD_RELOC_FR30_8_IN_8, R_FR30_8_IN_8 }, { BFD_RELOC_FR30_9_IN_8, R_FR30_9_IN_8 }, { BFD_RELOC_FR30_10_IN_8, R_FR30_10_IN_8 }, { BFD_RELOC_FR30_9_PCREL, R_FR30_9_PCREL }, { BFD_RELOC_FR30_12_PCREL, R_FR30_12_PCREL }, { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT }, { BFD_RELOC_VTABLE_ENTRY, R_FR30_GNU_VTENTRY },};static reloc_howto_type *fr30_reloc_type_lookup (abfd, code) bfd * abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code;{ unsigned int i; for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]); --i;) if (fr30_reloc_map [i].bfd_reloc_val == code) return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val]; return NULL;}/* Set the howto pointer for an FR30 ELF reloc. */static voidfr30_info_to_howto_rela (abfd, cache_ptr, dst) bfd * abfd ATTRIBUTE_UNUSED; arelent * cache_ptr; Elf32_Internal_Rela * dst;{ unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); BFD_ASSERT (r_type < (unsigned int) R_FR30_max); cache_ptr->howto = & fr30_elf_howto_table [r_type];}/* Perform a single relocation. By default we use the standard BFD routines, but a few relocs, we have to do them ourselves. */static bfd_reloc_status_typefr30_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation) reloc_howto_type * howto; bfd * input_bfd; asection * input_section; bfd_byte * contents; Elf_Internal_Rela * rel; bfd_vma relocation;{ bfd_reloc_status_type r = bfd_reloc_ok; bfd_vma x; bfd_signed_vma srel; switch (howto->type) { case R_FR30_20: contents += rel->r_offset; relocation += rel->r_addend; if (relocation > ((1 << 20) - 1)) return bfd_reloc_overflow; x = bfd_get_32 (input_bfd, contents);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?