elf64-sparc.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,055 行 · 第 1/5 页
C
2,055 行
if (!sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr, symbols, dynamic)) return false; if (rel_hdr2 && !sparc64_elf_slurp_one_reloc_table (abfd, asect, rel_hdr2, symbols, dynamic)) return false; return true;}/* Canonicalize the dynamic relocation entries. Note that we return the dynamic relocations as a single block, although they are actually associated with particular sections; the interface, which was designed for SunOS style shared libraries, expects that there is only one set of dynamic relocs. Any section that was actually installed in the BFD, and has type SHT_REL or SHT_RELA, and uses the dynamic symbol table, is considered to be a dynamic reloc section. */static longsparc64_elf_canonicalize_dynamic_reloc (abfd, storage, syms) bfd *abfd; arelent **storage; asymbol **syms;{ asection *s; long ret; if (elf_dynsymtab (abfd) == 0) { bfd_set_error (bfd_error_invalid_operation); return -1; } ret = 0; for (s = abfd->sections; s != NULL; s = s->next) { if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd) && (elf_section_data (s)->this_hdr.sh_type == SHT_RELA)) { arelent *p; long count, i; if (! sparc64_elf_slurp_reloc_table (abfd, s, syms, true)) return -1; count = s->reloc_count; p = s->relocation; for (i = 0; i < count; i++) *storage++ = p++; ret += count; } } *storage = NULL; return ret;}/* Write out the relocs. */static voidsparc64_elf_write_relocs (abfd, sec, data) bfd *abfd; asection *sec; PTR data;{ boolean *failedp = (boolean *) data; Elf_Internal_Shdr *rela_hdr; Elf64_External_Rela *outbound_relocas, *src_rela; unsigned int idx, count; asymbol *last_sym = 0; int last_sym_idx = 0; /* If we have already failed, don't do anything. */ if (*failedp) return; if ((sec->flags & SEC_RELOC) == 0) return; /* The linker backend writes the relocs out itself, and sets the reloc_count field to zero to inhibit writing them here. Also, sometimes the SEC_RELOC flag gets set even when there aren't any relocs. */ if (sec->reloc_count == 0) return; /* We can combine two relocs that refer to the same address into R_SPARC_OLO10 if first one is R_SPARC_LO10 and the latter is R_SPARC_13 with no associated symbol. */ count = 0; for (idx = 0; idx < sec->reloc_count; idx++) { bfd_vma addr; ++count; addr = sec->orelocation[idx]->address; if (sec->orelocation[idx]->howto->type == R_SPARC_LO10 && idx < sec->reloc_count - 1) { arelent *r = sec->orelocation[idx + 1]; if (r->howto->type == R_SPARC_13 && r->address == addr && bfd_is_abs_section ((*r->sym_ptr_ptr)->section) && (*r->sym_ptr_ptr)->value == 0) ++idx; } } rela_hdr = &elf_section_data (sec)->rel_hdr; rela_hdr->sh_size = rela_hdr->sh_entsize * count; rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size); if (rela_hdr->contents == NULL) { *failedp = true; return; } /* Figure out whether the relocations are RELA or REL relocations. */ if (rela_hdr->sh_type != SHT_RELA) abort (); /* orelocation has the data, reloc_count has the count... */ outbound_relocas = (Elf64_External_Rela *) rela_hdr->contents; src_rela = outbound_relocas; for (idx = 0; idx < sec->reloc_count; idx++) { Elf_Internal_Rela dst_rela; arelent *ptr; asymbol *sym; int n; ptr = sec->orelocation[idx]; /* The address of an ELF reloc is section relative for an object file, and absolute for an executable file or shared library. The address of a BFD reloc is always section relative. */ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) dst_rela.r_offset = ptr->address; else dst_rela.r_offset = ptr->address + sec->vma; sym = *ptr->sym_ptr_ptr; if (sym == last_sym) n = last_sym_idx; else if (bfd_is_abs_section (sym->section) && sym->value == 0) n = STN_UNDEF; else { last_sym = sym; n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym); if (n < 0) { *failedp = true; return; } last_sym_idx = n; } if ((*ptr->sym_ptr_ptr)->the_bfd != NULL && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec && ! _bfd_elf_validate_reloc (abfd, ptr)) { *failedp = true; return; } if (ptr->howto->type == R_SPARC_LO10 && idx < sec->reloc_count - 1) { arelent *r = sec->orelocation[idx + 1]; if (r->howto->type == R_SPARC_13 && r->address == ptr->address && bfd_is_abs_section ((*r->sym_ptr_ptr)->section) && (*r->sym_ptr_ptr)->value == 0) { idx++; dst_rela.r_info = ELF64_R_INFO (n, ELF64_R_TYPE_INFO (r->addend, R_SPARC_OLO10)); } else dst_rela.r_info = ELF64_R_INFO (n, R_SPARC_LO10); } else dst_rela.r_info = ELF64_R_INFO (n, ptr->howto->type); dst_rela.r_addend = ptr->addend; bfd_elf64_swap_reloca_out (abfd, &dst_rela, src_rela); ++src_rela; }}/* Sparc64 ELF linker hash table. */struct sparc64_elf_app_reg{ unsigned char bind; unsigned short shndx; bfd *abfd; char *name;};struct sparc64_elf_link_hash_table{ struct elf_link_hash_table root; struct sparc64_elf_app_reg app_regs [4];};/* Get the Sparc64 ELF linker hash table from a link_info structure. */#define sparc64_elf_hash_table(p) \ ((struct sparc64_elf_link_hash_table *) ((p)->hash))/* Create a Sparc64 ELF linker hash table. */static struct bfd_link_hash_table *sparc64_elf_bfd_link_hash_table_create (abfd) bfd *abfd;{ struct sparc64_elf_link_hash_table *ret; ret = ((struct sparc64_elf_link_hash_table *) bfd_zalloc (abfd, sizeof (struct sparc64_elf_link_hash_table))); if (ret == (struct sparc64_elf_link_hash_table *) NULL) return NULL; if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, _bfd_elf_link_hash_newfunc)) { bfd_release (abfd, ret); return NULL; } return &ret->root.root;}/* Utility for performing the standard initial work of an instruction relocation. *PRELOCATION will contain the relocated item. *PINSN will contain the instruction from the input stream. If the result is `bfd_reloc_other' the caller can continue with performing the relocation. Otherwise it must stop and return the value to its caller. */static bfd_reloc_status_typeinit_insn_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, prelocation, pinsn) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; bfd_vma *prelocation; bfd_vma *pinsn;{ bfd_vma relocation; reloc_howto_type *howto = reloc_entry->howto; if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 && (! howto->partial_inplace || reloc_entry->addend == 0)) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } /* This works because partial_inplace == false. */ if (output_bfd != NULL) return bfd_reloc_continue; if (reloc_entry->address > input_section->_cooked_size) return bfd_reloc_outofrange; relocation = (symbol->value + symbol->section->output_section->vma + symbol->section->output_offset); relocation += reloc_entry->addend; if (howto->pc_relative) { relocation -= (input_section->output_section->vma + input_section->output_offset); relocation -= reloc_entry->address; } *prelocation = relocation; *pinsn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); return bfd_reloc_other;}/* For unsupported relocs. */static bfd_reloc_status_typesparc_elf_notsup_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; PTR data ATTRIBUTE_UNUSED; asection *input_section ATTRIBUTE_UNUSED; bfd *output_bfd ATTRIBUTE_UNUSED; char **error_message ATTRIBUTE_UNUSED;{ return bfd_reloc_notsupported;}/* Handle the WDISP16 reloc. */static bfd_reloc_status_typesparc_elf_wdisp16_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED;{ bfd_vma relocation; bfd_vma insn; bfd_reloc_status_type status; status = init_insn_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, &relocation, &insn); if (status != bfd_reloc_other) return status; insn = (insn & ~0x303fff) | ((((relocation >> 2) & 0xc000) << 6) | ((relocation >> 2) & 0x3fff)); bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); if ((bfd_signed_vma) relocation < - 0x40000 || (bfd_signed_vma) relocation > 0x3ffff) return bfd_reloc_overflow; else return bfd_reloc_ok;}/* Handle the HIX22 reloc. */static bfd_reloc_status_typesparc_elf_hix22_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED;{ bfd_vma relocation; bfd_vma insn; bfd_reloc_status_type status; status = init_insn_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, &relocation, &insn); if (status != bfd_reloc_other) return status; relocation ^= MINUS_ONE; insn = (insn & ~0x3fffff) | ((relocation >> 10) & 0x3fffff); bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); if ((relocation & ~ (bfd_vma) 0xffffffff) != 0) return bfd_reloc_overflow; else return bfd_reloc_ok;}/* Handle the LOX10 reloc. */static bfd_reloc_status_typesparc_elf_lox10_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?