elf32-sparc.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,014 行 · 第 1/5 页
C
2,014 行
&& ((y & F3I(~0)) || (y & RS2(~0)) != RS2(O7))) { bfd_vma reloc; reloc = relocation + rel->r_addend - rel->r_offset; reloc -= (input_section->output_section->vma + input_section->output_offset); /* Ensure the reloc fits into simm22. */ if ((reloc & 3) == 0 && ((reloc & ~(bfd_vma)0x7fffff) == 0 || ((reloc | 0x7fffff) == ~(bfd_vma)0))) { reloc >>= 2; /* Check whether it fits into simm19 on v9. */ if (((reloc & 0x3c0000) == 0 || (reloc & 0x3c0000) == 0x3c0000) && (elf_elfheader (output_bfd)->e_flags & EF_SPARC_32PLUS)) x = INSN_BPA | (reloc & 0x7ffff); /* ba,pt %xcc */ else x = INSN_BA | (reloc & 0x3fffff); /* ba */ bfd_put_32 (input_bfd, x, contents + rel->r_offset); r = bfd_reloc_ok; if (rel->r_offset >= 4 && (y & (0xffffffff ^ RS1(~0))) == (INSN_OR | RD(O7) | RS2(G0))) { bfd_vma z; unsigned int reg; z = bfd_get_32 (input_bfd, contents + rel->r_offset - 4); if ((z & (0xffffffff ^ RD(~0))) != (INSN_OR | RS1(O7) | RS2(G0))) break; /* The sequence was or %o7, %g0, %rN call foo or %rN, %g0, %o7 If call foo was replaced with ba, replace or %rN, %g0, %o7 with nop. */ reg = (y & RS1(~0)) >> 14; if (reg != ((z & RD(~0)) >> 25) || reg == G0 || reg == O7) break; bfd_put_32 (input_bfd, INSN_NOP, contents + rel->r_offset + 4); } } } } } if (r == bfd_reloc_continue) r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, rel->r_addend); if (r != bfd_reloc_ok) { switch (r) { default: case bfd_reloc_outofrange: abort (); case bfd_reloc_overflow: { const char *name; if (h != NULL) name = h->root.root.string; else { name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); if (name == NULL) return false; if (*name == '\0') name = bfd_section_name (input_bfd, sec); } if (! ((*info->callbacks->reloc_overflow) (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset))) return false; } break; } } } return true;}/* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */static booleanelf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) bfd *output_bfd; struct bfd_link_info *info; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym;{ bfd *dynobj; dynobj = elf_hash_table (info)->dynobj; if (h->plt.offset != (bfd_vma) -1) { asection *splt; asection *srela; Elf_Internal_Rela rela; /* This symbol has an entry in the procedure linkage table. Set it up. */ BFD_ASSERT (h->dynindx != -1); splt = bfd_get_section_by_name (dynobj, ".plt"); srela = bfd_get_section_by_name (dynobj, ".rela.plt"); BFD_ASSERT (splt != NULL && srela != NULL); /* Fill in the entry in the procedure linkage table. */ bfd_put_32 (output_bfd, PLT_ENTRY_WORD0 + h->plt.offset, splt->contents + h->plt.offset); bfd_put_32 (output_bfd, (PLT_ENTRY_WORD1 + (((- (h->plt.offset + 4)) >> 2) & 0x3fffff)), splt->contents + h->plt.offset + 4); bfd_put_32 (output_bfd, PLT_ENTRY_WORD2, splt->contents + h->plt.offset + 8); /* Fill in the entry in the .rela.plt section. */ rela.r_offset = (splt->output_section->vma + splt->output_offset + h->plt.offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_JMP_SLOT); rela.r_addend = 0; bfd_elf32_swap_reloca_out (output_bfd, &rela, ((Elf32_External_Rela *) srela->contents + h->plt.offset / PLT_ENTRY_SIZE - 4)); if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value alone. */ sym->st_shndx = SHN_UNDEF; /* If the symbol is weak, we do need to clear the value. Otherwise, the PLT entry would provide a definition for the symbol even if the symbol wasn't defined anywhere, and so the symbol would never be NULL. */ if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) == 0) sym->st_value = 0; } } if (h->got.offset != (bfd_vma) -1) { asection *sgot; asection *srela; Elf_Internal_Rela rela; /* This symbol has an entry in the global offset table. Set it up. */ sgot = bfd_get_section_by_name (dynobj, ".got"); srela = bfd_get_section_by_name (dynobj, ".rela.got"); BFD_ASSERT (sgot != NULL && srela != NULL); rela.r_offset = (sgot->output_section->vma + sgot->output_offset + (h->got.offset &~ 1)); /* If this is a -Bsymbolic link, and the symbol is defined locally, we just want to emit a RELATIVE reloc. Likewise if the symbol was forced to be local because of a version file. The entry in the global offset table will already have been initialized in the relocate_section function. */ if (info->shared && (info->symbolic || h->dynindx == -1) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) rela.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE); else { bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_GLOB_DAT); } rela.r_addend = 0; bfd_elf32_swap_reloca_out (output_bfd, &rela, ((Elf32_External_Rela *) srela->contents + srela->reloc_count)); ++srela->reloc_count; } if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) { asection *s; Elf_Internal_Rela rela; /* This symbols needs a copy reloc. Set it up. */ BFD_ASSERT (h->dynindx != -1); s = bfd_get_section_by_name (h->root.u.def.section->owner, ".rela.bss"); BFD_ASSERT (s != NULL); rela.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_COPY); rela.r_addend = 0; bfd_elf32_swap_reloca_out (output_bfd, &rela, ((Elf32_External_Rela *) s->contents + s->reloc_count)); ++s->reloc_count; } /* Mark some specially defined symbols as absolute. */ if (strcmp (h->root.root.string, "_DYNAMIC") == 0 || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0) sym->st_shndx = SHN_ABS; return true;}/* Finish up the dynamic sections. */static booleanelf32_sparc_finish_dynamic_sections (output_bfd, info) bfd *output_bfd; struct bfd_link_info *info;{ bfd *dynobj; asection *sdyn; asection *sgot; dynobj = elf_hash_table (info)->dynobj; sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); if (elf_hash_table (info)->dynamic_sections_created) { asection *splt; Elf32_External_Dyn *dyncon, *dynconend; splt = bfd_get_section_by_name (dynobj, ".plt"); BFD_ASSERT (splt != NULL && sdyn != NULL); dyncon = (Elf32_External_Dyn *) sdyn->contents; dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; const char *name; boolean size; bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); switch (dyn.d_tag) { case DT_PLTGOT: name = ".plt"; size = false; break; case DT_PLTRELSZ: name = ".rela.plt"; size = true; break; case DT_JMPREL: name = ".rela.plt"; size = false; break; default: name = NULL; size = false; break; } if (name != NULL) { asection *s; s = bfd_get_section_by_name (output_bfd, name); if (s == NULL) dyn.d_un.d_val = 0; else { if (! size) dyn.d_un.d_ptr = s->vma; else { if (s->_cooked_size != 0) dyn.d_un.d_val = s->_cooked_size; else dyn.d_un.d_val = s->_raw_size; } } bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); } } /* Clear the first four entries in the procedure linkage table, and put a nop in the last four bytes. */ if (splt->_raw_size > 0) { memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE); bfd_put_32 (output_bfd, SPARC_NOP, splt->contents + splt->_raw_size - 4); } elf_section_data (splt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE; } /* Set the first entry in the global offset table to the address of the dynamic section. */ sgot = bfd_get_section_by_name (dynobj, ".got"); BFD_ASSERT (sgot != NULL); if (sgot->_raw_size > 0) { if (sdyn == NULL) bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); else bfd_put_32 (output_bfd, sdyn->output_section->vma + sdyn->output_offset, sgot->contents); } elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; return true;}/* Functions for dealing with the e_flags field. We don't define set_private_flags or copy_private_bfd_data because the only currently defined values are based on the bfd mach number, so we use the latter instead and defer setting e_flags until the file is written out. *//* Merge backend specific data from an object file to the output object file when linking. */static booleanelf32_sparc_merge_private_bfd_data (ibfd, obfd) bfd *ibfd; bfd *obfd;{ boolean error; /* FIXME: This should not be static. */ static unsigned long previous_ibfd_e_flags = (unsigned long) -1; if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return true; error = false; if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9) { error = true; (*_bfd_error_handler) (_("%s: compiled for a 64 bit system and target is 32 bit"), bfd_get_filename (ibfd)); } else if ((ibfd->flags & DYNAMIC) == 0) { if (bfd_get_mach (obfd) < bfd_get_mach (ibfd)) bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd)); } if (((elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA) != previous_ibfd_e_flags) && previous_ibfd_e_flags != (unsigned long) -1) { (*_bfd_error_handler) (_("%s: linking little endian files with big endian files"), bfd_get_filename (ibfd)); error = true; } previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA; if (error) { bfd_set_error (bfd_error_bad_value); return false; } return true;}/* Set the right machine number. */static booleanelf32_sparc_object_p (abfd) bfd *abfd;{ if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS) { if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US3) return bfd_def
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?