📄 elf64-x86-64.c
字号:
off = (_bfd_stab_section_offset (output_bfd, &elf_hash_table (info)->stab_info, input_section, &elf_section_data (input_section)->stab_info, rela->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); relocate = false; } /* h->dynindx may be -1 if this 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); relocate = false; outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); outrel.r_addend = relocation + rela->r_addend; } else { if (r_type == R_X86_64_64) { relocate = true; outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); outrel.r_addend = relocation + rela->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; BFD_ASSERT (indx > 0); } relocate = false; outrel.r_info = ELF64_R_INFO (indx, r_type); outrel.r_addend = relocation + rela->r_addend; } } bfd_elf64_swap_reloca_out (output_bfd, &outrel, (((Elf64_External_Rela *) sreloc->contents) + sreloc->reloc_count)); ++sreloc->reloc_count; /* If this reloc is against an external symbol, we do not want to fiddle with the addend. Otherwise, we need to include the symbol value so that it becomes an addend for the dynamic reloc. */ if (! relocate) continue; } break; default: break; } r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rela->r_offset, relocation, rela->r_addend); if (r != bfd_reloc_ok) { switch (r) { default: case bfd_reloc_outofrange: abort (); case bfd_reloc_overflow: { const char *name; if (h != NULL) name = h->root.root.string; else { name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); if (name == NULL) return false; if (*name == '\0') name = bfd_section_name (input_bfd, sec); } if (! ((*info->callbacks->reloc_overflow) (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, rela->r_offset))) return false; } break; } } } return true;}/* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */static booleanelf64_x86_64_finish_dynamic_symbol (output_bfd, info, h, sym) bfd *output_bfd; struct bfd_link_info *info; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym;{ bfd *dynobj; dynobj = elf_hash_table (info)->dynobj; if (h->plt.offset != (bfd_vma) -1) { asection *splt; asection *sgot; asection *srela; bfd_vma plt_index; bfd_vma got_offset; Elf_Internal_Rela rela; /* This symbol has an entry in the procedure linkage table. Set it up. */ BFD_ASSERT (h->dynindx != -1); splt = bfd_get_section_by_name (dynobj, ".plt"); sgot = bfd_get_section_by_name (dynobj, ".got.plt"); srela = bfd_get_section_by_name (dynobj, ".rela.plt"); BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL); /* Get the index in the procedure linkage table which corresponds to this symbol. This is the index of this symbol in all the symbols for which we are making plt entries. The first entry in the procedure linkage table is reserved. */ plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* Get the offset into the .got table of the entry that corresponds to this function. Each .got entry is GOT_ENTRY_SIZE bytes. The first three are reserved for the dynamic linker. */ got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; /* Fill in the entry in the procedure linkage table. */ memcpy (splt->contents + h->plt.offset, elf64_x86_64_plt_entry, PLT_ENTRY_SIZE); /* Insert the relocation positions of the plt section. The magic numbers at the end of the statements are the positions of the relocations in the plt section. */ /* Put offset for jmp *name@GOTPCREL(%rip), since the instruction uses 6 bytes, subtract this value. */ bfd_put_32 (output_bfd, (sgot->output_section->vma + sgot->output_offset + got_offset - splt->output_section->vma - splt->output_offset - h->plt.offset - 6), splt->contents + h->plt.offset + 2); /* Put relocation index. */ bfd_put_32 (output_bfd, plt_index, splt->contents + h->plt.offset + 7); /* Put offset for jmp .PLT0. */ bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), splt->contents + h->plt.offset + 12); /* Fill in the entry in the global offset table, initially this points to the pushq instruction in the PLT which is at offset 6. */ bfd_put_64 (output_bfd, (splt->output_section->vma + splt->output_offset + h->plt.offset + 6), sgot->contents + got_offset); /* Fill in the entry in the .rela.plt section. */ rela.r_offset = (sgot->output_section->vma + sgot->output_offset + got_offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_JUMP_SLOT); rela.r_addend = 0; bfd_elf64_swap_reloca_out (output_bfd, &rela, ((Elf64_External_Rela *) srela->contents + plt_index)); if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value alone. */ sym->st_shndx = SHN_UNDEF; /* If the symbol is weak, we do need to clear the value. Otherwise, the PLT entry would provide a definition for the symbol even if the symbol wasn't defined anywhere, and so the symbol would never be NULL. */ if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) == 0) sym->st_value = 0; } } if (h->got.offset != (bfd_vma) -1) { asection *sgot; asection *srela; Elf_Internal_Rela rela; /* This symbol has an entry in the global offset table. Set it up. */ sgot = bfd_get_section_by_name (dynobj, ".got"); srela = bfd_get_section_by_name (dynobj, ".rela.got"); BFD_ASSERT (sgot != NULL && srela != NULL); rela.r_offset = (sgot->output_section->vma + sgot->output_offset + (h->got.offset &~ 1)); /* If this is a static link, or it is a -Bsymbolic link and the symbol is defined locally or was forced to be local because of a version file, we just want to emit a RELATIVE reloc. The entry in the global offset table will already have been initialized in the relocate_section function. */ 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))) { BFD_ASSERT((h->got.offset & 1) != 0); rela.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); rela.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); } else { BFD_ASSERT((h->got.offset & 1) == 0); bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_GLOB_DAT); rela.r_addend = 0; } bfd_elf64_swap_reloca_out (output_bfd, &rela, ((Elf64_External_Rela *) srela->contents + srela->reloc_count)); ++srela->reloc_count; } if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) { asection *s; Elf_Internal_Rela rela; /* This symbol needs a copy reloc. Set it up. */ BFD_ASSERT (h->dynindx != -1 && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak)); s = bfd_get_section_by_name (h->root.u.def.section->owner, ".rela.bss"); BFD_ASSERT (s != NULL); rela.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_COPY); rela.r_addend = 0; bfd_elf64_swap_reloca_out (output_bfd, &rela, ((Elf64_External_Rela *) s->contents + s->reloc_count)); ++s->reloc_count; } /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ if (strcmp (h->root.root.string, "_DYNAMIC") == 0 || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) sym->st_shndx = SHN_ABS; return true;}/* Finish up the dynamic sections. */static booleanelf64_x86_64_finish_dynamic_sections (output_bfd, info) bfd *output_bfd; struct bfd_link_info *info;{ bfd *dynobj; asection *sdyn; asection *sgot; dynobj = elf_hash_table (info)->dynobj; sgot = bfd_get_section_by_name (dynobj, ".got.plt"); BFD_ASSERT (sgot != NULL); sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); if (elf_hash_table (info)->dynamic_sections_created) { asection *splt; Elf64_External_Dyn *dyncon, *dynconend; BFD_ASSERT (sdyn != NULL); dyncon = (Elf64_External_Dyn *) sdyn->contents; dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; const char *name; asection *s; bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn); switch (dyn.d_tag) { default: continue; case DT_PLTGOT: name = ".got"; goto get_vma; case DT_JMPREL: name = ".rela.plt"; get_vma: s = bfd_get_section_by_name (output_bfd, name); BFD_ASSERT (s != NULL); dyn.d_un.d_ptr = s->vma; break; case DT_RELASZ: /* FIXME: This comment and code is from elf64-alpha.c: */ /* My interpretation of the TIS v1.1 ELF document indicates that RELASZ should not include JMPREL. This is not what the rest of the BFD does. It is, however, what the glibc ld.so wants. Do this fixup here until we found out who is right. */ s = bfd_get_section_by_name (output_bfd, ".rela.plt"); if (s) { /* Subtract JMPREL size from RELASZ. */ dyn.d_un.d_val -= (s->_cooked_size ? s->_cooked_size : s->_raw_size); } break; case DT_PLTRELSZ: s = bfd_get_section_by_name (output_bfd, ".rela.plt"); BFD_ASSERT (s != NULL); dyn.d_un.d_val = (s->_cooked_size != 0 ? s->_cooked_size : s->_raw_size); break; } bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); } /* Initialize the contents of the .plt section. */ splt = bfd_get_section_by_name (dynobj, ".plt"); BFD_ASSERT (splt != NULL); if (splt->_raw_size > 0) { /* Fill in the first entry in the procedure linkage table. */ memcpy (splt->contents, elf64_x86_64_plt0_entry, PLT_ENTRY_SIZE); /* Add offset for pushq GOT+8(%rip), since the instruction uses 6 bytes subtract this value. */ bfd_put_32 (output_bfd, (sgot->output_section->vma + sgot->output_offset + 8 - splt->output_section->vma - splt->output_offset - 6), splt->contents + 2); /* Add offset for jmp *GOT+16(%rip). The 12 is the offset to the end of the instruction. */ bfd_put_32 (output_bfd, (sgot->output_section->vma + sgot->output_offset + 16 - splt->output_section->vma - splt->output_offset - 12), splt->contents + 8); } elf_section_data (splt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE; } /* Set the first entry in the global offset table to the address of the dynamic section. */ if (sgot->_raw_size > 0) { if (sdyn == NULL) bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents); else bfd_put_64 (output_bfd, sdyn->output_section->vma + sdyn->output_offset, sgot->contents); /* Write GOT[1] and GOT[2], needed for the dynamic linker. */ bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + GOT_ENTRY_SIZE); bfd_put_64 (output_bfd, (bfd_vma) 0, sgot->contents + GOT_ENTRY_SIZE*2); } elf_section_data (sgot->output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE; return true;}#define TARGET_LITTLE_SYM bfd_elf64_x86_64_vec#define TARGET_LITTLE_NAME "elf64-x86-64"#define ELF_ARCH bfd_arch_i386#define ELF_MACHINE_CODE EM_X86_64#define ELF_MAXPAGESIZE 0x100000#define elf_backend_can_gc_sections 1#define elf_backend_want_got_plt 1#define elf_backend_plt_readonly 1#define elf_backend_want_plt_sym 0#define elf_backend_got_header_size (GOT_ENTRY_SIZE*3)#define elf_backend_plt_header_size PLT_ENTRY_SIZE#define elf_info_to_howto elf64_x86_64_info_to_howto#define bfd_elf64_bfd_final_link _bfd_elf64_gc_common_final_link#define bfd_elf64_bfd_link_hash_table_create \ elf64_x86_64_link_hash_table_create#define bfd_elf64_bfd_reloc_type_lookup elf64_x86_64_reloc_type_lookup#define elf_backend_adjust_dynamic_symbol elf64_x86_64_adjust_dynamic_symbol#define elf_backend_check_relocs elf64_x86_64_check_relocs#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections#define elf_backend_finish_dynamic_sections \ elf64_x86_64_finish_dynamic_sections#define elf_backend_finish_dynamic_symbol elf64_x86_64_finish_dynamic_symbol#define elf_backend_gc_mark_hook elf64_x86_64_gc_mark_hook#define elf_backend_gc_sweep_hook elf64_x86_64_gc_sweep_hook#define elf_backend_relocate_section elf64_x86_64_relocate_section#define elf_backend_size_dynamic_sections elf64_x86_64_size_dynamic_sections#define elf_backend_object_p elf64_x86_64_elf_object_p#include "elf64-target.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -