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

📄 coff-arm.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
			- 8;		      tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);		      bfd_put_32 (output_bfd, tmp, contents + rel->r_vaddr				  - input_section->vma);		      done = 1;		    }                }#ifndef ARM_WINCE	      /* Note: We used to check for ARM_THUMB9 and ARM_THUMB12 */              else if (howto->type == ARM_THUMB23)                {                  if (   h->class == C_EXT		      || h->class == C_STAT		      || h->class == C_LABEL)		    {		      /* Thumb code calling an ARM function */		      asection *                         s = 0;		      long int                           my_offset;		      unsigned long int                  tmp;		      long int                           ret_offset;		      struct coff_link_hash_entry *      myh;		      struct coff_arm_link_hash_table *  globals;		      myh = find_thumb_glue (info, name, input_bfd);		      if (myh == NULL)			return false;		      globals = coff_arm_hash_table (info);		      BFD_ASSERT (globals != NULL);		      BFD_ASSERT (globals->bfd_of_glue_owner != NULL);		      my_offset = myh->root.u.def.value;		      s = bfd_get_section_by_name (globals->bfd_of_glue_owner,						   THUMB2ARM_GLUE_SECTION_NAME);		      BFD_ASSERT (s != NULL);		      BFD_ASSERT (s->contents != NULL);		      BFD_ASSERT (s->output_section != NULL);		      if ((my_offset & 0x01) == 0x01)			{			  if (h_sec->owner != NULL			      && INTERWORK_SET (h_sec->owner)			      && ! INTERWORK_FLAG (h_sec->owner)			      && ! globals->support_old_code)			    {			      _bfd_error_handler				/* xgettext:c-format */				(_("%s(%s): warning: interworking not enabled."),				 bfd_get_filename (h_sec->owner), name);			      _bfd_error_handler				/* xgettext:c-format */				(_("  first occurrence: %s: thumb call to arm"),				 bfd_get_filename (input_bfd));			      _bfd_error_handler				(_("  consider relinking with --support-old-code enabled"));			    }			  -- my_offset;			  myh->root.u.def.value = my_offset;			  if (globals->support_old_code)			    {			      bfd_put_16 (output_bfd, t2a1_push_insn,					  s->contents + my_offset);			      bfd_put_16 (output_bfd, t2a2_ldr_insn,					  s->contents + my_offset + 2);			      bfd_put_16 (output_bfd, t2a3_mov_insn,					  s->contents + my_offset + 4);			      bfd_put_16 (output_bfd, t2a4_bx_insn,					  s->contents + my_offset + 6);			      bfd_put_32 (output_bfd, t2a5_pop_insn,					  s->contents + my_offset + 8);			      bfd_put_32 (output_bfd, t2a6_bx_insn,					  s->contents + my_offset + 12);			      /* Store the address of the function in the last word of the stub.  */			      bfd_put_32 (output_bfd, h_val,					  s->contents + my_offset + 16);                              if (info->base_file)                                arm_emit_base_file_entry (info, output_bfd, s, my_offset + 16);			    }			  else			    {			      bfd_put_16 (output_bfd, t2a1_bx_pc_insn,					  s->contents + my_offset);			      bfd_put_16 (output_bfd, t2a2_noop_insn,					  s->contents + my_offset + 2);			      ret_offset =				((bfd_signed_vma) h_val)	/* Address of destination of the stub */				- ((bfd_signed_vma)				   (s->output_offset 		/* Offset from the start of the current section to the start of the stubs.  */				    + my_offset			/* Offset of the start of this stub from the start of the stubs.  */				    + s->output_section->vma) 	/* Address of the start of the current section.  */				   + 4				/* The branch instruction is 4 bytes into the stub.  */				   + 8);			/* ARM branches work from the pc of the instruction + 8.  */			      bfd_put_32 (output_bfd,					  t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF),					  s->contents + my_offset + 4);			    }			}		      BFD_ASSERT (my_offset <= globals->thumb_glue_size);		      /* Now go back and fix up the original BL insn to point			 to here.  */		      ret_offset =			s->output_offset			+ my_offset			- (input_section->output_offset			   + rel->r_vaddr)			-4;		      tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr					- input_section->vma);		      bfd_put_32 (output_bfd,				  insert_thumb_branch (tmp, ret_offset),				  contents + rel->r_vaddr				  - input_section->vma);		      done = 1;                    }                }#endif            }          /* If the relocation type and destination symbol does not             fall into one of the above categories, then we can just             perform a direct link.  */	  if (done)	    rstat = bfd_reloc_ok;	  else#endif /* THUMBEXTENSION */	    if (   h->root.type == bfd_link_hash_defined		|| h->root.type == bfd_link_hash_defweak)	    {	      asection *sec;	      sec = h->root.u.def.section;	      val = (h->root.u.def.value		     + sec->output_section->vma		     + sec->output_offset);	      }	  else if (! info->relocateable)	    {	      if (! ((*info->callbacks->undefined_symbol)		     (info, h->root.root.string, input_bfd, input_section,		      rel->r_vaddr - input_section->vma, true)))		return false;	    }	}      if (info->base_file)	{	  /* Emit a reloc if the backend thinks it needs it.  */	  if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))            arm_emit_base_file_entry (info, output_bfd, input_section, rel->r_vaddr);	}#if 1 /* THUMBEXTENSION */      if (done)	rstat = bfd_reloc_ok;#ifndef ARM_WINCE      /* Only perform this fix during the final link, not a relocatable link.  nickc@cygnus.com  */      else if (! info->relocateable	       && howto->type == ARM_THUMB23)        {          /* This is pretty much a copy of what the default             _bfd_final_link_relocate and _bfd_relocate_contents             routines do to perform a relocation, with special             processing for the split addressing of the Thumb BL             instruction.  Again, it would probably be simpler adding a             ThumbBRANCH23 specific macro expansion into the default             code.  */          bfd_vma address = rel->r_vaddr - input_section->vma;          if (address > input_section->_raw_size)	    rstat = bfd_reloc_outofrange;          else            {              bfd_vma         relocation       = val + addend;	      int             size             = bfd_get_reloc_size (howto);	      boolean         overflow         = false;	      bfd_byte *      location         = contents + address;	      bfd_vma         x                = bfd_get_32 (input_bfd, location);	      bfd_vma         src_mask         = 0x007FFFFE;	      bfd_signed_vma  reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;	      bfd_signed_vma  reloc_signed_min = ~reloc_signed_max;	      bfd_vma         check;	      bfd_signed_vma  signed_check;	      bfd_vma         add;	      bfd_signed_vma  signed_add;	      BFD_ASSERT (size == 4);              /* howto->pc_relative should be TRUE for type 14 BRANCH23.  */              relocation -= (input_section->output_section->vma                             + input_section->output_offset);              /* howto->pcrel_offset should be TRUE for type 14 BRANCH23.  */              relocation -= address;	      /* No need to negate the relocation with BRANCH23.  */	      /* howto->complain_on_overflow == complain_overflow_signed for BRANCH23.  */	      /* howto->rightshift == 1 */	      /* Drop unwanted bits from the value we are relocating to.  */	      check = relocation >> howto->rightshift;	      /* If this is a signed value, the rightshift just dropped		 leading 1 bits (assuming twos complement).  */	      if ((bfd_signed_vma) relocation >= 0)		signed_check = check;	      else		signed_check = (check				| ((bfd_vma) - 1				   & ~((bfd_vma) - 1 >> howto->rightshift)));	      /* Get the value from the object file.  */	      if (bfd_big_endian (input_bfd))		add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);	      else		add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));	      /* Get the value from the object file with an appropriate sign.		 The expression involving howto->src_mask isolates the upper		 bit of src_mask.  If that bit is set in the value we are		 adding, it is negative, and we subtract out that number times		 two.  If src_mask includes the highest possible bit, then we		 can not get the upper bit, but that does not matter since		 signed_add needs no adjustment to become negative in that		 case.  */	      signed_add = add;	      if ((add & (((~ src_mask) >> 1) & src_mask)) != 0)		signed_add -= (((~ src_mask) >> 1) & src_mask) << 1;	      /* howto->bitpos == 0 */	      /* Add the value from the object file, shifted so that it is a		 straight number.  */	      signed_check += signed_add;	      relocation   += signed_add;	      BFD_ASSERT (howto->complain_on_overflow == complain_overflow_signed);	      /* Assumes two's complement.  */	      if (   signed_check > reloc_signed_max		  || signed_check < reloc_signed_min)		overflow = true;	      /* For the BLX(1) instruction remove bit 0 of the adjusted offset.		 Bit 0 can only be set if the upper insn is at a half-word boundary,		 since the destination address, an ARM instruction, must always be		 on a word boundary.  The semantics of the BLX (1) instruction,		 however, are that bit 0 in the offset must always be 0, and the		 corresponding bit 1 in the target address will be set from bit		 1 of the source address.  */	      if ((x & 0x18000000) == 0x08000000)		relocation &= ~0x2;	      /* Put the relocation into the correct bits.  */	      if (bfd_big_endian (input_bfd))		relocation = (((relocation & 0xffe) >> 1)  | ((relocation << 4) & 0x07ff0000));	      else		relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));	      /* Add the relocation to the correct bits of X.  */	      x = ((x & ~howto->dst_mask) | relocation);	      /* Put the relocated value back in the object file.  */	      bfd_put_32 (input_bfd, x, location);	      rstat = overflow ? bfd_reloc_overflow : bfd_reloc_ok;            }        }#endif      else#endif /* THUMBEXTENSION */        rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,                                          contents,                                          rel->r_vaddr - input_section->vma,                                          val, addend);#if 1 /* THUMBEXTENSION */      /* FIXME:	 Is this the best way to fix up thumb addresses? krk@cygnus.com	 Probably not, but it works, and if it works it don't need fixing!  nickc@cygnus.com */      /* Only perform this fix during the final link, not a relocatable link.  nickc@cygnus.com  */      if (! info->relocateable	  && (rel->r_type == ARM_32 || rel->r_type == ARM_RVA32))	{	  /* Determine if we need to set the bottom bit of a relocated address	     because the address is the address of a Thumb code symbol.  */	  int patchit = false;	  if (h != NULL	      && (   h->class == C_THUMBSTATFUNC		  || h->class == C_THUMBEXTFUNC))	    {	      patchit = true;	    }	  else if (sym != NULL		   && sym->n_scnum > N_UNDEF)	    {	      /* No hash entry - use the symbol instead.  */	      if (   sym->n_sclass == C_THUMBSTATFUNC		  || sym->n_sclass == C_THUMBEXTFUNC)		patchit = true;	    }	  if (patchit)	    {	      bfd_byte * location = contents + rel->r_vaddr - input_section->vma;	      bfd_vma    x        = bfd_get_32 (input_bfd, location);	      bfd_put_32 (input_bfd, x | 1, location);	    }	}#endif /* THUMBEXTENSION */      switch (rstat)	{	default:	  abort ();	case bfd_reloc_ok:	  break;	case bfd_reloc_outofrange:	  (*_bfd_error_handler)	    (_("%s: bad reloc address 0x%lx in section `%s'"),	     bfd_get_filename (input_bfd),	     (unsigned long) rel->r_vaddr,	     bfd_get_section_name (input_bfd, input_section));	  return false;	case bfd_reloc_overflow:	  {	    const char *name;	    char buf[SYMNMLEN + 1];	    if (symndx == -1)	      name = "*ABS*";	    else if (h != NULL)	      name = h->root.root.string;	    else	      {		name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);		if (name == NULL)		  return false;	      }	    if (! ((*info->callbacks->reloc_overflow)		   (info, name, howto->name, (bfd_vma) 0, input_bfd,		    input_section, rel->r_vaddr - input_section->vma)))	      return false;	  }	}    }  return true;}#ifndef COFF_IMAGE_WITH_PEbooleanbfd_arm_allocate_interworking_sections (info)     struct bfd_link_info * info;{  asection *                        s;  bfd_byte *                        foo;  struct coff_arm_link_hash_table * globals;#if 0  static char                       test_char = '1';#endif  globals = coff_arm_hash_table (info);  BFD_ASSERT (globals != NULL);  if (globals->arm_glue_size != 0)    {      BFD_ASSERT (globals->bfd_of_glue_owner != NULL);      s = bfd_get_section_by_name	(globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);      BFD_ASSERT (s != NULL);      foo = (bfd_byte *) bfd_alloc	(globals->bfd_of_glue_owner, globals->arm_glue_size);#if 0      memset (foo, test_char, globals->arm_glue_size);#endif      s->_raw_size = s->_cooked_size = globals->arm_glue_size;      s->contents = foo;    }  if (globals->thumb_glue_size != 0)    {      BFD_ASSERT (globals->bfd_of_glue_owner != NULL);      s = bfd_get_section_by_name	(globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);      BFD_ASSERT (s != NULL);      foo = (bfd_byte *) bfd_alloc	(globals->bfd_of_glue_owner, globals->thumb_glue_size);#if 0      memset (foo, test_char, globals->thumb_glue_size);#endif      s->_raw_size = s->_cooked_size = globals->thumb_glue_size;      s->contents = foo;    }  return true;}static voidrecord_arm_to_thumb_glue (info, h)     struct bfd_link_info *        info;     struct coff_link_hash_entry * h;{  const char *                      name = h->root.root.string;  register asection *               s;  char *                            tmp_name;  struct coff_link_hash_entry *     myh;  struct coff_arm_link_hash_table * globals;  globals = coff_arm_hash_table (info);  BFD_ASSERT (globals != NULL);  BFD_ASSERT (globals->bfd_of_glue_owner != NULL);  s = bfd_get_section_by_name    (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);  BFD_ASSERT (s != NULL);  tmp_name = ((char *)	      bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1));

⌨️ 快捷键说明

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