elf32-m68k.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,163 行 · 第 1/5 页
C
2,163 行
if (relocs) { if (!bfd_elf32_add_dynamic_entry (info, DT_RELA, 0) || !bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0) || !bfd_elf32_add_dynamic_entry (info, DT_RELAENT, sizeof (Elf32_External_Rela))) return false; } if (reltext) { if (!bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0)) return false; info->flags |= DF_TEXTREL; } } return true;}/* This function is called via elf_m68k_link_hash_traverse if we are creating a shared object with -Bsymbolic. It discards the space allocated to copy PC relative relocs against symbols which are defined in regular objects. We allocated space for them in the check_relocs routine, but we won't fill them in in the relocate_section routine. */static booleanelf_m68k_discard_copies (h, ignore) struct elf_m68k_link_hash_entry *h; PTR ignore ATTRIBUTE_UNUSED;{ struct elf_m68k_pcrel_relocs_copied *s; /* We only discard relocs for symbols defined in a regular object. */ if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) return true; for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) s->section->_raw_size -= s->count * sizeof (Elf32_External_Rela); return true;}/* Relocate an M68K ELF section. */static booleanelf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, contents, relocs, local_syms, local_sections) bfd *output_bfd; struct bfd_link_info *info; bfd *input_bfd; asection *input_section; bfd_byte *contents; Elf_Internal_Rela *relocs; Elf_Internal_Sym *local_syms; asection **local_sections;{ bfd *dynobj; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_vma *local_got_offsets; asection *sgot; asection *splt; asection *sreloc; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); local_got_offsets = elf_local_got_offsets (input_bfd); sgot = NULL; splt = NULL; sreloc = NULL; rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) { int r_type; reloc_howto_type *howto; unsigned long r_symndx; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; asection *sec; bfd_vma relocation; bfd_reloc_status_type r; r_type = ELF32_R_TYPE (rel->r_info); if (r_type < 0 || r_type >= (int) R_68K_max) { bfd_set_error (bfd_error_bad_value); return false; } howto = howto_table + r_type; r_symndx = ELF32_R_SYM (rel->r_info); if (info->relocateable) { /* This is a relocateable link. We don't have to change anything, unless the reloc is against a section symbol, in which case we have to adjust according to where the section symbol winds up in the output section. */ if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) { sec = local_sections[r_symndx]; rel->r_addend += sec->output_offset + sym->st_value; } } continue; } /* This is a final link. */ h = NULL; sym = NULL; sec = NULL; if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; sec = local_sections[r_symndx]; relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); } else { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { sec = h->root.u.def.section; if (((r_type == R_68K_PLT8 || r_type == R_68K_PLT16 || r_type == R_68K_PLT32 || r_type == R_68K_PLT8O || r_type == R_68K_PLT16O || r_type == R_68K_PLT32O) && h->plt.offset != (bfd_vma) -1 && elf_hash_table (info)->dynamic_sections_created) || ((r_type == R_68K_GOT8O || r_type == R_68K_GOT16O || r_type == R_68K_GOT32O || ((r_type == R_68K_GOT8 || r_type == R_68K_GOT16 || r_type == R_68K_GOT32) && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") != 0)) && 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)) || (info->shared && ((! info->symbolic && h->dynindx != -1) || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) && ((input_section->flags & SEC_ALLOC) != 0 /* DWARF will emit R_68K_32 relocations in its sections against symbols defined externally in shared libraries. We can't do anything with them here. */ || ((input_section->flags & SEC_DEBUGGING) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) && (r_type == R_68K_8 || r_type == R_68K_16 || r_type == R_68K_32 || r_type == R_68K_PC8 || r_type == R_68K_PC16 || r_type == R_68K_PC32))) { /* 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_68K_GOT8: case R_68K_GOT16: case R_68K_GOT32: /* Relocation is to the address of the entry for this symbol in the global offset table. */ 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: /* Relocation is the offset of the entry for this symbol in the global offset table. */ { bfd_vma off; if (sgot == NULL) { sgot = bfd_get_section_by_name (dynobj, ".got"); BFD_ASSERT (sgot != NULL); } if (h != NULL) { 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; } } } else { 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 generated the necessary reloc. */ 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; 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_68K_RELATIVE); outrel.r_addend = relocation; 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; if (r_type == R_68K_GOT8O || r_type == R_68K_GOT16O || r_type == R_68K_GOT32O) { /* This relocation does not use the addend. */ rel->r_addend = 0; } else relocation += sgot->output_section->vma; } break; case R_68K_PLT8: case R_68K_PLT16: case R_68K_PLT32: /* Relocation is to the entry for this symbol in the procedure linkage table. */ /* Resolve a PLTxx reloc against a local symbol directly, without using the procedure linkage table. */ if (h == NULL) break; if (h->plt.offset == (bfd_vma) -1 || !elf_hash_table (info)->dynamic_sections_created) { /* 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_68K_PLT8O: case R_68K_PLT16O: case R_68K_PLT32O: /* Relocation is the offset of the entry for this symbol in the procedure linkage table. */ BFD_ASSERT (h != NULL && h->plt.offset != (bfd_vma) -1); if (splt == NULL) { splt = bfd_get_section_by_name (dynobj, ".plt"); BFD_ASSERT (splt != NULL); } relocation = h->plt.offset; /* This relocation does not use the addend. */ rel->r_addend = 0; break; case R_68K_PC8: case R_68K_PC16: case R_68K_PC32: if (h == NULL) break; /* Fall through. */ case R_68K_8: case R_68K_16: case R_68K_32: if (info->shared && (input_section->flags & SEC_ALLOC) != 0 && ((r_type != R_68K_PC8 && r_type != R_68K_PC16 && r_type != R_68K_PC32) || (!info->symbolic || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { Elf_Internal_Rela outrel; boolean skip, relocate; /* 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; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?