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

📄 coff-mips.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
      symndx_to_section[RELOC_SECTION_NONE] = NULL;      symndx_to_section[RELOC_SECTION_TEXT] =	bfd_get_section_by_name (input_bfd, ".text");      symndx_to_section[RELOC_SECTION_RDATA] =	bfd_get_section_by_name (input_bfd, ".rdata");      symndx_to_section[RELOC_SECTION_DATA] =	bfd_get_section_by_name (input_bfd, ".data");      symndx_to_section[RELOC_SECTION_SDATA] =	bfd_get_section_by_name (input_bfd, ".sdata");      symndx_to_section[RELOC_SECTION_SBSS] =	bfd_get_section_by_name (input_bfd, ".sbss");      symndx_to_section[RELOC_SECTION_BSS] =	bfd_get_section_by_name (input_bfd, ".bss");      symndx_to_section[RELOC_SECTION_INIT] =	bfd_get_section_by_name (input_bfd, ".init");      symndx_to_section[RELOC_SECTION_LIT8] =	bfd_get_section_by_name (input_bfd, ".lit8");      symndx_to_section[RELOC_SECTION_LIT4] =	bfd_get_section_by_name (input_bfd, ".lit4");      symndx_to_section[RELOC_SECTION_XDATA] = NULL;      symndx_to_section[RELOC_SECTION_PDATA] = NULL;      symndx_to_section[RELOC_SECTION_FINI] =	bfd_get_section_by_name (input_bfd, ".fini");      symndx_to_section[RELOC_SECTION_LITA] = NULL;      symndx_to_section[RELOC_SECTION_ABS] = NULL;      ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;    }  sym_hashes = ecoff_data (input_bfd)->sym_hashes;  gp = _bfd_get_gp_value (output_bfd);  if (gp == 0)    gp_undefined = true;  else    gp_undefined = false;  got_lo = false;  adjust = 0;  if (ecoff_section_data (input_bfd, input_section) == NULL)    offsets = NULL;  else    offsets = ecoff_section_data (input_bfd, input_section)->offsets;  ext_rel = (struct external_reloc *) external_relocs;  ext_rel_end = ext_rel + input_section->reloc_count;  for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)    {      struct internal_reloc int_rel;      boolean use_lo = false;      bfd_vma addend;      reloc_howto_type *howto;      struct ecoff_link_hash_entry *h = NULL;      asection *s = NULL;      bfd_vma relocation;      bfd_reloc_status_type r;      if (! got_lo)	mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);      else	{	  int_rel = lo_int_rel;	  got_lo = false;	}      BFD_ASSERT (int_rel.r_type		  < sizeof mips_howto_table / sizeof mips_howto_table[0]);      /* The REFHI and RELHI relocs requires special handling.  they	 must be followed by a REFLO or RELLO reloc, respectively, and	 the addend is formed from both relocs.  */      if (int_rel.r_type == MIPS_R_REFHI	  || int_rel.r_type == MIPS_R_RELHI)	{	  struct external_reloc *lo_ext_rel;	  /* As a GNU extension, permit an arbitrary number of REFHI             or RELHI relocs before the REFLO or RELLO reloc.  This             permits gcc to emit the HI and LO relocs itself.  */	  for (lo_ext_rel = ext_rel + 1;	       lo_ext_rel < ext_rel_end;	       lo_ext_rel++)	    {	      mips_ecoff_swap_reloc_in (input_bfd, (PTR) lo_ext_rel,					&lo_int_rel);	      if (lo_int_rel.r_type != int_rel.r_type)		break;	    }	  if (lo_ext_rel < ext_rel_end	      && (lo_int_rel.r_type		  == (int_rel.r_type == MIPS_R_REFHI		      ? MIPS_R_REFLO		      : MIPS_R_RELLO))	      && int_rel.r_extern == lo_int_rel.r_extern	      && int_rel.r_symndx == lo_int_rel.r_symndx)	    {	      use_lo = true;	      if (lo_ext_rel == ext_rel + 1)		got_lo = true;	    }	}      howto = &mips_howto_table[int_rel.r_type];      /* The SWITCH reloc must be handled specially.  This reloc is	 marks the location of a difference between two portions of an	 object file.  The symbol index does not reference a symbol,	 but is actually the offset from the reloc to the subtrahend	 of the difference.  This reloc is correct in the object file,	 and needs no further adjustment, unless we are relaxing.  If	 we are relaxing, we may have to add in an offset.  Since no	 symbols are involved in this reloc, we handle it completely	 here.  */      if (int_rel.r_type == MIPS_R_SWITCH)	{	  if (offsets != NULL	      && offsets[i] != 0)	    {	      r = _bfd_relocate_contents (howto, input_bfd,					  (bfd_vma) offsets[i],					  (contents					   + adjust					   + int_rel.r_vaddr					   - input_section->vma));	      BFD_ASSERT (r == bfd_reloc_ok);	    }	  continue;	}      if (int_rel.r_extern)	{	  h = sym_hashes[int_rel.r_symndx];	  /* If h is NULL, that means that there is a reloc against an	     external symbol which we thought was just a debugging	     symbol.  This should not happen.  */	  if (h == (struct ecoff_link_hash_entry *) NULL)	    abort ();	}      else	{	  if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)	    s = NULL;	  else	    s = symndx_to_section[int_rel.r_symndx];	  if (s == (asection *) NULL)	    abort ();	}      /* The GPREL reloc uses an addend: the difference in the GP	 values.  */      if (int_rel.r_type != MIPS_R_GPREL	  && int_rel.r_type != MIPS_R_LITERAL)	addend = 0;      else	{	  if (gp_undefined)	    {	      if (! ((*info->callbacks->reloc_dangerous)		     (info, _("GP relative relocation when GP not defined"),		      input_bfd, input_section,		      int_rel.r_vaddr - input_section->vma)))		return false;	      /* Only give the error once per link.  */	      gp = 4;	      _bfd_set_gp_value (output_bfd, gp);	      gp_undefined = false;	    }	  if (! int_rel.r_extern)	    {	      /* This is a relocation against a section.  The current		 addend in the instruction is the difference between		 INPUT_SECTION->vma and the GP value of INPUT_BFD.  We		 must change this to be the difference between the		 final definition (which will end up in RELOCATION)		 and the GP value of OUTPUT_BFD (which is in GP).  */	      addend = ecoff_data (input_bfd)->gp - gp;	    }	  else if (! info->relocateable		   || h->root.type == bfd_link_hash_defined		   || h->root.type == bfd_link_hash_defweak)	    {	      /* This is a relocation against a defined symbol.  The		 current addend in the instruction is simply the		 desired offset into the symbol (normally zero).  We		 are going to change this into a relocation against a		 defined symbol, so we want the instruction to hold		 the difference between the final definition of the		 symbol (which will end up in RELOCATION) and the GP		 value of OUTPUT_BFD (which is in GP).  */	      addend = - gp;	    }	  else	    {	      /* This is a relocation against an undefined or common		 symbol.  The current addend in the instruction is		 simply the desired offset into the symbol (normally		 zero).  We are generating relocateable output, and we		 aren't going to define this symbol, so we just leave		 the instruction alone.  */	      addend = 0;	    }	}      /* If we are relaxing, mips_relax_section may have set	 offsets[i] to some value.  A value of 1 means we must expand	 a PC relative branch into a multi-instruction of sequence,	 and any other value is an addend.  */      if (offsets != NULL	  && offsets[i] != 0)	{	  BFD_ASSERT (! info->relocateable);	  BFD_ASSERT (int_rel.r_type == MIPS_R_PCREL16		      || int_rel.r_type == MIPS_R_RELHI		      || int_rel.r_type == MIPS_R_RELLO);	  if (offsets[i] != 1)	    addend += offsets[i];	  else	    {	      bfd_byte *here;	      BFD_ASSERT (int_rel.r_extern			  && int_rel.r_type == MIPS_R_PCREL16);	      /* Move the rest of the instructions up.  */	      here = (contents		      + adjust		      + int_rel.r_vaddr		      - input_section->vma);	      memmove (here + PCREL16_EXPANSION_ADJUSTMENT, here,		       (size_t) (input_section->_raw_size				 - (int_rel.r_vaddr - input_section->vma)));	      /* Generate the new instructions.  */	      if (! mips_relax_pcrel16 (info, input_bfd, input_section,					h, here,					(input_section->output_section->vma					 + input_section->output_offset					 + (int_rel.r_vaddr					    - input_section->vma)					 + adjust)))		return false;	      /* We must adjust everything else up a notch.  */	      adjust += PCREL16_EXPANSION_ADJUSTMENT;	      /* mips_relax_pcrel16 handles all the details of this		 relocation.  */	      continue;	    }	}      /* If we are relaxing, and this is a reloc against the .text	 segment, we may need to adjust it if some branches have been	 expanded.  The reloc types which are likely to occur in the	 .text section are handled efficiently by mips_relax_section,	 and thus do not need to be handled here.  */      if (ecoff_data (input_bfd)->debug_info.adjust != NULL	  && ! int_rel.r_extern	  && int_rel.r_symndx == RELOC_SECTION_TEXT	  && (strcmp (bfd_get_section_name (input_bfd, input_section),		      ".text") != 0	      || (int_rel.r_type != MIPS_R_PCREL16		  && int_rel.r_type != MIPS_R_SWITCH		  && int_rel.r_type != MIPS_R_RELHI		  && int_rel.r_type != MIPS_R_RELLO)))	{	  bfd_vma adr;	  struct ecoff_value_adjust *a;	  /* We need to get the addend so that we know whether we need	     to adjust the address.  */	  BFD_ASSERT (int_rel.r_type == MIPS_R_REFWORD);	  adr = bfd_get_32 (input_bfd,			    (contents			     + adjust			     + int_rel.r_vaddr			     - input_section->vma));	  for (a = ecoff_data (input_bfd)->debug_info.adjust;	       a != (struct ecoff_value_adjust *) NULL;	       a = a->next)	    {	      if (adr >= a->start && adr < a->end)		addend += a->adjust;	    }	}      if (info->relocateable)	{	  /* We are generating relocateable output, and must convert	     the existing reloc.  */	  if (int_rel.r_extern)	    {	      if ((h->root.type == bfd_link_hash_defined		   || h->root.type == bfd_link_hash_defweak)		  && ! bfd_is_abs_section (h->root.u.def.section))		{		  const char *name;		  /* This symbol is defined in the output.  Convert		     the reloc from being against the symbol to being		     against the section.  */		  /* Clear the r_extern bit.  */		  int_rel.r_extern = 0;		  /* Compute a new r_symndx value.  */		  s = h->root.u.def.section;		  name = bfd_get_section_name (output_bfd,					       s->output_section);		  int_rel.r_symndx = -1;		  switch (name[1])		    {		    case 'b':		      if (strcmp (name, ".bss") == 0)			int_rel.r_symndx = RELOC_SECTION_BSS;		      break;		    case 'd':		      if (strcmp (name, ".data") == 0)			int_rel.r_symndx = RELOC_SECTION_DATA;		      break;		    case 'f':		      if (strcmp (name, ".fini") == 0)			int_rel.r_symndx = RELOC_SECTION_FINI;		      break;		    case 'i':		      if (strcmp (name, ".init") == 0)			int_rel.r_symndx = RELOC_SECTION_INIT;		      break;		    case 'l':		      if (strcmp (name, ".lit8") == 0)			int_rel.r_symndx = RELOC_SECTION_LIT8;		      else if (strcmp (name, ".lit4") == 0)			int_rel.r_symndx = RELOC_SECTION_LIT4;		      break;		    case 'r':		      if (strcmp (name, ".rdata") == 0)			int_rel.r_symndx = RELOC_SECTION_RDATA;		      break;		    case 's':		      if (strcmp (name, ".sdata") == 0)			int_rel.r_symndx = RELOC_SECTION_SDATA;		      else if (strcmp (name, ".sbss") == 0)			int_rel.r_symndx = RELOC_SECTION_SBSS;		      break;		    case 't':		      if (strcmp (name, ".text") == 0)			int_rel.r_symndx = RELOC_SECTION_TEXT;		      break;		    }		  if (int_rel.r_symndx == -1)		    abort ();		  /* Add the section VMA and the symbol value.  */		  relocation = (h->root.u.def.value				+ s->output_section->vma				+ s->output_offset);		  /* For a PC relative relocation, the object file		     currently holds just the addend.  We must adjust		     by the address to get the right value.  */		  if (howto->pc_relative)		    {		      relocation -= int_rel.r_vaddr - input_section->vma;		      /* If we are converting a RELHI or RELLO reloc			 from being against an external symbol to			 being against a section, we must put a			 special value into the r_offset field.  This			 value is the old addend.  The r_offset for			 both the RELHI and RELLO relocs are the same,			 and we set both when we see RELHI.  */		      if (int_rel.r_type == MIPS_R_RELHI)			{			  long addhi, addlo;			  addhi = bfd_get_32 (input_bfd,					      (contents					       + adjust					       + int_rel.r_vaddr					       - input_section->vma));			  addhi &= 0xffff;			  if (addhi & 0x8000)			    addhi -= 0x10000;			  addhi <<= 16;			  if (! use_lo)			    addlo = 0;			  else			    {			      addlo = bfd_get_32 (input_bfd,						  (contents						   + adjust						   + lo_int_rel.r_vaddr						   - input_section->vma));			      addlo &= 0xffff;			      if (addlo & 0x8000)				addlo -= 0x10000;			      lo_int_rel.r_offset = addhi + addlo;			    }			  int_rel.r_offset = addhi + addlo;			}		    }		  h = NULL;		}	      else		{		  /* Change the symndx value to the right one for the		     output BFD.  */		  int_rel.r_symndx = h->indx;		  if (int_rel.r_symndx == -1)

⌨️ 快捷键说明

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