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

📄 elf-m10300.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
		  free_relocs = NULL;		}	      /* Cache or free any memory we allocated for the contents.  */	      if (free_contents != NULL)		{		  if (! link_info->keep_memory)		    free (free_contents);		  else		    {		      /* Cache the section contents for elf_link_input_bfd.  */		      elf_section_data (section)->this_hdr.contents = contents;		    }		  free_contents = NULL;		}	    }	  /* Cache or free any memory we allocated for the symbols.  */	  if (free_extsyms != NULL)	    {	      if (! link_info->keep_memory)		free (free_extsyms);	      else		{		  /* Cache the symbols for elf_link_input_bfd.  */		  symtab_hdr->contents = extsyms;		}	      free_extsyms = NULL;	    }	}    }  /* (Re)initialize for the basic instruction shortening/relaxing pass.  */  contents = NULL;  extsyms = NULL;  internal_relocs = NULL;  free_relocs = NULL;  free_contents = NULL;  free_extsyms = NULL;  /* We don't have to do anything for a relocateable link, if     this section does not have relocs, or if this is not a     code section.  */  if (link_info->relocateable      || (sec->flags & SEC_RELOC) == 0      || sec->reloc_count == 0      || (sec->flags & SEC_CODE) == 0)    return true;  /* If this is the first time we have been called for this section,     initialize the cooked size.  */  if (sec->_cooked_size == 0)    sec->_cooked_size = sec->_raw_size;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  /* Get a copy of the native relocations.  */  internal_relocs = (_bfd_elf32_link_read_relocs		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,		      link_info->keep_memory));  if (internal_relocs == NULL)    goto error_return;  if (! link_info->keep_memory)    free_relocs = internal_relocs;  /* Walk through them looking for relaxing opportunities.  */  irelend = internal_relocs + sec->reloc_count;  for (irel = internal_relocs; irel < irelend; irel++)    {      bfd_vma symval;      struct elf32_mn10300_link_hash_entry *h = NULL;      /* If this isn't something that can be relaxed, then ignore	 this reloc.  */      if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_NONE	  || ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_8	  || ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_MAX)	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;	    }	}      /* Get the value of the symbol referred to by the reloc.  */      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)	{	  Elf_Internal_Sym isym;	  asection *sym_sec = NULL;	  const char *sym_name;	  char *new_name;	  /* A local symbol.  */	  bfd_elf32_swap_symbol_in (abfd,				    extsyms + ELF32_R_SYM (irel->r_info),				    &isym);	  if (isym.st_shndx == SHN_UNDEF)	    sym_sec = bfd_und_section_ptr;	  else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)	    sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);	  else if (isym.st_shndx == SHN_ABS)	    sym_sec = bfd_abs_section_ptr;	  else if (isym.st_shndx == SHN_COMMON)	    sym_sec = bfd_com_section_ptr;	  else	    abort ();	  symval = (isym.st_value		    + sym_sec->output_section->vma		    + sym_sec->output_offset);	  sym_name = bfd_elf_string_from_elf_section (abfd,						      symtab_hdr->sh_link,						      isym.st_name);	  /* Tack on an ID so we can uniquely identify this	     local symbol in the global hash table.  */	  new_name = bfd_malloc (strlen (sym_name) + 10);	  if (new_name == 0)	    goto error_return;	  sprintf (new_name, "%s_%08x", sym_name, (int) sym_sec);	  sym_name = new_name;	  h = (struct elf32_mn10300_link_hash_entry *)		elf_link_hash_lookup (&hash_table->static_hash_table->root,				      sym_name, false, false, false);	  free (new_name);	}      else	{	  unsigned long indx;	  /* An external symbol.  */	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;	  h = (struct elf32_mn10300_link_hash_entry *)		(elf_sym_hashes (abfd)[indx]);	  BFD_ASSERT (h != NULL);	  if (h->root.root.type != bfd_link_hash_defined	      && h->root.root.type != bfd_link_hash_defweak)	    {	      /* This appears to be a reference to an undefined 		symbol.  Just ignore it--it will be caught by the 		regular reloc processing.  */	      continue;	    }	  symval = (h->root.root.u.def.value		    + h->root.root.u.def.section->output_section->vma		    + h->root.root.u.def.section->output_offset);	}      /* For simplicity of coding, we are going to modify the section	 contents, the section relocs, and the BFD symbol table.  We	 must tell the rest of the code not to free up this	 information.  It would be possible to instead create a table	 of changes which have to be made, as is done in coff-mips.c;	 that would be more work, but would require less memory when	 the linker is run.  */      /* Try to turn a 32bit pc-relative branch/call into a 16bit pc-relative	 branch/call, also deal with "call" -> "calls" conversions and	 insertion of prologue data into "call" instructions.  */      if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_PCREL32)	{	  bfd_vma value = symval;	  /* If we've got a "call" instruction that needs to be turned	     into a "calls" instruction, do so now.  It saves a byte.  */	  if (h && (h->flags & MN10300_CONVERT_CALL_TO_CALLS))	    {	      unsigned char code;	      /* Get the opcode.  */	      code = bfd_get_8 (abfd, contents + irel->r_offset - 1);	      /* Make sure we're working with a "call" instruction!  */	      if (code == 0xdd)		{		  /* Note that we've changed the relocs, section contents,		     etc.  */		  elf_section_data (sec)->relocs = internal_relocs;		  free_relocs = NULL;		  elf_section_data (sec)->this_hdr.contents = contents;		  free_contents = NULL;		  symtab_hdr->contents = (bfd_byte *) extsyms;		  free_extsyms = NULL;		  /* Fix the opcode.  */		  bfd_put_8 (abfd, 0xfc, contents + irel->r_offset - 1);		  bfd_put_8 (abfd, 0xff, contents + irel->r_offset);		  /* Fix irel->r_offset and irel->r_addend.  */		  irel->r_offset += 1;		  irel->r_addend += 1;		  /* Delete one byte of data.  */		  if (!mn10300_elf_relax_delete_bytes (abfd, sec,						       irel->r_offset + 3, 1))		    goto error_return;		  /* That will change things, so, we should relax again.		     Note that this is not required, and it may be slow.  */		  *again = true;		}	    }	  else if (h)	    {	      /* We've got a "call" instruction which needs some data		 from target function filled in.  */	      unsigned char code;	      /* Get the opcode.  */	      code = bfd_get_8 (abfd, contents + irel->r_offset - 1);	      /* Insert data from the target function into the "call"		 instruction if needed.  */	      if (code == 0xdd)		{		  bfd_put_8 (abfd, h->movm_args, contents + irel->r_offset + 4);		  bfd_put_8 (abfd, h->stack_size + h->movm_stack_size,			     contents + irel->r_offset + 5);		}	    }	  /* Deal with pc-relative gunk.  */	  value -= (sec->output_section->vma + sec->output_offset);	  value -= irel->r_offset;	  value += irel->r_addend;	  /* See if the value will fit in 16 bits, note the high value is	     0x7fff + 2 as the target will be two bytes closer if we are	     able to relax.  */	  if ((long) value < 0x8001 && (long) value > -0x8000)	    {	      unsigned char code;	      /* Get the opcode.  */	      code = bfd_get_8 (abfd, contents + irel->r_offset - 1);	      if (code != 0xdc && code != 0xdd && code != 0xff)		continue;	      /* Note that we've changed the relocs, section contents, etc.  */	      elf_section_data (sec)->relocs = internal_relocs;	      free_relocs = NULL;	      elf_section_data (sec)->this_hdr.contents = contents;	      free_contents = NULL;	      symtab_hdr->contents = (bfd_byte *) extsyms;	      free_extsyms = NULL;	      /* Fix the opcode.  */	      if (code == 0xdc)		bfd_put_8 (abfd, 0xcc, contents + irel->r_offset - 1);	      else if (code == 0xdd)		bfd_put_8 (abfd, 0xcd, contents + irel->r_offset - 1);	      else if (code == 0xff)		bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2);	      /* Fix the relocation's type.  */	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),					   R_MN10300_PCREL16);	      /* Delete two bytes of data.  */	      if (!mn10300_elf_relax_delete_bytes (abfd, sec,						   irel->r_offset + 1, 2))		goto error_return;	      /* That will change things, so, we should relax again.		 Note that this is not required, and it may be slow.  */	      *again = true;	    }	}      /* Try to turn a 16bit pc-relative branch into a 8bit pc-relative	 branch.  */      if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_PCREL16)	{	  bfd_vma value = symval;	  /* If we've got a "call" instruction that needs to be turned	     into a "calls" instruction, do so now.  It saves a byte.  */	  if (h && (h->flags & MN10300_CONVERT_CALL_TO_CALLS))	    {	      unsigned char code;	      /* Get the opcode.  */	      code = bfd_get_8 (abfd, contents + irel->r_offset - 1);	      /* Make sure we're working with a "call" instruction!  */	      if (code == 0xcd)		{		  /* Note that we've changed the relocs, section contents,		     etc.  */		  elf_section_data (sec)->relocs = internal_relocs;		  free_relocs = NULL;		  elf_section_data (sec)->this_hdr.contents = contents;		  free_contents = NULL;		  symtab_hdr->contents = (bfd_byte *) extsyms;		  free_extsyms = NULL;		  /* Fix the opcode.  */		  bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 1);		  bfd_put_8 (abfd, 0xff, contents + irel->r_offset);		  /* Fix irel->r_offset and irel->r_addend.  */		  irel->r_offset += 1;		  irel->r_addend += 1;		  /* Delete one byte of data.  */		  if (!mn10300_elf_relax_delete_bytes (abfd, sec,						       irel->r_offset + 1, 1))		    goto error_return;		  /* That will change things, so, we should relax again.		     Note that this is not required, and it may be slow.  */		  *again = true;		}	    }	  else if (h)	    {	      unsigned char code;	      /* Get the opcode.  */	      code = bfd_get_8 (abfd, contents + irel->r_offset - 1);	      /* Insert data from the target function into the "call"		 instruction if needed.  */	      if (code == 0xcd)		{		  bfd_put_8 (abfd, h->movm_args, contents + irel->r_offset + 2);		  bfd_put_8 (abfd, h->stack_size + h->movm_stack_size,			     contents + irel->r_offset + 3);		}	    }	  /* Deal with pc-relative gunk.  */	  value -= (sec->output_section->vma + sec->output_offset);	  value -= irel->r_offset;	  value += irel->r_addend;	  /* See if the value will fit in 8 bits, note the high value is	     0x7f + 1 as the target will be one bytes closer if we are	     able to relax.  */	  if ((long) value < 0x80 && (long) value > -0x80)	    {	      unsigned char code;	      /* Get the opcode.  */	      code = bfd_get_8 (abfd, contents + irel->r_offset - 1);	      if (code != 0xcc)		continue;	      /* Note that we've changed the relocs, section contents, etc.  */	      elf_section_data (sec)->relocs = internal_relocs;	      free_relocs = NULL;	      elf_section_data (sec)->this_hdr.contents = contents;	      free_contents = NULL;	      symtab_hdr->contents = (bfd_byte *) extsyms;	      free_extsyms = NULL;	      /* Fix the opcode.  */	      bfd_put_8 (abfd, 0xca, contents + irel->r_offset - 1);	      /* Fix the relocation's type.  */	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),					   R_MN10300_PCREL8);	      /* Delete one byte of data.  */	      if (!mn10300_elf_relax_delete_bytes (abfd, sec,						   irel->r_offset + 1, 1))		goto error_return;	      /* That will change things, so, we should relax again.		 Note that this is not required, and it may be slow.  */	      *again = true;	    }	}      /* Try to eliminate an unconditional 8 bit pc-relative branch	 which immediately follows a conditional 8 bit pc-relative	 branch around the unconditional branch.	    original:		new:	    bCC lab1		bCC' lab2	    bra lab2	   lab1:	       lab1:	 This happens when the bCC can't reach lab2 at assembly time,	 but due to other relaxations it can reach at link time.  */      if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_PCREL8)	{	  Elf_Internal_Rela *nrel;	  bfd_vma value = symval;	  unsigned char code;	  /* Deal with pc-relative gunk.  */	  value -= (sec->output_section->vma + sec->output_offset);	  value -= irel->r_offset;	  value += irel->r_addend;

⌨️ 快捷键说明

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