elf32-m68k.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,163 行 · 第 1/5 页
C
2,163 行
fputc ('\n', file); return true;}/* Look through the relocs for a section during the first phase, and allocate space in the global offset table or procedure linkage table. */static booleanelf_m68k_check_relocs (abfd, info, sec, relocs) bfd *abfd; struct bfd_link_info *info; asection *sec; const Elf_Internal_Rela *relocs;{ bfd *dynobj; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; asection *sgot; asection *srelgot; asection *sreloc; if (info->relocateable) return true; dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_got_refcounts = elf_local_got_refcounts (abfd); sgot = NULL; srelgot = NULL; sreloc = NULL; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { unsigned long r_symndx; struct elf_link_hash_entry *h; r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) h = NULL; else h = sym_hashes[r_symndx - symtab_hdr->sh_info]; switch (ELF32_R_TYPE (rel->r_info)) { case R_68K_GOT8: case R_68K_GOT16: case R_68K_GOT32: if (h != NULL && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) break; /* Fall through. */ case R_68K_GOT8O: case R_68K_GOT16O: case R_68K_GOT32O: /* This symbol requires a global offset table entry. */ if (dynobj == NULL) { /* Create the .got section. */ elf_hash_table (info)->dynobj = dynobj = abfd; if (!_bfd_elf_create_got_section (dynobj, info)) return false; } if (sgot == NULL) { sgot = bfd_get_section_by_name (dynobj, ".got"); BFD_ASSERT (sgot != NULL); } 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.refcount == -1) { h->got.refcount = 1; /* 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; } /* Allocate space in the .got section. */ sgot->_raw_size += 4; /* Allocate relocation space. */ srelgot->_raw_size += sizeof (Elf32_External_Rela); } else h->got.refcount++; } else { /* This is a global offset table entry for a local symbol. */ if (local_got_refcounts == NULL) { size_t size; size = symtab_hdr->sh_info * sizeof (bfd_signed_vma); local_got_refcounts = ((bfd_signed_vma *) bfd_alloc (abfd, size)); if (local_got_refcounts == NULL) return false; elf_local_got_refcounts (abfd) = local_got_refcounts; memset (local_got_refcounts, -1, size); } if (local_got_refcounts[r_symndx] == -1) { local_got_refcounts[r_symndx] = 1; sgot->_raw_size += 4; if (info->shared) { /* If we are generating a shared object, we need to output a R_68K_RELATIVE reloc so that the dynamic linker can adjust this GOT entry. */ srelgot->_raw_size += sizeof (Elf32_External_Rela); } } else local_got_refcounts[r_symndx]++; } break; case R_68K_PLT8: case R_68K_PLT16: case R_68K_PLT32: /* 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 which is never referenced by a dynamic object, in which case we don't need to generate a procedure linkage table entry after all. */ /* If this is a local symbol, we resolve it directly without creating a procedure linkage table entry. */ if (h == NULL) continue; h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; if (h->plt.refcount == -1) h->plt.refcount = 1; else h->plt.refcount++; break; case R_68K_PLT8O: case R_68K_PLT16O: case R_68K_PLT32O: /* This symbol requires a procedure linkage table entry. */ if (h == NULL) { /* It does not make sense to have this relocation for a local symbol. FIXME: does it? How to handle it if it does make sense? */ bfd_set_error (bfd_error_bad_value); return false; } /* 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; if (h->plt.refcount == -1) h->plt.refcount = 1; else h->plt.refcount++; break; case R_68K_PC8: case R_68K_PC16: case R_68K_PC32: /* If we are creating a shared library and this is not a local symbol, we need to copy the reloc into the shared library. However when linking with -Bsymbolic and this is a global symbol which is defined in an object we are including in the link (i.e., DEF_REGULAR is set), then we can resolve the reloc directly. 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). We account for that possibility below by storing information in the pcrel_relocs_copied field of the hash table entry. */ if (!(info->shared && (sec->flags & SEC_ALLOC) != 0 && h != NULL && (!info->symbolic || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { if (h != NULL) { /* Make sure a plt entry is created for this symbol if it turns out to be a function defined by a dynamic object. */ if (h->plt.refcount == -1) h->plt.refcount = 1; else h->plt.refcount++; } break; } /* Fall through. */ case R_68K_8: case R_68K_16: case R_68K_32: if (h != NULL) { /* Make sure a plt entry is created for this symbol if it turns out to be a function defined by a dynamic object. */ if (h->plt.refcount == -1) h->plt.refcount = 1; else h->plt.refcount++; } /* If we are creating a shared library, we need to copy the reloc into the shared library. */ if (info->shared && (sec->flags & SEC_ALLOC) != 0) { /* When creating a shared object, we must copy these reloc types into the output file. We create a reloc section in dynobj and make room for this 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) { sreloc = bfd_make_section (dynobj, name); if (sreloc == NULL || !bfd_set_section_flags (dynobj, sreloc, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY)) || !bfd_set_section_alignment (dynobj, sreloc, 2)) return false; } } sreloc->_raw_size += sizeof (Elf32_External_Rela); /* If we are linking with -Bsymbolic, we count the number of PC relative relocations we have entered for this symbol, so that we can discard them again if the symbol is later defined by a regular object. Note that this function is only called if we are using an m68kelf linker hash table, which means that h is really a pointer to an elf_m68k_link_hash_entry. */ if ((ELF32_R_TYPE (rel->r_info) == R_68K_PC8 || ELF32_R_TYPE (rel->r_info) == R_68K_PC16 || ELF32_R_TYPE (rel->r_info) == R_68K_PC32) && info->symbolic) { struct elf_m68k_link_hash_entry *eh; struct elf_m68k_pcrel_relocs_copied *p; eh = (struct elf_m68k_link_hash_entry *) h; for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next) if (p->section == sreloc) break; if (p == NULL) { p = ((struct elf_m68k_pcrel_relocs_copied *) bfd_alloc (dynobj, sizeof *p)); if (p == NULL) return false; p->next = eh->pcrel_relocs_copied; eh->pcrel_relocs_copied = p; p->section = sreloc; p->count = 0; } ++p->count; } } break; /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_68K_GNU_VTINHERIT: if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return false; break; /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_68K_GNU_VTENTRY: if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return false; break; default: break; } } return true;}/* Return the section that should be marked against GC for a given relocation. */static asection *elf_m68k_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_68K_GNU_VTINHERIT: case R_68K_GNU_VTENTRY: break; default: switch (h->root.type) { default: break; 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; } } } 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 booleanelf_m68k_gc_sweep_hook (abfd, info, sec, relocs) bfd *abfd; struct bfd_link_info *info; 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; bfd *dynobj; asection *sgot; asection *srelgot; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_got_refcounts = elf_local_got_refcounts (abfd); dynobj = elf_hash_table (info)->dynobj; if (dynobj == NULL) return true; sgot = bfd_get_section_by_name (dynobj, ".got"); srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?