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

📄 elf32-arm.h

📁 基于4个mips核的noc设计
💻 H
📖 第 1 页 / 共 5 页
字号:
  struct elf32_arm_link_hash_table *hash_table;  char bind;  hash_table = elf32_arm_hash_table (link_info);  BFD_ASSERT (hash_table != NULL);  BFD_ASSERT (hash_table->bfd_of_glue_owner != NULL);  s = bfd_get_section_by_name    (hash_table->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);  BFD_ASSERT (s != NULL);  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 = elf_link_hash_lookup    (&(hash_table)->root, tmp_name, false, false, true);  if (myh != NULL)    {      /* We've already seen this guy.  */      free (tmp_name);      return;    }  _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner, tmp_name,			     BSF_GLOBAL, s, hash_table->thumb_glue_size + 1,				    NULL, true, false,				    (struct bfd_link_hash_entry **) &myh);  /* If we mark it 'Thumb', the disassembler will do a better job.  */  bind = ELF_ST_BIND (myh->type);  myh->type = ELF_ST_INFO (bind, STT_ARM_TFUNC);  free (tmp_name);#define CHANGE_TO_ARM "__%s_change_to_arm"#define BACK_FROM_ARM "__%s_back_from_arm"  /* Allocate another symbol to mark where we switch to Arm mode.  */  tmp_name = (char *) bfd_malloc (strlen (name) + strlen (CHANGE_TO_ARM) + 1);  BFD_ASSERT (tmp_name);  sprintf (tmp_name, CHANGE_TO_ARM, name);  myh = NULL;  _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner, tmp_name,			      BSF_LOCAL, s, hash_table->thumb_glue_size + 4,				    NULL, true, false,				    (struct bfd_link_hash_entry **) &myh);  free (tmp_name);  hash_table->thumb_glue_size += THUMB2ARM_GLUE_SIZE;  return;}/* Select a BFD to be used to hold the sections used by the glue code.   This function is called from the linker scripts in ld/emultempl/   {armelf/pe}.em  */booleanbfd_elf32_arm_get_bfd_for_interworking (abfd, info)     bfd *abfd;     struct bfd_link_info *info;{  struct elf32_arm_link_hash_table *globals;  flagword flags;  asection *sec;  /* If we are only performing a partial link do not bother     getting a bfd to hold the glue.  */  if (info->relocateable)    return true;  globals = elf32_arm_hash_table (info);  BFD_ASSERT (globals != NULL);  if (globals->bfd_of_glue_owner != NULL)    return true;  sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);  if (sec == NULL)    {      /* Note: we do not include the flag SEC_LINKER_CREATED, as this	 will prevent elf_link_input_bfd() from processing the contents	 of this section.  */      flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;      sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME);      if (sec == NULL	  || !bfd_set_section_flags (abfd, sec, flags)	  || !bfd_set_section_alignment (abfd, sec, 2))	return false;      /* Set the gc mark to prevent the section from being removed by garbage	 collection, despite the fact that no relocs refer to this section.  */      sec->gc_mark = 1;    }  sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);  if (sec == NULL)    {      flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;      sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME);      if (sec == NULL	  || !bfd_set_section_flags (abfd, sec, flags)	  || !bfd_set_section_alignment (abfd, sec, 2))	return false;      sec->gc_mark = 1;    }  /* Save the bfd for later use.  */  globals->bfd_of_glue_owner = abfd;  return true;}booleanbfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge)     bfd *abfd;     struct bfd_link_info *link_info;     int no_pipeline_knowledge;{  Elf_Internal_Shdr *symtab_hdr;  Elf_Internal_Rela *free_relocs = NULL;  Elf_Internal_Rela *irel, *irelend;  bfd_byte *contents = NULL;  bfd_byte *free_contents = NULL;  Elf32_External_Sym *extsyms = NULL;  Elf32_External_Sym *free_extsyms = NULL;  asection *sec;  struct elf32_arm_link_hash_table *globals;  /* If we are only performing a partial link do not bother     to construct any glue.  */  if (link_info->relocateable)    return true;  /* Here we have a bfd that is to be included on the link.  We have a hook     to do reloc rummaging, before section sizes are nailed down.  */  globals = elf32_arm_hash_table (link_info);  BFD_ASSERT (globals != NULL);  BFD_ASSERT (globals->bfd_of_glue_owner != NULL);  globals->no_pipeline_knowledge = no_pipeline_knowledge;  /* Rummage around all the relocs and map the glue vectors.  */  sec = abfd->sections;  if (sec == NULL)    return true;  for (; sec != NULL; sec = sec->next)    {      if (sec->reloc_count == 0)	continue;      symtab_hdr = &elf_tdata (abfd)->symtab_hdr;      /* Load the relocs.  */      irel = (_bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL,					(Elf_Internal_Rela *) NULL, false));      BFD_ASSERT (irel != 0);      irelend = irel + sec->reloc_count;      for (; irel < irelend; irel++)	{	  long r_type;	  unsigned long r_index;	  struct elf_link_hash_entry *h;	  r_type = ELF32_R_TYPE (irel->r_info);	  r_index = ELF32_R_SYM (irel->r_info);	  /* These are the only relocation types we care about.  */	  if (   r_type != R_ARM_PC24	      && r_type != R_ARM_THM_PC22)	    continue;	  /* Get the section contents if we haven't done so already.  */	  if (contents == NULL)	    {	      /* Get cached copy if it exists.  */	      if (elf_section_data (sec)->this_hdr.contents != NULL)		contents = elf_section_data (sec)->this_hdr.contents;	      else		{		  /* Go get them off disk.  */		  contents = (bfd_byte *) bfd_malloc (sec->_raw_size);		  if (contents == NULL)		    goto error_return;		  free_contents = contents;		  if (!bfd_get_section_contents (abfd, sec, contents,					      (file_ptr) 0, sec->_raw_size))		    goto error_return;		}	    }	  /* Read this BFD's symbols if we haven't done so already.  */	  if (extsyms == NULL)	    {	      /* Get cached copy if it exists.  */	      if (symtab_hdr->contents != NULL)		extsyms = (Elf32_External_Sym *) symtab_hdr->contents;	      else		{		  /* Go get them off disk.  */		  extsyms = ((Elf32_External_Sym *)			     bfd_malloc (symtab_hdr->sh_size));		  if (extsyms == NULL)		    goto error_return;		  free_extsyms = extsyms;		  if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0		      || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)			  != symtab_hdr->sh_size))		    goto error_return;		}	    }	  /* If the relocation is not against a symbol it cannot concern us.  */	  h = NULL;	  /* We don't care about local symbols.  */	  if (r_index < symtab_hdr->sh_info)	    continue;	  /* This is an external symbol.  */	  r_index -= symtab_hdr->sh_info;	  h = (struct elf_link_hash_entry *)	    elf_sym_hashes (abfd)[r_index];	  /* If the relocation is against a static symbol it must be within	     the current section and so cannot be a cross ARM/Thumb relocation.  */	  if (h == NULL)	    continue;	  switch (r_type)	    {	    case R_ARM_PC24:	      /* This one is a call from arm code.  We need to look up	         the target of the call.  If it is a thumb target, we	         insert glue.  */	      if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC)		record_arm_to_thumb_glue (link_info, h);	      break;	    case R_ARM_THM_PC22:	      /* This one is a call from thumb code.  We look	         up the target of the call.  If it is not a thumb                 target, we insert glue.  */	      if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC)		record_thumb_to_arm_glue (link_info, h);	      break;	    default:	      break;	    }	}    }  return true;error_return:  if (free_relocs != NULL)    free (free_relocs);  if (free_contents != NULL)    free (free_contents);  if (free_extsyms != NULL)    free (free_extsyms);  return false;}/* 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    /* FIXME: abort is probably not the right call. krk@cygnus.com  */    abort ();			/* error - not a valid branch instruction form.  */  return br_insn;}/* Thumb code calling an ARM function.  */static intelf32_thumb_to_arm_stub (info, name, input_bfd, output_bfd, input_section,			 hit_data, sym_sec, offset, addend, val)     struct bfd_link_info * info;     const char *           name;     bfd *                  input_bfd;     bfd *                  output_bfd;     asection *             input_section;     bfd_byte *             hit_data;     asection *             sym_sec;     bfd_vma                offset;     bfd_signed_vma         addend;     bfd_vma                val;{  asection * s = 0;  long int my_offset;  unsigned long int tmp;  long int ret_offset;  struct elf_link_hash_entry * myh;  struct elf32_arm_link_hash_table * globals;  myh = find_thumb_glue (info, name, input_bfd);  if (myh == NULL)    return false;  globals = elf32_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 (sym_sec != NULL	  && sym_sec->owner != NULL	  && !INTERWORK_FLAG (sym_sec->owner))	{	  _bfd_error_handler	    (_("%s(%s): warning: interworking not enabled."),	     bfd_get_filename (sym_sec->owner), name);	  _bfd_error_handler	    (_("  first occurrence: %s: thumb call to arm"),	     bfd_get_filename (input_bfd));	  return false;	}      --my_offset;      myh->root.u.def.value = my_offset;      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 =	/* Address of destination of the stub.  */	((bfd_signed_vma) val)	- ((bfd_signed_vma)	   /* Offset from the start of the current section to the start of the stubs.  */	   (s->output_offset	    /* Offset of the start of this stub from the start of the stubs.  */	    + my_offset	    /* Address of the start of the current section.  */	    + s->output_section->vma)	   /* The branch instruction is 4 bytes into the stub.  */	   + 4	   /* ARM branches work from the pc of the instruction + 8.  */	   + 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);

⌨️ 快捷键说明

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