Fail* directories reorganized, Code-cleanup (-> coding-style), Typos+comments fixed.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1321 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
adrian
2012-06-08 20:09:43 +00:00
parent d474a5b952
commit 2575604b41
866 changed files with 1848 additions and 1879 deletions

View File

@ -0,0 +1,31 @@
set(EXPERIMENT_NAME l4-sys)
set(EXPERIMENT_TYPE L4SysExperiment)
configure_file(../instantiate-experiment.ah.in
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
)
## Setup desired protobuf descriptions HERE ##
set(MY_PROTOS
l4sys.proto
)
set(MY_CAMPAIGN_SRCS
experiment.hpp
experiment.cc
campaign.hpp
campaign.cc
)
#### PROTOBUFS ####
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
## Build library
add_library(${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
## This is the example's campaign server distributing experiment parameters
add_executable(${EXPERIMENT_NAME}-server main.cc)
target_link_libraries(${EXPERIMENT_NAME}-server ${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY})

View File

@ -0,0 +1,75 @@
#include <iostream>
#include <fstream>
#include "campaign.hpp"
#include "experimentInfo.hpp"
#include "cpn/CampaignManager.hpp"
#include "util/Logger.hpp"
#include "sal/SALConfig.hpp"
using namespace std;
using namespace fail;
char const * const results_csv = "l4sys.csv";
bool L4SysCampaign::run()
{
Logger log("L4SysCampaign");
#if 0
ifstream test(results_csv);
if (test.is_open()) {
log << results_csv << " already exists" << endl;
return false;
}
#endif
ofstream results(results_csv);
if (!results.is_open()) {
log << "failed to open " << results_csv << endl;
return false;
}
log << "startup" << endl;
int count = 0;
//iterate over one register
for (int bit_offset = 0; bit_offset < 1; ++bit_offset) {
for (int instr_offset = 0; instr_offset < L4SYS_NUMINSTR; ++instr_offset) {
L4SysExperimentData *d = new L4SysExperimentData;
d->msg.set_instr_offset(instr_offset);
d->msg.set_bit_offset(bit_offset);
d->msg.set_bit_offset(0);
campaignmanager.addParam(d);
++count;
}
}
campaignmanager.noMoreParameters();
log << "done enqueueing parameter sets (" << count << ")." << endl;
// collect results
L4SysExperimentData *res;
int rescount = 0;
results << "injection_ip,instr_offset,injection_bit,resulttype,resultdata,output,details" << endl;
while ((res = static_cast<L4SysExperimentData *>(campaignmanager.getDone()))) {
rescount++;
results << hex
<< res->msg.injection_ip() << ","
<< dec << res->msg.instr_offset() << ","
<< res->msg.bit_offset() << ","
<< res->msg.resulttype() << ","
<< res->msg.resultdata();
if(res->msg.has_output())
results << "," << res->msg.output();
if(res->msg.has_details())
results << "," << res->msg.details();
results << endl;
delete res;
}
log << "done. sent " << count << " received " << rescount << endl;
results.close();
return true;
}

View File

@ -0,0 +1,19 @@
#ifndef __L4SYS_CAMPAIGN_HPP__
#define __L4SYS_CAMPAIGN_HPP__
#include "cpn/Campaign.hpp"
#include "comm/ExperimentData.hpp"
#include "l4sys.pb.h"
class L4SysExperimentData : public fail::ExperimentData {
public:
L4SysProtoMsg msg;
L4SysExperimentData() : fail::ExperimentData(&msg) {}
};
class L4SysCampaign : public fail::Campaign {
public:
virtual bool run();
};
#endif // __L4SYS_CAMPAIGN_HPP__

View File

@ -0,0 +1,319 @@
#include <iostream>
#include <map>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "util/Logger.hpp"
#include "experiment.hpp"
#include "experimentInfo.hpp"
#include "campaign.hpp"
#include "sal/SALConfig.hpp"
#include "sal/SALInst.hpp"
#include "sal/Memory.hpp"
#include "sal/bochs/BochsRegister.hpp"
#include "sal/Event.hpp"
#include "config/FailConfig.hpp"
#include "l4sys.pb.h"
using namespace std;
using namespace fail;
// Check if configuration dependencies are satisfied:
#if !defined(CONFIG_EVENT_BREAKPOINTS) || !defined(CONFIG_SR_RESTORE) || \
!defined(CONFIG_SR_SAVE) || !defined(CONFIG_SUPPRESS_INTERRUPTS) || \
!defined(CONFIG_EVENT_TRAP) || !defined(CONFIG_EVENT_IOPORT) || \
!defined(CONFIG_EVENT_INTERRUPT)
#error This experiment needs: breakpoints, suppressed-interrupts, traps, I/O port and interrupt events, \
save, and restore. Enable these in the configuration.
#endif
char const * const state_folder = "l4sys.state";
char const * const instr_list_fn = "ip.list";
char const * const golden_run_fn = "golden.out";
address_t const aspace = 0x01e00000;
string output;
vector<address_t> instr_list;
string golden_run;
//the program needs to run 5 times without a fault
const unsigned times_run = 5;
string L4SysExperiment::sanitised(string in_str)
{
string result;
result.reserve(in_str.size());
for (string::iterator it = in_str.begin(); it != in_str.end(); it++) {
unsigned char_value = static_cast<unsigned>(*it);
if (char_value < 0x20 || char_value > 0x7E) {
char str_nr[5];
sprintf(str_nr, "\\%03o", char_value);
result += str_nr;
} else {
result += *it;
}
}
return result;
}
BaseEvent* L4SysExperiment::waitIOOrOther(bool clear_output)
{
IOPortEvent ev_ioport(0x3F8, true);
BaseEvent* ev = NULL;
if (clear_output)
output.clear();
while (true) {
simulator.addEvent(&ev_ioport);
ev = simulator.waitAny();
simulator.removeEvent(&ev_ioport);
if (ev == &ev_ioport) {
output += ev_ioport.getData();
} else {
break;
}
}
return ev;
}
bool L4SysExperiment::run()
{
Logger log("L4Sys", false);
BPSingleEvent bp(0, aspace);
log << "startup" << endl;
#ifdef PREPARE_EXPERIMENT
struct stat teststruct;
// STEP 1: run until interesting function starts, and save state
if (stat(state_folder, &teststruct) == -1) {
bp.setWatchInstructionPointer(L4SYS_FUNC_ENTRY);
simulator.addEventAndWait(&bp);
log << "test function entry reached, saving state" << endl;
log << "EIP = " << hex << bp.getTriggerInstructionPointer()
<< " or "
<< simulator.getRegisterManager().getInstructionPointer()
<< endl;
simulator.save(state_folder);
}
// STEP 2: determine instructions executed
if (stat(instr_list_fn, &teststruct) == -1) {
log << "restoring state" << endl;
simulator.restore(state_folder);
log << "EIP = " << hex
<< simulator.getRegisterManager().getInstructionPointer()
<< endl;
// make sure the timer interrupt doesn't disturb us
simulator.addSuppressedInterrupt(32);
ofstream instr_list_file(instr_list_fn);
instr_list_file << hex;
bp.setWatchInstructionPointer(ANY_ADDR);
while (bp.getTriggerInstructionPointer() != L4SYS_FUNC_EXIT) {
simulator.addEventAndWait(&bp);
//short sanity check
address_t curr_instr = bp.getTriggerInstructionPointer();
assert(
curr_instr == simulator.getRegisterManager().getInstructionPointer());
instr_list.push_back(curr_instr);
instr_list_file << curr_instr << endl;
}
log << "saving instructions triggered during normal execution" << endl;
instr_list_file.close();
} else {
ifstream instr_list_file(instr_list_fn);
instr_list_file >> hex;
while (!instr_list_file.eof()) {
address_t curr_instr;
instr_list_file >> curr_instr;
instr_list.push_back(curr_instr);
}
instr_list_file.close();
}
// STEP 3: determine the output of a "golden run"
if (stat(golden_run_fn, &teststruct) == -1) {
log << "restoring state" << endl;
simulator.restore(state_folder);
log << "EIP = " << hex
<< simulator.getRegisterManager().getInstructionPointer()
<< endl;
// make sure the timer interrupt doesn't disturb us
simulator.addSuppressedInterrupt(32);
ofstream golden_run_file(golden_run_fn);
bp.setWatchInstructionPointer(L4SYS_FUNC_EXIT);
bp.setCounter(times_run);
simulator.addEvent(&bp);
BaseEvent* ev = waitIOOrOther(true);
if (ev == &bp) {
golden_run.assign(output.c_str());
golden_run_file << output.c_str();
log << "Output successfully logged!" << endl;
} else {
log
<< "Obviously, there is some trouble with the events registered - aborting simulation!"
<< endl;
golden_run_file.close();
simulator.terminate(10);
}
simulator.clearEvents();
bp.setCounter(1);
log << "saving output generated during normal execution" << endl;
golden_run_file.close();
} else {
ifstream golden_run_file(golden_run_fn);
//shamelessly copied from http://stackoverflow.com/questions/2602013/:
golden_run_file.seekg(0, ios::end);
size_t flen = golden_run_file.tellg();
golden_run.reserve(flen);
golden_run_file.seekg(0, ios::beg);
golden_run.assign((istreambuf_iterator<char>(golden_run_file)),
istreambuf_iterator<char>());
golden_run_file.close();
//the generated output probably has a similar length
output.reserve(flen);
}
#endif
// STEP 4: The actual experiment.
for (int i = 0; i < 1/*L4SYS_NUMINSTR*/; i++) {
log << "restoring state" << endl;
simulator.restore(state_folder);
log << "asking job server for experiment parameters" << endl;
L4SysExperimentData param;
if (!m_jc.getParam(param)) {
log << "Dying." << endl;
// communicate that we were told to die
simulator.terminate(1);
}
int id = param.getWorkloadID();
int instr_offset = param.msg.instr_offset();
int bit_offset = param.msg.bit_offset();
log << "job " << id << " instr " << instr_offset << " bit "
<< bit_offset << endl;
bp.setWatchInstructionPointer(instr_list[instr_offset]);
simulator.addEvent(&bp);
//and log the output
waitIOOrOther(true);
// inject
RegisterManager& rm = simulator.getRegisterManager();
Register *ebx = rm.getRegister(RID_CBX);
regdata_t data = ebx->getData();
regdata_t newdata = data ^ (1 << bit_offset);
ebx->setData(newdata);
// note at what IP we did it
address_t injection_ip =
simulator.getRegisterManager().getInstructionPointer();
param.msg.set_injection_ip(injection_ip);
log << "inject @ ip " << injection_ip << " (offset " << dec
<< instr_offset << ")" << " bit " << bit_offset << ": 0x"
<< hex << ((int) data) << " -> 0x" << ((int) newdata)
<< endl;
// sanity check (only works if we're working with an instruction trace)
if (injection_ip != instr_list[instr_offset]) {
stringstream ss;
ss << "SANITY CHECK FAILED: " << injection_ip << " != "
<< instr_list[instr_offset] << endl;
log << ss.str();
param.msg.set_resulttype(param.msg.UNKNOWN);
param.msg.set_resultdata(injection_ip);
param.msg.set_details(ss.str());
simulator.clearEvents();
m_jc.sendResult(param);
continue;
}
// aftermath
BPSingleEvent ev_done(L4SYS_FUNC_EXIT, aspace);
ev_done.setCounter(times_run);
simulator.addEvent(&ev_done);
const unsigned instr_run = times_run * L4SYS_NUMINSTR;
BPSingleEvent ev_timeout(ANY_ADDR, aspace);
ev_timeout.setCounter(instr_run + 3000);
simulator.addEvent(&ev_timeout);
TrapEvent ev_trap(ANY_TRAP);
simulator.addEvent(&ev_trap);
InterruptEvent ev_intr(ANY_INTERRUPT);
//ten times as many interrupts as instructions justify an exception
ev_intr.setCounter(instr_run * 10);
simulator.addEvent(&ev_intr);
//do not discard output recorded so far
BaseEvent *ev = waitIOOrOther(false);
/* copying a string object that contains control sequences
* unfortunately does not work with the library I am using,
* which is why output is passed on as C string and
* the string compare is done on C strings
*/
if (ev == &ev_done) {
if (strcmp(output.c_str(), golden_run.c_str()) == 0) {
log << dec << "Result DONE" << endl;
param.msg.set_resulttype(param.msg.DONE);
} else {
log << dec << "Result WRONG" << endl;
param.msg.set_resulttype(param.msg.WRONG);
param.msg.set_output(sanitised(output.c_str()));
}
} else if (ev == &ev_timeout) {
log << dec << "Result TIMEOUT" << endl;
param.msg.set_resulttype(param.msg.TIMEOUT);
param.msg.set_resultdata(
simulator.getRegisterManager().getInstructionPointer());
param.msg.set_output(sanitised(output.c_str()));
} else if (ev == &ev_trap) {
log << dec << "Result TRAP #" << ev_trap.getTriggerNumber()
<< endl;
param.msg.set_resulttype(param.msg.TRAP);
param.msg.set_resultdata(
simulator.getRegisterManager().getInstructionPointer());
param.msg.set_output(sanitised(output.c_str()));
} else if (ev == &ev_intr) {
log << hex << "Result INT FLOOD; Last INT #:"
<< ev_intr.getTriggerNumber() << endl;
param.msg.set_resulttype(param.msg.INTR);
param.msg.set_resultdata(
simulator.getRegisterManager().getInstructionPointer());
param.msg.set_output(sanitised(output.c_str()));
} else {
log << dec << "Result WTF?" << endl;
param.msg.set_resulttype(param.msg.UNKNOWN);
param.msg.set_resultdata(
simulator.getRegisterManager().getInstructionPointer());
param.msg.set_output(sanitised(output.c_str()));
stringstream ss;
ss << "eventid " << ev << " EIP "
<< simulator.getRegisterManager().getInstructionPointer()
<< endl;
param.msg.set_details(ss.str());
}
simulator.clearEvents();
m_jc.sendResult(param);
}
#ifdef HEADLESS_EXPERIMENT
simulator.terminate(0);
#endif
// experiment successfully conducted
return true;
}

View File

@ -0,0 +1,23 @@
#ifndef __L4SYS_EXPERIMENT_HPP__
#define __L4SYS_EXPERIMENT_HPP__
#include <string>
#include "efw/ExperimentFlow.hpp"
#include "efw/JobClient.hpp"
class L4SysExperiment : public fail::ExperimentFlow {
fail::JobClient m_jc;
public:
L4SysExperiment() : m_jc("localhost") {}
bool run();
private:
// NOTE: It's good practise to use "const std::string&" as parameter type.
// Additionaly, if you don't need the return value to be copied,
// return a (const) reference to a class member or a static string-
// object.
std::string sanitised(std::string in_str);
fail::BaseEvent* waitIOOrOther(bool clear_output);
};
#endif // __L4SYS_EXPERIMENT_HPP__

View File

@ -0,0 +1,12 @@
#ifndef __EXPERIMENT_INFO_HPP__
#define __EXPERIMENT_INFO_HPP__
// FIXME autogenerate this
#define L4SYS_FUNC_ENTRY 0x1007cd0
#define L4SYS_FUNC_EXIT 0x1007d3a
#define L4SYS_NUMINSTR 3184
//#define HEADLESS_EXPERIMENT
#define PREPARE_EXPERIMENT
#endif // __EXPERIMENT_INFO_HPP__

View File

@ -0,0 +1,26 @@
message L4SysProtoMsg {
// parameters
required int32 instr_offset = 1;
required int32 bit_offset = 2;
// results
// make these optional to reduce overhead for server->client communication
enum ResultType {
DONE = 1;
TIMEOUT = 2;
TRAP = 3;
INTR = 4;
WRONG = 5;
UNKNOWN = 6;
}
// instruction pointer where injection was done
optional uint32 injection_ip = 3;
// result type, see above
optional ResultType resulttype = 4;
// result data, depending on resulttype (see source code)
optional uint32 resultdata = 5;
// generated output
optional string output = 6;
// optional textual description of what happened
optional string details = 7;
}

View File

@ -0,0 +1,15 @@
#include <iostream>
#include <cstdlib>
#include "cpn/CampaignManager.hpp"
#include "campaign.hpp"
int main(int argc, char **argv)
{
L4SysCampaign c;
if (fail::campaignmanager.runCampaign(&c)) {
return 0;
} else {
return 1;
}
}