📄 elf.c
字号:
}}/* Create an entry in an ELF linker hash table. */struct bfd_hash_entry *_bfd_elf_link_hash_newfunc (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string;{ struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (ret == (struct elf_link_hash_entry *) NULL) ret = ((struct elf_link_hash_entry *) bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry))); if (ret == (struct elf_link_hash_entry *) NULL) return (struct bfd_hash_entry *) ret; /* Call the allocation method of the superclass. */ ret = ((struct elf_link_hash_entry *) _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); if (ret != (struct elf_link_hash_entry *) NULL) { /* Set local fields. */ ret->indx = -1; ret->size = 0; ret->dynindx = -1; ret->dynstr_index = 0; ret->weakdef = NULL; ret->got.offset = (bfd_vma) -1; ret->plt.offset = (bfd_vma) -1; ret->linker_section_pointer = (elf_linker_section_pointers_t *)0; ret->verinfo.verdef = NULL; ret->vtable_entries_used = NULL; ret->vtable_entries_size = 0; ret->vtable_parent = NULL; ret->type = STT_NOTYPE; ret->other = 0; /* Assume that we have been called by a non-ELF symbol reader. This flag is then reset by the code which reads an ELF input file. This ensures that a symbol created by a non-ELF symbol reader will have the flag set correctly. */ ret->elf_link_hash_flags = ELF_LINK_NON_ELF; } return (struct bfd_hash_entry *) ret;}/* Copy data from an indirect symbol to its direct symbol, hiding the old indirect symbol. */void_bfd_elf_link_hash_copy_indirect (dir, ind) struct elf_link_hash_entry *dir, *ind;{ /* Copy down any references that we may have already seen to the symbol which just became indirect. */ dir->elf_link_hash_flags |= (ind->elf_link_hash_flags & (ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR | ELF_LINK_HASH_REF_REGULAR_NONWEAK | ELF_LINK_NON_GOT_REF)); /* Copy over the global and procedure linkage table offset entries. These may have been already set up by a check_relocs routine. */ if (dir->got.offset == (bfd_vma) -1) { dir->got.offset = ind->got.offset; ind->got.offset = (bfd_vma) -1; } BFD_ASSERT (ind->got.offset == (bfd_vma) -1); if (dir->plt.offset == (bfd_vma) -1) { dir->plt.offset = ind->plt.offset; ind->plt.offset = (bfd_vma) -1; } BFD_ASSERT (ind->plt.offset == (bfd_vma) -1); if (dir->dynindx == -1) { dir->dynindx = ind->dynindx; dir->dynstr_index = ind->dynstr_index; ind->dynindx = -1; ind->dynstr_index = 0; } BFD_ASSERT (ind->dynindx == -1);}void_bfd_elf_link_hash_hide_symbol (info, h) struct bfd_link_info *info ATTRIBUTE_UNUSED; struct elf_link_hash_entry *h;{ h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; h->plt.offset = (bfd_vma) -1; if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0) h->dynindx = -1;}/* Initialize an ELF linker hash table. */boolean_bfd_elf_link_hash_table_init (table, abfd, newfunc) struct elf_link_hash_table *table; bfd *abfd; struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));{ table->dynamic_sections_created = false; table->dynobj = NULL; /* The first dynamic symbol is a dummy. */ table->dynsymcount = 1; table->dynstr = NULL; table->bucketcount = 0; table->needed = NULL; table->runpath = NULL; table->hgot = NULL; table->stab_info = NULL; table->dynlocal = NULL; return _bfd_link_hash_table_init (&table->root, abfd, newfunc);}/* Create an ELF linker hash table. */struct bfd_link_hash_table *_bfd_elf_link_hash_table_create (abfd) bfd *abfd;{ struct elf_link_hash_table *ret; ret = ((struct elf_link_hash_table *) bfd_alloc (abfd, sizeof (struct elf_link_hash_table))); if (ret == (struct elf_link_hash_table *) NULL) return NULL; if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc)) { bfd_release (abfd, ret); return NULL; } return &ret->root;}/* This is a hook for the ELF emulation code in the generic linker to tell the backend linker what file name to use for the DT_NEEDED entry for a dynamic object. The generic linker passes name as an empty string to indicate that no DT_NEEDED entry should be made. */voidbfd_elf_set_dt_needed_name (abfd, name) bfd *abfd; const char *name;{ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour && bfd_get_format (abfd) == bfd_object) elf_dt_name (abfd) = name;}voidbfd_elf_set_dt_needed_soname (abfd, name) bfd *abfd; const char *name;{ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour && bfd_get_format (abfd) == bfd_object) elf_dt_soname (abfd) = name;}/* Get the list of DT_NEEDED entries for a link. This is a hook for the linker ELF emulation code. */struct bfd_link_needed_list *bfd_elf_get_needed_list (abfd, info) bfd *abfd ATTRIBUTE_UNUSED; struct bfd_link_info *info;{ if (info->hash->creator->flavour != bfd_target_elf_flavour) return NULL; return elf_hash_table (info)->needed;}/* Get the list of DT_RPATH/DT_RUNPATH entries for a link. This is a hook for the linker ELF emulation code. */struct bfd_link_needed_list *bfd_elf_get_runpath_list (abfd, info) bfd *abfd ATTRIBUTE_UNUSED; struct bfd_link_info *info;{ if (info->hash->creator->flavour != bfd_target_elf_flavour) return NULL; return elf_hash_table (info)->runpath;}/* Get the name actually used for a dynamic object for a link. This is the SONAME entry if there is one. Otherwise, it is the string passed to bfd_elf_set_dt_needed_name, or it is the filename. */const char *bfd_elf_get_dt_soname (abfd) bfd *abfd;{ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour && bfd_get_format (abfd) == bfd_object) return elf_dt_name (abfd); return NULL;}/* Get the list of DT_NEEDED entries from a BFD. This is a hook for the ELF linker emulation code. */booleanbfd_elf_get_bfd_needed_list (abfd, pneeded) bfd *abfd; struct bfd_link_needed_list **pneeded;{ asection *s; bfd_byte *dynbuf = NULL; int elfsec; unsigned long link; bfd_byte *extdyn, *extdynend; size_t extdynsize; void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *)); *pneeded = NULL; if (bfd_get_flavour (abfd) != bfd_target_elf_flavour || bfd_get_format (abfd) != bfd_object) return true; s = bfd_get_section_by_name (abfd, ".dynamic"); if (s == NULL || s->_raw_size == 0) return true; dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size); if (dynbuf == NULL) goto error_return; if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0, s->_raw_size)) goto error_return; elfsec = _bfd_elf_section_from_bfd_section (abfd, s); if (elfsec == -1) goto error_return; link = elf_elfsections (abfd)[elfsec]->sh_link; extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn; swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in; extdyn = dynbuf; extdynend = extdyn + s->_raw_size; for (; extdyn < extdynend; extdyn += extdynsize) { Elf_Internal_Dyn dyn; (*swap_dyn_in) (abfd, (PTR) extdyn, &dyn); if (dyn.d_tag == DT_NULL) break; if (dyn.d_tag == DT_NEEDED) { const char *string; struct bfd_link_needed_list *l; string = bfd_elf_string_from_elf_section (abfd, link, dyn.d_un.d_val); if (string == NULL) goto error_return; l = (struct bfd_link_needed_list *) bfd_alloc (abfd, sizeof *l); if (l == NULL) goto error_return; l->by = abfd; l->name = string; l->next = *pneeded; *pneeded = l; } } free (dynbuf); return true; error_return: if (dynbuf != NULL) free (dynbuf); return false;}/* Allocate an ELF string table--force the first byte to be zero. */struct bfd_strtab_hash *_bfd_elf_stringtab_init (){ struct bfd_strtab_hash *ret; ret = _bfd_stringtab_init (); if (ret != NULL) { bfd_size_type loc; loc = _bfd_stringtab_add (ret, "", true, false); BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1); if (loc == (bfd_size_type) -1) { _bfd_stringtab_free (ret); ret = NULL; } } return ret;}/* ELF .o/exec file reading *//* Create a new bfd section from an ELF section header. */booleanbfd_section_from_shdr (abfd, shindex) bfd *abfd; unsigned int shindex;{ Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex]; Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd); struct elf_backend_data *bed = get_elf_backend_data (abfd); char *name; name = elf_string_from_elf_strtab (abfd, hdr->sh_name); switch (hdr->sh_type) { case SHT_NULL: /* Inactive section. Throw it away. */ return true; case SHT_PROGBITS: /* Normal section with contents. */ case SHT_DYNAMIC: /* Dynamic linking information. */ case SHT_NOBITS: /* .bss section. */ case SHT_HASH: /* .hash section. */ case SHT_NOTE: /* .note section. */ return _bfd_elf_make_section_from_shdr (abfd, hdr, name); case SHT_SYMTAB: /* A symbol table */ if (elf_onesymtab (abfd) == shindex) return true; BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym); BFD_ASSERT (elf_onesymtab (abfd) == 0); elf_onesymtab (abfd) = shindex; elf_tdata (abfd)->symtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr; abfd->flags |= HAS_SYMS; /* Sometimes a shared object will map in the symbol table. If SHF_ALLOC is set, and this is a shared object, then we also treat this section as a BFD section. We can not base the decision purely on SHF_ALLOC, because that flag is sometimes set in a relocateable object file, which would confuse the linker. */ if ((hdr->sh_flags & SHF_ALLOC) != 0 && (abfd->flags & DYNAMIC) != 0 && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) return false; return true; case SHT_DYNSYM: /* A dynamic symbol table */ if (elf_dynsymtab (abfd) == shindex) return true; BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym); BFD_ASSERT (elf_dynsymtab (abfd) == 0); elf_dynsymtab (abfd) = shindex; elf_tdata (abfd)->dynsymtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynsymtab_hdr; abfd->flags |= HAS_SYMS; /* Besides being a symbol table, we also treat this as a regular section, so that objcopy can handle it. */ return _bfd_elf_make_section_from_shdr (abfd, hdr, name); case SHT_STRTAB: /* A string table */ if (hdr->bfd_section != NULL) return true; if (ehdr->e_shstrndx == shindex) { elf_tdata (abfd)->shstrtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr; return true; } { unsigned int i; for (i = 1; i < ehdr->e_shnum; i++) { Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i]; if (hdr2->sh_link == shindex) { if (! bfd_section_from_shdr (abfd, i)) return false; if (elf_onesymtab (abfd) == i) { elf_tdata (abfd)->strtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr; return true; } if (elf_dynsymtab (abfd) == i) { elf_tdata (abfd)->dynstrtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynstrtab_hdr; /* We also treat this as a regular section, so that objcopy can handle it. */ break; }#if 0 /* Not handling other string tables specially right now. */ hdr2 = elf_elfsections (abfd)[i]; /* in case it moved */ /* We have a strtab for some random other section. */ newsect = (asection *) hdr2->bfd_section; if (!newsect) break; hdr->bfd_section = newsect; hdr2 = &elf_section_data (newsect)->str_hdr; *hdr2 = *hdr; elf_elfsections (abfd)[shindex] = hdr2;#endif } } } return _bfd_elf_make_section_from_shdr (abfd, hdr, name); case SHT_REL: case SHT_RELA: /* *These* do a lot of work -- but build no sections! */ { asection *target_sect; Elf_Internal_Shdr *hdr2; /* Check for a bogus link to avoid crashing. */ if (hdr->sh_link >= ehdr->e_shnum)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -