Пример #1
0
SgAsmGenericSection *
SgAsmGenericFile::get_section_by_id(int id, size_t *nfound/*optional*/) const
{
    SgAsmGenericSectionPtrList possible = get_sections_by_id(id);
    if (nfound) *nfound = possible.size();
    return possible.size()==1 ? possible[0] : NULL;
}
Пример #2
0
/* Pre-unparsing updates */
bool
SgAsmPESectionTable::reallocate()
{
    bool reallocated = false;
    
    /* Resize based on section having largest ID */
    SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
    ROSE_ASSERT(fhdr != NULL);
    SgAsmGenericSectionPtrList sections = fhdr->get_sections()->get_sections();
    int max_id = 0;
    for (size_t i=0; i<sections.size(); i++) {

        max_id = std::max(max_id, sections[i]->get_id());

        }
    
    size_t nsections = max_id; /*PE section IDs are 1-origin*/
    size_t need = nsections * sizeof(SgAsmPESectionTableEntry::PESectionTableEntry_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;
    }

    return reallocated;
}
Пример #3
0
SgAsmGenericSection *
SgAsmGenericFile::get_section_by_name(const std::string &name, char sep/*or NUL*/, size_t *nfound/*optional*/) const
{
    SgAsmGenericSectionPtrList possible = get_sections_by_name(name, sep);
    if (nfound) *nfound = possible.size();
    return possible.size()==1 ? possible[0] : NULL;
}
Пример #4
0
/** Returns the section having a preferred or actual mapping that includes the specified virtual address. If @p use_preferred
 *  is set, then the condition is evaluated by looking at the section's preferred mapping, otherwise the actual mapping is
 *  used. If an actual mapping is used, the specified virtual address must be part of the actual mapped section, not merely in
 *  the memory region that was also mapped to satisfy alignment constraints.  If there are no sections or multiple sections
 *  satisfying this condition then a null pointer is returned. */
SgAsmGenericSection *
SgAsmGenericHeader::get_section_by_va(rose_addr_t va, bool use_preferred, size_t *nfound/*optional*/) const
{
    SgAsmGenericSectionPtrList possible = get_sections_by_va(va, use_preferred);
    if (nfound) *nfound = possible.size();
    return possible.size()==1 ? possible[0] : NULL;
}
Пример #5
0
SgAsmGenericSection *
SgAsmGenericFile::get_section_by_offset(rose_addr_t offset, rose_addr_t size, size_t *nfound) const
{
    SgAsmGenericSectionPtrList possible = get_sections_by_offset(offset, size);
    if (nfound) *nfound = possible.size();
    return possible.size()==1 ? possible[0] : NULL;
}
Пример #6
0
SgAsmGenericSectionPtrList
SgAsmGenericFile::get_sections_by_va(rose_addr_t va) const
{
    SgAsmGenericSectionPtrList retval;

    /* Holes (probably not mapped anyway) */
    for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) {
        rose_addr_t rva = va; /* Holes don't belong to any header and therefore have a zero base_va */
        if ((*i)->is_mapped() &&
            rva >= (*i)->get_mapped_preferred_rva() && rva < (*i)->get_mapped_preferred_rva() + (*i)->get_mapped_size())
            retval.push_back(*i);
    }

    /* Headers and their sections */
    for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) {
        /* Headers probably aren't mapped, but just in case... */
        rose_addr_t rva = va; /* Headers don't belong to any header and therefore have a zero base_va */
        if ((*i)->is_mapped() &&
            rva >= (*i)->get_mapped_preferred_rva() && rva < (*i)->get_mapped_preferred_rva() + (*i)->get_mapped_size())
            retval.push_back(*i);

        /* Header sections */
        const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_va(va, true);
        retval.insert(retval.end(), recurse.begin(), recurse.end());
    }
    return retval;
}
Пример #7
0
SgAsmGenericSection *
SgAsmGenericFile::get_section_by_va(rose_addr_t va, size_t *nfound/*optional*/) const
{
    SgAsmGenericSectionPtrList possible = get_sections_by_va(va);
    if (nfound) *nfound = possible.size();
    return possible.size()==1 ? possible[0] : NULL;
}
Пример #8
0
void
BinaryLoader::addSectionsForRemap(SgAsmGenericHeader* header, SgAsmGenericSectionPtrList &allSections)
{
    allSections.insert(allSections.end(),
                       header->get_sections()->get_sections().begin(),
                       header->get_sections()->get_sections().end());
}
Пример #9
0
rose_addr_t
SgAsmGenericFile::get_current_size() const
{
    rose_addr_t retval=0;
    SgAsmGenericSectionPtrList sections = get_sections();
    for (SgAsmGenericSectionPtrList::iterator i=sections.begin(); i!=sections.end(); ++i) {
        retval = std::max(retval, (*i)->get_end_offset());
    }
    return retval;
}
Пример #10
0
/** Returns sections in this header that have the specified ID. */
SgAsmGenericSectionPtrList
SgAsmGenericHeader::get_sections_by_id(int id) const
{
    SgAsmGenericSectionPtrList retval;
    for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
        if ((*i)->get_id() == id) {
            retval.push_back(*i);
        }
    }
    return retval;
}
Пример #11
0
SgAsmGenericSectionPtrList
SgAsmGenericFile::get_mapped_sections() const
{
    SgAsmGenericSectionPtrList retval;
    SgAsmGenericSectionPtrList all = get_sections(true);
    for (size_t i=0; i<all.size(); i++) {
        if (all[i]->is_mapped())
            retval.push_back(all[i]);
    }
    return retval;
}
Пример #12
0
/** Returns the list of sections that are memory mapped */
SgAsmGenericSectionPtrList
SgAsmGenericHeader::get_mapped_sections() const
{
    SgAsmGenericSectionPtrList retval;
    for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
        if ((*i)->is_mapped()) {
            retval.push_back(*i);
        }
    }
    return retval;
}
Пример #13
0
/** Get the list of sections defined in the ELF Segment Table */
SgAsmGenericSectionPtrList
SgAsmElfFileHeader::get_segtab_sections()
{
    SgAsmGenericSectionPtrList retval;
    SgAsmGenericSectionPtrList sections = get_sections()->get_sections();
    for (size_t i=0; i<sections.size(); i++) {
        SgAsmElfSection *elfsec = dynamic_cast<SgAsmElfSection*>(sections[i]);
        if (elfsec && elfsec->get_segment_entry()!=NULL)
            retval.push_back(elfsec);
    }
    return retval;
}
Пример #14
0
/* Same as parent, but also includes sections that aren't mapped but which contain code. */
SgAsmGenericSectionPtrList
BinaryLoaderElfObj::get_remap_sections(SgAsmGenericHeader *header)
{
    SgAsmGenericSectionPtrList retval = BinaryLoaderElf::get_remap_sections(header);
    const SgAsmGenericSectionPtrList &sections = header->get_sections()->get_sections();
    for (SgAsmGenericSectionPtrList::const_iterator si=sections.begin(); si!=sections.end(); ++si) {
        SgAsmGenericSection *section = *si;
        if (!section->is_mapped() && section->get_contains_code())
            retval.push_back(section);
    }
    return retval;
}
Пример #15
0
/** Returns info about the size of the entries based on information already available. Any or all arguments may be null
 *  pointers if the caller is not interested in the value. */
rose_addr_t
SgAsmElfSectionTable::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const
{
    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
    ROSE_ASSERT(fhdr!=NULL);

    size_t struct_size = 0;
    size_t extra_size = fhdr->get_shextrasz();
    size_t entry_size = 0;
    size_t nentries = 0;

    /* Size of required part of each entry */
    if (4==fhdr->get_word_size()) {
        struct_size = sizeof(SgAsmElfSectionTableEntry::Elf32SectionTableEntry_disk);
    } else if (8==fhdr->get_word_size()) {
        struct_size = sizeof(SgAsmElfSectionTableEntry::Elf64SectionTableEntry_disk);
    } else {
        throw FormatError("bad ELF word size");
    }

    /* Entire entry should be at least large enough for the required part. */
    entry_size = struct_size;

    /* Size of optional parts. If we've parsed the table then use the largest optional part, otherwise assume the entry from
     * the ELF File Header is correct. */
    SgAsmGenericSectionPtrList sections = fhdr->get_sections()->get_sections();
    for (size_t i=0; i<sections.size(); i++) {
        SgAsmElfSection *elfsec = dynamic_cast<SgAsmElfSection*>(sections[i]);
        if (elfsec && elfsec->get_section_entry()) {
            ROSE_ASSERT(elfsec->get_id()>=0);
            nentries = std::max(nentries, (size_t)elfsec->get_id()+1);
            extra_size = std::max(extra_size, elfsec->get_section_entry()->get_extra().size());
        }
    }

    /* Total number of entries. Either we haven't parsed the section table yet (nor created the sections it defines) or we
     * have. In the former case we use the setting from the ELF File Header. Otherwise the table has to be large enough to
     * store the section with the largest ID (ID also serves as the index into the ELF Section Table). */
    if (0==nentries)
        nentries = fhdr->get_e_shnum();

    /* Return values */
    if (entsize)
        *entsize = entry_size;
    if (required)
        *required = struct_size;
    if (optional)
        *optional = extra_size;
    if (entcount)
        *entcount = nentries;
    return entry_size * nentries;
}
Пример #16
0
/** Returns sections that have a preferred mapping that includes the specified relative virtual address. */
SgAsmGenericSectionPtrList
SgAsmGenericHeader::get_sections_by_rva(rose_addr_t rva) const
{
    SgAsmGenericSectionPtrList retval;
    for (SgAsmGenericSectionPtrList::iterator i = p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
        SgAsmGenericSection *section = *i;
        if (section->is_mapped() &&
            rva >= section->get_mapped_preferred_rva() && rva < section->get_mapped_preferred_rva() + section->get_mapped_size()) {
            retval.push_back(section);
        }
    }
    return retval;
}
Пример #17
0
/** Returns sectons in this header that contain all of the specified portion of the file. */
SgAsmGenericSectionPtrList
SgAsmGenericHeader::get_sections_by_offset(rose_addr_t offset, rose_addr_t size) const
{
    SgAsmGenericSectionPtrList retval;
    for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
        SgAsmGenericSection *section = *i;
        if (offset >= section->get_offset() &&
            offset < section->get_offset()+section->get_size() &&
            offset-section->get_offset() + size <= section->get_size())
            retval.push_back(section);
    }
    return retval;
}
Пример #18
0
/** Write the section table section back to disk */
void
SgAsmElfSectionTable::unparse(std::ostream &f) const
{
    SgAsmElfFileHeader *fhdr = dynamic_cast<SgAsmElfFileHeader*>(get_header());
    ROSE_ASSERT(fhdr!=NULL);
    ByteOrder::Endianness sex = fhdr->get_sex();
    SgAsmGenericSectionPtrList sections = fhdr->get_sectab_sections();

    /* Write the sections first */
    for (size_t i=0; i<sections.size(); i++)
        sections[i]->unparse(f);
    unparse_holes(f);

    /* Calculate sizes. The ELF File Header should have been updated in reallocate() prior to unparsing. */
    size_t ent_size, struct_size, opt_size, nentries;
    calculate_sizes(&ent_size, &struct_size, &opt_size, &nentries);
    ROSE_ASSERT(fhdr->get_shextrasz()==opt_size);
    ROSE_ASSERT(fhdr->get_e_shnum()==nentries);
    
    /* Write the section table entries */
    for (size_t i=0; i<sections.size(); ++i) {
        SgAsmElfSection *section = dynamic_cast<SgAsmElfSection*>(sections[i]);
        ROSE_ASSERT(section!=NULL);
        SgAsmElfSectionTableEntry *shdr = section->get_section_entry();
        ROSE_ASSERT(shdr!=NULL);
        ROSE_ASSERT(shdr->get_sh_offset()==section->get_offset());/*section table entry should have been updated in reallocate()*/

        int id = section->get_id();
        ROSE_ASSERT(id>=0 && (size_t)id<nentries);

        SgAsmElfSectionTableEntry::Elf32SectionTableEntry_disk disk32;
        SgAsmElfSectionTableEntry::Elf64SectionTableEntry_disk disk64;
        void *disk  = NULL;

        if (4==fhdr->get_word_size()) {
            disk = shdr->encode(sex, &disk32);
        } else if (8==fhdr->get_word_size()) {
            disk = shdr->encode(sex, &disk64);
        } else {
            ROSE_ASSERT(!"invalid word size");
        }

        /* The disk struct */
        rose_addr_t spos = write(f, id*ent_size, struct_size, disk);
        if (shdr->get_extra().size() > 0) {
            ROSE_ASSERT(shdr->get_extra().size()<=opt_size);
            write(f, spos, shdr->get_extra());
        }
    }
}
Пример #19
0
/* Parser */
SgAsmPESectionTable*
SgAsmPESectionTable::parse()
{
    SgAsmGenericSection::parse();

    SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
    ROSE_ASSERT(fhdr!=NULL);

    /* Parse section table and construct section objects, but do not parse the sections yet. */
    SgAsmGenericSectionPtrList pending;
    const size_t entsize = sizeof(SgAsmPESectionTableEntry::PESectionTableEntry_disk);
    for (size_t i=0; i<fhdr->get_e_nsections(); i++) {
        SgAsmPESectionTableEntry::PESectionTableEntry_disk disk;
        if (entsize!=read_content_local(i * entsize, &disk, entsize, false))
            fprintf(stderr, "SgAsmPESectionTable::parse: warning: section table entry %" PRIuPTR " at file offset 0x%08"PRIx64
                    " extends beyond end of defined section table.\n",
                    i, get_offset()+i*entsize);
        SgAsmPESectionTableEntry *entry = new SgAsmPESectionTableEntry(&disk);

        SgAsmPESection *section = NULL;
        if (entry->get_name() == ".idata") {
            section = new SgAsmPEImportSection(fhdr);
        } else {
            section = new SgAsmPESection(fhdr);
        }
        section->init_from_section_table(entry, i+1);
        pending.push_back(section);
    }

    /* Build the memory mapping like the real loader would do. This is the same code used by
     * SgAsmExecutableFileFormat::parseBinaryFormat() except we're doing it here early because we need it in the rest of the
     * PE parser. */
    ROSE_ASSERT(NULL==fhdr->get_loader_map());
    BinaryLoader *loader = BinaryLoader::lookup(fhdr); /*no need to clone; we're not changing any settings*/
    ROSE_ASSERT(loader!=NULL);
    MemoryMap *loader_map = new MemoryMap;
    loader->remap(loader_map, fhdr);
    fhdr->set_loader_map(loader_map);

    /* Parse each section after the loader map is created */
    for (size_t i=0; i<pending.size(); i++)
        pending[i]->parse();

    return this;
}
Пример #20
0
/** Returns sections having a preferred or actual mapping that includes the specified virtual address.  If @p use_preferred is
 *  set, then the condition is evaluated by looking at the section's preferred mapping, otherwise the actual mapping is used.
 *  If an actual mapping is used, the specified virtual address must be part of the actual mapped section, not merely in the
 *  memory region that was also mapped to satisfy alignment constraints. */
