700-nios2-2.15.patch

来自「這是一個實時嵌入式作業系統 實作了MCS51 ARM等MCU」· PATCH 代码 · 共 2,140 行 · 第 1/5 页

PATCH
2,140
字号
+	 FALSE,+	 0,+	 0,+	 FALSE),++  HOWTO (R_NIOS2_UJMP,+	 0,+	 2,+	 32,+	 FALSE,+	 6,+	 complain_overflow_dont,+	 nios2_elf32_ujmp_relocate,+	 "R_NIOS2_UJMP",+	 FALSE,+	 0x003fffc0,+	 0x003fffc0,+	 FALSE),++  HOWTO (R_NIOS2_CJMP,+	 0,+	 2,+	 32,+	 FALSE,+	 6,+	 complain_overflow_dont,+	 nios2_elf32_cjmp_relocate,+	 "R_NIOS2_CJMP",+	 FALSE,+	 0x003fffc0,+	 0x003fffc0,+	 FALSE),++  HOWTO (R_NIOS2_CALLR,+	 0,+	 2,+	 32,+	 FALSE,+	 6,+	 complain_overflow_dont,+	 nios2_elf32_callr_relocate,+	 "R_NIOS2_CALLR",+	 FALSE,+	 0x003fffc0,+	 0x003fffc0,+	 FALSE),++  HOWTO (R_NIOS2_ALIGN,+	 0,+	 2,+	 0,+	 FALSE,+	 0,+	 complain_overflow_dont,+	 nios2_elf32_ignore_reloc,+	 "R_NIOS2_ALIGN",+	 FALSE,+	 0,+	 0,+	 TRUE),++/* add other relocations here */+};++static unsigned char elf_code_to_howto_index[R_NIOS2_ILLEGAL + 1];++static reloc_howto_type *+lookup_howto (unsigned int rtype)+{+  static int initialized = 0;+  int i;+  int howto_tbl_size = (int) (sizeof (elf_nios2_howto_table_rel)+			      / sizeof (elf_nios2_howto_table_rel[0]));++  if (!initialized)+    {+      initialized = 1;+      memset (elf_code_to_howto_index, 0xff,+	      sizeof (elf_code_to_howto_index));+      for (i = 0; i < howto_tbl_size; i++)+	elf_code_to_howto_index[elf_nios2_howto_table_rel[i].type] = i;+    }++  BFD_ASSERT (rtype <= R_NIOS2_ILLEGAL);+  i = elf_code_to_howto_index[rtype];+  if (i >= howto_tbl_size)+    return 0;+  return elf_nios2_howto_table_rel + i;+}++/*+   map for converting BFD reloc types to New Jersey+   reloc types+ */+struct elf_reloc_map+{+  bfd_reloc_code_real_type bfd_val;+  enum elf_nios2_reloc_type elf_val;+};++static const struct elf_reloc_map nios2_reloc_map[] = {+  {BFD_RELOC_NIOS2_S16, R_NIOS2_S16},+  {BFD_RELOC_NIOS2_U16, R_NIOS2_U16},+  {BFD_RELOC_16_PCREL, R_NIOS2_PCREL16},+  {BFD_RELOC_NIOS2_CALL26, R_NIOS2_CALL26},+  {BFD_RELOC_NIOS2_IMM5, R_NIOS2_IMM5},+  {BFD_RELOC_NIOS2_CACHE_OPX, R_NIOS2_CACHE_OPX},+  {BFD_RELOC_NIOS2_IMM6, R_NIOS2_IMM6},+  {BFD_RELOC_NIOS2_IMM8, R_NIOS2_IMM8},+  {BFD_RELOC_NIOS2_HI16, R_NIOS2_HI16},+  {BFD_RELOC_NIOS2_LO16, R_NIOS2_LO16},+  {BFD_RELOC_NIOS2_HIADJ16, R_NIOS2_HIADJ16},+  {BFD_RELOC_32, R_NIOS2_BFD_RELOC_32},+  {BFD_RELOC_16, R_NIOS2_BFD_RELOC_16},+  {BFD_RELOC_8, R_NIOS2_BFD_RELOC_8},+  {BFD_RELOC_NIOS2_GPREL, R_NIOS2_GPREL},+  {BFD_RELOC_VTABLE_INHERIT, R_NIOS2_GNU_VTINHERIT},+  {BFD_RELOC_VTABLE_ENTRY, R_NIOS2_GNU_VTENTRY},+  {BFD_RELOC_NIOS2_UJMP, R_NIOS2_UJMP},+  {BFD_RELOC_NIOS2_CJMP, R_NIOS2_CJMP},+  {BFD_RELOC_NIOS2_CALLR, R_NIOS2_CALLR},+  {BFD_RELOC_NIOS2_ALIGN, R_NIOS2_ALIGN},+};++/* Given a BFD reloc type, return a howto structure.  */++static reloc_howto_type *+nios2_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,+				   bfd_reloc_code_real_type code)+{+  int i;+  for (i = 0;+       i < (int) (sizeof (nios2_reloc_map) / sizeof (struct elf_reloc_map));+       ++i)+    {+      if (nios2_reloc_map[i].bfd_val == code)+	return &elf_nios2_howto_table_rel[(int) nios2_reloc_map[i].elf_val];+    }++  return NULL;+}++/* Helper function for nios2_elf32_info_to_howto */++static reloc_howto_type *+nios2_elf32_rtype_to_howto (unsigned int r_type,+			    bfd_boolean rela_p ATTRIBUTE_UNUSED)+{+  BFD_ASSERT (r_type < R_NIOS2_ILLEGAL);+  return &elf_nios2_howto_table_rel[r_type];+}++/* Given a ELF32 relocation, fill in a arelent structure */++static void+nios2_elf32_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * cache_ptr,+			   Elf_Internal_Rela * dst)+{+  unsigned int r_type;++  r_type = ELF32_R_TYPE (dst->r_info);+  cache_ptr->howto = nios2_elf32_rtype_to_howto (r_type, FALSE);++  // FIXME - do we need to do anything else here???+}++/* The assembler has output long jmp/call sequences for all calls+ * and pc-relative branches that it cannot guarantee are within+ * range, so the linker must attempt to "relax" these sequences to+ * short branches and calls if it can. We avoid having to re-relax by+ * replacing redundant instructions with nops instead of deleting them.+ *+ *+ **/+static bfd_boolean+nios2_elf32_relax_section (bfd * abfd,+			   asection * sec,+			   struct bfd_link_info *link_info, bfd_boolean * again)+{+  Elf_Internal_Shdr *symtab_hdr;+  Elf_Internal_Rela *internal_relocs;+  Elf_Internal_Rela *irel, *irelend;+  bfd_byte *contents = NULL;+  Elf_Internal_Sym *isymbuf = NULL;++#define OP_MATCH_NOP 0x0001883a++  /* Assume nothing changes.  */+  *again = FALSE;++  /* We don't have to do anything for a relocatable link, if+     this section does not have relocs, or if this is not a+     code section.  */+  if (link_info->relocatable+      || (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_elf_link_read_relocs+		     (abfd, sec, (void *) NULL, (Elf_Internal_Rela *) NULL,+		      link_info->keep_memory));+  if (internal_relocs == NULL)+    goto error_return;++  /* Walk through them looking for relaxing opportunities.  */+  irelend = internal_relocs + sec->reloc_count;+  for (irel = internal_relocs; irel < irelend; irel++)+    {+      bfd_vma symval;++      /* If this isn't something that can be relaxed, then ignore+         this reloc.  */+      if (ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_UJMP+	  && ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_CJMP+	  && ELF32_R_TYPE (irel->r_info) != (int) R_NIOS2_CALLR)+	{+	  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;++	      if (!bfd_get_section_contents (abfd, sec, contents,+					     (file_ptr) 0, sec->_raw_size))+		goto error_return;+	    }+	}++      /* Read this BFD's local symbols if we haven't done so already.  */+      if (isymbuf == NULL && symtab_hdr->sh_info != 0)+	{+	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;+	  if (isymbuf == NULL)+	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,+					    symtab_hdr->sh_info, 0,+					    NULL, NULL, NULL);+	  if (isymbuf == NULL)+	    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)+	{+	  /* A local symbol.  */+	  Elf_Internal_Sym *isym;+	  asection *sym_sec;++	  isym = isymbuf + ELF32_R_SYM (irel->r_info);+	  if (isym->st_shndx == SHN_UNDEF)+	    sym_sec = bfd_und_section_ptr;+	  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+	    sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);+	  symval = (isym->st_value+		    + sym_sec->output_section->vma + sym_sec->output_offset);+	}+      else+	{+	  unsigned long indx;+	  struct elf_link_hash_entry *h;++	  /* An external symbol.  */+	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;+	  h = elf_sym_hashes (abfd)[indx];+	  BFD_ASSERT (h != NULL);+	  if (h->root.type != bfd_link_hash_defined+	      && h->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.u.def.value+		    + h->root.u.def.section->output_section->vma+		    + h->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 :+       *      movhi at, %hi(symbol)+       *      movui at, %lo(symbol)+       *      callr at+       * into:+       *      call symbol+       */+      if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_CALLR)+	{+	  bfd_vma targ_addr = symval + irel->r_addend;+	  bfd_vma curr_addr = (sec->output_section->vma + sec->output_offset);+	  bfd_vma targ_page, curr_page;+	  targ_page = targ_addr & 0xf0000000;+	  curr_page = curr_addr & 0xf0000000;++	  if (targ_page == curr_page)+	    {+	      /* change the opcode to a call */+	      bfd_put_32 (abfd, OP_MATCH_CALL, contents + irel->r_offset);+	      /* Note that we've changed the relocs, section contents, etc.  */+	      elf_section_data (sec)->relocs = internal_relocs;+	      elf_section_data (sec)->this_hdr.contents = contents;+	      symtab_hdr->contents = (unsigned char *) isymbuf;++	      /* Fix the relocation's type.  */+	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),+					   R_NIOS2_CALL26);++	      /* replace next two instructions with nops */+	      bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 4);+	      bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 8);+	    }+	}++      /* try to turn :+       *    movhi at, %hi(symbol)+       *    movui at, %lo(symbol)+       *    jmp at+       * into:+       *    br symbol+       */+      if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_UJMP)+	{+	  bfd_vma pcrel_offset;+	  Elf_Internal_Rela *irelalign = NULL;+	  Elf_Internal_Rela *irela = elf_section_data (sec)->relocs;+	  Elf_Internal_Rela *irelend = irel + sec->reloc_count;++	  for (; irela < irelend; irela++)+	    {+	      if (ELF32_R_TYPE (irela->r_info) == (int) R_NIOS2_ALIGN+		  && irela->r_offset > irel->r_offset + 4+		  && 8 < (1 << irela->r_addend))+		{+		  irelalign = irela;+		  break;+		}+	    }++	  /* calculate the pcrelative offset from current location */+	  pcrel_offset = symval;+	  pcrel_offset -= (sec->output_section->vma + sec->output_offset);+	  pcrel_offset += irel->r_addend;++	  /* we need to compute the pcrel_offset from the next instruction */+	  pcrel_offset -= (irel->r_offset + 4);++	  /* does this value fit in 16 bits  */+	  if ((irelalign == NULL && (long) pcrel_offset <= 0x8004+	       && (long) pcrel_offset >= -0x8000) || (irelalign != NULL+						      && (long) pcrel_offset+						      <= 0x7ffc+						      && (long) pcrel_offset+						      >= -0x8000))+	    {+	      /* change the opcode to an unconditional branch */+	      bfd_put_32 (abfd, OP_MATCH_BR, contents + irel->r_offset);+	      /* Note that we've changed the relocs, section contents, etc.  */+	      elf_section_data (sec)->relocs = internal_relocs;+	      elf_section_data (sec)->this_hdr.contents = contents;+	      symtab_hdr->contents = (unsigned char *) isymbuf;++	      /* Fix the relocation's type.  */+	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),+					   R_NIOS2_PCREL16);++	      /* replace next two instructions with nops */+	      bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 4);+	      bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 8);+	    }+	}++      /* try to turn :+       *   b{cond} a, b skip+       *   movhi at, %hi(symbol)+       *   movui at, %lo(symbol)+       *   jmp at+       * skip:+       *   ...+       * into:+       *   br{opp_cond} a, b, symbol+       */+      if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_CJMP)+	{+	  bfd_vma pcrel_offset;+	  Elf_Internal_Rela *irelalign = NULL;+	  Elf_Internal_Rela *irela = elf_section_data (sec)->relocs;+	  Elf_Internal_Rela *irelend = irel + sec->reloc_count;++	  for (; irela < irelend; irela++)+	    {+	      if (ELF32_R_TYPE (irela->r_info) == (int) R_NIOS2_ALIGN+		  && irela->r_offset > irel->r_offset + 4+		  && 8 < (1 << irela->r_addend))+		{+		  irelalign = irela;+		  break;+		}+	    }+

⌨️ 快捷键说明

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