📄 700-nios2-2.15.patch
字号:
+ /* 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 this instruction+ * ie the movhi */+ pcrel_offset -= (irel->r_offset);++ /* does this value fit in 16 bits */+ if ((irelalign == NULL && (long) pcrel_offset <= 0x8008+ && (long) pcrel_offset >= -0x8000) || (irelalign != NULL+ && (long) pcrel_offset+ <= 0x7ffc+ && (long) pcrel_offset+ >= -0x8000))+ {+ unsigned long opcode, op_a, op_b;+ /* get the conditional branch opcode */+ opcode = bfd_get_32 (abfd, contents + irel->r_offset - 4);+ /* reverse the condition */+ switch (opcode & OP_MASK_OP)+ {+ case OP_MATCH_BEQ:+ opcode = (opcode & ~OP_MASK_OP) | OP_MATCH_BNE;+ break;+ case OP_MATCH_BNE:+ opcode = (opcode & ~OP_MASK_OP) | OP_MATCH_BEQ;+ break;+ case OP_MATCH_BGE:+ case OP_MATCH_BGEU:+ case OP_MATCH_BLT:+ case OP_MATCH_BLTU:+ /* swap the operands */+ op_a = (opcode & OP_MASK_RRT) << 5;+ op_b = (opcode & OP_MASK_RRS) >> 5;+ opcode =+ (opcode & ~(OP_MASK_RRS | OP_MASK_RRT)) | op_a | op_b;+ break;+ default:+ fprintf (stderr,+ "relaxation error - expecting conditional branch, aborting\n");+ abort ();+ break;+ }++ /* we must set the branch target to zero so that the skip over the jmp doesn't get+ * added to the jmp */+ opcode = opcode & (~OP_MASK_IMM16);++ /* change the opcode to the reversed conditional branch */+ bfd_put_32 (abfd, opcode, contents + irel->r_offset - 4);+ /* 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);++ /* this relocation's offset has also been reduced by 4 bytes */+ irel->r_offset -= 4;++ /* 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);+ bfd_put_32 (abfd, OP_MATCH_NOP, contents + irel->r_offset + 12);+ }+ }++ /* otherwise, leave alone */+ }++ if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)+ {+ if (!link_info->keep_memory)+ free (isymbuf);+ else+ {+ /* Cache the symbols for elf_link_input_bfd. */+ symtab_hdr->contents = (unsigned char *) isymbuf;+ }+ }++ if (contents != NULL+ && elf_section_data (sec)->this_hdr.contents != contents)+ {+ if (!link_info->keep_memory)+ free (contents);+ else+ {+ /* Cache the section contents for elf_link_input_bfd. */+ elf_section_data (sec)->this_hdr.contents = contents;+ }+ }++ if (internal_relocs != NULL+ && elf_section_data (sec)->relocs != internal_relocs)+ free (internal_relocs);+++ return TRUE;++error_return:+ if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)+ free (isymbuf);+ if (contents != NULL+ && elf_section_data (sec)->this_hdr.contents != contents)+ free (contents);+ if (internal_relocs != NULL+ && elf_section_data (sec)->relocs != internal_relocs)+ free (internal_relocs);++ return FALSE;+}++/* Delete some bytes from a section while relaxing.+ * Copied from mn10200 port */++static bfd_boolean+nios2_elf32_relax_delete_bytes (bfd * abfd,+ asection * sec, bfd_vma addr, int count)+{+ Elf_Internal_Shdr *symtab_hdr;+ unsigned int sec_shndx;+ bfd_byte *contents;+ Elf_Internal_Rela *irel, *irelend;+ Elf_Internal_Rela *irelalign;+ bfd_vma toaddr;+ Elf_Internal_Sym *isym;+ Elf_Internal_Sym *isymend;+ struct elf_link_hash_entry **sym_hashes;+ struct elf_link_hash_entry **end_hashes;+ unsigned int symcount;+ asection *asec;++ sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);++ contents = elf_section_data (sec)->this_hdr.contents;++ /* The deletion must stop at the next ALIGN reloc for an aligment+ power larger than the number of bytes we are deleting. */++ irelalign = NULL;+ /* +1 because we need to readjust symbols at end of section */+ toaddr = sec->_cooked_size + 1;++ irel = elf_section_data (sec)->relocs;+ irelend = irel + sec->reloc_count;++ for (; irel < irelend; irel++)+ {+ if (ELF32_R_TYPE (irel->r_info) == (int) R_NIOS2_ALIGN+ && irel->r_offset > addr && count < (1 << irel->r_addend))+ {+ irelalign = irel;+ /* +1 because we need to readjust symbols at end of section */+ toaddr = irel->r_offset + 1;+ break;+ }+ }+++ /* Actually delete the bytes. */+ memmove (contents + addr, contents + addr + count,+ (size_t) ((toaddr - 1) - addr - count));++ if (irelalign == NULL)+ sec->_cooked_size -= count;+ else+ {+ int i;++#define NOP_OPCODE (0x0001883a)++ BFD_ASSERT ((count & 3) == 0);+ for (i = 0; i < count; i += 4)+ bfd_put_32 (abfd, (bfd_vma) NOP_OPCODE,+ contents + (toaddr - 1) - count + i);+ }++ /* get the symbol table */+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;+ isym = (Elf_Internal_Sym *) symtab_hdr->contents;++ /* Adjust all the reloc offsets in this section. */+ for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)+ {+ /* Get the new reloc address. */+ if ((irel->r_offset > addr && irel->r_offset < toaddr))+ irel->r_offset -= count;+ }++ /* Adjust relocations against targets in this section whose positions+ * have moved as a result of the relaxation */++ for (asec = abfd->sections; asec; asec = asec->next)+ {+ irelend = elf_section_data (asec)->relocs + asec->reloc_count;+ for (irel = elf_section_data (asec)->relocs; irel < irelend; irel++)+ {+ Elf_Internal_Sym *sym;+ /* if the symbol which this reloc is against doesn't change+ * we need to change the reloc addend */++ sym = isym + ELF32_R_SYM (irel->r_info);+ if (sym->st_shndx == sec_shndx+ && !(sym->st_value > addr && sym->st_value < toaddr)+ && sym->st_value + irel->r_addend > addr+ && sym->st_value + irel->r_addend < toaddr)+ {+ irel->r_addend -= count;+ }++ }+ }++ /* Adjust the local symbols defined in this section. */+ for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)+ {+ if (isym->st_shndx == sec_shndx+ && isym->st_value > addr && isym->st_value < toaddr)+ isym->st_value -= count;+++ }++ /* Now adjust the global symbols defined in this section. */+ symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)+ - symtab_hdr->sh_info);+ sym_hashes = elf_sym_hashes (abfd);+ end_hashes = sym_hashes + symcount;+ for (; sym_hashes < end_hashes; sym_hashes++)+ {+ struct elf_link_hash_entry *sym_hash = *sym_hashes;+ if ((sym_hash->root.type == bfd_link_hash_defined+ || sym_hash->root.type == bfd_link_hash_defweak)+ && sym_hash->root.u.def.section == sec+ && sym_hash->root.u.def.value > addr+ && sym_hash->root.u.def.value < toaddr)+ {+ sym_hash->root.u.def.value -= count;+ }+ }++ return TRUE;+}++struct bfd_link_info *nios2_link_info = NULL;++void+_bfd_set_link_info (info)+ struct bfd_link_info *info;+{+ nios2_link_info = info;+}++bfd_boolean linker_force_make_executable = FALSE;++void+_bfd_set_force_make_executable (force)+ bfd_boolean force;+{+ linker_force_make_executable = force;+}++/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a+ dangerous relocation. */++static bfd_boolean+nios2_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp, struct bfd_link_info *info)+{++ bfd_boolean gp_found;+ struct bfd_hash_entry *h;+ struct bfd_link_hash_entry *lh;++ /* If we've already figured out what GP will be, just return it. */+ *pgp = _bfd_get_gp_value (output_bfd);+ if (*pgp)+ return TRUE;++ h = bfd_hash_lookup (&info->hash->table, "_gp", FALSE, FALSE);+ lh = (struct bfd_link_hash_entry *) h;+lookup:+ if (lh)+ {+ switch (lh->type)+ {+ case bfd_link_hash_undefined:+ case bfd_link_hash_undefweak:+ case bfd_link_hash_common:+ gp_found = FALSE;+ break;+ case bfd_link_hash_defined:+ case bfd_link_hash_defweak:+ gp_found = TRUE;+ *pgp = lh->u.def.value;+ break;+ case bfd_link_hash_indirect:+ case bfd_link_hash_warning:+ lh = lh->u.i.link;+ /* @@FIXME ignoring warning for now */+ goto lookup;+ case bfd_link_hash_new:+ default:+ abort ();+ }+ }+ else+ gp_found = FALSE;++ if (!gp_found)+ {+ /* Only get the error once. */+ *pgp = 4;+ _bfd_set_gp_value (output_bfd, *pgp);+ return FALSE;+ }++ _bfd_set_gp_value (output_bfd, *pgp);++ return TRUE;+}++/* We have to figure out the gp value, so that we can adjust the+ symbol value correctly. We look up the symbol _gp in the output+ BFD. If we can't find it, we're stuck. We cache it in the ELF+ target data. We don't need to adjust the symbol value for an+ external symbol if we are producing relocatable output. */++static bfd_reloc_status_type+nios2_elf_final_gp (bfd *output_bfd, asymbol *symbol, bfd_boolean relocatable, + char **error_message, bfd_vma *pgp, struct bfd_link_info *info)+{+ if (bfd_is_und_section (symbol->section) && !relocatable)+ {+ *pgp = 0;+ return bfd_reloc_undefined;+ }++ *pgp = _bfd_get_gp_value (output_bfd);+ if (*pgp == 0 && (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0))+ {+ /* if this is called without link_info, then+ we cannot be doing a final link */+ if (info == NULL)+ relocatable = TRUE;++ if (relocatable)+ {+ /* Make up a value. */+ *pgp = symbol->section->output_section->vma + 0x4000;+ _bfd_set_gp_value (output_bfd, *pgp);+ }+ else if (!nios2_elf_assign_gp (output_bfd, pgp, info))+ {+ *error_message =+ (char *)+ _("global pointer relative relocation when _gp not defined");+ return bfd_reloc_dangerous;+ }+ }++ return bfd_reloc_ok;+}+++/* Relocations that require special handling */++/* This is for relocations used only when relaxing to ensure+ * changes in size of section don't screw up .align */+static bfd_reloc_status_type+nios2_elf32_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,+ asymbol *symbol ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED,+ asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)+{+ if (output_bfd != NULL)+ reloc_entry->address += input_section->output_offset;+ return bfd_reloc_ok;+}++static bfd_reloc_status_type+nios2_elf32_hi16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void *data,+ asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)+{+ /* This part is from bfd_elf_generic_reloc. */+ if (output_bfd != (bfd *) NULL+ && (symbol->flags & BSF_SECTION_SYM) == 0+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))+ {+ reloc_entry->address += input_section->output_offset;+ return bfd_reloc_ok;+ }++ if (output_bfd != NULL)+ /* FIXME: See bfd_perform_relocation. Is this right? */+ return bfd_reloc_ok;++ return nios2_elf32_do_hi16_relocate (abfd, reloc_entry->howto,+ input_section,+ data, reloc_entry->address,+ (symbol->value+ + symbol->section->output_section->vma+ + symbol->section->output_offset),+ reloc_entry->addend);+}++static bfd_reloc_status_type+nios2_elf32_lo16_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,+ void *data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED)+{+/* This part is from bfd_elf_generic_reloc. */+ if (output_bfd != (bfd *) NULL+ && (symbol->flags & BSF_SECTION_SYM) == 0+ && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))+ {+ reloc_entry->address += input_section->output_offset;+ return bfd_reloc_ok;+ }++ if (output_bfd != NULL)+ /* FIXME: See bfd_perform_relocation. Is this right? */+ return bfd_reloc_ok;++ return nios2_elf32_do_lo16_relocate (abfd, reloc_entry->howto,+ input_sectio
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -