Exemplo n.º 1
0
bool InputProcessor::check(InputGroup keyGroup) const
{
	for (unsigned int i = 0; i < keyGroup.getKeyCount(); ++i)
		if (check(keyGroup.get(i))) return true;

	return false;
}
Exemplo n.º 2
0
// Return the specified queue of the specified input group.
static InputQueue &
queue(int igroup_id, InputQueueName qn)
{
    InputGroup *ig = igroup(igroup_id);
    if (!ig)
        throw Exception("input group "+StringUtility::numberToString(igroup_id)+" does not exist");
    return ig->queue(qn);
}
Exemplo n.º 3
0
// Return the input group with the specified ID, loading it from the database if necessary.
static InputGroup *
igroup(int igroup_id)
{
    InputGroups::iterator found = igroup_cache.find(igroup_id);
    if (found!=igroup_cache.end())
        return found->second;

    InputGroup *igroup = new InputGroup;
    if (!igroup->load(transaction, igroup_id)) {
        delete igroup;
        igroup_cache.insert(std::make_pair(igroup_id, (InputGroup*)0));
        return NULL;
    }

    igroup_cache.insert(std::make_pair(igroup_id, igroup));
    return igroup;
}
Exemplo n.º 4
0
bool InputGroup::containsAllOf(const InputGroup & input) const
{
	for (std::vector<Input>::const_iterator it = myKeys.begin(); it != myKeys.end(); ++it)
	{
		if (!input.contains(*it))
			return false;
	}
	return true;
}
Exemplo n.º 5
0
int
main(int argc, char *argv[])
{
    std::ios::sync_with_stdio();
    argv0 = argv[0];
    {
        size_t slash = argv0.rfind('/');
        argv0 = slash==std::string::npos ? argv0 : argv0.substr(slash+1);
        if (0==argv0.substr(0, 3).compare("lt-"))
            argv0 = argv0.substr(3);
    }

    // Parse switches
    Switches opt;
    int argno = 1, ngenerators = 0;
    for (/*void*/; argno<argc && '-'==argv[argno][0]; ++argno) {
        if (!strcmp(argv[argno], "--")) {
            ++argno;
            break;
        } else if (!strcmp(argv[argno], "--help") || !strcmp(argv[argno], "-h")) {
            usage(0);
        } else if (!strncmp(argv[argno], "--ngroups=", 10)) {
            opt.ngroups = strtoul(argv[argno]+10, NULL, 0);
            opt.ngroups_set = true;
        } else if (!strcmp(argv[argno], "--collection")) {
            opt.single_collection = true;
        } else if (!strncmp(argv[argno], "--collection=", 13)) {
            opt.collection_id = strtoul(argv[argno]+13, NULL, 0);
            opt.collection_id_set = opt.single_collection = true;
        } else if (!strncmp(argv[argno], "--default=", 10)) {
            opt.default_queue = parse_queuename(argv[argno]+10);
        } else if (!strcmp(argv[argno], "--memhash") || !strncmp(argv[argno], "--memhash=", 10)) {
            std::string s;
            if (char *equal = strchr(argv[argno], '='))
                s = equal+1;
            std::vector<std::string> valargs = StringUtility::split(',', s, 3);
            valargs.resize(3);
            if (valargs[0].empty())
                valargs[0] = "0";
            if (valargs[1].empty())
                valargs[1] = "255";
            std::vector<std::string> randargs(1, "1");
            randargs.push_back(valargs[2]);
            valargs.pop_back();
            opt.queue_modifiers.push_back(new ValuesGenerator(IQ_MEMHASH, valargs));
            opt.queue_modifiers.push_back(new RandomGenerator(IQ_MEMHASH, randargs));
            ++ngenerators;
        } else {
            std::cerr <<argv0 <<": unrecognized switch: " <<argv[argno] <<"\n"
                      <<"see \"" <<argv0 <<" --help\" for usage info.\n";
            exit(1);
        }
    }
    if (!opt.ngroups_set) {
        std::cerr <<argv0 <<": missing --ngroups switch\n"
                  <<argv0 <<": see --help for more info\n";
        exit(1);
    }

    // Parse non-switch arguments (allow the database connection string to appear anywhere in this list since simplifies
    // the run-analysis.sh script.
    for (/*void*/; argno<argc; argno++) {
        std::vector<std::string> colon_parts = StringUtility::split(':', argv[argno], 2);
        InputQueueName qn = parse_queuename(colon_parts[0]);
        if (IQ_NONE!=qn && 2==colon_parts.size()) {
            std::vector<std::string> equal_parts = StringUtility::split('=', colon_parts[1], 2);
            std::string gname = equal_parts[0];
            std::vector<std::string> args;
            try {
                if (2==equal_parts.size())
                    args = StringUtility::split(',', equal_parts[1], (size_t)-1, true);
                if (0==gname.compare("values")) {
                    opt.queue_modifiers.push_back(new ValuesGenerator(qn, args));
                } else if (0==gname.compare("set") || 0==gname.compare("reset")) {
                    opt.queue_modifiers.push_back(new ResetGenerator(qn, args));
                } else if (0==gname.compare("pad")) {
                    opt.queue_modifiers.push_back(new PaddingGenerator(qn, args));
                    ++ngenerators;
                } else if (0==gname.compare("random")) {
                    opt.queue_modifiers.push_back(new RandomGenerator(qn, args));
                    ++ngenerators;
                } else if (0==gname.compare("copy")) {
                    opt.queue_modifiers.push_back(new CopyGenerator(qn, args));
                    ++ngenerators;
                } else if (0==gname.compare("permute")) {
                    opt.queue_modifiers.push_back(new PermuteFilter(qn, args));
                } else if (0==gname.compare("shuffle")) {
                    opt.queue_modifiers.push_back(new ShuffleFilter(qn, args));
                } else if (0==gname.compare("redirect")) {
                    opt.queue_modifiers.push_back(new RedirectFilter(qn, args));
                } else {
                    std::cerr <<argv0 <<": unknown generator or filter name: " <<gname <<"\n";
                    exit(1);
                }
            } catch (const Exception &e) {
                std::cerr <<argv0 <<": " <<argv[argno] <<": " <<e <<"\n";
                exit(1);
            }
        } else if (transaction==NULL) {
            transaction = SqlDatabase::Connection::create(argv[argno])->transaction();
        } else {
            std::cerr <<argv0 <<": unknown generator or filter: " <<argv[argno] <<"\n";
            exit(1);
        }
    }
    if (transaction==NULL) {
        std::cerr <<argv0 <<": missing database URL\n"
                  <<argv0 <<": see --help for more info\n";
        exit(1);
    }
    if (opt.queue_modifiers.empty()) {
        if (opt.ngroups>0) {
            std::cerr <<argv0 <<": no generators specified; all input groups would be empty\n";
            exit(1);
        } else {
            exit(0);
        }
    }

    // Get the list of queues that are affected.
    std::vector<int> queue_modified(IQ_NQUEUES, 0);
    for (size_t i=0; i<opt.queue_modifiers.size(); ++i)
        queue_modified[opt.queue_modifiers[i]->queuename] = 1;

    // Generate the inputs
    int64_t cmd_id = start_command(transaction, argc, argv, "generating input groups");
    int first_id = transaction->statement("select coalesce(max(igroup_id),-1)+1 from semantic_inputvalues")->execute_int();
    if (!opt.collection_id_set)
        opt.collection_id = first_id;
    Progress progress(opt.ngroups);
    for (size_t gi=0; gi<opt.ngroups; ++gi) {
        ++progress;
        int igroup_id = first_id + gi;
        InputGroup igroup;
        igroup.set_collection_id(opt.single_collection ? opt.collection_id : igroup_id);

        // All queues initialize redirect to the default queue.  If any generator or filter is applied, then
        // we don't do the default redirect.
        for (size_t qi=0; qi<IQ_NQUEUES; ++qi) {
            if (!queue_modified[qi])
                igroup.queue((InputQueueName)qi).redirect(opt.default_queue);
        }

        // Build the queues
        for (size_t qmi=0; qmi<opt.queue_modifiers.size(); ++qmi) {
            QueueModifier *qm = opt.queue_modifiers[qmi];
            qm->reseed(igroup_id);
            InputQueue &q = igroup.queue(qm->queuename);
            qm->operator()(q, igroup_id);
        }

        // Save all queues
        igroup.save(transaction, igroup_id, cmd_id);
    }
    progress.clear();

    std::string desc = "generated "+StringUtility::numberToString(opt.ngroups)+" input group"+(1==opt.ngroups?"":"s")+
                       " starting at "+StringUtility::numberToString(first_id);
    if (opt.ngroups>0) {
        finish_command(transaction, cmd_id, desc);
        transaction->commit();
    }

    std::cerr <<argv0 <<": " <<desc <<"\n";
    return 0;
}
Exemplo n.º 6
0
    void operator()() {
        // Database connections don't survive over fork() according to SqLite and PostgreSQL documentation, so open it again
        SqlDatabase::TransactionPtr tx = SqlDatabase::Connection::create(databaseUrl)->transaction();

        // Use zero for the number of tests ran so that this child process doesn't try to update the semantic_history table.
        // If two or more processes try to change the same row (which they will if there's a non-zero number of tests) then
        // they will deadlock with each other.
        static const size_t NO_TESTS_RAN = 0;

        NameSet builtin_function_names;
        add_builtin_functions(builtin_function_names/*out*/);

        InputGroup igroup;
        WorkItem prevWorkItem;
        SgAsmInterpretation *prev_interp = NULL;
        MemoryMap ro_map;
        Disassembler::AddressSet whitelist_exports;         // dynamic functions that should be called
        PointerDetectors pointers;
        InsnCoverage insn_coverage;
        DynamicCallGraph dynamic_cg;
        Tracer tracer;
        ConsumedInputs consumed_inputs;
        FuncAnalyses funcinfo;
        OutputGroups ogroups; // do not load from database (that might take a very long time)
        time_t last_checkpoint = time(NULL);
        for (size_t workIdx=0; workIdx<work.size(); ++workIdx) {
            WorkItem &workItem = work[workIdx];

            // Load the input group from the database if necessary.
            if (workItem.igroup_id!=prevWorkItem.igroup_id) {
                if (!igroup.load(tx, workItem.igroup_id)) {
                    std::cerr <<argv0 <<": input group " <<workItem.igroup_id <<" is empty or does not exist\n";
                    exit(1);
                }
            }

            // Find the function to test
            IdFunctionMap::iterator func_found = functions.find(workItem.func_id);
            assert(func_found!=functions.end());
            SgAsmFunction *func = func_found->second;
            if (opt.verbosity>=LACONIC) {
                if (opt.verbosity>=EFFUSIVE)
                    std::cerr <<argv0 <<": " <<std::string(100, '=') <<"\n";
                std::cerr <<argv0 <<": processing function " <<function_to_str(func, function_ids) <<"\n";
            }
            SgAsmInterpretation *interp = SageInterface::getEnclosingNode<SgAsmInterpretation>(func);
            assert(interp!=NULL);

            // Do per-interpretation stuff
            if (interp!=prev_interp) {
                prev_interp = interp;
                assert(interp->get_map()!=NULL);
                ro_map = *interp->get_map();
                ro_map.require(MemoryMap::READABLE).prohibit(MemoryMap::WRITABLE).keep();
                Disassembler::AddressSet whitelist_imports = get_import_addresses(interp, builtin_function_names);
                whitelist_exports.clear(); // imports are addresses of import table slots; exports are functions
                overmap_dynlink_addresses(interp, *insns, opt.params.follow_calls, &ro_map, GOTPLT_VALUE,
                                          whitelist_imports, whitelist_exports/*out*/);
                if (opt.verbosity>=EFFUSIVE) {
                    std::cerr <<argv0 <<": memory map for SgAsmInterpretation:\n";
                    interp->get_map()->dump(std::cerr, argv0+":   ");
                }
            }

            // Run the test
            assert(insns!=NULL);
            assert(entry2id!=NULL);
            std::cerr <<"process " <<getpid() <<" about to run test " <<workIdx <<"/" <<work.size() <<" " <<workItem <<"\n";
            runOneTest(tx, workItem, pointers, func, function_ids, insn_coverage, dynamic_cg, tracer, consumed_inputs,
                       interp, whitelist_exports, cmd_id, igroup, funcinfo, *insns, &ro_map, *entry2id, ogroups);
            ++ntests_ran;

            // Checkpoint
            if (opt.checkpoint>0 && time(NULL)-last_checkpoint > opt.checkpoint) {
                if (!opt.dry_run)
                    tx = checkpoint(tx, ogroups, tracer, insn_coverage, dynamic_cg, consumed_inputs, NULL, NO_TESTS_RAN,
                                    cmd_id);
                last_checkpoint = time(NULL);
            }

            prevWorkItem = workItem;
        }
        std::cerr <<"process " <<getpid() <<" is done testing; now finishing up...\n";

        if (!tx->is_terminated()) {
            SqlDatabase::StatementPtr stmt = tx->statement("insert into semantic_funcpartials"
                                             " (func_id, ncalls, nretused, ntests, nvoids) values"
                                             " (?,       ?,      ?,        ?,      ?)");
            for (FuncAnalyses::iterator fi=funcinfo.begin(); fi!=funcinfo.end(); ++fi) {
                stmt->bind(0, fi->first);
                stmt->bind(1, fi->second.ncalls);
                stmt->bind(2, fi->second.nretused);
                stmt->bind(3, fi->second.ntests);
                stmt->bind(4, fi->second.nvoids);
                stmt->execute();
            }
        }

        // Cleanup
        if (!tx->is_terminated() && !opt.dry_run) {
            std::cerr <<"process " <<getpid() <<" is doing the final checkpoint\n";
            checkpoint(tx, ogroups, tracer, insn_coverage, dynamic_cg, consumed_inputs, NULL, NO_TESTS_RAN, cmd_id);
        }
        tx.reset();

        std::cerr <<"process " <<getpid() <<" finished\n";
    }
Exemplo n.º 7
0
bool InputGroup::containsOnly(const InputGroup & input) const
{
	return containsAllOf(input) && input.getKeyCount() == getKeyCount();
}