SgAsmGenericSectionPtrList
SgAsmGenericHeader::get_sections_by_va(rose_addr_t va, bool use_preferred) const
{
    if (use_preferred) {
        if (va < get_base_va())
            return SgAsmGenericSectionPtrList();
        rose_addr_t rva = va - get_base_va();
        return get_sections_by_rva(rva);
    }
     
    SgAsmGenericSectionPtrList retval;
    for (size_t i=0; i<p_sections->get_sections().size(); i++) {
        SgAsmGenericSection *section = p_sections->get_sections()[i];
        if (section->is_mapped() &&
            va>=section->get_mapped_actual_va() && va<section->get_mapped_actual_va()+section->get_mapped_size())
            retval.push_back(section);
    }
    return retval;
}
Пример #21
0
SgAsmGenericSectionPtrList
SgAsmGenericFile::get_sections_by_id(int id) const
{
    SgAsmGenericSectionPtrList retval;

    /* Holes */
    for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) {
        if ((*i)->get_id()==id)
            retval.push_back(*i);
    }

    /* Headers and their sections */
    for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) {
        if ((*i)->get_id()==id)
            retval.push_back(*i);
        const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_id(id);
        retval.insert(retval.end(), recurse.begin(), recurse.end());
    }
    return retval;
}
Пример #22
0
SgAsmGenericSectionPtrList
SgAsmGenericFile::get_sections_by_name(std::string name, char sep/*or NUL*/) const
{
    SgAsmGenericSectionPtrList retval;

    /* Truncate name */
    if (sep) {
        size_t pos = name.find(sep);
        if (pos!=name.npos)
            name.erase(pos);
    }

    /* Holes */
    for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) {
        std::string secname = (*i)->get_name()->get_string();
        if (sep) {
            size_t pos = secname.find(sep);
            if (pos!=secname.npos)
                secname.erase(pos);
        }
        if (0==secname.compare(name))
            retval.push_back(*i);
    }

    /* Headers and their sections */
    for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) {
        std::string secname = (*i)->get_name()->get_string();
        if (sep) {
            size_t pos = secname.find(sep);
            if (pos!=secname.npos)
                secname.erase(pos);
        }
        if (0==secname.compare(name))
            retval.push_back(*i);

        const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_name(name, sep);
        retval.insert(retval.end(), recurse.begin(), recurse.end());
    }
    return retval;
}
Пример #23
0
/** Returns sections in this header that have the specified name. If 'SEP' is a non-null string then ignore any part of name at
 *  and after SEP. */
