示例#1
0
/** Attaches a previously unattached ELF Segment (SgAsmElfSection) to the ELF Segment Table (SgAsmElfSegmentTable). This
 *  method complements SgAsmElfSection::init_from_segment_table. This method initializes the segment table from the segment
 *  while init_from_segment_table() initializes the segment from the segment table.
 *  
 *  ELF Segments are represented by SgAsmElfSection objects since ELF Segments and ELF Sections overlap very much in their
 *  features and thus should share an interface. An SgAsmElfSection can appear in the ELF Section Table and/or the ELF Segment
 *  Table and you can determine where it was located by calling get_section_entry() and get_segment_entry().
 *
 *  Returns the new segment table entry linked into the AST. */
SgAsmElfSegmentTableEntry *
SgAsmElfSegmentTable::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_segment_entry()==NULL);            /* must not be in the segment table yet */

    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
    ROSE_ASSERT(fhdr);
    
    /* Assign a slot in the segment table */
    int idx = fhdr->get_e_phnum();
    fhdr->set_e_phnum(idx+1);

    /* Create a new segment table entry */
    SgAsmElfSegmentTableEntry *shdr = new SgAsmElfSegmentTableEntry;
    shdr->set_index(idx);
    shdr->update_from_section(section);
    section->set_segment_entry(shdr);

    return shdr;
}
示例#2
0
/** Parses an ELF Segment (Program Header) Table and constructs and parses all segments reachable from the table. The section
 *  is extended as necessary based on the number of entries and teh size of each entry. */
SgAsmElfSegmentTable *
SgAsmElfSegmentTable::parse()
{
    SgAsmGenericSection::parse();

    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
    ROSE_ASSERT(fhdr!=NULL);
    ByteOrder sex = fhdr->get_sex();

    size_t ent_size, struct_size, opt_size, nentries;
    calculate_sizes(&ent_size, &struct_size, &opt_size, &nentries);
    ROSE_ASSERT(opt_size==fhdr->get_phextrasz() && nentries==fhdr->get_e_phnum());

    /* If the current size is very small (0 or 1 byte) then we're coming straight from the constructor and the parsing should
     * also extend this section to hold all the entries. Otherwise the caller must have assigned a specific size for a good
     * reason and we should leave that alone, reading zeros if the entries extend beyond the defined size. */
    if (get_size()<=1 && get_size()<nentries*ent_size)
        extend(nentries*ent_size - get_size());
    
    rose_addr_t offset=0;                                /* w.r.t. the beginning of this section */
    for (size_t i=0; i<nentries; i++, offset+=ent_size) {
        /* Read/decode the segment header */
        SgAsmElfSegmentTableEntry *shdr = NULL;
        if (4==fhdr->get_word_size()) {
            SgAsmElfSegmentTableEntry::Elf32SegmentTableEntry_disk disk;
            read_content_local(offset, &disk, struct_size);
            shdr = new SgAsmElfSegmentTableEntry(sex, &disk);
        } else {
            SgAsmElfSegmentTableEntry::Elf64SegmentTableEntry_disk disk;
            read_content_local(offset, &disk, struct_size);
            shdr = new SgAsmElfSegmentTableEntry(sex, &disk);
        }
        shdr->set_index(i);
        if (opt_size>0)
            shdr->get_extra() = read_content_local_ucl(offset+struct_size, opt_size);

        /* Null segments are just unused slots in the table; no real section to create */
        if (SgAsmElfSegmentTableEntry::PT_NULL == shdr->get_type())
            continue;

        /* Create SgAsmElfSection objects for each ELF Segment. However, if the ELF Segment Table describes a segment
         * that's the same offset and size as a section from the Elf Section Table (and the memory mappings are
         * consistent) then use the preexisting section instead of creating a new one. */
        SgAsmElfSection *s = NULL;
        SgAsmGenericSectionPtrList possible = fhdr->get_file()->get_sections_by_offset(shdr->get_offset(), shdr->get_filesz());
        for (size_t j=0; !s && j<possible.size(); j++) {
            if (possible[j]->get_offset()!=shdr->get_offset() || possible[j]->get_size()!=shdr->get_filesz())
                continue; /*different file extent*/
            if (possible[j]->is_mapped()) {
                if (possible[j]->get_mapped_preferred_rva()!=shdr->get_vaddr() ||
                    possible[j]->get_mapped_size()!=shdr->get_memsz())
                    continue; /*different mapped address or size*/
                unsigned section_perms = (possible[j]->get_mapped_rperm() ? 0x01 : 0x00) |
                                         (possible[j]->get_mapped_wperm() ? 0x02 : 0x00) |
                                         (possible[j]->get_mapped_xperm() ? 0x04 : 0x00);
                unsigned segment_perms = (shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_RPERM ? 0x01 : 0x00) |
                                         (shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_WPERM ? 0x02 : 0x00) |
                                         (shdr->get_flags() & SgAsmElfSegmentTableEntry::PF_XPERM ? 0x04 : 0x00);
                if (section_perms != segment_perms)
                    continue; /*different mapped permissions*/
            }

            /* Found a match. Set memory mapping params only. */
            s = dynamic_cast<SgAsmElfSection*>(possible[j]);
            if (!s) continue; /*potential match was not from the ELF Section or Segment table*/
            if (s->get_segment_entry()) continue; /*potential match is assigned to some other segment table entry*/
            s->init_from_segment_table(shdr, true); /*true=>set memory mapping params only*/
        }

        /* Create a new segment if no matching section was found. */
        if (!s) {
            if (SgAsmElfSegmentTableEntry::PT_NOTE == shdr->get_type()) {
                s = new SgAsmElfNoteSection(fhdr);
            } else {
                s = new SgAsmElfSection(fhdr);
            }
            s->init_from_segment_table(shdr);
            s->parse();
        }
    }
    return this;
}