From 1e572faa041ef77942e335429f778ff0fb7579a4 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Wed, 5 Aug 2015 12:35:06 +0200 Subject: [PATCH] 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 --- src/experiments/cored-tracing/CMakeLists.txt | 18 ----- .../{cored-tester => dosek}/CMakeLists.txt | 18 +++-- .../{cored-tester => dosek}/campaign.cc | 0 .../{cored-tester => dosek}/campaign.hpp | 0 .../{cored-tester => dosek}/config.cmake | 9 ++- .../cored-tester.proto | 0 src/experiments/dosek/experiment.cc | 40 +++++++++++ .../{cored-tester => dosek}/main.cc | 0 .../experiment.cc => dosek/tester.cc} | 70 ++++++++++++++++--- .../experiment.hpp => dosek/tester.hpp} | 4 +- .../experiment.cc => dosek/tracer.cc} | 8 +-- .../experiment.hpp => dosek/tracer.hpp} | 6 +- 12 files changed, 129 insertions(+), 44 deletions(-) delete mode 100644 src/experiments/cored-tracing/CMakeLists.txt rename src/experiments/{cored-tester => dosek}/CMakeLists.txt (82%) rename src/experiments/{cored-tester => dosek}/campaign.cc (100%) rename src/experiments/{cored-tester => dosek}/campaign.hpp (100%) rename src/experiments/{cored-tester => dosek}/config.cmake (57%) rename src/experiments/{cored-tester => dosek}/cored-tester.proto (100%) create mode 100644 src/experiments/dosek/experiment.cc rename src/experiments/{cored-tester => dosek}/main.cc (100%) rename src/experiments/{cored-tester/experiment.cc => dosek/tester.cc} (88%) rename src/experiments/{cored-tester/experiment.hpp => dosek/tester.hpp} (86%) rename src/experiments/{cored-tracing/experiment.cc => dosek/tracer.cc} (97%) rename src/experiments/{cored-tracing/experiment.hpp => dosek/tracer.hpp} (78%) diff --git a/src/experiments/cored-tracing/CMakeLists.txt b/src/experiments/cored-tracing/CMakeLists.txt deleted file mode 100644 index 45f10904..00000000 --- a/src/experiments/cored-tracing/CMakeLists.txt +++ /dev/null @@ -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) \ No newline at end of file diff --git a/src/experiments/cored-tester/CMakeLists.txt b/src/experiments/dosek/CMakeLists.txt similarity index 82% rename from src/experiments/cored-tester/CMakeLists.txt rename to src/experiments/dosek/CMakeLists.txt index 8b046fb9..cd111f77 100644 --- a/src/experiments/cored-tester/CMakeLists.txt +++ b/src/experiments/dosek/CMakeLists.txt @@ -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 + 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 diff --git a/src/experiments/cored-tester/campaign.cc b/src/experiments/dosek/campaign.cc similarity index 100% rename from src/experiments/cored-tester/campaign.cc rename to src/experiments/dosek/campaign.cc diff --git a/src/experiments/cored-tester/campaign.hpp b/src/experiments/dosek/campaign.hpp similarity index 100% rename from src/experiments/cored-tester/campaign.hpp rename to src/experiments/dosek/campaign.hpp diff --git a/src/experiments/cored-tester/config.cmake b/src/experiments/dosek/config.cmake similarity index 57% rename from src/experiments/cored-tester/config.cmake rename to src/experiments/dosek/config.cmake index ace8740c..f547161c 100644 --- a/src/experiments/cored-tester/config.cmake +++ b/src/experiments/dosek/config.cmake @@ -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) diff --git a/src/experiments/cored-tester/cored-tester.proto b/src/experiments/dosek/cored-tester.proto similarity index 100% rename from src/experiments/cored-tester/cored-tester.proto rename to src/experiments/dosek/cored-tester.proto diff --git a/src/experiments/dosek/experiment.cc b/src/experiments/dosek/experiment.cc new file mode 100644 index 00000000..6cd3fbc1 --- /dev/null +++ b/src/experiments/dosek/experiment.cc @@ -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] ... \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); + } +} diff --git a/src/experiments/cored-tester/main.cc b/src/experiments/dosek/main.cc similarity index 100% rename from src/experiments/cored-tester/main.cc rename to src/experiments/dosek/main.cc diff --git a/src/experiments/cored-tester/experiment.cc b/src/experiments/dosek/tester.cc similarity index 88% rename from src/experiments/cored-tester/experiment.cc rename to src/experiments/dosek/tester.cc index 51b76691..ace4cb9c 100644 --- a/src/experiments/cored-tester/experiment.cc +++ b/src/experiments/dosek/tester.cc @@ -8,7 +8,7 @@ #include #include -#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 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; + 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"; diff --git a/src/experiments/cored-tester/experiment.hpp b/src/experiments/dosek/tester.hpp similarity index 86% rename from src/experiments/cored-tester/experiment.hpp rename to src/experiments/dosek/tester.hpp index a173089c..131a87d5 100644 --- a/src/experiments/cored-tester/experiment.hpp +++ b/src/experiments/dosek/tester.hpp @@ -11,7 +11,7 @@ #include #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(); }; diff --git a/src/experiments/cored-tracing/experiment.cc b/src/experiments/dosek/tracer.cc similarity index 97% rename from src/experiments/cored-tracing/experiment.cc rename to src/experiments/dosek/tracer.cc index e7e2aef7..81fa9fda 100644 --- a/src/experiments/cored-tracing/experiment.cc +++ b/src/experiments/dosek/tracer.cc @@ -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] ... \n\n"); + cmd.addOption("", "", Arg::None, "Tracer: -Wf,--mode=tracer -Wf,[option] -Wf,[option] ... \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(); diff --git a/src/experiments/cored-tracing/experiment.hpp b/src/experiments/dosek/tracer.hpp similarity index 78% rename from src/experiments/cored-tracing/experiment.hpp rename to src/experiments/dosek/tracer.hpp index 5a076000..776e35da 100644 --- a/src/experiments/cored-tracing/experiment.hpp +++ b/src/experiments/dosek/tracer.hpp @@ -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__ \ No newline at end of file +#endif // __CORED_TRACING_HPP__