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 + -
显示快捷键?