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