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

📄 coff-arm.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
static voidarm_emit_base_file_entry (info, output_bfd, input_section, reloc_offset)      struct bfd_link_info *info;      bfd *output_bfd;      asection *input_section;      bfd_vma reloc_offset;{  bfd_vma addr = reloc_offset                - input_section->vma                + input_section->output_offset                  + input_section->output_section->vma;  if (coff_data(output_bfd)->pe)     addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;  fwrite (&addr, 1, sizeof (addr), (FILE *) info->base_file);}/* The thumb form of a long branch is a bit finicky, because the offset   encoding is split over two fields, each in it's own instruction. They   can occur in any order. So given a thumb form of long branch, and an   offset, insert the offset into the thumb branch and return finished   instruction.   It takes two thumb instructions to encode the target address. Each has   11 bits to invest. The upper 11 bits are stored in one (identifed by   H-0.. see below), the lower 11 bits are stored in the other (identified   by H-1).   Combine together and shifted left by 1 (it's a half word address) and   there you have it.     Op: 1111 = F,     H-0, upper address-0 = 000     Op: 1111 = F,     H-1, lower address-0 = 800   They can be ordered either way, but the arm tools I've seen always put   the lower one first. It probably doesn't matter. krk@cygnus.com   XXX:  Actually the order does matter.  The second instruction (H-1)   moves the computed address into the PC, so it must be the second one   in the sequence.  The problem, however is that whilst little endian code   stores the instructions in HI then LOW order, big endian code does the   reverse.  nickc@cygnus.com  */#define LOW_HI_ORDER 0xF800F000#define HI_LOW_ORDER 0xF000F800static insn32insert_thumb_branch (br_insn, rel_off)     insn32 br_insn;     int rel_off;{  unsigned int low_bits;  unsigned int high_bits;  BFD_ASSERT((rel_off & 1) != 1);  rel_off >>= 1;                              /* half word aligned address */  low_bits = rel_off & 0x000007FF;            /* the bottom 11 bits */  high_bits = (rel_off >> 11) & 0x000007FF;   /* the top 11 bits */  if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)    br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;  else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER)    br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;  else    abort (); /* error - not a valid branch instruction form */  /* FIXME: abort is probably not the right call. krk@cygnus.com */  return br_insn;}static struct coff_link_hash_entry *find_thumb_glue (info, name, input_bfd)     struct bfd_link_info * info;     CONST char *           name;     bfd *                  input_bfd;{  char *                        tmp_name;  struct coff_link_hash_entry * myh;  tmp_name = ((char *)	 bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1));  BFD_ASSERT (tmp_name);  sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);  myh = coff_link_hash_lookup    (coff_hash_table (info), tmp_name, false, false, true);  if (myh == NULL)    /* xgettext:c-format */    _bfd_error_handler (_("%s: unable to find THUMB glue '%s' for `%s'"),			bfd_get_filename (input_bfd), tmp_name, name);  free (tmp_name);  return myh;}static struct coff_link_hash_entry *find_arm_glue (info, name, input_bfd)     struct bfd_link_info * info;     CONST char *           name;     bfd *                  input_bfd;{  char *                        tmp_name;  struct coff_link_hash_entry * myh;  tmp_name = ((char *)	      bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1));  BFD_ASSERT (tmp_name);  sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);  myh = coff_link_hash_lookup    (coff_hash_table (info), tmp_name, false, false, true);  if (myh == NULL)    /* xgettext:c-format */    _bfd_error_handler (_("%s: unable to find ARM glue '%s' for `%s'"),			bfd_get_filename (input_bfd), tmp_name, name);  free (tmp_name);  return myh;}/*  ARM->Thumb glue:       .arm       __func_from_arm:	     ldr r12, __func_addr	     bx  r12       __func_addr:            .word func    @ behave as if you saw a ARM_32 reloc*/#define ARM2THUMB_GLUE_SIZE 12static const insn32 a2t1_ldr_insn       = 0xe59fc000;static const insn32 a2t2_bx_r12_insn    = 0xe12fff1c;static const insn32 a2t3_func_addr_insn = 0x00000001;/*   Thumb->ARM:				Thumb->(non-interworking aware) ARM   .thumb				.thumb   .align 2				.align 2      __func_from_thumb:		   __func_from_thumb:	   bx pc				push {r6, lr}	   nop					ldr  r6, __func_addr   .arm						mov  lr, pc      __func_change_to_arm:			bx   r6	   b func   			.arm					   __func_back_to_thumb:   		  				ldmia r13! {r6, lr}   					        bx    lr   					   __func_addr:					        .word	func*/#define THUMB2ARM_GLUE_SIZE (globals->support_old_code ? 20 : 8)static const insn16 t2a1_bx_pc_insn = 0x4778;static const insn16 t2a2_noop_insn  = 0x46c0;static const insn32 t2a3_b_insn     = 0xea000000;static const insn16 t2a1_push_insn  = 0xb540;static const insn16 t2a2_ldr_insn   = 0x4e03;static const insn16 t2a3_mov_insn   = 0x46fe;static const insn16 t2a4_bx_insn    = 0x4730;static const insn32 t2a5_pop_insn   = 0xe8bd4040;static const insn32 t2a6_bx_insn    = 0xe12fff1e;/* TODO:     We should really create new local (static) symbols in destination     object for each stub we create.  We should also create local     (static) symbols within the stubs when switching between ARM and     Thumb code.  This will ensure that the debugger and disassembler     can present a better view of stubs.     We can treat stubs like literal sections, and for the THUMB9 ones     (short addressing range) we should be able to insert the stubs     between sections. i.e. the simplest approach (since relocations     are done on a section basis) is to dump the stubs at the end of     processing a section. That way we can always try and minimise the     offset to and from a stub. However, this does not map well onto     the way that the linker/BFD does its work: mapping all input     sections to output sections via the linker script before doing     all the processing.     Unfortunately it may be easier to just to disallow short range     Thumb->ARM stubs (i.e. no conditional inter-working branches,     only branch-and-link (BL) calls.  This will simplify the processing     since we can then put all of the stubs into their own section.  TODO:     On a different subject, rather than complaining when a     branch cannot fit in the number of bits available for the     instruction we should generate a trampoline stub (needed to     address the complete 32bit address space).  *//* The standard COFF backend linker does not cope with the special   Thumb BRANCH23 relocation.  The alternative would be to split the   BRANCH23 into seperate HI23 and LO23 relocations. However, it is a   bit simpler simply providing our own relocation driver.  *//* The reloc processing routine for the ARM/Thumb COFF linker.  NOTE:   This code is a very slightly modified copy of   _bfd_coff_generic_relocate_section.  It would be a much more   maintainable solution to have a MACRO that could be expanded within   _bfd_coff_generic_relocate_section that would only be provided for   ARM/Thumb builds.  It is only the code marked THUMBEXTENSION that   is different from the original.  */static booleancoff_arm_relocate_section (output_bfd, info, input_bfd, input_section,                           contents, relocs, syms, sections)     bfd *output_bfd;     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;  rel = relocs;  relend = rel + input_section->reloc_count;  for (; rel < relend; rel++)    {      int                            done = 0;      long                           symndx;      struct coff_link_hash_entry *  h;      struct internal_syment *       sym;      bfd_vma                        addend;      bfd_vma                        val;      reloc_howto_type *             howto;      bfd_reloc_status_type          rstat;      bfd_vma                        h_val;      symndx = rel->r_symndx;      if (symndx == -1)	{	  h = NULL;	  sym = NULL;	}      else	{	  h = obj_coff_sym_hashes (input_bfd)[symndx];	  sym = syms + symndx;	}      /* COFF treats common symbols in one of two ways.  Either the         size of the symbol is included in the section contents, or it         is not.  We assume that the size is not included, and force         the rtype_to_howto function to adjust the addend as needed.  */      if (sym != NULL && sym->n_scnum != 0)	addend = - sym->n_value;      else	addend = 0;      howto = coff_rtype_to_howto (input_bfd, input_section, rel, h,				       sym, &addend);      if (howto == NULL)	return false;      /* The relocation_section function will skip pcrel_offset relocs         when doing a relocateable link.  However, we want to convert         ARM26 to ARM26D relocs if possible.  We return a fake howto in         this case without pcrel_offset set, and adjust the addend to         compensate.  */      if (rel->r_type == ARM_26          && h != NULL          && info->relocateable          && (h->root.type == bfd_link_hash_defined	      || h->root.type == bfd_link_hash_defweak)          && h->root.u.def.section->output_section == input_section->output_section)        {          static reloc_howto_type fake_arm26_reloc =	    HOWTO (ARM_26,    	       2,    	       2,    	       24,    	       true,    	       0,    	       complain_overflow_signed,    	       aoutarm_fix_pcrel_26 ,    	       "ARM_26",    	       false,    	       0x00ffffff,    	       0x00ffffff,    	       false);          addend -= rel->r_vaddr - input_section->vma;          howto = &fake_arm26_reloc;        }#ifdef ARM_WINCE      /* MS ARM-CE makes the reloc relative to the opcode's pc, not	 the next opcode's pc, so is off by one.  */      if (howto->pc_relative && !info->relocateable)	addend -= 8;#endif      /* If we are doing a relocateable link, then we can just ignore         a PC relative reloc that is pcrel_offset.  It will already         have the correct value.  If this is not a relocateable link,         then we should ignore the symbol value.  */      if (howto->pc_relative && howto->pcrel_offset)        {          if (info->relocateable)            continue;	  /* FIXME - it is not clear which targets need this next test	     and which do not.  It is known that it is needed for the	     VXworks target (hence the #ifdef), but it is also known	     that it was supressed for other (arm) targets.  This ought	     to be sorted out one day.  */#ifdef VXWORKS	  /* We must not ignore the symbol value.  If the symbol is	     within the same section, the relocation should have already	     been fixed, but if it is not, we'll be handed a reloc into	     the beginning of the symbol's section, so we must not cancel	     out the symbol's value, otherwise we'll be adding it in	     twice.  */          if (sym != NULL && sym->n_scnum != 0)            addend += sym->n_value;#endif        }      val = 0;      if (h == NULL)	{	  asection *sec;	  if (symndx == -1)	    {	      sec = bfd_abs_section_ptr;	      val = 0;	    }	  else	    {	      sec = sections[symndx];              val = (sec->output_section->vma		     + sec->output_offset		     + sym->n_value		     - sec->vma);	    }	}      else	{#if 1 /* THUMBEXTENSION */          /* We don't output the stubs if we are generating a             relocatable output file, since we may as well leave the             stub generation to the final linker pass. If we fail to	     verify that the name is defined, we'll try to build stubs	     for an undefined name...  */          if (! info->relocateable	      && (   h->root.type == bfd_link_hash_defined		  || h->root.type == bfd_link_hash_defweak))            {	      asection *   h_sec = h->root.u.def.section;	      const char * name  = h->root.root.string;	      /* h locates the symbol referenced in the reloc.  */	      h_val = (h->root.u.def.value		       + h_sec->output_section->vma		       + h_sec->output_offset);              if (howto->type == ARM_26)                {                  if (   h->class == C_THUMBSTATFUNC		      || h->class == C_THUMBEXTFUNC)		    {		      /* Arm code calling a Thumb function */		      unsigned long int                 tmp;		      long int                          my_offset;		      asection *                        s;		      long int                          ret_offset;		      struct coff_link_hash_entry *     myh;		      struct coff_arm_link_hash_table * globals;		      myh = find_arm_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,						  ARM2THUMB_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))			    {			      _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: arm call to thumb"),				 bfd_get_filename (input_bfd));			    }			  --my_offset;			  myh->root.u.def.value = my_offset;			  bfd_put_32 (output_bfd, a2t1_ldr_insn,				      s->contents + my_offset);			  bfd_put_32 (output_bfd, a2t2_bx_r12_insn,				      s->contents + my_offset + 4);			  /* It's a thumb address.  Add the low order bit.  */			  bfd_put_32 (output_bfd, h_val | a2t3_func_addr_insn,				      s->contents + my_offset + 8);                          if (info->base_file)                            arm_emit_base_file_entry (info, output_bfd, s,                                                            my_offset + 8);			}		      BFD_ASSERT (my_offset <= globals->arm_glue_size);		      tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr					- input_section->vma);		      tmp = tmp & 0xFF000000;		      /* Somehow these are both 4 too far, so subtract 8.  */		      ret_offset =			s->output_offset			+ my_offset			+ s->output_section->vma			- (input_section->output_offset			   + input_section->output_section->vma			   + rel->r_vaddr)

⌨️ 快捷键说明

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