SgAsmGenericSectionPtrList
SgAsmGenericHeader::get_sections_by_name(std::string name, char sep/*or NUL*/) const
{
    if (sep) {
        size_t pos = name.find(sep);
        if (pos!=name.npos)
            name.erase(pos);
    }

    SgAsmGenericSectionPtrList retval;
    for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
        std::string secname = (*i)->get_name()->get_string();
        if (sep) {
            size_t pos = secname.find(sep);
            if (pos!=secname.npos)
                secname.erase(pos);
        }
        if (0==secname.compare(name))
            retval.push_back(*i);
    }
    return retval;
}
Пример #24
0
SgAsmGenericSectionPtrList
SgAsmGenericFile::get_sections_by_rva(rose_addr_t rva) const
{
    SgAsmGenericSectionPtrList retval;

    /* Holes (probably not mapped anyway) */
    for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) {
        if ((*i)->is_mapped() &&
            rva >= (*i)->get_mapped_preferred_rva() && rva < (*i)->get_mapped_preferred_rva() + (*i)->get_mapped_size())
            retval.push_back(*i);
    }

    /* Headers and their sections */
    for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) {
        if ((*i)->is_mapped() &&
            rva >= (*i)->get_mapped_preferred_rva() && rva < (*i)->get_mapped_preferred_rva() + (*i)->get_mapped_size())
            retval.push_back(*i);
        const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_rva(rva);
        retval.insert(retval.end(), recurse.begin(), recurse.end());
    }
    return retval;
}
Пример #25
0
/* Returns sections to be mapped */
SgAsmGenericSectionPtrList
BinaryLoaderPe::get_remap_sections(SgAsmGenericHeader *header)
{
    SgAsmGenericSectionPtrList retval;

    /* The NT loader always loads the PE header, so we include that first in the list. */
    retval.push_back(header);

    /* Add the sections in the order they appear in the section table */
    const SgAsmGenericSectionPtrList &sections = header->get_sections()->get_sections();
    std::map<int, SgAsmGenericSection*> candidates;
    for (size_t i=0; i<sections.size(); i++) {
        if (sections[i]->get_id()>=0) {
            ROSE_ASSERT(candidates.find(sections[i]->get_id())==candidates.end());
            candidates.insert(std::make_pair(sections[i]->get_id(), sections[i]));
        }
    }
    for (std::map<int, SgAsmGenericSection*>::iterator ci=candidates.begin(); ci!=candidates.end(); ++ci) {
        retval.push_back(ci->second);
    }
    return retval;
}
Пример #26
0
/* Writes the section table back to disk. */
void
SgAsmPESectionTable::unparse(std::ostream &f) const
{
    SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
    ROSE_ASSERT(fhdr != NULL);
    SgAsmGenericSectionPtrList sections = fhdr->get_sections()->get_sections();

    for (size_t i = 0; i < sections.size(); i++) {
        if (sections[i]->get_id()>=0) {
            SgAsmPESection *section = isSgAsmPESection(sections[i]);
            ROSE_ASSERT(section!=NULL);

            /* Write the table entry */
            ROSE_ASSERT(section->get_id() > 0); /*ID's are 1-origin in PE*/
            size_t slot = section->get_id() - 1;
            SgAsmPESectionTableEntry *shdr = section->get_section_entry();
            SgAsmPESectionTableEntry::PESectionTableEntry_disk disk;
            shdr->encode(&disk);
            write(f, slot*sizeof(disk), sizeof disk, &disk);
        }
    }
}
Пример #27
0
/** Class method that prints info about offsets into known sections */
void
SgAsmGenericSection::dump_containing_sections(FILE *f, const std::string &prefix, rose_rva_t rva,
                                              const SgAsmGenericSectionPtrList &slist)
{
    for (size_t i=0; i<slist.size(); i++) {
        SgAsmGenericSection *s = slist[i];
        if (s->is_mapped() && rva>=s->get_mapped_preferred_rva() && rva<s->get_mapped_preferred_rva()+s->get_mapped_size()) {
            rose_addr_t offset = rva - s->get_mapped_preferred_rva();
            fprintf(f, "%-*s   is 0x%08"PRIx64" (%"PRIu64") bytes into section [%d] \"%s\"\n",
                    DUMP_FIELD_WIDTH, prefix.c_str(), offset, offset, s->get_id(), s->get_name()->get_string(true).c_str());
        }
    }
}
Пример #28
0
SgAsmGenericSectionPtrList
SgAsmGenericFile::get_sections_by_offset(rose_addr_t offset, rose_addr_t size) const
{
    SgAsmGenericSectionPtrList retval;

    /* Holes */
    for (SgAsmGenericSectionPtrList::iterator i=p_holes->get_sections().begin(); i!=p_holes->get_sections().end(); ++i) {
        if (offset >= (*i)->get_offset() &&
            offset < (*i)->get_offset()+(*i)->get_size() &&
            offset-(*i)->get_offset() + size <= (*i)->get_size())
            retval.push_back(*i);
    }

    /* Headers and their sections */
    for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) {
        if (offset >= (*i)->get_offset() &&
            offset < (*i)->get_offset()+(*i)->get_size() &&
            offset-(*i)->get_offset() + size <= (*i)->get_size())
            retval.push_back(*i);
        const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections_by_offset(offset, size);
        retval.insert(retval.end(), recurse.begin(), recurse.end());
    }
    return retval;
}
Пример #29
0
SgAsmGenericSectionPtrList
SgAsmGenericFile::get_sections(bool include_holes) const
{
    SgAsmGenericSectionPtrList retval;

    /* Start with headers and holes */
    retval.insert(retval.end(), p_headers->get_headers().begin(), p_headers->get_headers().end());
    if (include_holes)
        retval.insert(retval.end(), p_holes->get_sections().begin(), p_holes->get_sections().end());

    /* Add sections pointed to by headers. */
    for (SgAsmGenericHeaderPtrList::iterator i=p_headers->get_headers().begin(); i!=p_headers->get_headers().end(); ++i) {
        if ((*i)->get_sections()!=NULL) {
            const SgAsmGenericSectionPtrList &recurse = (*i)->get_sections()->get_sections();
            retval.insert(retval.end(), recurse.begin(), recurse.end());
        }
    }
    return retval;
}
Пример #30
0
void
SgAsmGenericFile::shift_extend(SgAsmGenericSection *s, rose_addr_t sa, rose_addr_t sn, AddressSpace space, Elasticity elasticity)
{
    ROSE_ASSERT(s!=NULL);
    ROSE_ASSERT(s->get_file()==this);
    ROSE_ASSERT((space & (ADDRSP_FILE|ADDRSP_MEMORY)) != 0);

    const bool debug = false;
    static size_t ncalls=0;
    char p[256];

    if (debug) {
        const char *space_s="unknown";
        if (space & ADDRSP_FILE) {
            space_s = "file";
        } else if (space & ADDRSP_MEMORY) {
            space_s = "memory";
        }
        sprintf(p, "SgAsmGenericFile::shift_extend[%" PRIuPTR "]: ", ncalls++);
        fprintf(stderr, "%s    -- START --\n", p);
        fprintf(stderr, "%s    S = [%d] \"%s\"\n", p, s->get_id(), s->get_name()->get_string(true).c_str());
        fprintf(stderr, "%s    %s Sa=0x%08" PRIx64 " (%" PRIu64 "), Sn=0x%08" PRIx64 " (%" PRIu64 ")\n",
                p, space_s, sa, sa, sn, sn);
        fprintf(stderr, "%s    elasticity = %s\n", p, (ELASTIC_NONE==elasticity ? "none" :
                                                       ELASTIC_UNREF==elasticity ? "unref" :
                                                       ELASTIC_HOLE==elasticity ? "unref+holes" :
                                                       "unknown"));
    }

    /* No-op case */
    if (0==sa && 0==sn) {
        if (debug) {
            fprintf(stderr, "%s    No change necessary.\n", p);
            fprintf(stderr, "%s    -- END --\n", p);
        }
        return;
    }

    bool filespace = (space & ADDRSP_FILE)!=0;
    bool memspace = (space & ADDRSP_MEMORY)!=0;
    rose_addr_t align=1, aligned_sa, aligned_sasn;
    SgAsmGenericSectionPtrList neighbors, villagers;
    ExtentMap amap; /* address mappings for all extents */
    Extent sp;

    /* Get a list of all sections that may need to be adjusted. */
    SgAsmGenericSectionPtrList all;
    switch (elasticity) {
      case ELASTIC_NONE:
      case ELASTIC_UNREF:
        all = filespace ? get_sections() : get_mapped_sections();
        break;
      case ELASTIC_HOLE:
        all = filespace ? get_sections(false) : get_mapped_sections();
        break;
    }
    if (debug) {
        fprintf(stderr, "%s    Following sections are in 'all' set:\n", p);
        for (size_t i=0; i<all.size(); i++) {
            Extent ep;
            if (filespace) {
                ep = all[i]->get_file_extent();
            } else {
                ROSE_ASSERT(all[i]->is_mapped());
                ep = all[i]->get_mapped_preferred_extent();
            }
            fprintf(stderr, "%s        0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64 " [%d] \"%s\"\n",
                    p, ep.relaxed_first(), ep.size(), ep.relaxed_first()+ep.size(), all[i]->get_id(),
                    all[i]->get_name()->get_string(true).c_str());
        }
    }

    for (size_t pass=0; pass<2; pass++) {
        if (debug) {
            fprintf(stderr, "%s    -- %s --\n",
                    p, 0==pass?"FIRST PASS":"******");
        }

        /* S offset and size in file or memory address space */
        if (filespace) {
            sp = s->get_file_extent();
        } else if (!memspace || !s->is_mapped()) {
            return; /*nothing to do*/
        } else {
            sp = s->get_mapped_preferred_extent();
        }

        /* Build address map */
        for (size_t i=0; i<all.size(); i++) {
            if (filespace) {
                amap.insert(all[i]->get_file_extent());
            } else {
                ROSE_ASSERT(all[i]->is_mapped());
                amap.insert(all[i]->get_mapped_preferred_extent());
            }
        }
        if (debug) {
            fprintf(stderr, "%s    Address map:\n", p);
            amap.dump_extents(stderr, (std::string(p)+"        ").c_str(), "amap");
            fprintf(stderr, "%s    Extent of S:\n", p);
            fprintf(stderr, "%s        start=0x%08" PRIx64 " size=0x%08" PRIx64 " end=0x%08" PRIx64 "\n",
                    p, sp.relaxed_first(), sp.size(), sp.relaxed_first()+sp.size());
        }

        /* Neighborhood (nhs) of S is a single extent. However, if S is zero size then nhs might be empty.  The neighborhood of
         * S is S plus all sections that overlap with S and all sections that are right-contiguous with S. */
        ExtentMap nhs_map;
        for (ExtentMap::iterator amapi=amap.begin(); amapi!=amap.end(); ++amapi) {
            if (amapi->first.relaxed_first() <= sp.relaxed_first()+sp.size() &&
                amapi->first.relaxed_first()+amapi->first.size() > sp.relaxed_first())
                nhs_map.insert(amapi->first, amapi->second);
        }
        if (debug) {
            fprintf(stderr, "%s    Neighborhood of S:\n", p);
            nhs_map.dump_extents(stderr, (std::string(p)+"        ").c_str(), "nhs_map");
        }
        Extent nhs;
        if (nhs_map.size()>0) {
            assert(nhs_map.nranges()==1);
            nhs = nhs_map.begin()->first;
        } else {
            nhs = sp;
        }

        /* What sections are in the neighborhood (including S), and right of the neighborhood? */
        neighbors.clear(); /*sections in neighborhood*/
        neighbors.push_back(s);
        villagers.clear(); /*sections right of neighborhood*/
        if (debug)
            fprintf(stderr, "%s    Ignoring left (L) sections:\n", p);
        for (size_t i=0; i<all.size(); i++) {
            SgAsmGenericSection *a = all[i];
            if (a==s) continue; /*already pushed onto neighbors*/
            Extent ap;
            if (filespace) {
                ap = a->get_file_extent();
            } else if (!a->is_mapped()) {
                continue;
            } else {
                ap = a->get_mapped_preferred_extent();
            }
            switch (ExtentMap::category(ap, nhs)) {
              case 'L':
                if (debug)
                    fprintf(stderr, "%s        L 0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64 " [%d] \"%s\"\n",
                            p, ap.relaxed_first(), ap.size(), ap.relaxed_first()+ap.size(),
                            a->get_id(), a->get_name()->get_string(true).c_str());
                break;
              case 'R':
                  if (ap.relaxed_first()==nhs.relaxed_first()+nhs.size() && 0==ap.size()) {
                    /* Empty sections immediately right of the neighborhood of S should actually be considered part of the
                     * neighborhood rather than right of it. */
                    neighbors.push_back(a);
                } else if (elasticity!=ELASTIC_NONE) {
                    /* If holes are elastic then treat things right of the hole as being part of the right village; otherwise
                     * add those sections to the neighborhood of S even though they fall outside 'nhs' (it's OK because this
                     * partitioning of sections is the only thing we use 'nhs' for anyway. */
                    villagers.push_back(a);
                } else if ('L'==ExtentMap::category(ap, sp)) {
                    /*ignore sections left of S*/
                } else {
                    neighbors.push_back(a);
                }
                break;
              default:
                if ('L'!=ExtentMap::category(ap, sp)) /*ignore sections left of S*/
                    neighbors.push_back(a);
                break;
            }
        }
        if (debug) {
            fprintf(stderr, "%s    Neighbors:\n", p);
            for (size_t i=0; i<neighbors.size(); i++) {
                SgAsmGenericSection *a = neighbors[i];
                Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent();
                rose_addr_t align = filespace ? a->get_file_alignment() : a->get_mapped_alignment();
                char cat = ExtentMap::category(ap, sp);
                fprintf(stderr, "%s        %c %c0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64,
                        p, cat, 0==ap.relaxed_first() % (align?align:1) ? ' ' : '!',
                        ap.relaxed_first(), ap.size(), ap.relaxed_first()+ap.size());
                if (strchr("RICE", cat)) {
                    fprintf(stderr, " align=0x%08" PRIx64, align);
                } else {
                    fputs("                 ", stderr);
                }
                fprintf(stderr, " [%2d] \"%s\"\n", a->get_id(), a->get_name()->get_string(true).c_str());
            }
            if (villagers.size()>0) fprintf(stderr, "%s    Villagers:\n", p);
            for (size_t i=0; i<villagers.size(); i++) {
                SgAsmGenericSection *a = villagers[i];
                Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent();
                rose_addr_t align = filespace ? a->get_file_alignment() : a->get_mapped_alignment();
                fprintf(stderr, "%s        %c %c0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64,
                        p, ExtentMap::category(ap, sp), /*cat should always be R*/
                        0==ap.relaxed_first() % (align?align:1) ? ' ' : '!',
                        ap.relaxed_first(), ap.size(), ap.relaxed_first()+ap.size());
                fputs("                 ", stderr);
                fprintf(stderr, " [%2d] \"%s\"\n", a->get_id(), a->get_name()->get_string(true).c_str());
            }
        }

        /* Adjust Sa to satisfy all alignment constraints in neighborhood(S) for sections that will move (cats R, I, C, and E). */
        align = 1;
        for (size_t i=0; i<neighbors.size(); i++) {
            SgAsmGenericSection *a = neighbors[i];
            Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent();
            if (strchr("RICE", ExtentMap::category(ap, sp))) {
                rose_addr_t x = filespace ? a->get_file_alignment() : a->get_mapped_alignment();
#if BOOST_VERSION < 106900
                align = boost::math::lcm(align, x?x:1); // deprecated in boost-1.69.0
#else
                align = boost::integer::lcm(align, x?x:1); // not present before boost-1.60.0
#endif
            }
        }
        aligned_sa = (sa/align + (sa%align?1:0))*align;
        aligned_sasn = ((sa+sn)/align + ((sa+sn)%align?1:0))*align;
        if (debug) {
            fprintf(stderr, "%s    Alignment LCM = 0x%08" PRIx64 " (%" PRIu64 ")\n", p, align, align);
            fprintf(stderr, "%s    Aligned Sa    = 0x%08" PRIx64 " (%" PRIu64 ")\n", p, aligned_sa, aligned_sa);
            fprintf(stderr, "%s    Aligned Sa+Sn = 0x%08" PRIx64 " (%" PRIu64 ")\n", p, aligned_sasn, aligned_sasn);
        }

        /* Are there any sections to the right of neighborhood(S)? If so, find the one with the lowest start address and use
         * that to define the size of the hole right of neighborhood(S). */
        if (0==villagers.size()) break;
        SgAsmGenericSection *after_hole = NULL;
        Extent hp(0, 0);
        for (size_t i=0; i<villagers.size(); i++) {
            SgAsmGenericSection *a = villagers[i];
            Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent();
            if (!after_hole || ap.relaxed_first()<hp.relaxed_first()) {
                after_hole = a;
                hp = ap;
            }
        }
        ROSE_ASSERT(after_hole);
        ROSE_ASSERT(hp.relaxed_first() > nhs.relaxed_first()+nhs.size());
        rose_addr_t hole_size = hp.relaxed_first() - (nhs.relaxed_first()+nhs.size());
        if (debug) {
            fprintf(stderr, "%s    hole size = 0x%08" PRIx64 " (%" PRIu64 "); need 0x%08" PRIx64 " (%" PRIu64 "); %s\n",
                    p, hole_size, hole_size, aligned_sasn, aligned_sasn,
                    hole_size>=aligned_sasn ? "large enough" : "not large enough");
        }
        if (hole_size >= aligned_sasn) break;
        rose_addr_t need_more = aligned_sasn - hole_size;

        /* Hole is not large enough. We need to recursively move things that are right of our neighborhood, then recompute the
         * all-sections address map and neighborhood(S). */
        ROSE_ASSERT(0==pass); /*logic problem since the recursive call should have enlarged the hole enough*/
        if (debug) {
            fprintf(stderr, "%s    Calling recursively to increase hole size by 0x%08" PRIx64 " (%" PRIu64 ") bytes\n",
                    p, need_more, need_more);
        }
        shift_extend(after_hole, need_more, 0, space, elasticity);
        if (debug) fprintf(stderr, "%s    Returned from recursive call\n", p);
    }

    /* Consider sections that are in the same neighborhood as S */
    if (debug) fprintf(stderr, "%s    -- ADJUSTING --\n", p);
    bool resized_mem = false;
    for (size_t i=0; i<neighbors.size(); i++) {
        SgAsmGenericSection *a = neighbors[i];
        Extent ap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent();
        switch (ExtentMap::category(ap, sp)) {
          case 'L':
            break;
          case 'R':
            if (filespace) {
                a->set_offset(a->get_offset()+aligned_sasn);
            } else {
                a->set_mapped_preferred_rva(a->get_mapped_preferred_rva()+aligned_sasn);
            }
            break;
          case 'C': /*including S itself*/
          case 'E':
            if (filespace) {
                a->set_offset(a->get_offset()+aligned_sa);
                a->set_size(a->get_size()+sn);
                if (memspace && !resized_mem && a->is_mapped()) {
                    shift_extend(a, 0, sn, ADDRSP_MEMORY, elasticity);
                    resized_mem = true;
                }
            } else {
                a->set_mapped_preferred_rva(a->get_mapped_preferred_rva()+aligned_sa);
                a->set_mapped_size(a->get_mapped_size()+sn);
            }
            break;
          case 'O':
              if (ap.relaxed_first()==sp.relaxed_first()) {
                if (filespace) {
                    a->set_offset(a->get_offset()+aligned_sa);
                    a->set_size(a->get_size()+sn);
                } else {
                    a->set_mapped_preferred_rva(a->get_mapped_preferred_rva()+aligned_sa);
                    a->set_mapped_size(a->get_mapped_size()+sn);
                }
            } else {
                if (filespace) {
                    a->set_size(a->get_size()+aligned_sasn);
                    if (memspace && !resized_mem && a->is_mapped()) {
                        shift_extend(a, 0, aligned_sasn, ADDRSP_MEMORY, elasticity);
                        resized_mem = true;
                    }
                } else {
                    a->set_mapped_size(a->get_mapped_size()+aligned_sasn);
                }
            }
            break;
          case 'I':
            if (filespace) {
                a->set_offset(a->get_offset()+aligned_sa);
            } else {
                a->set_mapped_preferred_rva(a->get_mapped_preferred_rva()+aligned_sa);
            }
            break;
          case 'B':
            if (filespace) {
                a->set_size(a->get_size()+sn);
                if (memspace && !resized_mem && a->is_mapped()) {
                    shift_extend(a, 0, sn, ADDRSP_MEMORY, elasticity);
                    resized_mem = true;
                }
            } else {
                a->set_mapped_size(a->get_size()+sn);
            }
            break;
          default:
            ROSE_ASSERT(!"invalid extent category");
            break;
        }
        if (debug) {
            const char *space_name = filespace ? "file" : "mem";
            rose_addr_t x = filespace ? a->get_file_alignment() : a->get_mapped_alignment();
            fprintf(stderr, "%s   %4s-%c %c0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64,
                    p, space_name, ExtentMap::category(ap, sp),
                    0==ap.relaxed_first()%(x?x:1)?' ':'!',
                    ap.relaxed_first(), ap.size(), ap.relaxed_first()+ap.size());
            Extent newap = filespace ? a->get_file_extent() : a->get_mapped_preferred_extent();
            fprintf(stderr, " -> %c0x%08" PRIx64 " 0x%08" PRIx64 " 0x%08" PRIx64,
                    0==newap.relaxed_first()%(x?x:1)?' ':'!',
                    newap.relaxed_first(), newap.size(), newap.relaxed_first()+newap.size());
            fprintf(stderr, " [%2d] \"%s\"\n", a->get_id(), a->get_name()->get_string(true).c_str());
        }
    }
    if (debug) fprintf(stderr, "%s    -- END --\n", p);
}