/** Attaches a previously unattached PE Section to the PE Section Table. This method complements * SgAsmPESection::init_from_section_table. This method initializes the section table from the section while * init_from_section_table() initializes the section from the section table. */ void SgAsmPESectionTable::add_section(SgAsmPESection *section) { ROSE_ASSERT(section!=NULL); ROSE_ASSERT(section->get_file()==get_file()); ROSE_ASSERT(section->get_header()==get_header()); ROSE_ASSERT(section->get_section_entry()==NULL); /* must not be in the section table yet */ SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header()); ROSE_ASSERT(fhdr!=NULL); /* Assign an ID if there isn't one yet. */ if (section->get_id()<0) { SgAsmGenericSectionList *seclist = fhdr->get_sections();; int max_id=0; /*assume zero is used so we start at one*/ for (size_t i=0; i<seclist->get_sections().size(); i++) { SgAsmGenericSection *s = seclist->get_sections()[i]; max_id = std::max(max_id, s->get_id()); } section->set_id(max_id+1); } /* Create a new section table entry. */ SgAsmPESectionTableEntry *entry = new SgAsmPESectionTableEntry; entry->update_from_section(section); section->set_section_entry(entry); }
/** Attaches a previously unattached ELF Section to the section table. If @p section is an ELF String Section * (SgAsmElfStringSection) that contains an ELF String Table (SgAsmElfStringTable) and the ELF Section Table has no * associated string table then the @p section will be used as the string table to hold the section names. * * This method complements SgAsmElfSection::init_from_section_table. This method initializes the section table from the * section while init_from_section_table() initializes the section from the section table. * * Returns the new section table entry linked into the AST. */ SgAsmElfSectionTableEntry * SgAsmElfSectionTable::add_section(SgAsmElfSection *section) { ROSE_ASSERT(section!=NULL); ROSE_ASSERT(section->get_file()==get_file()); ROSE_ASSERT(section->get_header()==get_header()); ROSE_ASSERT(section->get_section_entry()==NULL); /* must not be in the section table yet */ SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header()); ROSE_ASSERT(fhdr!=NULL); /* Assign an ID if there isn't one yet */ if (section->get_id()<0) { int id = fhdr->get_e_shnum(); fhdr->set_e_shnum(id+1); section->set_id(id); } /* If the supplied section is a string table and the ELF Section Table doesn't have a string table associated with it yet, * then use the supplied section as the string table to hold the names of the sections. When this happens, all sections * that are already defined in the ELF Section Table should have their names moved into the new string table. */ SgAsmElfStringSection *strsec = NULL; if (fhdr->get_e_shstrndx()==0) { strsec = dynamic_cast<SgAsmElfStringSection*>(section); if (strsec) { fhdr->set_e_shstrndx(section->get_id()); SgAsmGenericSectionList *all = fhdr->get_sections(); for (size_t i=0; i<all->get_sections().size(); i++) { SgAsmElfSection *s = dynamic_cast<SgAsmElfSection*>(all->get_sections()[i]); if (s && s->get_id()>=0 && s->get_section_entry()!=NULL) { s->allocate_name_to_storage(strsec); } } } } else { strsec = dynamic_cast<SgAsmElfStringSection*>(fhdr->get_section_by_id(fhdr->get_e_shstrndx())); ROSE_ASSERT(strsec!=NULL); } /* Make sure the name is in the correct string table */ if (strsec) section->allocate_name_to_storage(strsec); /* Create a new section table entry. */ SgAsmElfSectionTableEntry *shdr = new SgAsmElfSectionTableEntry; shdr->update_from_section(section); section->set_section_entry(shdr); return shdr; }
/* Change size of PE header based on word size */ bool SgAsmPEFileHeader::reallocate() { bool reallocated = SgAsmGenericHeader::reallocate(); /* Resize if necessary */ rose_addr_t need = sizeof(PEFileHeader_disk); if (4==get_word_size()) { need += sizeof(PE32OptHeader_disk); } else if (8==get_word_size()) { need += sizeof(PE64OptHeader_disk); } else { throw FormatError("unsupported PE word size"); } need += p_rvasize_pairs->get_pairs().size() * sizeof(SgAsmPERVASizePair::RVASizePair_disk); if (need<get_size()) { if (is_mapped()) { ROSE_ASSERT(get_mapped_size()==get_size()); set_mapped_size(need); } set_size(need); reallocated = true; } else if (need>get_size()) { get_file()->shift_extend(this, 0, need-get_size(), SgAsmGenericFile::ADDRSP_ALL, SgAsmGenericFile::ELASTIC_HOLE); reallocated = true; } /* Make sure the RVA/Size pairs at the end of the header are consistent with the sections to which they point. Reallocate() * has already been called recursively for the sections. */ update_rvasize_pairs(); /* Make sure header is consistent with sections. Reallocate() has already been called recursively for the sections. * Count the number of sections in the table and update the header's e_nsections member. */ if (p_section_table) { ROSE_ASSERT(p_section_table->get_header()==this); SgAsmGenericSectionList *all = get_sections(); p_e_nsections = 0; for (size_t i=0; i<all->get_sections().size(); i++) { SgAsmPESection *pesec = dynamic_cast<SgAsmPESection*>(all->get_sections()[i]); if (pesec && pesec->get_section_entry()!=NULL) p_e_nsections++; } rose_addr_t header_size = ALIGN_UP(p_section_table->get_offset() + p_section_table->get_size(), p_e_file_align>0 ? p_e_file_align : 1); #if 1 /* The PE Specification regarding e_header_size (known as "SizeOfHeader" on page 14 of "Microsoft Portable Executable * and Common Object File Format Specification: Revision 8.1 February 15, 2008" is not always followed. We recompute * it here as being the minimum RVA from all the sections defined in the PE Section Table, but not smaller * than the value according to the specification. This alternate value is kept if it's already in the parse tree, * otherwise we use the correct value. (RPM 2008-10-21) */ rose_addr_t min_offset = 0; for (size_t i=0, nfound=0; i<all->get_sections().size(); i++) { SgAsmPESection *pesec = dynamic_cast<SgAsmPESection*>(all->get_sections()[i]); if (pesec && pesec->get_section_entry()!=NULL) { if (0==nfound++) { min_offset = pesec->get_offset(); } else { min_offset = std::min(min_offset, pesec->get_offset() ); } } } rose_addr_t header_size2 = std::max(header_size, min_offset); if (p_e_header_size==header_size2) header_size = header_size2; /* If the original header size was zero then don't change that--leave it at zero. Some tiny executables have a zero * value here and as a result, since this is near the end of the NT Optional Header, they can truncate the file and * the loader will fill the optional header with zeros when reading. (RPM 2008-11-11) */ if (p_e_header_size==0) header_size = 0; #endif p_e_header_size = header_size; } /* The size of the optional header. If there's a section table then we use its offset to calculate the optional header * size in order to be compatible with the PE loader. Otherwise use the actual optional header size. */ if (p_section_table) { ROSE_ASSERT(p_section_table->get_offset() >= get_offset() + sizeof(PEFileHeader_disk)); p_e_nt_hdr_size = p_section_table->get_offset() - (get_offset() + sizeof(PEFileHeader_disk)); } else if (4==get_word_size()) { p_e_nt_hdr_size = sizeof(PE32OptHeader_disk); } else if (8==get_word_size()) { p_e_nt_hdr_size = sizeof(PE64OptHeader_disk); } else { throw FormatError("invalid PE word size"); } /* Update COFF symbol table related data members in the file header */ if (get_coff_symtab()) { ROSE_ASSERT(get_coff_symtab()->get_header()==this); set_e_coff_symtab(get_coff_symtab()->get_offset()); set_e_coff_nsyms(get_coff_symtab()->get_nslots()); } /* Update some additional header fields */ set_e_num_rvasize_pairs(get_rvasize_pairs()->get_pairs().size()); set_e_opt_magic(4==get_word_size() ? 0x010b : 0x020b); set_e_lmajor((get_exec_format()->get_version() >> 16) & 0xffff); set_e_lminor(get_exec_format()->get_version() & 0xffff); /* Adjust the COFF Header's e_nt_hdr_size to accommodate the NT Optional Header in such a way that EXEs from tinype.com * don't change (i.e., don't increase e_nt_hdr_size if the bytes beyond it are zero anyway, and if they aren't then adjust * it as little as possible. The RVA/Size pairs are considered to be part of the NT Optional Header. */ size_t oh_size = p_rvasize_pairs->get_pairs().size() * sizeof(SgAsmPERVASizePair::RVASizePair_disk); size_t rvasize_offset; /*offset with respect to "oh" buffer allocated below*/ if (4==get_word_size()) { oh_size += sizeof(PE32OptHeader_disk); } else if (8==get_word_size()) { oh_size += sizeof(PE64OptHeader_disk); } else { throw FormatError("unsupported PE word size"); } unsigned char *oh = new unsigned char[oh_size]; if (4==get_word_size()) { encode((PE32OptHeader_disk*)oh); rvasize_offset = sizeof(PE32OptHeader_disk); } else if (8==get_word_size()) { encode((PE64OptHeader_disk*)oh); rvasize_offset = sizeof(PE64OptHeader_disk); } else { delete[] oh; throw FormatError("unsupported PE word size"); } while (oh_size>p_e_nt_hdr_size) { if (0!=oh[oh_size-1]) break; --oh_size; } set_e_nt_hdr_size(oh_size); return reallocated; }