elf32-sparc.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,014 行 · 第 1/5 页
C
2,014 行
&& (r_type == R_SPARC_8 || r_type == R_SPARC_16 || r_type == R_SPARC_32 || r_type == R_SPARC_DISP8 || r_type == R_SPARC_DISP16 || r_type == R_SPARC_DISP32 || r_type == R_SPARC_WDISP30 || r_type == R_SPARC_WDISP22 || r_type == R_SPARC_WDISP19 || r_type == R_SPARC_WDISP16 || r_type == R_SPARC_HI22 || r_type == R_SPARC_22 || r_type == R_SPARC_13 || r_type == R_SPARC_LO10 || r_type == R_SPARC_UA16 || r_type == R_SPARC_UA32 || r_type == R_SPARC_UA64 || ((r_type == R_SPARC_PC10 || r_type == R_SPARC_PC22) && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") != 0)))) { /* In these cases, we don't need the relocation value. We check specially because in some obscure cases sec->output_section will be NULL. */ relocation = 0; } else relocation = (h->root.u.def.value + sec->output_section->vma + sec->output_offset); } else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared && !info->symbolic && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; else { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, rel->r_offset, (!info->shared || info->no_undefined || ELF_ST_VISIBILITY (h->other))))) return false; relocation = 0; } } switch (r_type) { case R_SPARC_GOT10: case R_SPARC_GOT13: case R_SPARC_GOT22: /* Relocation is to the entry for this symbol in the global offset table. */ if (sgot == NULL) { sgot = bfd_get_section_by_name (dynobj, ".got"); BFD_ASSERT (sgot != NULL); } if (h != NULL) { bfd_vma off; off = h->got.offset; BFD_ASSERT (off != (bfd_vma) -1); if (! elf_hash_table (info)->dynamic_sections_created || (info->shared && (info->symbolic || h->dynindx == -1) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) { /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined locally, or the symbol was forced to be local because of a version file. We must initialize this entry in the global offset table. Since the offset must always be a multiple of 4, we use the least significant bit to record whether we have initialized it already. When doing a dynamic link, we create a .rela.got relocation entry to initialize the value. This is done in the finish_dynamic_symbol routine. */ if ((off & 1) != 0) off &= ~1; else { bfd_put_32 (output_bfd, relocation, sgot->contents + off); h->got.offset |= 1; } } relocation = sgot->output_offset + off - got_base; } else { bfd_vma off; BFD_ASSERT (local_got_offsets != NULL && local_got_offsets[r_symndx] != (bfd_vma) -1); off = local_got_offsets[r_symndx]; /* The offset must always be a multiple of 4. We use the least significant bit to record whether we have already processed this entry. */ if ((off & 1) != 0) off &= ~1; else { bfd_put_32 (output_bfd, relocation, sgot->contents + off); if (info->shared) { asection *srelgot; Elf_Internal_Rela outrel; /* We need to generate a R_SPARC_RELATIVE reloc for the dynamic linker. */ srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); BFD_ASSERT (srelgot != NULL); outrel.r_offset = (sgot->output_section->vma + sgot->output_offset + off); outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE); outrel.r_addend = 0; bfd_elf32_swap_reloca_out (output_bfd, &outrel, (((Elf32_External_Rela *) srelgot->contents) + srelgot->reloc_count)); ++srelgot->reloc_count; } local_got_offsets[r_symndx] |= 1; } relocation = sgot->output_offset + off - got_base; } break; case R_SPARC_WPLT30: /* Relocation is to the entry for this symbol in the procedure linkage table. */ /* The Solaris native assembler will generate a WPLT30 reloc for a local symbol if you assemble a call from one section to another when using -K pic. We treat it as WDISP30. */ if (h == NULL) break; if (h->plt.offset == (bfd_vma) -1) { /* We didn't make a PLT entry for this symbol. This happens when statically linking PIC code, or when using -Bsymbolic. */ break; } if (splt == NULL) { splt = bfd_get_section_by_name (dynobj, ".plt"); BFD_ASSERT (splt != NULL); } relocation = (splt->output_section->vma + splt->output_offset + h->plt.offset); break; case R_SPARC_PC10: case R_SPARC_PC22: if (h != NULL && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) break; /* Fall through. */ case R_SPARC_DISP8: case R_SPARC_DISP16: case R_SPARC_DISP32: case R_SPARC_WDISP30: case R_SPARC_WDISP22: case R_SPARC_WDISP19: case R_SPARC_WDISP16: if (h == NULL || (info->symbolic && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)) break; /* Fall through. */ case R_SPARC_8: case R_SPARC_16: case R_SPARC_32: case R_SPARC_HI22: case R_SPARC_22: case R_SPARC_13: case R_SPARC_LO10: case R_SPARC_UA16: case R_SPARC_UA32: case R_SPARC_UA64: if (info->shared) { Elf_Internal_Rela outrel; boolean skip; /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ if (sreloc == NULL) { const char *name; name = (bfd_elf_string_from_elf_section (input_bfd, elf_elfheader (input_bfd)->e_shstrndx, elf_section_data (input_section)->rel_hdr.sh_name)); if (name == NULL) return false; BFD_ASSERT (strncmp (name, ".rela", 5) == 0 && strcmp (bfd_get_section_name (input_bfd, input_section), name + 5) == 0); sreloc = bfd_get_section_by_name (dynobj, name); BFD_ASSERT (sreloc != NULL); } skip = false; if (elf_section_data (input_section)->stab_info == NULL) outrel.r_offset = rel->r_offset; else { bfd_vma off; off = (_bfd_stab_section_offset (output_bfd, &elf_hash_table (info)->stab_info, input_section, &elf_section_data (input_section)->stab_info, rel->r_offset)); if (off == (bfd_vma) -1) skip = true; outrel.r_offset = off; } outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); if (skip) memset (&outrel, 0, sizeof outrel); /* h->dynindx may be -1 if the symbol was marked to become local. */ else if (h != NULL && ((! info->symbolic && h->dynindx != -1) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) { BFD_ASSERT (h->dynindx != -1); outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); outrel.r_addend = rel->r_addend; } else { if (r_type == R_SPARC_32) { outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE); outrel.r_addend = relocation + rel->r_addend; } else { long indx; if (h == NULL) sec = local_sections[r_symndx]; else { BFD_ASSERT (h->root.type == bfd_link_hash_defined || (h->root.type == bfd_link_hash_defweak)); sec = h->root.u.def.section; } if (sec != NULL && bfd_is_abs_section (sec)) indx = 0; else if (sec == NULL || sec->owner == NULL) { bfd_set_error (bfd_error_bad_value); return false; } else { asection *osec; osec = sec->output_section; indx = elf_section_data (osec)->dynindx; /* FIXME: we really should be able to link non-pic shared libraries. */ if (indx == 0) { BFD_FAIL (); (*_bfd_error_handler) (_("%s: probably compiled without -fPIC?"), bfd_get_filename (input_bfd)); bfd_set_error (bfd_error_bad_value); return false; } } outrel.r_info = ELF32_R_INFO (indx, r_type); outrel.r_addend = relocation + rel->r_addend; } } bfd_elf32_swap_reloca_out (output_bfd, &outrel, (((Elf32_External_Rela *) sreloc->contents) + sreloc->reloc_count)); ++sreloc->reloc_count; /* This reloc will be computed at runtime, so there's no need to do anything now, unless this is a RELATIVE reloc in an unallocated section. */ if (skip || (input_section->flags & SEC_ALLOC) != 0 || ELF32_R_TYPE (outrel.r_info) != R_SPARC_RELATIVE) continue; } break; default: break; } r = bfd_reloc_continue; if (r_type == R_SPARC_WDISP16) { bfd_vma x; relocation += rel->r_addend; relocation -= (input_section->output_section->vma + input_section->output_offset); relocation -= rel->r_offset; x = bfd_get_32 (input_bfd, contents + rel->r_offset); x |= ((((relocation >> 2) & 0xc000) << 6) | ((relocation >> 2) & 0x3fff)); bfd_put_32 (input_bfd, x, contents + rel->r_offset); if ((bfd_signed_vma) relocation < - 0x40000 || (bfd_signed_vma) relocation > 0x3ffff) r = bfd_reloc_overflow; else r = bfd_reloc_ok; } else if (r_type == R_SPARC_REV32) { bfd_vma x; relocation = relocation + rel->r_addend; x = bfd_get_32 (input_bfd, contents + rel->r_offset); x = x + relocation; bfd_putl32 (/*input_bfd,*/ x, contents + rel->r_offset); r = bfd_reloc_ok; } else if ((r_type == R_SPARC_WDISP30 || r_type == R_SPARC_WPLT30) && SEC_DO_RELAX (input_section) && rel->r_offset + 4 < input_section->_raw_size) {#define G0 0#define O7 15#define XCC (2 << 20)#define COND(x) (((x)&0xf)<<25)#define CONDA COND(0x8)#define INSN_BPA (F2(0,1) | CONDA | BPRED | XCC)#define INSN_BA (F2(0,2) | CONDA)#define INSN_OR F3(2, 0x2, 0)#define INSN_NOP F2(0,4) bfd_vma x, y; /* If the instruction is a call with either: restore arithmetic instruction with rd == %o7 where rs1 != %o7 and rs2 if it is register != %o7 then we can optimize if the call destination is near by changing the call into a branch always. */ x = bfd_get_32 (input_bfd, contents + rel->r_offset); y = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); if ((x & OP(~0)) == OP(1) && (y & OP(~0)) == OP(2)) { if (((y & OP3(~0)) == OP3(0x3d) /* restore */ || ((y & OP3(0x28)) == 0 /* arithmetic */ && (y & RD(~0)) == RD(O7))) && (y & RS1(~0)) != RS1(O7)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?