coff-h8300.c

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

C
1,341
字号
/* BFD back-end for Hitachi H8/300 COFF binaries.   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,   2000   Free Software Foundation, Inc.   Written by Steve Chamberlain, <sac@cygnus.com>.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 "bfdlink.h"#include "genlink.h"#include "coff/h8300.h"#include "coff/internal.h"#include "libcoff.h"#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)/* We derive a hash table from the basic BFD hash table to   hold entries in the function vector.  Aside from the   info stored by the basic hash table, we need the offset   of a particular entry within the hash table as well as   the offset where we'll add the next entry.  */struct funcvec_hash_entry{  /* The basic hash table entry.  */  struct bfd_hash_entry root;  /* The offset within the vectors section where     this entry lives.  */  bfd_vma offset;};struct funcvec_hash_table{  /* The basic hash table.  */  struct bfd_hash_table root;  bfd *abfd;  /* Offset at which we'll add the next entry.  */  unsigned int offset;};static struct bfd_hash_entry *funcvec_hash_newfunc  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static booleanfuncvec_hash_table_init  PARAMS ((struct funcvec_hash_table *, bfd *,           struct bfd_hash_entry *(*) PARAMS ((struct bfd_hash_entry *,                                               struct bfd_hash_table *,                                               const char *))));/* To lookup a value in the function vector hash table.  */#define funcvec_hash_lookup(table, string, create, copy) \  ((struct funcvec_hash_entry *) \   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))/* The derived h8300 COFF linker table.  Note it's derived from   the generic linker hash table, not the COFF backend linker hash   table!  We use this to attach additional data structures we   need while linking on the h8300.  */struct h8300_coff_link_hash_table{  /* The main hash table.  */  struct generic_link_hash_table root;  /* Section for the vectors table.  This gets attached to a     random input bfd, we keep it here for easy access.  */  asection *vectors_sec;  /* Hash table of the functions we need to enter into the function     vector.  */  struct funcvec_hash_table *funcvec_hash_table;};static struct bfd_link_hash_table *h8300_coff_link_hash_table_create  PARAMS ((bfd *));/* Get the H8/300 COFF linker hash table from a link_info structure.  */#define h8300_coff_hash_table(p) \  ((struct h8300_coff_link_hash_table *) ((coff_hash_table (p))))/* Initialize fields within a funcvec hash table entry.  Called whenever   a new entry is added to the funcvec hash table.  */static struct bfd_hash_entry *funcvec_hash_newfunc (entry, gen_table, string)     struct bfd_hash_entry *entry;     struct bfd_hash_table *gen_table;     const char *string;{  struct funcvec_hash_entry *ret;  struct funcvec_hash_table *table;  ret = (struct funcvec_hash_entry *) entry;  table = (struct funcvec_hash_table *) gen_table;  /* Allocate the structure if it has not already been allocated by a     subclass.  */  if (ret == NULL)    ret = ((struct funcvec_hash_entry *)           bfd_hash_allocate (gen_table,                              sizeof (struct funcvec_hash_entry)));  if (ret == NULL)    return NULL;  /* Call the allocation method of the superclass.  */  ret = ((struct funcvec_hash_entry *)         bfd_hash_newfunc ((struct bfd_hash_entry *) ret, gen_table, string));  if (ret == NULL)    return NULL;  /* Note where this entry will reside in the function vector table.  */  ret->offset = table->offset;  /* Bump the offset at which we store entries in the function     vector.  We'd like to bump up the size of the vectors section,     but it's not easily available here.  */  if (bfd_get_mach (table->abfd) == bfd_mach_h8300)    table->offset += 2;  else if (bfd_get_mach (table->abfd) == bfd_mach_h8300h	   || bfd_get_mach (table->abfd) == bfd_mach_h8300s)    table->offset += 4;  else    return NULL;  /* Everything went OK.  */  return (struct bfd_hash_entry *) ret;}/* Initialize the function vector hash table.  */static booleanfuncvec_hash_table_init (table, abfd, newfunc)     struct funcvec_hash_table *table;     bfd *abfd;     struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,                                                struct bfd_hash_table *,                                                const char *));{  /* Initialize our local fields, then call the generic initialization     routine.  */  table->offset = 0;  table->abfd = abfd;  return (bfd_hash_table_init (&table->root, newfunc));}/* Create the derived linker hash table.  We use a derived hash table   basically to hold "static" information during an h8/300 coff link   without using static variables.  */static struct bfd_link_hash_table *h8300_coff_link_hash_table_create (abfd)     bfd *abfd;{  struct h8300_coff_link_hash_table *ret;  ret = ((struct h8300_coff_link_hash_table *)         bfd_alloc (abfd, sizeof (struct h8300_coff_link_hash_table)));  if (ret == NULL)    return NULL;  if (!_bfd_link_hash_table_init (&ret->root.root, abfd, _bfd_generic_link_hash_newfunc))    {      bfd_release (abfd, ret);      return NULL;    }  /* Initialize our data.  */  ret->vectors_sec = NULL;  ret->funcvec_hash_table = NULL;  /* OK.  Everything's intialized, return the base pointer.  */  return &ret->root.root;}/* Special handling for H8/300 relocs.   We only come here for pcrel stuff and return normally if not an -r link.   When doing -r, we can't do any arithmetic for the pcrel stuff, because   the code in reloc.c assumes that we can manipulate the targets of   the pcrel branches.  This isn't so, since the H8/300 can do relaxing,   which means that the gap after the instruction may not be enough to   contain the offset required for the branch, so we have to use only   the addend until the final link.  */static bfd_reloc_status_typespecial (abfd, reloc_entry, symbol, data, input_section, output_bfd,	 error_message)     bfd *abfd ATTRIBUTE_UNUSED;     arelent *reloc_entry ATTRIBUTE_UNUSED;     asymbol *symbol ATTRIBUTE_UNUSED;     PTR data ATTRIBUTE_UNUSED;     asection *input_section ATTRIBUTE_UNUSED;     bfd *output_bfd;     char **error_message ATTRIBUTE_UNUSED;{  if (output_bfd == (bfd *) NULL)    return bfd_reloc_continue;  /* Adjust the reloc address to that in the output section.  */  reloc_entry->address += input_section->output_offset;  return bfd_reloc_ok;}static reloc_howto_type howto_table[] ={  HOWTO (R_RELBYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "8", false, 0x000000ff, 0x000000ff, false),  HOWTO (R_RELWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16", false, 0x0000ffff, 0x0000ffff, false),  HOWTO (R_RELLONG, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "32", false, 0xffffffff, 0xffffffff, false),  HOWTO (R_PCRBYTE, 0, 0, 8, true, 0, complain_overflow_signed, special, "DISP8", false, 0x000000ff, 0x000000ff, true),  HOWTO (R_PCRWORD, 0, 1, 16, true, 0, complain_overflow_signed, special, "DISP16", false, 0x0000ffff, 0x0000ffff, true),  HOWTO (R_PCRLONG, 0, 2, 32, true, 0, complain_overflow_signed, special, "DISP32", false, 0xffffffff, 0xffffffff, true),  HOWTO (R_MOV16B1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "relaxable mov.b:16", false, 0x0000ffff, 0x0000ffff, false),  HOWTO (R_MOV16B2, 0, 1, 8, false, 0, complain_overflow_bitfield, special, "relaxed mov.b:16", false, 0x000000ff, 0x000000ff, false),  HOWTO (R_JMP1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/pcrel", false, 0x0000ffff, 0x0000ffff, false),  HOWTO (R_JMP2, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pcrecl/16", false, 0x000000ff, 0x000000ff, false),  HOWTO (R_JMPL1, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "24/pcrell", false, 0x00ffffff, 0x00ffffff, false),  HOWTO (R_JMPL2, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pc8/24", false, 0x000000ff, 0x000000ff, false),  HOWTO (R_MOV24B1, 0, 1, 32, false, 0, complain_overflow_bitfield, special, "relaxable mov.b:24", false, 0xffffffff, 0xffffffff, false),  HOWTO (R_MOV24B2, 0, 1, 8, false, 0, complain_overflow_bitfield, special, "relaxed mov.b:24", false, 0x0000ffff, 0x0000ffff, false),  /* An indirect reference to a function.  This causes the function's address     to be added to the function vector in lo-mem and puts the address of     the function vector's entry in the jsr instruction.  */  HOWTO (R_MEM_INDIRECT, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "8/indirect", false, 0x000000ff, 0x000000ff, false),  /* Internal reloc for relaxing.  This is created when a 16bit pc-relative     branch is turned into an 8bit pc-relative branch.  */  HOWTO (R_PCRWORD_B, 0, 0, 8, true, 0, complain_overflow_bitfield, special, "relaxed bCC:16", false, 0x000000ff, 0x000000ff, false),  HOWTO (R_MOVL1, 0, 2, 32, false, 0, complain_overflow_bitfield,special, "32/24 relaxable move", false, 0xffffffff, 0xffffffff, false),  HOWTO (R_MOVL2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "32/24 relaxed move", false, 0x0000ffff, 0x0000ffff, false),  HOWTO (R_BCC_INV, 0, 0, 8, true, 0, complain_overflow_signed, special, "DISP8 inverted", false, 0x000000ff, 0x000000ff, true),  HOWTO (R_JMP_DEL, 0, 0, 8, true, 0, complain_overflow_signed, special, "Deleted jump", false, 0x000000ff, 0x000000ff, true),};/* Turn a howto into a reloc number.  */#define SELECT_RELOC(x,howto) \  { x.r_type = select_reloc(howto); }#define BADMAG(x) (H8300BADMAG(x) && H8300HBADMAG(x) && H8300SBADMAG(x))#define H8300 1			/* Customize coffcode.h */#define __A_MAGIC_SET__/* Code to swap in the reloc.  */#define SWAP_IN_RELOC_OFFSET   bfd_h_get_32#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \  dst->r_stuff[0] = 'S'; \  dst->r_stuff[1] = 'C';static intselect_reloc (howto)     reloc_howto_type *howto;{  return howto->type;}/* Code to turn a r_type into a howto ptr, uses the above howto table.  */static voidrtype2howto (internal, dst)     arelent *internal;     struct internal_reloc *dst;{  switch (dst->r_type)    {    case R_RELBYTE:      internal->howto = howto_table + 0;      break;    case R_RELWORD:      internal->howto = howto_table + 1;      break;    case R_RELLONG:      internal->howto = howto_table + 2;      break;    case R_PCRBYTE:      internal->howto = howto_table + 3;      break;    case R_PCRWORD:      internal->howto = howto_table + 4;      break;    case R_PCRLONG:      internal->howto = howto_table + 5;      break;    case R_MOV16B1:      internal->howto = howto_table + 6;      break;    case R_MOV16B2:      internal->howto = howto_table + 7;      break;    case R_JMP1:      internal->howto = howto_table + 8;      break;    case R_JMP2:      internal->howto = howto_table + 9;      break;    case R_JMPL1:      internal->howto = howto_table + 10;      break;    case R_JMPL2:      internal->howto = howto_table + 11;      break;    case R_MOV24B1:      internal->howto = howto_table + 12;      break;    case R_MOV24B2:      internal->howto = howto_table + 13;      break;    case R_MEM_INDIRECT:      internal->howto = howto_table + 14;      break;    case R_PCRWORD_B:      internal->howto = howto_table + 15;      break;    case R_MOVL1:      internal->howto = howto_table + 16;      break;    case R_MOVL2:      internal->howto = howto_table + 17;      break;    case R_BCC_INV:      internal->howto = howto_table + 18;      break;    case R_JMP_DEL:      internal->howto = howto_table + 19;      break;    default:      abort ();      break;    }}#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)/* Perform any necessary magic to the addend in a reloc entry.  */#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \ cache_ptr->addend =  ext_reloc.r_offset;#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \ reloc_processing(relent, reloc, symbols, abfd, section)static voidreloc_processing (relent, reloc, symbols, abfd, section)     arelent *relent;     struct internal_reloc *reloc;     asymbol **symbols;     bfd *abfd;     asection *section;{  relent->address = reloc->r_vaddr;  rtype2howto (relent, reloc);  if (((int) reloc->r_symndx) > 0)    {      relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];    }  else    {      relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;    }  relent->addend = reloc->r_offset;  relent->address -= section->vma;#if 0  relent->section = 0;#endif}static booleanh8300_symbol_address_p (abfd, input_section, address)     bfd *abfd;     asection *input_section;     bfd_vma address;{  asymbol **s;  s = _bfd_generic_link_get_symbols (abfd);  BFD_ASSERT (s != (asymbol **) NULL);  /* Search all the symbols for one in INPUT_SECTION with     address ADDRESS.  */  while (*s)    {      asymbol *p = *s;      if (p->section == input_section	  && (input_section->output_section->vma	      + input_section->output_offset	      + p->value) == address)	return true;      s++;    }  return false;}/* If RELOC represents a relaxable instruction/reloc, change it into   the relaxed reloc, notify the linker that symbol addresses   have changed (bfd_perform_slip) and return how much the current   section has shrunk by.   FIXME: Much of this code has knowledge of the ordering of entries   in the howto table.  This needs to be fixed.  */static inth8300_reloc16_estimate (abfd, input_section, reloc, shrink, link_info)     bfd *abfd;     asection *input_section;     arelent *reloc;     unsigned int shrink;     struct bfd_link_info *link_info;{  bfd_vma value;  bfd_vma dot;  bfd_vma gap;  static asection *last_input_section = NULL;  static arelent *last_reloc = NULL;  /* The address of the thing to be relocated will have moved back by     the size of the shrink - but we don't change reloc->address here,     since we need it to know where the relocation lives in the source     uncooked section.  */  bfd_vma address = reloc->address - shrink;

⌨️ 快捷键说明

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