⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 coff-mips.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
     PTR ext_ptr;     struct internal_reloc *intern;{  const RELOC *ext = (RELOC *) ext_ptr;  intern->r_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_vaddr);  if (bfd_header_big_endian (abfd))    {      intern->r_symndx = (((int) ext->r_bits[0]			   << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)			  | ((int) ext->r_bits[1]			     << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)			  | ((int) ext->r_bits[2]			     << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));      intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)			>> RELOC_BITS3_TYPE_SH_BIG);      intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;    }  else    {      intern->r_symndx = (((int) ext->r_bits[0]			   << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)			  | ((int) ext->r_bits[1]			     << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)			  | ((int) ext->r_bits[2]			     << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));      intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)			 >> RELOC_BITS3_TYPE_SH_LITTLE)			| ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)			   << RELOC_BITS3_TYPEHI_SH_LITTLE));      intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;    }  /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or     MIPS_R_RELLO reloc, r_symndx is actually the offset from the     reloc address to the base of the difference (see     include/coff/mips.h for more details).  We copy symndx into the     r_offset field so as not to confuse ecoff_slurp_reloc_table in     ecoff.c.  In adjust_reloc_in we then copy r_offset into the reloc     addend.  */  if (intern->r_type == MIPS_R_SWITCH      || (! intern->r_extern	  && (intern->r_type == MIPS_R_RELLO	      || intern->r_type == MIPS_R_RELHI)))    {      BFD_ASSERT (! intern->r_extern);      intern->r_offset = intern->r_symndx;      if (intern->r_offset & 0x800000)	intern->r_offset -= 0x1000000;      intern->r_symndx = RELOC_SECTION_TEXT;    }}/* Swap a reloc out.  */static voidmips_ecoff_swap_reloc_out (abfd, intern, dst)     bfd *abfd;     const struct internal_reloc *intern;     PTR dst;{  RELOC *ext = (RELOC *) dst;  long r_symndx;  BFD_ASSERT (intern->r_extern	      || (intern->r_symndx >= 0 && intern->r_symndx <= 12));  /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELLO or     MIPS_R_RELHI reloc, we actually want to write the contents of     r_offset out as the symbol index.  This undoes the change made by     mips_ecoff_swap_reloc_in.  */  if (intern->r_type != MIPS_R_SWITCH      && (intern->r_extern	  || (intern->r_type != MIPS_R_RELHI	      && intern->r_type != MIPS_R_RELLO)))    r_symndx = intern->r_symndx;  else    {      BFD_ASSERT (intern->r_symndx == RELOC_SECTION_TEXT);      r_symndx = intern->r_offset & 0xffffff;    }  bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);  if (bfd_header_big_endian (abfd))    {      ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;      ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;      ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;      ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)			 & RELOC_BITS3_TYPE_BIG)			| (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));    }  else    {      ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;      ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;      ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;      ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)			 & RELOC_BITS3_TYPE_LITTLE)			| ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE			    & RELOC_BITS3_TYPEHI_LITTLE))			| (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));    }}/* Finish canonicalizing a reloc.  Part of this is generic to all   ECOFF targets, and that part is in ecoff.c.  The rest is done in   this backend routine.  It must fill in the howto field.  */static voidmips_adjust_reloc_in (abfd, intern, rptr)     bfd *abfd;     const struct internal_reloc *intern;     arelent *rptr;{  if (intern->r_type > MIPS_R_SWITCH)    abort ();  if (! intern->r_extern      && (intern->r_type == MIPS_R_GPREL	  || intern->r_type == MIPS_R_LITERAL))    rptr->addend += ecoff_data (abfd)->gp;  /* If the type is MIPS_R_IGNORE, make sure this is a reference to     the absolute section so that the reloc is ignored.  */  if (intern->r_type == MIPS_R_IGNORE)    rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;  /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or     MIPS_R_RELLO reloc, we want the addend field of the BFD relocto     hold the value which was originally in the symndx field of the     internal MIPS ECOFF reloc.  This value was copied into     intern->r_offset by mips_swap_reloc_in, and here we copy it into     the addend field.  */  if (intern->r_type == MIPS_R_SWITCH      || (! intern->r_extern	  && (intern->r_type == MIPS_R_RELHI	      || intern->r_type == MIPS_R_RELLO)))    rptr->addend = intern->r_offset;  rptr->howto = &mips_howto_table[intern->r_type];}/* Make any adjustments needed to a reloc before writing it out.  None   are needed for MIPS.  */static voidmips_adjust_reloc_out (abfd, rel, intern)     bfd *abfd ATTRIBUTE_UNUSED;     const arelent *rel;     struct internal_reloc *intern;{  /* For a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or     MIPS_R_RELLO reloc, we must copy rel->addend into     intern->r_offset.  This will then be written out as the symbol     index by mips_ecoff_swap_reloc_out.  This operation parallels the     action of mips_adjust_reloc_in.  */  if (intern->r_type == MIPS_R_SWITCH      || (! intern->r_extern	  && (intern->r_type == MIPS_R_RELHI	      || intern->r_type == MIPS_R_RELLO)))    intern->r_offset = rel->addend;}/* ECOFF relocs are either against external symbols, or against   sections.  If we are producing relocateable output, and the reloc   is against an external symbol, and nothing has given us any   additional addend, the resulting reloc will also be against the   same symbol.  In such a case, we don't want to change anything   about the way the reloc is handled, since it will all be done at   final link time.  Rather than put special case code into   bfd_perform_relocation, all the reloc types use this howto   function.  It just short circuits the reloc if producing   relocateable output against an external symbol.  */static bfd_reloc_status_typemips_generic_reloc (abfd,		    reloc_entry,		    symbol,		    data,		    input_section,		    output_bfd,		    error_message)     bfd *abfd ATTRIBUTE_UNUSED;     arelent *reloc_entry;     asymbol *symbol;     PTR data ATTRIBUTE_UNUSED;     asection *input_section;     bfd *output_bfd;     char **error_message ATTRIBUTE_UNUSED;{  if (output_bfd != (bfd *) NULL      && (symbol->flags & BSF_SECTION_SYM) == 0      && reloc_entry->addend == 0)    {      reloc_entry->address += input_section->output_offset;      return bfd_reloc_ok;    }  return bfd_reloc_continue;}/* Do a REFHI relocation.  This has to be done in combination with a   REFLO reloc, because there is a carry from the REFLO to the REFHI.   Here we just save the information we need; we do the actual   relocation when we see the REFLO.  MIPS ECOFF requires that the   REFLO immediately follow the REFHI.  As a GNU extension, we permit   an arbitrary number of HI relocs to be associated with a single LO   reloc.  This extension permits gcc to output the HI and LO relocs   itself.  */struct mips_hi{  struct mips_hi *next;  bfd_byte *addr;  bfd_vma addend;};/* FIXME: This should not be a static variable.  */static struct mips_hi *mips_refhi_list;static bfd_reloc_status_typemips_refhi_reloc (abfd,		  reloc_entry,		  symbol,		  data,		  input_section,		  output_bfd,		  error_message)     bfd *abfd ATTRIBUTE_UNUSED;     arelent *reloc_entry;     asymbol *symbol;     PTR data;     asection *input_section;     bfd *output_bfd;     char **error_message ATTRIBUTE_UNUSED;{  bfd_reloc_status_type ret;  bfd_vma relocation;  struct mips_hi *n;  /* If we're relocating, and this an external symbol, we don't want     to change anything.  */  if (output_bfd != (bfd *) NULL      && (symbol->flags & BSF_SECTION_SYM) == 0      && reloc_entry->addend == 0)    {      reloc_entry->address += input_section->output_offset;      return bfd_reloc_ok;    }  ret = bfd_reloc_ok;  if (bfd_is_und_section (symbol->section)      && output_bfd == (bfd *) NULL)    ret = bfd_reloc_undefined;  if (bfd_is_com_section (symbol->section))    relocation = 0;  else    relocation = symbol->value;  relocation += symbol->section->output_section->vma;  relocation += symbol->section->output_offset;  relocation += reloc_entry->addend;  if (reloc_entry->address > input_section->_cooked_size)    return bfd_reloc_outofrange;  /* Save the information, and let REFLO do the actual relocation.  */  n = (struct mips_hi *) bfd_malloc (sizeof *n);  if (n == NULL)    return bfd_reloc_outofrange;  n->addr = (bfd_byte *) data + reloc_entry->address;  n->addend = relocation;  n->next = mips_refhi_list;  mips_refhi_list = n;  if (output_bfd != (bfd *) NULL)    reloc_entry->address += input_section->output_offset;  return ret;}/* Do a REFLO relocation.  This is a straightforward 16 bit inplace   relocation; this function exists in order to do the REFHI   relocation described above.  */static bfd_reloc_status_typemips_reflo_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;{  if (mips_refhi_list != NULL)    {      struct mips_hi *l;      l = mips_refhi_list;      while (l != NULL)	{	  unsigned long insn;	  unsigned long val;	  unsigned long vallo;	  struct mips_hi *next;	  /* Do the REFHI relocation.  Note that we actually don't	     need to know anything about the REFLO itself, except	     where to find the low 16 bits of the addend needed by the	     REFHI.  */	  insn = bfd_get_32 (abfd, l->addr);	  vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)		   & 0xffff);	  val = ((insn & 0xffff) << 16) + vallo;	  val += l->addend;	  /* The low order 16 bits are always treated as a signed	     value.  Therefore, a negative value in the low order bits	     requires an adjustment in the high order bits.  We need	     to make this adjustment in two ways: once for the bits we	     took from the data, and once for the bits we are putting	     back in to the data.  */	  if ((vallo & 0x8000) != 0)	    val -= 0x10000;	  if ((val & 0x8000) != 0)	    val += 0x10000;	  insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);	  bfd_put_32 (abfd, insn, l->addr);	  next = l->next;	  free (l);	  l = next;	}      mips_refhi_list = NULL;    }  /* Now do the REFLO reloc in the usual way.  */  return mips_generic_reloc (abfd, reloc_entry, symbol, data,			      input_section, output_bfd, error_message);}/* Do a GPREL relocation.  This is a 16 bit value which must become   the offset from the gp register.  */static bfd_reloc_status_typemips_gprel_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;{  boolean relocateable;  bfd_vma gp;  bfd_vma relocation;  unsigned long val;  unsigned long insn;  /* If we're relocating, and this is an external symbol with no     addend, we don't want to change anything.  We will only have an     addend if this is a newly created reloc, not read from an ECOFF     file.  */  if (output_bfd != (bfd *) NULL      && (symbol->flags & BSF_SECTION_SYM) == 0      && reloc_entry->addend == 0)    {      reloc_entry->address += input_section->output_offset;      return bfd_reloc_ok;    }  if (output_bfd != (bfd *) NULL)    relocateable = true;  else    {      relocateable = false;      output_bfd = symbol->section->output_section->owner;    }  if (bfd_is_und_section (symbol->section)      && relocateable == false)    return bfd_reloc_undefined;  /* We have to figure out the gp value, so that we can adjust the     symbol value correctly.  We look up the symbol _gp in the output     BFD.  If we can't find it, we're stuck.  We cache it in the ECOFF     target data.  We don't need to adjust the symbol value for an     external symbol if we are producing relocateable output.  */  gp = _bfd_get_gp_value (output_bfd);  if (gp == 0      && (relocateable == false	  || (symbol->flags & BSF_SECTION_SYM) != 0))    {      if (relocateable != false)	{	  /* Make up a value.  */	  gp = symbol->section->output_section->vma + 0x4000;	  _bfd_set_gp_value (output_bfd, gp);	}      else	{	  unsigned int count;	  asymbol **sym;	  unsigned int i;

⌨️ 快捷键说明

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