Example #1
0
/** 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);
}
Example #2
0
/** 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;
}
Example #3
0
/* 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;
}