From 191b14c0e618aeeb36de1aae012d50525d394f6b Mon Sep 17 00:00:00 2001 From: Tobias Stumpf Date: Fri, 13 Jun 2014 20:39:40 +0200 Subject: [PATCH] Enhancd experiment to accept config parameters. Combine all prep steps as well as the final example in one binary. Use parameter prep to specify what you would like to do. --- src/experiments/l4-sys/experiment.cc | 411 ++++++++++++++++++++------ src/experiments/l4-sys/experiment.hpp | 50 +++- src/experiments/l4-sys/main.cc | 7 + 3 files changed, 372 insertions(+), 96 deletions(-) diff --git a/src/experiments/l4-sys/experiment.cc b/src/experiments/l4-sys/experiment.cc index 8dbafc23..01c3daaa 100644 --- a/src/experiments/l4-sys/experiment.cc +++ b/src/experiments/l4-sys/experiment.cc @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -17,11 +18,12 @@ #include "sal/SALInst.hpp" #include "sal/Memory.hpp" #include "sal/Listener.hpp" -#include "config/FailConfig.hpp" -#include "util/ProtoStream.hpp" -#include "TracePlugin.pb.h" -#include "util/gzstream/gzstream.h" #include +#include "config/FailConfig.hpp" +#include "TracePlugin.pb.h" +#include "util/ProtoStream.hpp" +#include "util/gzstream/gzstream.h" +#include "util/CommandLine.hpp" using namespace std; using namespace fail; @@ -88,10 +90,10 @@ const Bit8u *L4SysExperiment::calculateInstructionAddress() { return result; } -unsigned L4SysExperiment::calculateTimeout(unsigned instr_left) { +unsigned L4SysExperiment::calculateTimeout(unsigned instr_left, unsigned ips) { // the timeout in seconds, plus one backup second (avoids rounding overhead) // [instr] / [instr / s] = [s] - unsigned seconds = instr_left / L4SYS_BOCHS_IPS + 1; + unsigned seconds = instr_left / ips + 1; // 1.1 (+10 percent) * 1000000 mus/s * [s] return 1100000 * seconds; } @@ -135,9 +137,12 @@ void L4SysExperiment::terminateWithError(string details, int reason, } -void L4SysExperiment::startAndSaveInitState(fail::BPSingleListener* bp) +void L4SysExperiment::runToStart(fail::BPSingleListener *bp) { - bp->setWatchInstructionPointer(L4SYS_FUNC_ENTRY); + bp->setWatchInstructionPointer(conf.func_entry); + + log << "run until ip reaches 0x" << hex << conf.func_entry << endl; + simulator.addListenerAndResume(bp); log << "test function entry reached, saving state" << endl; @@ -146,22 +151,15 @@ void L4SysExperiment::startAndSaveInitState(fail::BPSingleListener* bp) << simulator.getCPU(0).getInstructionPointer() << endl; log << "check the source code if the two instruction pointers are not equal" << endl; - simulator.save(L4SYS_STATE_FOLDER); - delete bp; + + if(conf.address_space == conf.address_space_trace) { + conf.address_space_trace = BX_CPU(0)->cr3; + } + + conf.address_space = BX_CPU(0)->cr3; } -void L4SysExperiment::CR3run(fail::BPSingleListener *bp) -{ - log << "CR_3Run: Watching for instruction " << hex << L4SYS_FUNC_ENTRY << endl; - bp->setWatchInstructionPointer(L4SYS_FUNC_ENTRY); - simulator.addListenerAndResume(bp); - log << "Reached entry point @ " << hex << bp->getTriggerInstructionPointer() - << " == " << simulator.getCPU(0).getInstructionPointer() - << endl; - log << "CR3 = " << hex << BX_CPU(0)->cr3 << endl; -} - BaseListener* L4SysExperiment::afterInjection(L4SysProtoMsg_Result* res) { @@ -170,14 +168,14 @@ BaseListener* L4SysExperiment::afterInjection(L4SysProtoMsg_Result* res) simtime_t t_inject = simulator.getTimerTicks(); simtime_t t_bailout; - ifstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::binary); + ifstream instr_list_file(conf.instruction_list.c_str(), ios::binary); instr_list_file.seekg((1 + res->instr_offset()) * sizeof(TraceInstr)); - RangeSetInstructionFilter filtering(L4SYS_FILTER); + RangeSetInstructionFilter filtering(conf.filter.c_str()); for (;;) { // Step over _all_ instructions in the trace AS - BPSingleListener stepListener(ANY_ADDR, L4SYS_ADDRESS_SPACE_TRACE); + BPSingleListener stepListener(ANY_ADDR, conf.address_space_trace); TraceInstr curr_instr; instr_list_file.read(reinterpret_cast(&curr_instr), @@ -230,16 +228,16 @@ BaseListener* L4SysExperiment::afterInjection(L4SysProtoMsg_Result* res) void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp) { - fail::MemAccessListener ML(ANY_ADDR, MemAccessEvent::MEM_READWRITE); - ogzstream out("trace.pb"); - ProtoOStream *os = new ProtoOStream(&out); + fail::MemAccessListener ML(ANY_ADDR, MemAccessEvent::MEM_READWRITE); + ogzstream out(conf.trace.c_str()); + ProtoOStream *os = new ProtoOStream(&out); size_t count = 0, inst_accepted = 0, mem = 0, mem_valid = 0; simtime_t prevtime = 0, currtime; simtime_diff_t deltatime; log << "restoring state" << endl; - simulator.restore(L4SYS_STATE_FOLDER); + simulator.restore(conf.state_folder.c_str()); currtime = simulator.getTimerTicks(); log << "EIP = " << hex @@ -256,14 +254,14 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp) } #if L4SYS_FILTER_INSTRUCTIONS - ofstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::binary); - RangeSetInstructionFilter filtering(L4SYS_FILTER); + ofstream instr_list_file(conf.instruction_list.c_str(), ios::binary); + RangeSetInstructionFilter filtering(conf.filter.c_str()); bp->setWatchInstructionPointer(ANY_ADDR); map times_called_map; bool injecting = false; - while (bp->getTriggerInstructionPointer() != L4SYS_FUNC_EXIT) { + while (bp->getTriggerInstructionPointer() != conf.func_exit) { fail::BaseListener *res = simulator.resume(); address_t curr_addr = 0; @@ -271,7 +269,7 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp) if (res == &ML) { curr_addr = ML.getTriggerInstructionPointer(); simulator.addListener(&ML); - if ((L4SYS_ADDRESS_SPACE_TRACE != ANY_ADDR) && (BX_CPU(0)->cr3 != L4SYS_ADDRESS_SPACE_TRACE)) { + if ((conf.address_space_trace != ANY_ADDR) && (BX_CPU(0)->cr3 != conf.address_space_trace)) { continue; } ++mem; @@ -285,11 +283,11 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp) currtime = simulator.getTimerTicks(); deltatime = currtime - prevtime; - if (curr_addr == L4SYS_FILTER_ENTRY) { + if (curr_addr == conf.filter_entry) { injecting = true; } - if (curr_addr == L4SYS_FILTER_EXIT) { + if (curr_addr == conf.filter_exit) { injecting = false; } @@ -300,7 +298,7 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp) if (!injecting or !filtering.isValidInstr(curr_addr, reinterpret_cast(calculateInstructionAddress())) or - (BX_CPU(0)->cr3 != L4SYS_ADDRESS_SPACE_TRACE) + (BX_CPU(0)->cr3 != conf.address_space_trace) ) { //log << "connt..." << std::endl; continue; @@ -365,7 +363,7 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp) log << "mem accesses: " << mem << ", valid: " << mem_valid << std::endl; #else bp->setWatchInstructionPointer(ANY_ADDR); - while (bp->getTriggerInstructionPointer() != L4SYS_FUNC_EXIT) + while (bp->getTriggerInstructionPointer() != conf.func_exit) { fail::BaseListener *res = simulator.resume(); address_t curr_addr = 0; @@ -374,7 +372,7 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp) if (res == &ML) { curr_addr = ML.getTriggerInstructionPointer(); simulator.addListener(&ML); - if ((L4SYS_ADDRESS_SPACE_TRACE != ANY_ADDR) && (BX_CPU(0)->cr3 != L4SYS_ADDRESS_SPACE_TRACE)) { + if ((func.address_space_trace != ANY_ADDR) && (BX_CPU(0)->cr3 != func.address_space_trace)) { continue; } ++mem; @@ -421,20 +419,22 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener* bp) << dec << count << " instructions; " << count << " accepted" << endl; log << "mem accesses: " << mem << ", valid: " << mem_valid << std::endl; #endif + conf.numinstr = inst_accepted; + conf.totinstr = count; delete bp; } void L4SysExperiment::goldenRun(fail::BPSingleListener* bp) { log << "restoring state" << endl; - simulator.restore(L4SYS_STATE_FOLDER); + simulator.restore(conf.state_folder.c_str()); log << "EIP = " << hex << simulator.getCPU(0).getInstructionPointer() << endl; std::string golden_run; - ofstream golden_run_file(L4SYS_CORRECT_OUTPUT); - bp->setWatchInstructionPointer(L4SYS_FUNC_EXIT); + ofstream golden_run_file(conf.golden_run.c_str()); + bp->setWatchInstructionPointer(conf.func_exit); simulator.addListener(bp); BaseListener* ev = waitIOOrOther(true); if (ev == bp) { @@ -468,23 +468,23 @@ void L4SysExperiment::getJobParameters() } -void L4SysExperiment::validatePrerequisites() +void L4SysExperiment::validatePrerequisites(std::string state, std::string output) { struct stat teststruct; - if (stat(L4SYS_STATE_FOLDER, &teststruct) == -1 || - stat(L4SYS_CORRECT_OUTPUT, &teststruct) == -1) { + if (stat(state.c_str(), &teststruct) == -1 || + stat(output.c_str(), &teststruct) == -1) { log << "Important data missing - call \"prepare\" first." << endl; terminate(10); } } -void L4SysExperiment::readGoldenRun(std::string& target) +void L4SysExperiment::readGoldenRun(std::string& target, std::string golden_run) { - ifstream golden_run_file(L4SYS_CORRECT_OUTPUT); + ifstream golden_run_file(golden_run.c_str()); if (!golden_run_file.good()) { - log << "Could not open file " << L4SYS_CORRECT_OUTPUT << endl; + log << "Could not open file " << golden_run.c_str() << endl; terminate(20); } @@ -495,7 +495,7 @@ void L4SysExperiment::readGoldenRun(std::string& target) } -void L4SysExperiment::setupFilteredBreakpoint(fail::BPSingleListener* bp, int instOffset) +void L4SysExperiment::setupFilteredBreakpoint(fail::BPSingleListener* bp, int instOffset, std::string instr_list) { /* * The L4Sys experiment uses instruction filtering to restrict the range @@ -513,7 +513,7 @@ void L4SysExperiment::setupFilteredBreakpoint(fail::BPSingleListener* bp, int in * index into this trace file and determine the value for the breakpoint * counter. */ - ifstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::binary); + ifstream instr_list_file(instr_list.c_str(), ios::binary); if (!instr_list_file.good()) { log << "Missing instruction trace" << endl; @@ -542,12 +542,12 @@ void L4SysExperiment::setupFilteredBreakpoint(fail::BPSingleListener* bp, int in fail::BPSingleListener* L4SysExperiment::prepareMemoryExperiment(int ip, int offset, int dataAddress) { - fail::BPSingleListener *bp = new BPSingleListener(0, L4SYS_ADDRESS_SPACE_TRACE); + fail::BPSingleListener *bp = new BPSingleListener(0, conf.address_space_trace); log << "\033[34;1mMemory fault injection\033[0m at instruction " << std::hex << offset << ", ip " << ip << ", address " << dataAddress << std::endl; #if L4SYS_FILTER_INSTRUCTIONS - setupFilteredBreakpoint(bp, offset); + setupFilteredBreakpoint(bp, offset, conf.instruction_list); assert(bp->getWatchInstructionPointer() == (address_t)(ip & 0xFFFFFFFF)); #else bp->setWatchInstructionPointer(ANY_ADDR); @@ -560,7 +560,7 @@ L4SysExperiment::prepareMemoryExperiment(int ip, int offset, int dataAddress) fail::BPSingleListener* L4SysExperiment::prepareRegisterExperiment(int ip, int offset, int dataAddress) { - fail::BPSingleListener *bp = new BPSingleListener(0, L4SYS_ADDRESS_SPACE_TRACE); + fail::BPSingleListener *bp = new BPSingleListener(0, conf.address_space_trace); int reg, regOffset; reg = ((dataAddress >> 4) & 0xF) + 1; // regs start at 1 @@ -571,7 +571,7 @@ L4SysExperiment::prepareRegisterExperiment(int ip, int offset, int dataAddress) << regOffset << ")" << std::endl; #if L4SYS_FILTER_INSTRUCTIONS - setupFilteredBreakpoint(bp, offset); + setupFilteredBreakpoint(bp, offset, conf.instruction_list); log << bp->getWatchInstructionPointer() << std::endl; log << ip << std::endl; assert(bp->getWatchInstructionPointer() == (address_t)(ip & 0xFFFFFFFF)); @@ -618,38 +618,13 @@ void L4SysExperiment::doRegisterInjection(int regDesc, int bit) << newdata << std::endl; } - -bool L4SysExperiment::run() -{ - BPSingleListener *bp = 0; - srand(time(NULL)); - - log << "Starting L4Sys Experiment, phase " << PREPARATION_STEP << endl; - -#if PREPARATION_STEP == 1 - // STEP 1: run until interesting function starts, and save state - // -> needs L4SYS_ADDRESS_SPACE, because it runs until L4SYS_FUNC_ENTRY - startAndSaveInitState(new BPSingleListener(0, L4SYS_ADDRESS_SPACE)); -#elif PREPARATION_STEP == 2 - // STEP 2: determine instructions executed - collectInstructionTrace(new BPSingleListener(0, ANY_ADDR)); - -#elif PREPARATION_STEP == 3 - // STEP 3: determine the output of a "golden run" - // -> golden run needs L4SYS_ADDRESS_SPACE as it breaks on - // L4SYS_FUNC_EXIT - goldenRun(new BPSingleListener(0, L4SYS_ADDRESS_SPACE)); - -#elif PREPARATION_STEP == 4 - CR3run(new BPSingleListener(0)); - -#elif PREPARATION_STEP == 0 +void L4SysExperiment::doExperiments(fail::BPSingleListener* bp) { // LAST STEP: The actual experiment. - validatePrerequisites(); + validatePrerequisites(conf.state_folder, conf.golden_run); // Read the golden run output for validation purposes std::string golden_run; - readGoldenRun(golden_run); + readGoldenRun(golden_run, conf.golden_run); getJobParameters(); @@ -680,7 +655,7 @@ bool L4SysExperiment::run() simulator.clearListeners(); log << "Bit " << bit << ", restoring state." << endl; - simulator.restore(L4SYS_STATE_FOLDER); + simulator.restore(conf.state_folder.c_str()); log << " ... EIP = " << std::hex << simulator.getCPU(0).getInstructionPointer() << std::endl; simulator.addListener(bp); @@ -717,23 +692,23 @@ bool L4SysExperiment::run() log << "doing nothing for experiment type " << exp_type << std::endl; } - BPSingleListener ev_done(L4SYS_FUNC_EXIT, L4SYS_ADDRESS_SPACE); + BPSingleListener ev_done(conf.func_exit, conf.address_space); simulator.addListener(&ev_done); // Well-known bailout point -- if we hit L4SYS_BREAK_BLINK, which // is the entry of Vga::blink_cursor(), we know that we are in some // kind of error handler - BPSingleListener ev_blink(L4SYS_BREAK_BLINK); + BPSingleListener ev_blink(conf.break_blink); simulator.addListener(&ev_blink); - BPSingleListener ev_longjmp(L4SYS_BREAK_LONGJMP); + BPSingleListener ev_longjmp(conf.break_longjmp); simulator.addListener(&ev_longjmp); //If we come to our own exit function, we can stop - BPSingleListener ev_exit(L4SYS_BREAK_EXIT); + BPSingleListener ev_exit(conf.break_exit); simulator.addListener(&ev_exit); - unsigned instr_left = L4SYS_TOTINSTR - instr_offset; // XXX offset is in NUMINSTR, TOTINSTR is higher - BPSingleListener ev_incomplete(ANY_ADDR, L4SYS_ADDRESS_SPACE); + unsigned instr_left = conf.totinstr - instr_offset; // XXX offset is in NUMINSTR, TOTINSTR is higher + BPSingleListener ev_incomplete(ANY_ADDR, conf.address_space); /* * Use hard-coded value for incomplete counter. We are currently looking at short-running pieces * of code. This means that in the error case, where a lot of data is still to be printed to serial @@ -746,7 +721,7 @@ bool L4SysExperiment::run() /* * This timeout will always be at least one second - see calculateTimeout() */ - TimerListener ev_timeout(calculateTimeout(instr_left)); + TimerListener ev_timeout(calculateTimeout(instr_left, conf.emul_ips)); simulator.addListener(&ev_timeout); log << "continue... (" << simulator.getListenerCount() << " breakpoints, timeout @ " << ev_timeout.getTimeout() @@ -797,10 +772,266 @@ bool L4SysExperiment::run() } m_jc.sendResult(*param); +} -#endif - terminate(0); + +void L4SysExperiment::parseOptions(L4SysConfig &conf) { + CommandLine &cmd = CommandLine::Inst(); + + cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... "); + CommandLine::option_handle HELP = + cmd.addOption("h", "help", Arg::None, "-h,--help \tPrint usage and exit"); + CommandLine::option_handle STEP = + cmd.addOption("s", "step", Arg::Optional, "-s,--step \tSpecify preparation step, without this argumnt fail-client start in experiment mode (cr3: get CR3, cc: Create Checkpoint, it: collect instruction trace, gr: golden run, all: do the whole preparation)"); + + + CommandLine::option_handle OPT_MAX_INSTR_BYTES = + cmd.addOption("", "max_instr_bytes", Arg::Optional, "--max_instr_bytes \t define MAX_INSTR_BYTES"); + CommandLine::option_handle OPT_ADDRESS_SPACE = + cmd.addOption("", "address_space", Arg::Optional, "--address_space \t define L4SYS_ADDRESS_SPACE"); + CommandLine::option_handle OPT_ADDRESS_SPACE_TRACE = + cmd.addOption("", "address_space_trace", Arg::Optional, "--address_space_trace \t define L4SYS_ADDRESS_SPACE_TRACE"); + CommandLine::option_handle OPT_FUNC_ENTRY = + cmd.addOption("", "func_entry", Arg::Optional, "--func_entry \t define L4SYS_FUNC_ENTRY"); + CommandLine::option_handle OPT_FUNC_EXIT = + cmd.addOption("", "func_exit", Arg::Optional, "--func_exit \t define L4SYS_FUNC_EXIT"); + CommandLine::option_handle OPT_FILTER_ENTRY = + cmd.addOption("", "filter_entry", Arg::Optional, "--filter_entry \t define L4SYS_FILTER_ENTRY"); + CommandLine::option_handle OPT_FILTER_EXIT = + cmd.addOption("", "filter_exit", Arg::Optional, "--filter_exit \t define L4SYS_FILTER_EXIT"); + CommandLine::option_handle OPT_BREAK_BLINK = + cmd.addOption("", "break_blink", Arg::Optional, "--break_blink \t define L4SYS_BREAK_BLINK"); + CommandLine::option_handle OPT_BREAK_LONGJMP = + cmd.addOption("", "break_longjmp", Arg::Optional, "--break_longjmp \t define L4SYS_BREAK_LONGJMP"); + CommandLine::option_handle OPT_BREAK_EXIT = + cmd.addOption("", "break_exit", Arg::Optional, "--break_exit \t define L4SYS_BREAK_EXIT"); + CommandLine::option_handle OPT_FILTER_INSTRUCTIONS = + cmd.addOption("", "filter_instructions", Arg::Optional, "--filter_instructions \t define L4SYS_FILTER_INSTRUCTIONS"); + CommandLine::option_handle OPT_NUMINSTR = + cmd.addOption("", "numinstr", Arg::Optional, "--numinstr \t define L4SYS_NUMINSTR"); + CommandLine::option_handle OPT_TOTINSTR = + cmd.addOption("", "totinstr", Arg::Optional, "--totinstr \t define L4SYS_TOTINSTR"); + CommandLine::option_handle OPT_EMUL_IPS = + cmd.addOption("", "bochs_ips", Arg::Optional, "--bochs_ips \t define L4SYS_BOCHS_IPS"); + CommandLine::option_handle OPT_STATE_FOLDER = + cmd.addOption("", "state_folder", Arg::Optional, "--state_folder \t define L4SYS_STATE_FOLDER"); + CommandLine::option_handle OPT_INSTRUCTION_LIST = + cmd.addOption("", "instruction_list", Arg::Optional, "--instruction_list \t define L4SYS_INSTRUCTION_LIST"); + CommandLine::option_handle OPT_ALU_INSTRUCTIONS = + cmd.addOption("", "alu_instructions", Arg::Optional, "--alu_instructions \t define L4SYS_ALU_INSTRUCTIONS"); + CommandLine::option_handle OPT_CORRECT_OUTPUT = + cmd.addOption("", "golden_run", Arg::Optional, "--correct_output \t define L4SYS_CORRECT_OUTPUT"); + CommandLine::option_handle OPT_FILTER = + cmd.addOption("", "filter", Arg::Optional, "--filter \t define L4SYS_FILTER"); + CommandLine::option_handle OPT_TRACE = + cmd.addOption("", "trace", Arg::Optional, "--trace \t define outputfile for trace (default trace.pb)"); + + if (!cmd.parse()) { + cerr << "Error parsing arguments." << endl; + simulator.terminate(1); + } else if (cmd[HELP]) { + cmd.printUsage(); + simulator.terminate(0); + } + + if (cmd[OPT_MAX_INSTR_BYTES]) { + conf.max_instr_bytes = strtol(cmd[OPT_MAX_INSTR_BYTES].arg, NULL, 16); + } else { + conf.max_instr_bytes = MAX_INSTR_BYTES; + } + + if (cmd[OPT_ADDRESS_SPACE]) { + conf.address_space = strtol(cmd[OPT_ADDRESS_SPACE].arg, NULL, 16); + } else { + conf.address_space = L4SYS_ADDRESS_SPACE; + } + + if (cmd[OPT_ADDRESS_SPACE_TRACE]) { + conf.address_space_trace = strtol(cmd[OPT_ADDRESS_SPACE_TRACE].arg, NULL, 16); + } else { + conf.address_space_trace = L4SYS_ADDRESS_SPACE_TRACE; + } + + if (cmd[OPT_FUNC_ENTRY]) { + conf.func_entry = strtol(cmd[OPT_FUNC_ENTRY].arg, NULL, 16); + } else { + conf.func_entry = L4SYS_FUNC_ENTRY; + } + + if (cmd[OPT_FUNC_EXIT]) { + conf.func_exit = strtol(cmd[OPT_FUNC_EXIT].arg, NULL, 16); + } else { + conf.func_exit = L4SYS_FUNC_EXIT; + } + + if (cmd[OPT_FILTER_ENTRY]) { + conf.filter_entry = strtol(cmd[OPT_FILTER_ENTRY].arg, NULL, 16); + } else { + conf.filter_entry = L4SYS_FILTER_ENTRY; + } + + if (cmd[OPT_FILTER_EXIT]) { + conf.filter_exit = strtol(cmd[OPT_FILTER_EXIT].arg, NULL, 16); + } else { + conf.filter_exit = L4SYS_FILTER_EXIT; + } + + if (cmd[OPT_BREAK_BLINK]) { + conf.break_blink = strtol(cmd[OPT_BREAK_BLINK].arg, NULL, 16); + } else { + conf.break_blink = L4SYS_BREAK_BLINK; + } + + if (cmd[OPT_BREAK_LONGJMP]) { + conf.break_longjmp = strtol(cmd[OPT_BREAK_LONGJMP].arg, NULL, 16); + } else { + conf.break_longjmp = L4SYS_BREAK_LONGJMP; + } + + if (cmd[OPT_BREAK_EXIT]) { + conf.break_exit = strtol(cmd[OPT_BREAK_EXIT].arg, NULL, 16); + } else { + conf.break_exit = L4SYS_BREAK_EXIT; + } + + if (cmd[OPT_FILTER_INSTRUCTIONS]) { + conf.filter_instructions = strtol(cmd[OPT_FILTER_INSTRUCTIONS].arg, NULL, 16); + } else { + conf.filter_instructions = L4SYS_FILTER_INSTRUCTIONS; + } + + if (cmd[OPT_NUMINSTR]) { + conf.numinstr = strtol(cmd[OPT_NUMINSTR].arg, NULL, 16); + } else { + conf.numinstr = L4SYS_NUMINSTR; + } + + if (cmd[OPT_TOTINSTR]) { + conf.totinstr = strtol(cmd[OPT_TOTINSTR].arg, NULL, 16); + } else { + conf.totinstr = L4SYS_TOTINSTR; + } + + if (cmd[OPT_EMUL_IPS]) { + conf.emul_ips = strtol(cmd[OPT_EMUL_IPS].arg, NULL, 16); + } else { + conf.emul_ips = L4SYS_BOCHS_IPS; + } + + if (cmd[OPT_STATE_FOLDER]) { + conf.state_folder = std::string(cmd[OPT_STATE_FOLDER].arg); + } else { + conf.state_folder = L4SYS_STATE_FOLDER; + } + + if (cmd[OPT_INSTRUCTION_LIST]) { + conf.instruction_list = std::string(cmd[OPT_INSTRUCTION_LIST].arg); + } else { + conf.instruction_list = L4SYS_INSTRUCTION_LIST; + } + + if (cmd[OPT_ALU_INSTRUCTIONS]) { + conf.alu_instructions = std::string(cmd[OPT_ALU_INSTRUCTIONS].arg); + } else { + conf.alu_instructions = L4SYS_ALU_INSTRUCTIONS; + } + + if (cmd[OPT_CORRECT_OUTPUT]) { + conf.golden_run = std::string(cmd[OPT_CORRECT_OUTPUT].arg); + } else { + conf.golden_run = L4SYS_CORRECT_OUTPUT; + } + + if (cmd[OPT_FILTER]) { + conf.filter = std::string(cmd[OPT_FILTER].arg); + } else { + conf.filter = L4SYS_FILTER; + } + + if (cmd[OPT_TRACE]) { + conf.trace = std::string(cmd[OPT_TRACE].arg); + } else { + conf.trace = std::string("trace.pb"); + } + + if (cmd[STEP]) { + if (!std::string("cr3").compare(cmd[STEP].arg) ) { + log << "calculate cr3" << endl; + conf.step = L4SysConfig::GET_CR3; + } else if (!std::string("cc").compare(cmd[STEP].arg) ) { + log << "Create Checkpoint" << endl; + conf.step = L4SysConfig::CREATE_CHECKPOINT; + } else if (!std::string("it").compare(cmd[STEP].arg) ) { + log << "collect instruction trace" << endl; + conf.step = L4SysConfig::COLLECT_INSTR_TRACE; + } else if (!std::string("gr").compare(cmd[STEP].arg) ) { + log << "golden run" << endl; + conf.step = L4SysConfig::GOLDEN_RUN; + } else if (!std::string("all").compare(cmd[STEP].arg) ) { + log << "do all preparation steps" << endl; + conf.step = L4SysConfig::FULL_PREPARATION; + } else { + cerr << "Wrong argument for option '--step'" << endl; + simulator.terminate(1); + } + } else { + conf.step = L4SysConfig::NO_PREP; + } + +} + +bool L4SysExperiment::run() +{ + srand(time(NULL)); + + log << "Starting L4Sys Experiment, phase " << PREPARATION_STEP << endl; + + parseOptions(conf); + + switch(conf.step) { + case L4SysConfig::GET_CR3: { + log << "CR_3Run: Watching for instruction " << hex << conf.func_entry << endl; + runToStart(new BPSingleListener(0)); + log << "CR3 = " << hex << conf.address_space << endl; + break; + } + case L4SysConfig::CREATE_CHECKPOINT: { + // STEP 1: run until interesting function starts, and save state + // -> needs L4SYS_ADDRESS_SPACE, because it runs until L4SYS_FUNC_ENTRY + runToStart(new BPSingleListener(0, conf.address_space)); + simulator.save(conf.state_folder); + break; + } + case L4SysConfig::COLLECT_INSTR_TRACE: { + // STEP 2: determine instructions executed + collectInstructionTrace(new BPSingleListener(0, ANY_ADDR)); + break; + } + case L4SysConfig::GOLDEN_RUN: { + // STEP 3: determine the output of a "golden run" + // -> golden run needs L4SYS_ADDRESS_SPACE as it breaks on + // L4SYS_FUNC_EXIT + goldenRun(new BPSingleListener(0, L4SYS_ADDRESS_SPACE)); + break; + } + case L4SysConfig::FULL_PREPARATION: { + runToStart(new BPSingleListener(0)); + simulator.save(conf.state_folder); + simulator.clearListeners(); + collectInstructionTrace(new BPSingleListener(0, ANY_ADDR)); + simulator.clearListeners(); + goldenRun(new BPSingleListener(0, L4SYS_ADDRESS_SPACE)); + break; + } + default: { + BPSingleListener *bp = 0; + doExperiments(bp); + } + } + + + terminate(0); // experiment successfully conducted return true; } diff --git a/src/experiments/l4-sys/experiment.hpp b/src/experiments/l4-sys/experiment.hpp index 091f6451..34afc43c 100644 --- a/src/experiments/l4-sys/experiment.hpp +++ b/src/experiments/l4-sys/experiment.hpp @@ -28,6 +28,7 @@ typedef struct TraceInstrType { class L4SysExperiment : public fail::ExperimentFlow { private: + class L4SysConfig; fail::JobClient m_jc; //!< the job client connecting to the campaign server fail::Logger log; //