elf32-sparc.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,014 行 · 第 1/5 页
C
2,014 行
} if (srelgot == NULL && (h != NULL || info->shared)) { srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); if (srelgot == NULL) { srelgot = bfd_make_section (dynobj, ".rela.got"); if (srelgot == NULL || ! bfd_set_section_flags (dynobj, srelgot, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY)) || ! bfd_set_section_alignment (dynobj, srelgot, 2)) return false; } } if (h != NULL) { if (h->got.offset != (bfd_vma) -1) { /* We have already allocated space in the .got. */ break; } h->got.offset = sgot->_raw_size; /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { if (! bfd_elf32_link_record_dynamic_symbol (info, h)) return false; } srelgot->_raw_size += sizeof (Elf32_External_Rela); } else { /* This is a global offset table entry for a local symbol. */ if (local_got_offsets == NULL) { size_t size; register unsigned int i; size = symtab_hdr->sh_info * sizeof (bfd_vma); local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size); if (local_got_offsets == NULL) return false; elf_local_got_offsets (abfd) = local_got_offsets; for (i = 0; i < symtab_hdr->sh_info; i++) local_got_offsets[i] = (bfd_vma) -1; } if (local_got_offsets[r_symndx] != (bfd_vma) -1) { /* We have already allocated space in the .got. */ break; } local_got_offsets[r_symndx] = sgot->_raw_size; if (info->shared) { /* If we are generating a shared object, we need to output a R_SPARC_RELATIVE reloc so that the dynamic linker can adjust this GOT entry. */ srelgot->_raw_size += sizeof (Elf32_External_Rela); } } sgot->_raw_size += 4; /* If the .got section is more than 0x1000 bytes, we add 0x1000 to the value of _GLOBAL_OFFSET_TABLE_, so that 13 bit relocations have a greater chance of working. */ if (sgot->_raw_size >= 0x1000 && elf_hash_table (info)->hgot->root.u.def.value == 0) elf_hash_table (info)->hgot->root.u.def.value = 0x1000; break; case R_SPARC_WPLT30: /* This symbol requires a procedure linkage table entry. We actually build the entry in adjust_dynamic_symbol, because this might be a case of linking PIC code without linking in any dynamic objects, in which case we don't need to generate a procedure linkage table after all. */ if (h == NULL) { /* 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. */ break; } /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1) { if (! bfd_elf32_link_record_dynamic_symbol (info, h)) return false; } h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; break; case R_SPARC_PC10: case R_SPARC_PC22: if (h != NULL) h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; 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) h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; /* If we are linking with -Bsymbolic, we do not need to copy a PC relative reloc against a global symbol which is defined in an object we are including in the link (i.e., DEF_REGULAR is set). FIXME: At this point we have not seen all the input files, so it is possible that DEF_REGULAR is not set now but will be set later (it is never cleared). This needs to be handled as in elf32-i386.c. */ 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 (h != NULL) h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; if (info->shared) { /* When creating a shared object, we must copy these relocs into the output file. We create a reloc section in dynobj and make room for the reloc. */ if (sreloc == NULL) { const char *name; name = (bfd_elf_string_from_elf_section (abfd, elf_elfheader (abfd)->e_shstrndx, elf_section_data (sec)->rel_hdr.sh_name)); if (name == NULL) return false; BFD_ASSERT (strncmp (name, ".rela", 5) == 0 && strcmp (bfd_get_section_name (abfd, sec), name + 5) == 0); sreloc = bfd_get_section_by_name (dynobj, name); if (sreloc == NULL) { flagword flags; sreloc = bfd_make_section (dynobj, name); flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED); if ((sec->flags & SEC_ALLOC) != 0) flags |= SEC_ALLOC | SEC_LOAD; if (sreloc == NULL || ! bfd_set_section_flags (dynobj, sreloc, flags) || ! bfd_set_section_alignment (dynobj, sreloc, 2)) return false; } } sreloc->_raw_size += sizeof (Elf32_External_Rela); } break; case R_SPARC_GNU_VTINHERIT: if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return false; break; case R_SPARC_GNU_VTENTRY: if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return false; break; default: break; } } return true;}static asection *elf32_sparc_gc_mark_hook (abfd, info, rel, h, sym) bfd *abfd; struct bfd_link_info *info ATTRIBUTE_UNUSED; Elf_Internal_Rela *rel; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym;{ if (h != NULL) { switch (ELF32_R_TYPE (rel->r_info)) { case R_SPARC_GNU_VTINHERIT: case R_SPARC_GNU_VTENTRY: break; default: switch (h->root.type) { case bfd_link_hash_defined: case bfd_link_hash_defweak: return h->root.u.def.section; case bfd_link_hash_common: return h->root.u.c.p->section; default: break; } } } else { if (!(elf_bad_symtab (abfd) && ELF_ST_BIND (sym->st_info) != STB_LOCAL) && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) && sym->st_shndx != SHN_COMMON)) { return bfd_section_from_elf_index (abfd, sym->st_shndx); } } return NULL;}/* Update the got entry reference counts for the section being removed. */static booleanelf32_sparc_gc_sweep_hook (abfd, info, sec, relocs) bfd *abfd; struct bfd_link_info *info ATTRIBUTE_UNUSED; asection *sec; const Elf_Internal_Rela *relocs;{ Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; unsigned long r_symndx; struct elf_link_hash_entry *h; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_got_refcounts = elf_local_got_refcounts (abfd); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) switch (ELF32_R_TYPE (rel->r_info)) { case R_SPARC_GOT10: case R_SPARC_GOT13: case R_SPARC_GOT22: r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx >= symtab_hdr->sh_info) { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; if (h->got.refcount > 0) h->got.refcount--; } else { if (local_got_refcounts[r_symndx] > 0) local_got_refcounts[r_symndx]--; } break; case R_SPARC_PLT32: case R_SPARC_HIPLT22: case R_SPARC_LOPLT10: case R_SPARC_PCPLT32: case R_SPARC_PCPLT10: r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx >= symtab_hdr->sh_info) { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; if (h->plt.refcount > 0) h->plt.refcount--; } break; default: break; } return true;}/* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to change the definition to something the rest of the link can understand. */static booleanelf32_sparc_adjust_dynamic_symbol (info, h) struct bfd_link_info *info; struct elf_link_hash_entry *h;{ bfd *dynobj; asection *s; unsigned int power_of_two; dynobj = elf_hash_table (info)->dynobj; /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) || h->weakdef != NULL || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))); /* If this is a function, put it in the procedure linkage table. We will fill in the contents of the procedure linkage table later (although we could actually do it here). The STT_NOTYPE condition is a hack specifically for the Oracle libraries delivered for Solaris; for some inexplicable reason, they define some of their functions as STT_NOTYPE when they really should be STT_FUNC. */ if (h->type == STT_FUNC || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0 || (h->type == STT_NOTYPE && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && (h->root.u.def.section->flags & SEC_CODE) != 0)) { 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) != 0)) { /* This case can occur if we saw a WPLT30 reloc in an input file, but none of the input files were dynamic objects. Or, when linking the main application or a -Bsymbolic shared library against PIC code. Or when a global symbol has been made private, e.g. via versioning. In these cases we know what value the symbol will resolve to, so we don't actually need to build a procedure linkage table, and we can just do a WDISP30 reloc instead. */ h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; return true; } s = bfd_get_section_by_name (dynobj, ".plt"); BFD_ASSERT (s != NULL); /* The first four entries in .plt are reserved. */ if (s->_raw_size == 0) s->_raw_size = 4 * PLT_ENTRY_SIZE; /* The procedure linkage table has a maximum size. */ if (s->_raw_size >= 0x400000) { bfd_set_error (bfd_error_bad_value); return false; } /* If this symbol is not defined in a regular file, and we are not generating a shared library, then set the symbol to this location in the .plt. This is required to make function
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?