dosek: merge trace and test experiment

With the instantiate-indirect.ah method, we can choose between different
experiment flows at runtime. By this, we can combine tracing and actual
injection into one fail-client binary. A -Wf,--mode={tester,tracer}
switch does hand the control to different experiment flows.

Change-Id: Ia268489ff6bc74dffea745b7aedcb36e262e8079
This commit is contained in:
Christian Dietrich
2015-08-05 12:35:06 +02:00
parent f73008f60a
commit 1e572faa04
12 changed files with 129 additions and 44 deletions

View File

@ -1,18 +0,0 @@
set(EXPERIMENT_NAME cored-tracing)
set(EXPERIMENT_TYPE CoRedTracing)
configure_file(../instantiate-experiment.ah.in
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
)
set(MY_CAMPAIGN_SRCS
experiment.hpp
experiment.cc
)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
## Build library
add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
add_dependencies(fail-${EXPERIMENT_NAME} fail-comm)
target_link_libraries(fail-${EXPERIMENT_NAME} fail-tracing fail-randomgenerator fail-checkpoint fail-comm)

View File

@ -1,6 +1,6 @@
set(EXPERIMENT_NAME cored-tester)
set(EXPERIMENT_TYPE CoredTester)
configure_file(../instantiate-experiment.ah.in
set(EXPERIMENT_NAME dosek)
set(EXPERIMENT_TYPE dOSEK)
configure_file(../instantiate-experiment-indirect.ah.in
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
)
@ -10,8 +10,14 @@ set(MY_PROTOS
)
set(MY_CAMPAIGN_SRCS
experiment.hpp
experiment.cc
tracer.cc
tracer.hpp
tester.hpp
tester.cc
campaign.hpp
campaign.cc
)
@ -27,7 +33,7 @@ PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
## Build library
add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
add_dependencies(fail-${EXPERIMENT_NAME} fail-comm)
target_link_libraries(fail-${EXPERIMENT_NAME} fail-comm)
target_link_libraries(fail-${EXPERIMENT_NAME} fail-comm fail-tracing)
target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY} fail-llvmdisassembler)
## This is the example's campaign server distributing experiment parameters

View File

@ -1,5 +1,10 @@
SET(bochs_configure_params "--enable-a20-pin;--enable-x86-64;--enable-cpu-level=6;--enable-ne2000;--enable-acpi;--enable-pci;--enable-usb;--enable-trace-cache;--enable-fast-function-calls;--enable-host-specific-asms;--enable-readline;--enable-clgd54xx;--enable-fpu;--enable-vmx=2;--enable-monitor-mwait;--enable-cdrom;--enable-sb16=linux;--enable-gdb-stub;--with-nogui" CACHE STRING "")
SET(BUILD_LLVM_DISASSEMBLER ON CACHE BOOL "" FORCE)
SET(PLUGINS_ACTIVATED "tracing;checkpoint;randomgenerator" CACHE STRING "")
SET(PLUGINS_ACTIVATED "checkpoint;randomgenerator" CACHE STRING "")
# Build the import and prune trace tools always
SET(BUILD_IMPORT_TRACE ON CACHE BOOL "" FORCE)
SET(BUILD_PRUNE_TRACE ON CACHE BOOL "" FORCE)
SET(BUILD_CONVERT_TRACE ON CACHE BOOL "" FORCE)
SET(BUILD_DUMP_TRACE ON CACHE BOOL "" FORCE)
SET(BUILD_LLVM_DISASSEMBLER ON CACHE BOOL "" FORCE)

View File

@ -0,0 +1,40 @@
#include "tester.hpp"
#include "sal/SALInst.hpp"
#include "util/Logger.hpp"
#include "util/CommandLine.hpp"
#include "tester.hpp"
#include "tracer.hpp"
using namespace fail;
using namespace std;
static fail::Logger m_log("dOSEK FAIL* Client");
void instantiatedOSEK()
{
CommandLine &cmd = CommandLine::Inst();
cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... <BochsOptions...>\n\n");
CommandLine::option_handle MODE = cmd.addOption("", "mode", Arg::Required,
"--mode \t Mode: tracer, tester (default: tester)");
if (!cmd.parse()) {
std::cerr << "Error parsing arguments." << endl;
simulator.terminate(-1);
}
std::string mode = "tester";
if (cmd[MODE].count() > 0)
mode = std::string(cmd[MODE].first()->arg);
m_log << "Handing over to " << mode << " mode" << std::endl;
if (mode == "tester") {
fail::simulator.addFlow(new dOSEKTester);
} else if (mode == "tracer") {
fail::simulator.addFlow(new dOSEKTracer);
} else {
std::cerr << "Invalid mode: " << mode << " (available: tracer, tester)" << std::endl;
simulator.terminate(-1);
}
}

View File

