예제 #1
0
int main(int argc, char *argv[]) {
    ROSE_INITIALIZE;
    Diagnostics::initAndRegister(&mlog, "tool");

    // Parse command line
    Settings settings;
    std::vector<std::string> args = parseCommandLine(argc, argv, settings).unreachedArgs();
    if (args.size()!=2)
        throw std::runtime_error("invalid usage; see --help");

    // Load the CSV files
    FunctionByAddress code1, data1, code2, data2;
    readCsvFile(args[0], code1 /*out*/, data1 /*out*/);
    readCsvFile(args[1], code2 /*out*/, data2 /*out*/);

    showStats(FileSystem::Path(args[0]).filename().string(), code1, data1,
              FileSystem::Path(args[1]).filename().string(), code2, data2);
    std::cout <<"\n";

    // Parse the specimen
    if (!settings.specimenName.empty()) {
        P2::Engine engine;
        MemoryMap::Ptr map = engine.loadSpecimens(settings.specimenName);
        InstructionProvider::Ptr insns = InstructionProvider::instance(engine.obtainDisassembler(), map);
        map->dump(std::cout);
        listInstructions(insns, map, code1, code2);
    }
}
예제 #2
0
size_t
SgAsmGenericFile::read_content(const MemoryMap::Ptr &map, rose_addr_t start_va, void *dst_buf, rose_addr_t size, bool strict)
{
    ROSE_ASSERT(map!=NULL);

    /* Note: This is the same algorithm as used by MemoryMap::read() except we do it here so that we have an opportunity
     *       to track the file byte references. */
    size_t ncopied = 0;
    while (ncopied < size) {
        rose_addr_t va = start_va + ncopied;
        size_t nread = map->at(va).limit(size-ncopied).singleSegment().read((uint8_t*)dst_buf+ncopied).size();
        if (0==nread) break;

        if (get_tracking_references()) {
            assert(map->at(va).exists());
            const MemoryMap::Node &me = *(map->at(va).findNode());
            if (me.value().buffer()->data()==&(get_data()[0])) {
                /* We are tracking file reads and this segment does, indeed, point into the file. */
                size_t file_offset = me.value().offset() + va - me.key().least();
                mark_referenced_extent(file_offset, nread);
            }
        }

        ncopied += nread;
    }

    if (ncopied<size) {
        if (strict)
            throw MemoryMap::NotMapped("SgAsmGenericFile::read_content() no mapping", map, start_va+ncopied);
        memset((char*)dst_buf+ncopied, 0, size-ncopied);                /*zero pad result if necessary*/
    }
    return ncopied;
}
예제 #3
0
static void
listInstructions(const InstructionProvider::Ptr &insns, const MemoryMap::Ptr &map,
                 const FunctionByAddress &code1, FunctionByAddress &code2) {
    std::ostream &out = std::cout;
    static const size_t insnWidth = 110;
    rose_addr_t va1 = code1.hull().least();
    rose_addr_t va2 = code2.hull().least();
    rose_addr_t va = std::min(va1, va2);
    rose_addr_t expectedVa = va;
    AsmUnparser unparser;

    while (va<=code1.hull().greatest() || va<=code2.hull().greatest()) {
        // Address and contents
        if (va != expectedVa)
            out <<"\n";                                 // visual cue that addresses are not sequential here
        std::ostringstream ss;
        size_t size;
        if (!map->at(va).require(MemoryMap::EXECUTABLE).exists()) {
            ss <<StringUtility::addrToString(va) <<": " <<(map->at(va).exists() ? "not executable" : "not mapped");
            size = 1;
        } else if (SgAsmInstruction *insn = (*insns)[va]) {
            unparser.unparse(ss, insn);
            size = insn->get_size();
        } else {
            ss <<StringUtility::addrToString(va) <<": bad instruction";
            size = 1;
        }
        std::vector<std::string> lines = StringUtility::split('\n', ss.str());
        while (lines.size()>0 && lines[lines.size()-1]=="")
            lines.pop_back();
        for (size_t i=0; i<lines.size(); ++i) {
            if (i+1 < lines.size()) {
                out <<lines[i] <<"\n";
            } else {
                out <<std::setw(insnWidth) <<std::left <<lines[i];
            }
        }
        
        // Functions owning
        Sawyer::Optional<rose_addr_t> f1 = code1.getOptional(va);
        Sawyer::Optional<rose_addr_t> f2 = code2.getOptional(va);
        out <<"\t" <<std::setw(10) <<std::left <<(f1 ? StringUtility::addrToString(*f1) : std::string("none"));
        out <<"\t" <<std::setw(10) <<std::left <<(f2 ? StringUtility::addrToString(*f2) : std::string("none"));
        out <<" " <<(f1.isEqual(f2) ? "" : "<---") <<"\n";

        // Advance address pointer
        rose_addr_t next = va + size;
        expectedVa = next;
        FunctionByAddress::ConstIntervalIterator i1 = code1.upperBound(va);
        if (i1!=code1.nodes().end() && i1->least() < next)
            next = i1->least();
        FunctionByAddress::ConstIntervalIterator i2 = code2.upperBound(va);
        if (i2!=code2.nodes().end() && i2->least() < next)
            next = i2->least();
        if (!map->atOrAfter(next).next().assignTo(va))
            break;
    }
}
예제 #4
0
 uint64_t readMemory(rose_addr_t va) const {
     MemoryMap::Ptr map = ConcreteSemantics::MemoryState::promote(ops_->currentState()->memoryState())->memoryMap();
     uint8_t buf[16];
     memset(buf, 0, sizeof buf);
     size_t nBytes = wordSize_ / 8;
     ASSERT_require(sizeof(buf) >= nBytes);
     map->at(va).limit(nBytes).read(buf);
     uint64_t retval = 0;
     for (size_t i=0; i<nBytes; ++i)
         retval |= buf[i] << (8*i);                  // FIXME[Robb P. Matzke 2015-05-19]: this is only little endian
     return retval;
 }
예제 #5
0
SgAsmInterpretation*
RSIM_ColdFire::parseMainExecutable(RSIM_Process *process) {
    namespace P2 = rose::BinaryAnalysis::Partitioner2;
    using namespace Sawyer::CommandLine;

    // This is raw hardware, so assume that all the arguments are for loading the specimen.
    P2::Engine engine;
    Parser parser;
    parser
        .purpose("initializes ColdFire memory")
        .version(std::string(ROSE_SCM_VERSION_ID).substr(0, 8), ROSE_CONFIGURE_DATE)
        .chapter(1, "ROSE Command-line Tools")
        .doc("Synopsis", "@prop{programName} ... -- [@v{loader_switches}] @v{resources}")
        .doc("Description",
             "This part of the simulator command-line is responsible for configuring how @v{resources} are loaded into "
             "simulated FreeScale ColdFire system memory.  If switches are provided here they must be separated from "
             "simulator switches with a \"--\" to prevent the simulator itself from interpreting them.\n\n" +
             engine.specimenNameDocumentation())
        .with(Switch("help", 'h')
              .hidden(true)
              .action(showHelpAndExit(0)))
        .with(engine.loaderSwitches());
    std::vector<std::string> resources = parser.parse(exeArgs()).apply().unreachedArgs();
    engine.isaName("coldfire");
    MemoryMap::Ptr map = engine.loadSpecimens(resources);
    process->mem_transaction_start("specimen main memory");
    *process->get_memory() = *map;                      // shallow copy, new segments point to same old data

    // The initial program counter is stored at address 4, the second entry in the interrupt vector.
    uint32_t initialIpBe = 0;
    if (!map->at(4).limit(sizeof initialIpBe).read((uint8_t*)&initialIpBe)) {
        mlog[FATAL] <<"failed to read initial program counter from address zero\n";
        exit(1);
    }
    uint32_t initialIp = ByteOrder::be_to_host(initialIpBe);
    process->entryPointOriginalVa(initialIp);
    process->entryPointStartVa(initialIp);

    process->disassembler(engine.obtainDisassembler());
    return engine.interpretation();                     // probably null since args not likely to be ELF or PE
}
예제 #6
0
 void reset(const MemoryMap::Ptr &map) {
     BOOST_FOREACH (MemoryMap::Segment &segment, map->segments())
         segment.buffer()->copyOnWrite(true);        // prevent the VM from changing the real map
     BaseSemantics::StatePtr state = ops_->currentState()->clone();
     state->clear();
     ConcreteSemantics::MemoryStatePtr memState = ConcreteSemantics::MemoryState::promote(state->memoryState());
     memState->memoryMap(map);
     ops_->currentState(state);
     BaseSemantics::SValuePtr sp = ops_->number_(wordSize_, stackVa_);
     ops_->writeRegister(regSp_, sp);
     ops_->writeMemory(regSs_, sp, ops_->number_(wordSize_, returnMarker_), ops_->boolean_(true));
 }
예제 #7
0
int
main(int argc, char *argv[]) {
    ROSE_INITIALIZE;

    BinaryAnalysis::Partitioner2::Engine engine;
    Settings settings;
    std::vector<std::string> specimenNames = parseCommandLine(argc, argv, engine, settings /*in,out*/);

    BinaryAnalysis::MagicNumber analyzer;
    analyzer.maxBytesToCheck(settings.maxBytes);

    MemoryMap::Ptr map = engine.loadSpecimens(specimenNames);
    map->dump(mlog[INFO]);

    size_t step = std::max(size_t(1), settings.step);
    AddressInterval limits = settings.limits.isEmpty() ? map->hull() : (settings.limits & map->hull());
    Sawyer::Container::IntervalSet<AddressInterval> addresses(*map);
    addresses.intersect(limits);
    size_t nPositions = addresses.size() / step;
    mlog[INFO] <<"approximately " <<StringUtility::plural(nPositions, "positions") <<" to check\n";

    {
        Sawyer::ProgressBar<size_t> progress(nPositions, mlog[INFO], "positions");
        for (rose_addr_t va=limits.least();
             va<=limits.greatest() && map->atOrAfter(va).next().assignTo(va);
             va+=step, ++progress) {
            std::string magicString = analyzer.identify(map, va);
            if (magicString!="data") {                  // runs home to Momma when it gets confused
                uint8_t buf[8];
                size_t nBytes = map->at(va).limit(sizeof buf).read(buf).size();
                std::cout <<StringUtility::addrToString(va) <<" |" <<leadingBytes(buf, nBytes) <<" | " <<magicString <<"\n";
            }
            if (va==limits.greatest())
                break;                                  // prevent overflow at top of address space
        }
    }
}
예제 #8
0
/* Print some debugging information */
void
SgAsmPEFileHeader::dump(FILE *f, const char *prefix, ssize_t idx) const
{
    char p[4096];
    if (idx>=0) {
        sprintf(p, "%sPEFileHeader[%zd].", prefix, idx);
    } else {
        sprintf(p, "%sPEFileHeader.", prefix);
    }

    int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
    time_t t = p_e_time;
    char time_str[128];
    struct tm *tm = localtime(&t);
    if (tm) {
        strftime(time_str, sizeof time_str, "%c", tm);
    } else {
        strcpy(time_str, "INVALID");
    }

    SgAsmGenericHeader::dump(f, p, -1);
    fprintf(f, "%s%-*s = 0x%04x (%u)\n",               p, w, "e_cpu_type",          p_e_cpu_type, p_e_cpu_type);
    fprintf(f, "%s%-*s = %u\n",                        p, w, "e_nsections",         p_e_nsections);
    fprintf(f, "%s%-*s = %u (%s)\n",                   p, w, "e_time",              p_e_time, time_str);
    fprintf(f, "%s%-*s = 0x%08" PRIx64 " (%" PRIu64 ")\n", p, w, "e_coff_symtab",   p_e_coff_symtab, p_e_coff_symtab);
    fprintf(f, "%s%-*s = %u\n",                        p, w, "e_coff_nsyms",        p_e_coff_nsyms);
    if (p_coff_symtab) {
        fprintf(f, "%s%-*s = [%d] \"%s\"\n",           p, w, "coff_symtab",
                p_coff_symtab->get_id(), p_coff_symtab->get_name()->get_string(true).c_str());
    } else {
        fprintf(f, "%s%-*s = none\n",                  p, w, "coff_symtab");
    }
    fprintf(f, "%s%-*s = 0x%08" PRIx64 " (%" PRIu64 ")\n", p, w, "e_nt_hdr_size",   p_e_nt_hdr_size, p_e_nt_hdr_size);
    fprintf(f, "%s%-*s = 0x%04x (%u)\n",               p, w, "e_flags",             p_e_flags, p_e_flags);
    fprintf(f, "%s%-*s = 0x%04x %s\n",                 p, w, "e_opt_magic",         p_e_opt_magic,
            0x10b == p_e_opt_magic ? "PE32" : (0x20b == p_e_opt_magic ? "PE32+" : "other"));
    fprintf(f, "%s%-*s = %u.%u\n",                     p, w, "linker_vers",         p_e_lmajor, p_e_lminor);
    fprintf(f, "%s%-*s = 0x%08x (%u) bytes\n",         p, w, "e_code_size",         p_e_code_size, p_e_code_size);
    fprintf(f, "%s%-*s = 0x%08x (%u) bytes\n",         p, w, "e_data_size",         p_e_data_size, p_e_data_size);
    fprintf(f, "%s%-*s = 0x%08x (%u) bytes\n",         p, w, "e_bss_size",          p_e_bss_size, p_e_bss_size);
    fprintf(f, "%s%-*s = %s\n",                        p, w, "e_code_rva",          p_e_code_rva.to_string().c_str());
    fprintf(f, "%s%-*s = %s\n",                        p, w, "e_data_rva",          p_e_data_rva.to_string().c_str());
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_section_align",     p_e_section_align, p_e_section_align);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_file_align",        p_e_file_align, p_e_file_align);
    fprintf(f, "%s%-*s = %u.%u\n",                     p, w, "os_vers",             p_e_os_major, p_e_os_minor);
    fprintf(f, "%s%-*s = %u.%u\n",                     p, w, "user_vers",           p_e_user_major, p_e_user_minor);
    fprintf(f, "%s%-*s = %u.%u\n",                     p, w, "subsys_vers",         p_e_subsys_major, p_e_subsys_minor);
    fprintf(f, "%s%-*s = %u\n",                        p, w, "e_reserved9",         p_e_reserved9);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_image_size",        p_e_image_size, p_e_image_size);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_header_size",       p_e_header_size, p_e_header_size);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_file_checksum",     p_e_file_checksum, p_e_file_checksum);
    fprintf(f, "%s%-*s = %u\n",                        p, w, "e_subsystem",         p_e_subsystem);
    fprintf(f, "%s%-*s = 0x%04x (%u)\n",               p, w, "e_dll_flags",         p_e_dll_flags, p_e_dll_flags);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_stack_reserve_size",
            p_e_stack_reserve_size, p_e_stack_reserve_size);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_stack_commit_size", p_e_stack_commit_size, p_e_stack_commit_size);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_heap_reserve_size", p_e_heap_reserve_size, p_e_heap_reserve_size);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_heap_commit_size",  p_e_heap_commit_size, p_e_heap_commit_size);
    fprintf(f, "%s%-*s = 0x%08x (%u)\n",               p, w, "e_loader_flags",      p_e_loader_flags, p_e_loader_flags);
    fprintf(f, "%s%-*s = %u\n",                        p, w, "e_num_rvasize_pairs", p_e_num_rvasize_pairs);
    for (unsigned i = 0; i < p_rvasize_pairs->get_pairs().size(); i++) {
        char p2[256];
        int nprint __attribute__((unused)) = snprintf(p2, sizeof p2, "%s.pair[%d].", p, i);
        assert((size_t)nprint<sizeof p2);
        w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p2));
        fprintf(f, "%s%-*s = rva %s,\tsize 0x%08" PRIx64 " (%" PRIu64 ")\n", p2, w, "..",
                p_rvasize_pairs->get_pairs()[i]->get_e_rva().to_string().c_str(),
                p_rvasize_pairs->get_pairs()[i]->get_e_size(), p_rvasize_pairs->get_pairs()[i]->get_e_size());
    }
    if (p_section_table) {
        fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "section_table",
                p_section_table->get_id(), p_section_table->get_name()->get_string(true).c_str());
    } else {
        fprintf(f, "%s%-*s = none\n", p, w, "section_table");
    }

    if (variantT() == V_SgAsmPEFileHeader) //unless a base class
        hexdump(f, 0, std::string(p)+"data at ", p_data);

    /* Show the simulated loader memory map */
    const MemoryMap::Ptr map = get_loader_map();
    if (map) {
        map->dump(f, (std::string(p)+"loader_map: ").c_str());
    } else {
        fprintf(f, "%s%-*s = not defined\n", p, w, "loader_map");
    }
}
예제 #9
0
/* Looks at the RVA/Size pairs in the PE header and creates an SgAsmGenericSection object for each one.  This must be done
 * after we build the mapping from virtual addresses to file offsets. */
void
SgAsmPEFileHeader::create_table_sections()
{

    /* First, only create the sections. */
    for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++) {
        SgAsmPERVASizePair *pair = p_rvasize_pairs->get_pairs()[i];
        if (0==pair->get_e_size())
            continue;

        /* Table names come from PE file specification and are hard coded by RVA/Size pair index */
        const char *tabname_short;
        std::string tabname = rvasize_pair_name((PairPurpose)i, &tabname_short);

        /* Find the starting offset in the file.
         * FIXME: We have a potential problem here in that ROSE sections are always contiguous in the file but a section created
         *        from an RVA/Size pair is not necessarily contiguous in the file.  Normally such sections are in fact
         *        contiguous and we'll just ignore this for now.  In any case, as long as these sections only ever read their
         *        data via the same MemoryMap that we use here, everything should be fine. [RPM 2009-08-17] */
        rose_addr_t pair_va = get_base_va() + pair->get_e_rva();
        MemoryMap::Ptr map = get_loader_map();
        ROSE_ASSERT(map!=NULL);
        if (!map->baseSize(pair_va, pair->get_e_size()).exists(Sawyer::Container::MATCH_WHOLE)) {
            mlog[WARN] <<"SgAsmPEFileHeader::create_table_sections: pair-" <<i
                       <<", rva=" <<StringUtility::addrToString(pair->get_e_rva().get_rva())
                       <<", size=" <<StringUtility::plural(pair->get_e_size(), "bytes")
                       <<" \"" <<StringUtility::cEscape(tabname) <<"\":"
                       <<" unable to find a mapping for the virtual address (skipping)\n";
            continue;
        }
        const MemoryMap::Node &me = *map->at(pair_va).findNode();
        rose_addr_t file_offset = me.value().offset() + pair_va - me.key().least();

        /* Create the new section */
        SgAsmGenericSection *tabsec = NULL;
        switch (i) {
            case 0: {
                /* Sometimes export sections are represented by a ".edata" section, and sometimes they're represented by an
                 * RVA/Size pair, sometimes both point to the same part of the file, and sometimes the RVA/Size pair points to
                 * a different part of the file. We don't want the exports duplicated in the AST, so we only create this table
                 * as exports if we haven't already seen some other export section. */
                SgAsmGenericSectionPtrList &sections = get_sections()->get_sections();
                bool seen_exports = false;
                for (SgAsmGenericSectionPtrList::iterator si=sections.begin(); !seen_exports && si!=sections.end(); ++si)
                    seen_exports = isSgAsmPEExportSection(*si);
                if (seen_exports) {
                    tabsec = new SgAsmGenericSection(get_file(), this);
                } else {
                    tabsec = new SgAsmPEExportSection(this);
                }
                break;
            }
            case 1: {
                /* Sometimes import sections are represented by a ".idata" section, and sometimes they're represented by an
                 * RVA/Size pair, and sometimes both point to the same part of the file.  We don't want the imports duplicated
                 * in the AST, so we only create this table as imports if we haven't already seen some other import section. */
                SgAsmGenericSectionPtrList &sections = get_sections()->get_sections();
                bool seen_imports = false;
                for (SgAsmGenericSectionPtrList::iterator si=sections.begin(); !seen_imports && si!=sections.end(); ++si)
                    seen_imports = isSgAsmPEImportSection(*si);
                if (seen_imports) {
                    tabsec = new SgAsmGenericSection(get_file(), this);
                } else {
                    tabsec = new SgAsmPEImportSection(this);
                }
                break;
            }
            default: {
                tabsec = new SgAsmGenericSection(get_file(), this);
                break;
            }
        }
        tabsec->set_name(new SgAsmBasicString(tabname));
        tabsec->set_short_name(tabname_short);
        tabsec->set_synthesized(true);
        tabsec->set_purpose(SP_HEADER);

        tabsec->set_offset(file_offset);
        tabsec->set_size(pair->get_e_size());
        tabsec->set_file_alignment(1);

        tabsec->set_mapped_alignment(1);
        tabsec->set_mapped_preferred_rva(pair->get_e_rva().get_rva());
        tabsec->set_mapped_actual_va(pair->get_e_rva().get_rva()+get_base_va()); /*FIXME: not sure this is correct. [RPM 2009-09-11]*/
        tabsec->set_mapped_size(pair->get_e_size());
        tabsec->set_mapped_rperm(true);
        tabsec->set_mapped_wperm(false);
        tabsec->set_mapped_xperm(false);
        pair->set_section(tabsec);
        pair->set_e_rva(pair->get_e_rva().set_section(tabsec));
    }

    /* Now parse the sections */
    for (size_t i=0; i<p_rvasize_pairs->get_pairs().size(); i++) {
        SgAsmPERVASizePair *pair = p_rvasize_pairs->get_pairs()[i];
        SgAsmGenericSection *tabsec = pair->get_section();
        if (tabsec)
            tabsec->parse();
    }
}
예제 #10
0
 std::string readString(rose_addr_t va) const {
     MemoryMap::Ptr map = ConcreteSemantics::MemoryState::promote(ops_->currentState()->memoryState())->memoryMap();
     return map->readString(va, 256 /*arbitrary*/);
 }