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.
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -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 <sal/bochs/BochsMemory.hpp>
|
||||
#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<char*>(&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<address_t, unsigned> 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<char const*>(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] ... <BochsOptions...>");
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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; //<! the logger
|
||||
L4SysExperimentData *param; //<! the parameter set currently in use by the client
|
||||
@ -75,7 +76,7 @@ private:
|
||||
/**
|
||||
* Calculate the timeout of the current workload in milliseconds.
|
||||
*/
|
||||
unsigned calculateTimeout(unsigned instr_left);
|
||||
unsigned calculateTimeout(unsigned instr_left, unsigned ips);
|
||||
/**
|
||||
* Send back the experiment parameter set with a description of the error.
|
||||
*/
|
||||
@ -84,8 +85,7 @@ private:
|
||||
* Run until L4SYS_FUNC_ENTRY and save state (experiment preparation,
|
||||
* phase 1)
|
||||
*/
|
||||
void startAndSaveInitState(fail::BPSingleListener* bp);
|
||||
void CR3run(fail::BPSingleListener *bp);
|
||||
void runToStart(fail::BPSingleListener *bp);
|
||||
/**
|
||||
* Collect list of executed instructions, considering instruction
|
||||
* filtering if configured (experiment preparation, phase 2).
|
||||
@ -96,10 +96,15 @@ private:
|
||||
*/
|
||||
void goldenRun(fail::BPSingleListener* bp);
|
||||
|
||||
/**
|
||||
* Doing fault injection expiriments (experiment preparation, phase 0)
|
||||
*/
|
||||
void doExperiments(fail::BPSingleListener *bp);
|
||||
|
||||
/**
|
||||
* Check that all required setup has been done before an experiment run.
|
||||
*/
|
||||
void validatePrerequisites();
|
||||
void validatePrerequisites(std::string state, std::string output);
|
||||
|
||||
/**
|
||||
* Load job parameters for an experiment.
|
||||
@ -111,7 +116,7 @@ private:
|
||||
/**
|
||||
* Read the golden run output into the target string.
|
||||
*/
|
||||
void readGoldenRun(std::string& target);
|
||||
void readGoldenRun(std::string& target, std::string golden_run);
|
||||
|
||||
/*
|
||||
* Prepare memory experiment. Creates a breakpoint to run until the
|
||||
@ -137,7 +142,40 @@ private:
|
||||
void doRegisterInjection(int regDesc, int bit);
|
||||
|
||||
|
||||
void setupFilteredBreakpoint(fail::BPSingleListener* bp, int instOffset);
|
||||
void setupFilteredBreakpoint(fail::BPSingleListener* bp, int instOffset, std::string instr_list);
|
||||
|
||||
void parseOptions(L4SysConfig&);
|
||||
|
||||
class L4SysConfig {
|
||||
public:
|
||||
unsigned long int max_instr_bytes;
|
||||
unsigned long int address_space;
|
||||
unsigned long int address_space_trace;
|
||||
unsigned long int func_entry;
|
||||
unsigned long int func_exit;
|
||||
unsigned long int filter_entry;
|
||||
unsigned long int filter_exit;
|
||||
unsigned long int break_blink;
|
||||
unsigned long int break_longjmp;
|
||||
unsigned long int break_exit;
|
||||
unsigned long int filter_instructions;
|
||||
unsigned long int emul_ips;
|
||||
std::string state_folder;
|
||||
std::string instruction_list;
|
||||
std::string alu_instructions;
|
||||
std::string golden_run;
|
||||
std::string filter;
|
||||
std::string trace;
|
||||
|
||||
unsigned long int numinstr;
|
||||
unsigned long int totinstr;
|
||||
|
||||
enum {NO_PREP, GET_CR3, CREATE_CHECKPOINT, COLLECT_INSTR_TRACE, GOLDEN_RUN, FULL_PREPARATION} step;
|
||||
};
|
||||
|
||||
private:
|
||||
L4SysConfig conf;
|
||||
};
|
||||
|
||||
|
||||
#endif // __L4SYS_EXPERIMENT_HPP__
|
||||
|
||||
@ -3,9 +3,16 @@
|
||||
|
||||
#include "cpn/CampaignManager.hpp"
|
||||
#include "campaign.hpp"
|
||||
#include "util/CommandLine.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
fail::CommandLine &cmd = fail::CommandLine::Inst();
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
cmd.add_args(argv[i]);
|
||||
}
|
||||
|
||||
L4SysCampaign c;
|
||||
if (fail::campaignmanager.runCampaign(&c)) {
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user