coff-a29k.c

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

C
604
字号
    }  else    {      asymbol *ptr;      relent->sym_ptr_ptr = symbols + obj_convert(abfd)[reloc->r_symndx];      ptr = *(relent->sym_ptr_ptr);      if (ptr	  && bfd_asymbol_bfd(ptr) == abfd	  && ((ptr->flags & BSF_OLD_COMMON)== 0))	{	  relent->addend = 0;	}      else	{	  relent->addend = 0;	}      relent->address-= section->vma;      if (reloc->r_type == R_IHIHALF)	ihihalf_vaddr = relent->address;      else if (ihihalf_vaddr != (bfd_vma) -1)	abort ();    }}/* The reloc processing routine for the optimized COFF linker.  */static booleancoff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,			    contents, relocs, syms, sections)     bfd *output_bfd ATTRIBUTE_UNUSED;     struct bfd_link_info *info;     bfd *input_bfd;     asection *input_section;     bfd_byte *contents;     struct internal_reloc *relocs;     struct internal_syment *syms;     asection **sections;{  struct internal_reloc *rel;  struct internal_reloc *relend;  boolean hihalf;  bfd_vma hihalf_val;  /* If we are performing a relocateable link, we don't need to do a     thing.  The caller will take care of adjusting the reloc     addresses and symbol indices.  */  if (info->relocateable)    return true;  hihalf = false;  hihalf_val = 0;  rel = relocs;  relend = rel + input_section->reloc_count;  for (; rel < relend; rel++)    {      long symndx;      bfd_byte *loc;      struct coff_link_hash_entry *h;      struct internal_syment *sym;      asection *sec;      bfd_vma val;      boolean overflow;      unsigned long insn;      long signed_value;      unsigned long unsigned_value;      bfd_reloc_status_type rstat;      symndx = rel->r_symndx;      loc = contents + rel->r_vaddr - input_section->vma;      if (symndx == -1 || rel->r_type == R_IHCONST)	h = NULL;      else	h = obj_coff_sym_hashes (input_bfd)[symndx];      sym = NULL;      sec = NULL;      val = 0;      /* An R_IHCONST reloc does not have a symbol.  Instead, the         symbol index is an addend.  R_IHCONST is always used in         conjunction with R_IHHALF.  */      if (rel->r_type != R_IHCONST)	{	  if (h == NULL)	    {	      if (symndx == -1)		sec = bfd_abs_section_ptr;	      else		{		  sym = syms + symndx;		  sec = sections[symndx];		  val = (sec->output_section->vma			 + sec->output_offset			 + sym->n_value			 - sec->vma);		}	    }	  else	    {	      if (h->root.type == bfd_link_hash_defined		  || h->root.type == bfd_link_hash_defweak)		{		  sec = h->root.u.def.section;		  val = (h->root.u.def.value			 + sec->output_section->vma			 + sec->output_offset);		}	      else		{		  if (! ((*info->callbacks->undefined_symbol)			 (info, h->root.root.string, input_bfd, input_section,			  rel->r_vaddr - input_section->vma, true)))		    return false;		}	    }	  if (hihalf)	    {	      if (! ((*info->callbacks->reloc_dangerous)		     (info, _("missing IHCONST reloc"), input_bfd,		      input_section, rel->r_vaddr - input_section->vma)))		return false;	      hihalf = false;	    }	}      overflow = false;      switch (rel->r_type)	{	default:	  bfd_set_error (bfd_error_bad_value);	  return false;	case R_IREL:	  insn = bfd_get_32 (input_bfd, loc);	  /* Extract the addend.  */	  signed_value = EXTRACT_HWORD (insn);	  signed_value = SIGN_EXTEND_HWORD (signed_value);	  signed_value <<= 2;	  /* Unfortunately, there are two different versions of COFF	     a29k.  In the original AMD version, the value stored in	     the field for the R_IREL reloc is a simple addend.  In	     the GNU version, the value is the negative of the address	     of the reloc within section.  We try to cope here by	     assuming the AMD version, unless the addend is exactly	     the negative of the address; in the latter case we assume	     the GNU version.  This means that something like	         .text		 nop		 jmp i-4	     will fail, because the addend of -4 will happen to equal	     the negative of the address within the section.  The	     compiler will never generate code like this.	     At some point in the future we may want to take out this	     check.  */	  if (signed_value == - (long) (rel->r_vaddr - input_section->vma))	    signed_value = 0;	  /* Determine the destination of the jump.  */	  signed_value += val;	  if ((signed_value & ~0x3ffff) == 0)	    {	      /* We can use an absolute jump.  */	      insn |= (1 << 24);	    }	  else	    {	      /* Make the destination PC relative.  */	      signed_value -= (input_section->output_section->vma			       + input_section->output_offset			       + (rel->r_vaddr - input_section->vma));	      if (signed_value > 0x1ffff || signed_value < - 0x20000)		{		  overflow = true;		  signed_value = 0;		}	    }	  /* Put the adjusted value back into the instruction.  */	  signed_value >>= 2;	  insn = INSERT_HWORD (insn, signed_value);	  bfd_put_32 (input_bfd, (bfd_vma) insn, loc);	  break;	case R_ILOHALF:	  insn = bfd_get_32 (input_bfd, loc);	  unsigned_value = EXTRACT_HWORD (insn);	  unsigned_value += val;	  insn = INSERT_HWORD (insn, unsigned_value);	  bfd_put_32 (input_bfd, insn, loc);	  break;	case R_IHIHALF:	  /* Save the value for the R_IHCONST reloc.  */	  hihalf = true;	  hihalf_val = val;	  break;	case R_IHCONST:	  if (! hihalf)	    {	      if (! ((*info->callbacks->reloc_dangerous)		     (info, _("missing IHIHALF reloc"), input_bfd,		      input_section, rel->r_vaddr - input_section->vma)))		return false;	      hihalf_val = 0;	    }	  insn = bfd_get_32 (input_bfd, loc);	  unsigned_value = rel->r_symndx + hihalf_val;	  unsigned_value >>= 16;	  insn = INSERT_HWORD (insn, unsigned_value);	  bfd_put_32 (input_bfd, (bfd_vma) insn, loc);	  hihalf = false;	  break;	case R_BYTE:	case R_HWORD:	case R_WORD:	  rstat = _bfd_relocate_contents (howto_table + rel->r_type,					  input_bfd, val, loc);	  if (rstat == bfd_reloc_overflow)	    overflow = true;	  else if (rstat != bfd_reloc_ok)	    abort ();	  break;	}      if (overflow)	{	  const char *name;	  char buf[SYMNMLEN + 1];	  if (symndx == -1)	    name = "*ABS*";	  else if (h != NULL)	    name = h->root.root.string;	  else if (sym == NULL)	    name = "*unknown*";	  else if (sym->_n._n_n._n_zeroes == 0		   && sym->_n._n_n._n_offset != 0)	    name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;	  else	    {	      strncpy (buf, sym->_n._n_name, SYMNMLEN);	      buf[SYMNMLEN] = '\0';	      name = buf;	    }	  if (! ((*info->callbacks->reloc_overflow)		 (info, name, howto_table[rel->r_type].name, (bfd_vma) 0,		  input_bfd, input_section,		  rel->r_vaddr - input_section->vma)))	    return false;	}    }  return true;}#define coff_relocate_section coff_a29k_relocate_section/* We don't want to change the symndx of a R_IHCONST reloc, since it   is actually an addend, not a symbol index at all.  */static booleancoff_a29k_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)     bfd *obfd ATTRIBUTE_UNUSED;     struct bfd_link_info *info ATTRIBUTE_UNUSED;     bfd *ibfd ATTRIBUTE_UNUSED;     asection *sec ATTRIBUTE_UNUSED;     struct internal_reloc *irel;     boolean *adjustedp;{  if (irel->r_type == R_IHCONST)    *adjustedp = true;  else    *adjustedp = false;  return true;}#define coff_adjust_symndx coff_a29k_adjust_symndx#include "coffcode.h"CREATE_BIG_COFF_TARGET_VEC (a29kcoff_big_vec, "coff-a29k-big", 0, SEC_READONLY, '_', NULL)

⌨️ 快捷键说明

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