@ -8,7 +8,7 @@
#include <unistd.h>
#include <stdlib.h>
#include "experiment.hpp"
#include "tester.hpp"
#include "sal/SALConfig.hpp"
#include "sal/SALInst.hpp"
#include "sal/Memory.hpp"
@ -45,7 +45,7 @@ using namespace fail;
#error This experiment needs: MemRead and MemWrite. Enable these in the configuration.
#endif
void CoredTester::redecodeCurrentInstruction() {
void dOSEKTester::redecodeCurrentInstruction() {
/* Flush Instruction Caches and Prefetch queue */
BX_CPU_C *cpu_context = simulator.getCPUContext();
cpu_context->invalidate_prefetch_q();
@ -87,7 +87,7 @@ void CoredTester::redecodeCurrentInstruction() {
}
unsigned CoredTester::injectBitFlip(address_t data_address, unsigned data_width, unsigned bitpos) {
unsigned dOSEKTester::injectBitFlip(address_t data_address, unsigned data_width, unsigned bitpos) {
/* First 32 Registers, this might neeed adaption */
if (data_address < (32 << 8)) {
LLVMtoFailTranslator::reginfo_t reginfo = LLVMtoFailTranslator::reginfo_t::fromDataAddress(data_address, data_width);
@ -172,7 +172,7 @@ std::string handleMemoryAccessEvent(fail::MemAccessListener* l_mem) {
}
const ElfSymbol& CoredTester::getELFSymbol(const std::string name) {
const ElfSymbol& dOSEKTester::getELFSymbol(const std::string name) {
const ElfSymbol &symbol = m_elf.getSymbol(name);
if (!symbol.isValid()) {
m_log << "Couldn't find symbol: " << name << std::endl;
@ -183,7 +183,7 @@ const ElfSymbol& CoredTester::getELFSymbol(const std::string name) {
}
bool CoredTester::run() {
bool dOSEKTester::run() {
m_log << "STARTING EXPERIMENT" << endl;
// seed random number generator
@ -200,8 +200,10 @@ bool CoredTester::run() {
const ElfSymbol &s_panic_handler = getELFSymbol("__OS_HOOK_FaultDetectedHook");
const ElfSymbol &s_panic_handler_2 = getELFSymbol("irq_handler_2");
const ElfSymbol &s_panic_handler_3 = getELFSymbol("irq_handler_14");
assert(s_panic_handler.isValid() && s_panic_handler_2.isValid());
assert(s_panic_handler_3.isValid());
const ElfSymbol &s_fail_trace = getELFSymbol("fail_trace");
@ -225,6 +227,9 @@ bool CoredTester::run() {
m_log << "PANIC handler @ " << std::hex << s_panic_handler.getAddress() << std::endl;
BPSingleListener l_panic_2(s_panic_handler_2.getAddress());
m_log << "PANIC2 handler @ " << std::hex << s_panic_handler_2.getAddress() << std::endl;
BPSingleListener l_panic_3(s_panic_handler_3.getAddress());
m_log << "PANIC3 handler @ " << std::hex << s_panic_handler_3.getAddress() << std::endl;
unsigned upper_timeout, lower_timeout, instr_timeout;
if (m_elf.getFilename().find("isorc") != std::string::npos) {
@ -300,6 +305,7 @@ bool CoredTester::run() {
// Extract stack ranges for checkpoint plugin
Checkpoint::range_vector check_ranges;
ElfReader::symbol_iterator it = m_elf.sym_begin();
std::map<fail::address_t, fail::address_t> stackpointers;
for( ; it != m_elf.sym_end(); ++it) {
const std::string name = it->getName();
@ -324,6 +330,14 @@ bool CoredTester::run() {
Checkpoint::indirectable_address_t start = std::make_pair(s_sptr.getAddress(), true);
Checkpoint::indirectable_address_t end = std::make_pair(s_end.getEnd(), false);
check_ranges.push_back(std::make_pair(start, end));
// Save the stackpointer address (in this variable the
// actual stackpointer is stored)
address_t paddr = s_sptr.getAddress();
stackpointers[paddr] = paddr;
stackpointers[paddr+1] = paddr;
stackpointers[paddr+2] = paddr;
stackpointers[paddr+3] = paddr;
}
// Init Plugins
@ -412,6 +426,9 @@ bool CoredTester::run() {
continue; // next experiment
}
MemWriteListener *stackpointer_event = 0;
bool stackpointer_event_valid = false;
// perform injection
if (pc_injection) {
// jump to "data" address
@ -427,6 +444,20 @@ bool CoredTester::run() {
} else {
// inject random bitflip
// experiment_id == bitpos
// We cache the stackpointer value inside the
// checkpoint plugin, if we inject it. This prevents
// the Checkpoint plugin to read invalid values.
if (stackpointers.find(data_address) != stackpointers.end()) {
guest_address_t paddr = stackpointers[data_address];
guest_address_t value = 0;
simulator.getMemoryManager().getBytes(paddr, 4, &value);
cpoint.cache_stackpointer_variable(paddr, value);
stackpointer_event = new MemWriteListener(paddr);
stackpointer_event_valid = true;
m_log << "Injected Stackpointer; saved old stackpointer value ("
<< hex << "0x" << paddr << "="<< value << dec << ")"<< std::endl;
}
result->set_original_value(injectBitFlip(data_address, data_width, experiment_id));
}
@ -435,6 +466,7 @@ bool CoredTester::run() {
simulator.clearListeners(this);
simulator.addListener(&l_panic);
simulator.addListener(&l_panic_2);
simulator.addListener(&l_panic_3);
l_timeout.setTimeout(upper_timeout);
simulator.addListener(&l_timeout);
simulator.addListener(&l_timeout_hard);
@ -454,13 +486,29 @@ bool CoredTester::run() {
}
simulator.addListener(&l_trace_end_marker);
if (stackpointer_event_valid) {
m_log << "Injected Stackpointer; add listener 0x"
<< hex << stackpointer_event->getWatchAddress() << dec
<< " " << stackpointer_event->getTriggerAccessType() << endl;
simulator.addListener(stackpointer_event);
}
// resume and wait for results
m_log << "Resuming till the crash (time: " << simulator.getTimerTicks() << ")" << std::endl;
bool reached_check_start = false;
fail::BaseListener* l = simulator.resume();
int checkpoints = 0;
while(l == &l_fail_trace) {
while(l == &l_fail_trace || l == stackpointer_event) {
m_log << "Trace_event!" << endl;
if (l == stackpointer_event) {
cpoint.uncache_stackpointer_variable(stackpointer_event->getWatchAddress());
m_log << "Injected Stackpointer; cleared stackpointer cache" << std::endl;
l = simulator.resume();
continue;
}
assert (l == &l_fail_trace);
Checkpoint::check_result res = cpoint.check(s_fail_trace, l_fail_trace.getTriggerInstructionPointer());
checkpoints ++;
if(res == Checkpoint::DIFFERENT_IP) {
@ -505,9 +553,13 @@ bool CoredTester::run() {
l = simulator.addListenerAndResume(&l_fail_trace);
}
if (stackpointer_event_valid)
delete stackpointer_event;
// End of Injection Phase. Now we have crashed
m_log << "Crashed (time: " << simulator.getTimerTicks() << ")"<< std::endl;
m_log << "Crashed (time: " << simulator.getTimerTicks() << "), IP=0x"
<< hex << simulator.getCPU(0).getInstructionPointer() << dec
<< ")"<< std::endl;
result->set_time_crash(simulator.getTimerTicks());
if(l == &l_fail_trace) {
@ -517,7 +569,7 @@ bool CoredTester::run() {
std::stringstream ss;
ss << "correct end after " << cpoint.getCount() << " checkpoints";
handleEvent(*result, result->OK, ss.str());
} else if (l == &l_panic || l == &l_panic_2) {
} else if (l == &l_panic || l == &l_panic_2 || l == &l_panic_3) {
// error detected
stringstream sstr;
sstr << "PANIC";

View File

@ -11,7 +11,7 @@
#include <string>
#include "util/llvmdisassembler/LLVMtoFailTranslator.hpp"
class CoredTester : public fail::ExperimentFlow {
class dOSEKTester : public fail::ExperimentFlow {
public:
private:
@ -25,7 +25,7 @@ private:
const fail::ElfSymbol& getELFSymbol(const std::string name);
public:
CoredTester() : m_log("CoredTester", false), m_mm(fail::simulator.getMemoryManager()) {}
dOSEKTester() : m_log("dOSEKTester", false), m_mm(fail::simulator.getMemoryManager()) {}
bool run();
};

View File

@ -4,7 +4,7 @@
#include "sal/SALInst.hpp"
#include "sal/Register.hpp"
#include "sal/Listener.hpp"
#include "experiment.hpp"
#include "tracer.hpp"
#include "util/CommandLine.hpp"
#include "util/gzstream/gzstream.h"
@ -16,9 +16,9 @@
using namespace std;
using namespace fail;
void CoRedTracing::parseOptions() {
void dOSEKTracer::parseOptions() {
CommandLine &cmd = CommandLine::Inst();
cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... <BochsOptions...>\n\n");
cmd.addOption("", "", Arg::None, "Tracer: -Wf,--mode=tracer -Wf,[option] -Wf,[option] ... <BochsOptions...>\n\n");
CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help \tPrint usage and exit");
@ -173,7 +173,7 @@ void CoRedTracing::parseOptions() {
}
bool CoRedTracing::run()
bool dOSEKTracer::run()
{
parseOptions();

View File

@ -10,7 +10,7 @@
class CoRedTracing : public fail::ExperimentFlow {
class dOSEKTracer : public fail::ExperimentFlow {
std::string start_symbol;
std::string stop_symbol;
std::string save_symbol;
@ -31,7 +31,7 @@ public:
void parseOptions();
bool run();
CoRedTracing() : full_trace(false), m_log("CoRedTracing", false) {};
dOSEKTracer() : full_trace(false), m_log("dOSEKTracer", false) {};
};
#endif // __CORED_TRACING_HPP__