📄 elf.c
字号:
{ ((*_bfd_error_handler) (_("%s: invalid link %lu for reloc section %s (index %u)"), bfd_get_filename (abfd), hdr->sh_link, name, shindex)); return _bfd_elf_make_section_from_shdr (abfd, hdr, name); } /* For some incomprehensible reason Oracle distributes libraries for Solaris in which some of the objects have bogus sh_link fields. It would be nice if we could just reject them, but, unfortunately, some people need to use them. We scan through the section headers; if we find only one suitable symbol table, we clobber the sh_link to point to it. I hope this doesn't break anything. */ if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_SYMTAB && elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_DYNSYM) { int scan; int found; found = 0; for (scan = 1; scan < ehdr->e_shnum; scan++) { if (elf_elfsections (abfd)[scan]->sh_type == SHT_SYMTAB || elf_elfsections (abfd)[scan]->sh_type == SHT_DYNSYM) { if (found != 0) { found = 0; break; } found = scan; } } if (found != 0) hdr->sh_link = found; } /* Get the symbol table. */ if (elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB && ! bfd_section_from_shdr (abfd, hdr->sh_link)) return false; /* If this reloc section does not use the main symbol table we don't treat it as a reloc section. BFD can't adequately represent such a section, so at least for now, we don't try. We just present it as a normal section. We also can't use it as a reloc section if it points to the null section. */ if (hdr->sh_link != elf_onesymtab (abfd) || hdr->sh_info == SHN_UNDEF) return _bfd_elf_make_section_from_shdr (abfd, hdr, name); if (! bfd_section_from_shdr (abfd, hdr->sh_info)) return false; target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info); if (target_sect == NULL) return false; if ((target_sect->flags & SEC_RELOC) == 0 || target_sect->reloc_count == 0) hdr2 = &elf_section_data (target_sect)->rel_hdr; else { BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL); hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*hdr2)); elf_section_data (target_sect)->rel_hdr2 = hdr2; } *hdr2 = *hdr; elf_elfsections (abfd)[shindex] = hdr2; target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr); target_sect->flags |= SEC_RELOC; target_sect->relocation = NULL; target_sect->rel_filepos = hdr->sh_offset; /* In the section to which the relocations apply, mark whether its relocations are of the REL or RELA variety. */ if (hdr->sh_size != 0) elf_section_data (target_sect)->use_rela_p = (hdr->sh_type == SHT_RELA); abfd->flags |= HAS_RELOC; return true; } break; case SHT_GNU_verdef: elf_dynverdef (abfd) = shindex; elf_tdata (abfd)->dynverdef_hdr = *hdr; return _bfd_elf_make_section_from_shdr (abfd, hdr, name); break; case SHT_GNU_versym: elf_dynversym (abfd) = shindex; elf_tdata (abfd)->dynversym_hdr = *hdr; return _bfd_elf_make_section_from_shdr (abfd, hdr, name); break; case SHT_GNU_verneed: elf_dynverref (abfd) = shindex; elf_tdata (abfd)->dynverref_hdr = *hdr; return _bfd_elf_make_section_from_shdr (abfd, hdr, name); break; case SHT_SHLIB: return true; default: /* Check for any processor-specific section types. */ { if (bed->elf_backend_section_from_shdr) (*bed->elf_backend_section_from_shdr) (abfd, hdr, name); } break; } return true;}/* Given an ELF section number, retrieve the corresponding BFD section. */asection *bfd_section_from_elf_index (abfd, index) bfd *abfd; unsigned int index;{ BFD_ASSERT (index > 0 && index < SHN_LORESERVE); if (index >= elf_elfheader (abfd)->e_shnum) return NULL; return elf_elfsections (abfd)[index]->bfd_section;}boolean_bfd_elf_new_section_hook (abfd, sec) bfd *abfd; asection *sec;{ struct bfd_elf_section_data *sdata; sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, sizeof (*sdata)); if (!sdata) return false; sec->used_by_bfd = (PTR) sdata; /* Indicate whether or not this section should use RELA relocations. */ sdata->use_rela_p = get_elf_backend_data (abfd)->default_use_rela_p; return true;}/* Create a new bfd section from an ELF program header. Since program segments have no names, we generate a synthetic name of the form segment<NUM>, where NUM is generally the index in the program header table. For segments that are split (see below) we generate the names segment<NUM>a and segment<NUM>b. Note that some program segments may have a file size that is different than (less than) the memory size. All this means is that at execution the system must allocate the amount of memory specified by the memory size, but only initialize it with the first "file size" bytes read from the file. This would occur for example, with program segments consisting of combined data+bss. To handle the above situation, this routine generates TWO bfd sections for the single program segment. The first has the length specified by the file size of the segment, and the second has the length specified by the difference between the two sizes. In effect, the segment is split into it's initialized and uninitialized parts. */boolean_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename) bfd *abfd; Elf_Internal_Phdr *hdr; int index; const char *typename;{ asection *newsect; char *name; char namebuf[64]; int split; split = ((hdr->p_memsz > 0) && (hdr->p_filesz > 0) && (hdr->p_memsz > hdr->p_filesz)); sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : ""); name = bfd_alloc (abfd, strlen (namebuf) + 1); if (!name) return false; strcpy (name, namebuf); newsect = bfd_make_section (abfd, name); if (newsect == NULL) return false; newsect->vma = hdr->p_vaddr; newsect->lma = hdr->p_paddr; newsect->_raw_size = hdr->p_filesz; newsect->filepos = hdr->p_offset; newsect->flags |= SEC_HAS_CONTENTS; if (hdr->p_type == PT_LOAD) { newsect->flags |= SEC_ALLOC; newsect->flags |= SEC_LOAD; if (hdr->p_flags & PF_X) { /* FIXME: all we known is that it has execute PERMISSION, may be data. */ newsect->flags |= SEC_CODE; } } if (!(hdr->p_flags & PF_W)) { newsect->flags |= SEC_READONLY; } if (split) { sprintf (namebuf, "%s%db", typename, index); name = bfd_alloc (abfd, strlen (namebuf) + 1); if (!name) return false; strcpy (name, namebuf); newsect = bfd_make_section (abfd, name); if (newsect == NULL) return false; newsect->vma = hdr->p_vaddr + hdr->p_filesz; newsect->lma = hdr->p_paddr + hdr->p_filesz; newsect->_raw_size = hdr->p_memsz - hdr->p_filesz; if (hdr->p_type == PT_LOAD) { newsect->flags |= SEC_ALLOC; if (hdr->p_flags & PF_X) newsect->flags |= SEC_CODE; } if (!(hdr->p_flags & PF_W)) newsect->flags |= SEC_READONLY; } return true;}booleanbfd_section_from_phdr (abfd, hdr, index) bfd *abfd; Elf_Internal_Phdr *hdr; int index;{ struct elf_backend_data *bed; switch (hdr->p_type) { case PT_NULL: return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "null"); case PT_LOAD: return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "load"); case PT_DYNAMIC: return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "dynamic"); case PT_INTERP: return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "interp"); case PT_NOTE: if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note")) return false; if (! elfcore_read_notes (abfd, hdr->p_offset, hdr->p_filesz)) return false; return true; case PT_SHLIB: return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "shlib"); case PT_PHDR: return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "phdr"); default: /* Check for any processor-specific program segment types. If no handler for them, default to making "segment" sections. */ bed = get_elf_backend_data (abfd); if (bed->elf_backend_section_from_phdr) return (*bed->elf_backend_section_from_phdr) (abfd, hdr, index); else return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "segment"); }}/* Initialize REL_HDR, the section-header for new section, containing relocations against ASECT. If USE_RELA_P is true, we use RELA relocations; otherwise, we use REL relocations. */boolean_bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p) bfd *abfd; Elf_Internal_Shdr *rel_hdr; asection *asect; boolean use_rela_p;{ char *name; struct elf_backend_data *bed; bed = get_elf_backend_data (abfd); name = bfd_alloc (abfd, sizeof ".rela" + strlen (asect->name)); if (name == NULL) return false; sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name); rel_hdr->sh_name = (unsigned int) _bfd_stringtab_add (elf_shstrtab (abfd), name, true, false); if (rel_hdr->sh_name == (unsigned int) -1) return false; rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL; rel_hdr->sh_entsize = (use_rela_p ? bed->s->sizeof_rela : bed->s->sizeof_rel); rel_hdr->sh_addralign = bed->s->file_align; rel_hdr->sh_flags = 0; rel_hdr->sh_addr = 0; rel_hdr->sh_size = 0; rel_hdr->sh_offset = 0; return true;}/* Set up an ELF internal section header for a section. */static voidelf_fake_sections (abfd, asect, failedptrarg) bfd *abfd; asection *asect; PTR failedptrarg;{ struct elf_backend_data *bed = get_elf_backend_data (abfd); boolean *failedptr = (boolean *) failedptrarg; Elf_Internal_Shdr *this_hdr; if (*failedptr) { /* We already failed; just get out of the bfd_map_over_sections loop. */ return; } this_hdr = &elf_section_data (asect)->this_hdr; this_hdr->sh_name = (unsigned long) _bfd_stringtab_add (elf_shstrtab (abfd), asect->name, true, false); if (this_hdr->sh_name == (unsigned long) -1) { *failedptr = true; return; } this_hdr->sh_flags = 0; if ((asect->flags & SEC_ALLOC) != 0 || asect->user_set_vma) this_hdr->sh_addr = asect->vma; else this_hdr->sh_addr = 0; this_hdr->sh_offset = 0; this_hdr->sh_size = asect->_raw_size; this_hdr->sh_link = 0; this_hdr->sh_addralign = 1 << asect->alignment_power; /* The sh_entsize and sh_info fields may have been set already by copy_private_section_data. */ this_hdr->bfd_section = asect; this_hdr->contents = NULL; /* FIXME: This should not be based on section names. */ if (strcmp (asect->name, ".dynstr") == 0) this_hdr->sh_type = SHT_STRTAB; else if (strcmp (asect->name, ".hash") == 0) { this_hdr->sh_type = SHT_HASH; this_hdr->sh_entsize = bed->s->sizeof_hash_entry; } else if (strcmp (asect->name, ".dynsym") == 0) { this_hdr->sh_type = SHT_DYNSYM; this_hdr->sh_entsize = bed->s->sizeof_sym; } else if (strcmp (asect->name, ".dynamic") == 0) { this_hdr->sh_type = SHT_DYNAMIC; this_hdr->sh_entsize = bed->s->sizeof_dyn; } else if (strncmp (asect->name, ".rela", 5) == 0 && get_elf_backend_data (abfd)->may_use_rela_p) { this_hdr->sh_type = SHT_RELA; this_hdr->sh_entsize = bed->s->sizeof_rela; } else if (strncmp (asect->name, ".rel", 4) == 0 && get_elf_backend_data (abfd)->may_use_rel_p) { this_hdr->sh_type = SHT_REL; this_hdr->sh_entsize = bed->s->sizeof_rel; } else if (strncmp (asect->name, ".note", 5) == 0) this_hdr->sh_type = SHT_NOTE; else if (strncmp (asect->name, ".stab", 5) == 0 && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0) this_hdr->sh_type = SHT_STRTAB; else if (strcmp (asect->name, ".gnu.version") == 0) { this_hdr->sh_type = SHT_GNU_versym; this_hdr->sh_entsize = sizeof (Elf_External_Versym); } else if (strcmp (asect->name, ".gnu.version_d") == 0) { this_hdr->sh_type = SHT_GNU_verdef; this_hdr->sh_entsize = 0; /* objcopy or strip will copy over sh_info, but may not set cverdefs. The linker will set cverdefs, but sh_info will be zero. */ if (this_hdr->sh_info == 0) this_hdr->sh_info = elf_tdata (abfd)->cverdefs; else BFD_ASSERT (elf_tdata (abfd)->cverdefs == 0 || this_hdr->sh_info == elf_tdata (abfd)->cverdefs); } else if (strcmp (asect->name, ".gnu.version_r") == 0) { this_hdr->sh_type = SHT_GNU_verneed; this_hdr->sh_entsize = 0; /* objcopy or strip will copy over sh_info, but may not set cverrefs. The linker will set cverrefs, but sh_info will be zero. */ if (this_hdr->sh_info == 0) this_hdr->sh_info = elf_tdata (abfd)->cverrefs; else BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0 || this_hdr->sh_info == elf_tdata (abfd)->cverrefs); } else if ((asect->flags & SEC_ALLOC) != 0 && ((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)) this_hdr->sh_type = SHT_NOBITS; else this_hdr->sh_type = SHT_PROGBITS; if ((asect->flags & SEC_ALLOC) != 0) this_hdr->sh_flags |= SHF_ALLOC; if ((asect->flags & SEC_READONLY) == 0) this_hdr->sh_flags |= SHF_WRITE; if ((asect->flags & SEC_CODE) != 0) this_hdr->sh_flags |= SHF_EXECINSTR; /* Check for processor-specific section types. */ if (bed->elf_backend_fake_sections) (*bed->elf_backend_fake_sections) (abfd, this_hdr, asect);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -