📄 elf32-i386.c
字号:
relocate = false; outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32); } } bfd_elf32_swap_reloc_out (output_bfd, &outrel, (((Elf32_External_Rel *) 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, rel->r_offset, relocation, (bfd_vma) 0); 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, rel->r_offset))) return false; } break; } } } return true;}/* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */static booleanelf_i386_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 *srel; bfd_vma plt_index; bfd_vma got_offset; Elf_Internal_Rel rel; /* 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"); srel = bfd_get_section_by_name (dynobj, ".rel.plt"); BFD_ASSERT (splt != NULL && sgot != NULL && srel != 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 4 bytes. The first three are reserved. */ got_offset = (plt_index + 3) * 4; /* Fill in the entry in the procedure linkage table. */ if (! info->shared) { memcpy (splt->contents + h->plt.offset, elf_i386_plt_entry, PLT_ENTRY_SIZE); bfd_put_32 (output_bfd, (sgot->output_section->vma + sgot->output_offset + got_offset), splt->contents + h->plt.offset + 2); } else { memcpy (splt->contents + h->plt.offset, elf_i386_pic_plt_entry, PLT_ENTRY_SIZE); bfd_put_32 (output_bfd, got_offset, splt->contents + h->plt.offset + 2); } bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), splt->contents + h->plt.offset + 7); 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. */ bfd_put_32 (output_bfd, (splt->output_section->vma + splt->output_offset + h->plt.offset + 6), sgot->contents + got_offset); /* Fill in the entry in the .rel.plt section. */ rel.r_offset = (sgot->output_section->vma + sgot->output_offset + got_offset); rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT); bfd_elf32_swap_reloc_out (output_bfd, &rel, ((Elf32_External_Rel *) srel->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 (h->got.offset != (bfd_vma) -1) { asection *sgot; asection *srel; Elf_Internal_Rel rel; /* This symbol has an entry in the global offset table. Set it up. */ sgot = bfd_get_section_by_name (dynobj, ".got"); srel = bfd_get_section_by_name (dynobj, ".rel.got"); BFD_ASSERT (sgot != NULL && srel != NULL); rel.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))) { rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); } else { BFD_ASSERT((h->got.offset & 1) == 0); bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); } bfd_elf32_swap_reloc_out (output_bfd, &rel, ((Elf32_External_Rel *) srel->contents + srel->reloc_count)); ++srel->reloc_count; } if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) { asection *s; Elf_Internal_Rel rel; /* 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, ".rel.bss"); BFD_ASSERT (s != NULL); rel.r_offset = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY); bfd_elf32_swap_reloc_out (output_bfd, &rel, ((Elf32_External_Rel *) 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 booleanelf_i386_finish_dynamic_sections (output_bfd, info) bfd *output_bfd; struct bfd_link_info *info;{ bfd *dynobj; asection *sgot; asection *sdyn; 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; Elf32_External_Dyn *dyncon, *dynconend; BFD_ASSERT (sdyn != NULL); dyncon = (Elf32_External_Dyn *) sdyn->contents; dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; const char *name; asection *s; bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); switch (dyn.d_tag) { default: break; case DT_PLTGOT: name = ".got"; goto get_vma; case DT_JMPREL: name = ".rel.plt"; get_vma: s = bfd_get_section_by_name (output_bfd, name); BFD_ASSERT (s != NULL); dyn.d_un.d_ptr = s->vma; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; case DT_PLTRELSZ: s = bfd_get_section_by_name (output_bfd, ".rel.plt"); BFD_ASSERT (s != NULL); if (s->_cooked_size != 0) dyn.d_un.d_val = s->_cooked_size; else dyn.d_un.d_val = s->_raw_size; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; case DT_RELSZ: /* My reading of the SVR4 ABI indicates that the procedure linkage table relocs (DT_JMPREL) should be included in the overall relocs (DT_REL). This is what Solaris does. However, UnixWare can not handle that case. Therefore, we override the DT_RELSZ entry here to make it not include the JMPREL relocs. Since the linker script arranges for .rel.plt to follow all other relocation sections, we don't have to worry about changing the DT_REL entry. */ s = bfd_get_section_by_name (output_bfd, ".rel.plt"); if (s != NULL) { if (s->_cooked_size != 0) dyn.d_un.d_val -= s->_cooked_size; else dyn.d_un.d_val -= s->_raw_size; } bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); break; } } /* Fill in the first entry in the procedure linkage table. */ splt = bfd_get_section_by_name (dynobj, ".plt"); if (splt && splt->_raw_size > 0) { if (info->shared) memcpy (splt->contents, elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE); else { memcpy (splt->contents, elf_i386_plt0_entry, PLT_ENTRY_SIZE); bfd_put_32 (output_bfd, sgot->output_section->vma + sgot->output_offset + 4, splt->contents + 2); bfd_put_32 (output_bfd, sgot->output_section->vma + sgot->output_offset + 8, splt->contents + 8); } /* UnixWare sets the entsize of .plt to 4, although that doesn't really seem like the right value. */ elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4; } } /* Fill in the first three entries in the global offset table. */ if (sgot->_raw_size > 0) { if (sdyn == NULL) bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); else bfd_put_32 (output_bfd, sdyn->output_section->vma + sdyn->output_offset, sgot->contents); bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4); bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8); } elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; return true;}/* Set the correct type for an x86 ELF section. We do this by the section name, which is a hack, but ought to work. */static booleanelf_i386_fake_sections (abfd, hdr, sec) bfd *abfd ATTRIBUTE_UNUSED; Elf32_Internal_Shdr *hdr; asection *sec;{ register const char *name; name = bfd_get_section_name (abfd, sec); if (strcmp (name, ".reloc") == 0) /* * This is an ugly, but unfortunately necessary hack that is * needed when producing EFI binaries on x86. It tells * elf.c:elf_fake_sections() not to consider ".reloc" as a section * containing ELF relocation info. We need this hack in order to * be able to generate ELF binaries that can be translated into * EFI applications (which are essentially COFF objects). Those * files contain a COFF ".reloc" section inside an ELFNN object, * which would normally cause BFD to segfault because it would * attempt to interpret this section as containing relocation * entries for section "oc". With this hack enabled, ".reloc" * will be treated as a normal data section, which will avoid the * segfault. However, you won't be able to create an ELFNN binary * with a section named "oc" that needs relocations, but that's * the kind of ugly side-effects you get when detecting section * types based on their names... In practice, this limitation is * unlikely to bite. */ hdr->sh_type = SHT_PROGBITS; return true;}#define TARGET_LITTLE_SYM bfd_elf32_i386_vec#define TARGET_LITTLE_NAME "elf32-i386"#define ELF_ARCH bfd_arch_i386#define ELF_MACHINE_CODE EM_386#define ELF_MAXPAGESIZE 0x1000#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 12#define elf_backend_plt_header_size PLT_ENTRY_SIZE#define elf_info_to_howto elf_i386_info_to_howto#define elf_info_to_howto_rel elf_i386_info_to_howto_rel#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol#define elf_backend_check_relocs elf_i386_check_relocs#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections#define elf_backend_finish_dynamic_sections elf_i386_finish_dynamic_sections#define elf_backend_finish_dynamic_symbol elf_i386_finish_dynamic_symbol#define elf_backend_gc_mark_hook elf_i386_gc_mark_hook#define elf_backend_gc_sweep_hook elf_i386_gc_sweep_hook#define elf_backend_relocate_section elf_i386_relocate_section#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections#define elf_ba
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -