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

📄 coff-mips.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
		    {		      /* This symbol is not being written out.  */		      if (! ((*info->callbacks->unattached_reloc)			     (info, h->root.root.string, input_bfd,			      input_section,			      int_rel.r_vaddr - input_section->vma)))			return false;		      int_rel.r_symndx = 0;		    }		  relocation = 0;		}	    }	  else	    {	      /* This is a relocation against a section.  Adjust the		 value by the amount the section moved.  */	      relocation = (s->output_section->vma			    + s->output_offset			    - s->vma);	    }	  relocation += addend;	  addend = 0;	  /* Adjust a PC relative relocation by removing the reference	     to the original address in the section and including the	     reference to the new address.  However, external RELHI	     and RELLO relocs are PC relative, but don't include any	     reference to the address.  The addend is merely an	     addend.  */	  if (howto->pc_relative	      && (! int_rel.r_extern		  || (int_rel.r_type != MIPS_R_RELHI		      && int_rel.r_type != MIPS_R_RELLO)))	    relocation -= (input_section->output_section->vma			   + input_section->output_offset			   - input_section->vma);	  /* Adjust the contents.  */	  if (relocation == 0)	    r = bfd_reloc_ok;	  else	    {	      if (int_rel.r_type != MIPS_R_REFHI		  && int_rel.r_type != MIPS_R_RELHI)		r = _bfd_relocate_contents (howto, input_bfd, relocation,					    (contents					     + adjust					     + int_rel.r_vaddr					     - input_section->vma));	      else		{		  mips_relocate_hi (&int_rel,				    use_lo ? &lo_int_rel : NULL,				    input_bfd, input_section, contents,				    adjust, relocation,				    int_rel.r_type == MIPS_R_RELHI);		  r = bfd_reloc_ok;		}	    }	  /* Adjust the reloc address.  */	  int_rel.r_vaddr += (input_section->output_section->vma			      + input_section->output_offset			      - input_section->vma);	  /* Save the changed reloc information.  */	  mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);	}      else	{	  /* We are producing a final executable.  */	  if (int_rel.r_extern)	    {	      /* This is a reloc against a symbol.  */	      if (h->root.type == bfd_link_hash_defined		  || h->root.type == bfd_link_hash_defweak)		{		  asection *hsec;		  hsec = h->root.u.def.section;		  relocation = (h->root.u.def.value				+ hsec->output_section->vma				+ hsec->output_offset);		}	      else		{		  if (! ((*info->callbacks->undefined_symbol)			 (info, h->root.root.string, input_bfd,			  input_section,			  int_rel.r_vaddr - input_section->vma, true)))		    return false;		  relocation = 0;		}	    }	  else	    {	      /* This is a reloc against a section.  */	      relocation = (s->output_section->vma			    + s->output_offset			    - s->vma);	      /* A PC relative reloc is already correct in the object		 file.  Make it look like a pcrel_offset relocation by		 adding in the start address.  */	      if (howto->pc_relative)		{		  if (int_rel.r_type != MIPS_R_RELHI || ! use_lo)		    relocation += int_rel.r_vaddr + adjust;		  else		    relocation += lo_int_rel.r_vaddr + adjust;		}	    }	  if (int_rel.r_type != MIPS_R_REFHI	      && int_rel.r_type != MIPS_R_RELHI)	    r = _bfd_final_link_relocate (howto,					  input_bfd,					  input_section,					  contents,					  (int_rel.r_vaddr					   - input_section->vma					   + adjust),					  relocation,					  addend);	  else	    {	      mips_relocate_hi (&int_rel,				use_lo ? &lo_int_rel : NULL,				input_bfd, input_section, contents, adjust,				relocation,				int_rel.r_type == MIPS_R_RELHI);	      r = bfd_reloc_ok;	    }	}      /* MIPS_R_JMPADDR requires peculiar overflow detection.  The	 instruction provides a 28 bit address (the two lower bits are	 implicit zeroes) which is combined with the upper four bits	 of the instruction address.  */      if (r == bfd_reloc_ok	  && int_rel.r_type == MIPS_R_JMPADDR	  && (((relocation		+ addend		+ (int_rel.r_extern ? 0 : s->vma))	       & 0xf0000000)	      != ((input_section->output_section->vma		   + input_section->output_offset		   + (int_rel.r_vaddr - input_section->vma)		   + adjust)		  & 0xf0000000)))	r = bfd_reloc_overflow;      if (r != bfd_reloc_ok)	{	  switch (r)	    {	    default:	    case bfd_reloc_outofrange:	      abort ();	    case bfd_reloc_overflow:	      {		const char *name;		if (int_rel.r_extern)		  name = h->root.root.string;		else		  name = bfd_section_name (input_bfd, s);		if (! ((*info->callbacks->reloc_overflow)		       (info, name, howto->name, (bfd_vma) 0,			input_bfd, input_section,			int_rel.r_vaddr - input_section->vma)))		  return false;	      }	      break;	    }	}    }  return true;}/* Read in the relocs for a section.  */static booleanmips_read_relocs (abfd, sec)     bfd *abfd;     asection *sec;{  struct ecoff_section_tdata *section_tdata;  section_tdata = ecoff_section_data (abfd, sec);  if (section_tdata == (struct ecoff_section_tdata *) NULL)    {      sec->used_by_bfd =	(PTR) bfd_alloc (abfd, sizeof (struct ecoff_section_tdata));      if (sec->used_by_bfd == NULL)	return false;      section_tdata = ecoff_section_data (abfd, sec);      section_tdata->external_relocs = NULL;      section_tdata->contents = NULL;      section_tdata->offsets = NULL;    }  if (section_tdata->external_relocs == NULL)    {      bfd_size_type external_relocs_size;      external_relocs_size = (ecoff_backend (abfd)->external_reloc_size			      * sec->reloc_count);      section_tdata->external_relocs =	(PTR) bfd_alloc (abfd, external_relocs_size);      if (section_tdata->external_relocs == NULL && external_relocs_size != 0)	return false;      if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0	  || (bfd_read (section_tdata->external_relocs, 1,			external_relocs_size, abfd)	      != external_relocs_size))	return false;    }  return true;}/* Relax a section when linking a MIPS ECOFF file.  This is used for   embedded PIC code, which always uses PC relative branches which   only have an 18 bit range on MIPS.  If a branch is not in range, we   generate a long instruction sequence to compensate.  Each time we   find a branch to expand, we have to check all the others again to   make sure they are still in range.  This is slow, but it only has   to be done when -relax is passed to the linker.   This routine figures out which branches need to expand; the actual   expansion is done in mips_relocate_section when the section   contents are relocated.  The information is stored in the offsets   field of the ecoff_section_tdata structure.  An offset of 1 means   that the branch must be expanded into a multi-instruction PC   relative branch (such an offset will only occur for a PC relative   branch to an external symbol).  Any other offset must be a multiple   of four, and is the amount to change the branch by (such an offset   will only occur for a PC relative branch within the same section).   We do not modify the section relocs or contents themselves so that   if memory usage becomes an issue we can discard them and read them   again.  The only information we must save in memory between this   routine and the mips_relocate_section routine is the table of   offsets.  */static booleanmips_relax_section (abfd, sec, info, again)     bfd *abfd;     asection *sec;     struct bfd_link_info *info;     boolean *again;{  struct ecoff_section_tdata *section_tdata;  bfd_byte *contents = NULL;  long *offsets;  struct external_reloc *ext_rel;  struct external_reloc *ext_rel_end;  unsigned int i;  /* Assume we are not going to need another pass.  */  *again = false;  /* If we are not generating an ECOFF file, this is much too     confusing to deal with.  */  if (info->hash->creator->flavour != bfd_get_flavour (abfd))    return true;  /* If there are no relocs, there is nothing to do.  */  if (sec->reloc_count == 0)    return true;  /* We are only interested in PC relative relocs, and why would there     ever be one from anything but the .text section?  */  if (strcmp (bfd_get_section_name (abfd, sec), ".text") != 0)    return true;  /* Read in the relocs, if we haven't already got them.  */  section_tdata = ecoff_section_data (abfd, sec);  if (section_tdata == (struct ecoff_section_tdata *) NULL      || section_tdata->external_relocs == NULL)    {      if (! mips_read_relocs (abfd, sec))	goto error_return;      section_tdata = ecoff_section_data (abfd, sec);    }  if (sec->_cooked_size == 0)    {      /* We must initialize _cooked_size only the first time we are	 called.  */      sec->_cooked_size = sec->_raw_size;    }  contents = section_tdata->contents;  offsets = section_tdata->offsets;  /* Look for any external PC relative relocs.  Internal PC relative     relocs are already correct in the object file, so they certainly     can not overflow.  */  ext_rel = (struct external_reloc *) section_tdata->external_relocs;  ext_rel_end = ext_rel + sec->reloc_count;  for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)    {      struct internal_reloc int_rel;      struct ecoff_link_hash_entry *h;      asection *hsec;      bfd_signed_vma relocation;      struct external_reloc *adj_ext_rel;      unsigned int adj_i;      unsigned long ext_count;      struct ecoff_link_hash_entry **adj_h_ptr;      struct ecoff_link_hash_entry **adj_h_ptr_end;      struct ecoff_value_adjust *adjust;      /* If we have already expanded this reloc, we certainly don't	 need to do it again.  */      if (offsets != (long *) NULL && offsets[i] == 1)	continue;      /* Quickly check that this reloc is external PCREL16.  */      if (bfd_header_big_endian (abfd))	{	  if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_BIG) == 0	      || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_BIG)		   >> RELOC_BITS3_TYPE_SH_BIG)		  != MIPS_R_PCREL16))	    continue;	}      else	{	  if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) == 0	      || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)		   >> RELOC_BITS3_TYPE_SH_LITTLE)		  != MIPS_R_PCREL16))	    continue;	}      mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);      h = ecoff_data (abfd)->sym_hashes[int_rel.r_symndx];      if (h == (struct ecoff_link_hash_entry *) NULL)	abort ();      if (h->root.type != bfd_link_hash_defined	  && h->root.type != bfd_link_hash_defweak)	{	  /* Just ignore undefined symbols.  These will presumably	     generate an error later in the link.  */	  continue;	}      /* Get the value of the symbol.  */      hsec = h->root.u.def.section;      relocation = (h->root.u.def.value		    + hsec->output_section->vma		    + hsec->output_offset);      /* Subtract out the current address.  */      relocation -= (sec->output_section->vma		     + sec->output_offset		     + (int_rel.r_vaddr - sec->vma));      /* The addend is stored in the object file.  In the normal case	 of ``bal symbol'', the addend will be -4.  It will only be	 different in the case of ``bal symbol+constant''.  To avoid	 always reading in the section contents, we don't check the	 addend in the object file (we could easily check the contents	 if we happen to have already read them in, but I fear that	 this could be confusing).  This means we will screw up if	 there is a branch to a symbol that is in range, but added to	 a constant which puts it out of range; in such a case the	 link will fail with a reloc overflow error.  Since the	 compiler will never generate such code, it should be easy	 enough to work around it by changing the assembly code in the	 source file.  */      relocation -= 4;      /* Now RELOCATION is the number we want to put in the object	 file.  See whether it fits.  */      if (relocation >= -0x20000 && relocation < 0x20000)	continue;      /* Now that we know this reloc needs work, which will rarely	 happen, go ahead and grab the section contents.  */      if (contents == (bfd_byte *) NULL)	{	  if (info->keep_memory)	    contents = (bfd_byte *) bfd_alloc (abfd, sec->_raw_size);	  else	    contents = (bfd_byte *) bfd_malloc ((size_t) sec->_raw_size);	  if (contents == (bfd_byte *) NULL)	    goto error_return;	  if (! bfd_get_section_contents (abfd, sec, (PTR) contents,					  (file_ptr) 0, sec->_raw_size))	    goto error_return;	  if (info->keep_memory)	    section_tdata->contents = contents;	}      /* We only support changing the bal instruction.  It would be	 possible to handle other PC relative branches, but some of	 them (the conditional branches) would require a different	 length instruction sequence which would complicate both this	 routine and mips_relax_pcrel16.  It could be written if	 somebody felt it were important.  Ignoring this reloc will	 presumably cause a reloc overflow error later on.  */      if (bfd_get_32 (abfd, contents + int_rel.r_vaddr - sec->vma)	  != 0x0411ffff) /* bgezal $0,. == bal .  */	continue;      /* Bother.  We need to expand this reloc, and we will need to	 make another relaxation pass since this change may put other	 relocs out of range.  We need to examine the local branches	 and we need to allocate memory to hold the offsets we must	 add to them.  We also need to adjust the values of all	 symbols in the object file following this locati

⌨️ 快捷键说明

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