diff --git a/src/experiments/kesorefs/CMakeLists.txt b/src/experiments/kesorefs/CMakeLists.txt index 4ef3621b..f74e7597 100644 --- a/src/experiments/kesorefs/CMakeLists.txt +++ b/src/experiments/kesorefs/CMakeLists.txt @@ -5,15 +5,15 @@ configure_file(../instantiate-experiment.ah.in ) ## Setup desired protobuf descriptions HERE ## -set(MY_PROTOS -# vezs-example.proto +set(MY_PROTOS + kesoref.proto ) set(MY_CAMPAIGN_SRCS experiment.hpp experiment.cc - #campaign.hpp - #campaign.cc + campaign.hpp + campaign.cc ) #### PROTOBUFS #### @@ -21,13 +21,13 @@ find_package(Protobuf REQUIRED) include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) -#PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS}) +PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS}) ## Build library add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS}) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters -#add_executable(${EXPERIMENT_NAME}-server main.cc) -#target_link_libraries(${EXPERIMENT_NAME}-server fail-${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY}) -#install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin) +add_executable(${EXPERIMENT_NAME}-server main.cc) +target_link_libraries(${EXPERIMENT_NAME}-server fail-${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY}) +install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin) diff --git a/src/experiments/kesorefs/campaign.cc b/src/experiments/kesorefs/campaign.cc new file mode 100644 index 00000000..b628548d --- /dev/null +++ b/src/experiments/kesorefs/campaign.cc @@ -0,0 +1,85 @@ +#include +#include + +#include "campaign.hpp" +#include "experimentInfo.hpp" +#include "cpn/CampaignManager.hpp" +#include "util/Logger.hpp" +#include "util/ElfReader.hpp" +#include "util/ProtoStream.hpp" +#include "sal/SALConfig.hpp" + +//#if COOL_FAULTSPACE_PRUNING +//#include "../plugins/tracing/TracingPlugin.hpp" +//char const * const trace_filename = "trace.pb"; +//#endif + +using namespace std; +using namespace fail; + +char const * const results_csv = "kesorefs.csv"; + +bool KesoRefCampaign::run() +{ + Logger log("KesoRefCampaign"); + fail::ElfReader m_elf("/proj/mmtmp41/hoffmann/kesoeval/cdx_x86"); + + ifstream test(results_csv); + if (test.is_open()) { + log << results_csv << " already exists" << endl; + return false; + } + ofstream results(results_csv); + if (!results.is_open()) { + log << "failed to open " << results_csv << endl; + return false; + } + + ElfReader elf; + address_t injip = elf.getAddressByName("c23_PersistentDetectorScopeEntry_m5_run"); + + address_t rambase = elf.getAddressByName("__CIAO_APPDATA_cdx_det__heap"); + address_t ramend = rambase + 0x80000; + cout << "bla: " << hex << ramend << endl; + //address_t ramend = rambase + 4; + + log << "startup, injecting ram @ " << hex << rambase << endl; + + int count = 0; + for (address_t ram_address = rambase; ram_address < ramend ; ram_address += 4) { + for (int bit_offset = 23; bit_offset < 24; ++bit_offset) { + KesoRefExperimentData *d = new KesoRefExperimentData; + + d->msg.set_pc_address(injip); + d->msg.set_ram_address(ram_address); + d->msg.set_bit_offset(bit_offset); + + campaignmanager.addParam(d); + ++count; + } + } + campaignmanager.noMoreParameters(); + log << "done enqueueing parameter sets (" << dec << count << ")." << endl; + + // collect results + KesoRefExperimentData *res; + int rescount = 0; + results << "injection_ip\tram_address\tbit_offset\tresulttype\toriginal_value\tdetails" << endl; + while ((res = static_cast(campaignmanager.getDone()))) { + rescount++; + + results + << "0x" << hex << res->msg.pc_address() << "\t" + << "0x" << hex << res->msg.ram_address() << "\t" + << dec << res->msg.bit_offset() << "\t" + << res->msg.resulttype() << "\t" + << res->msg.original_value() << "\t" + << res->msg.details() << "\n"; + delete res; + } + + log << "done. sent " << count << " received " << rescount << endl; + results.close(); + + return true; +} diff --git a/src/experiments/kesorefs/campaign.hpp b/src/experiments/kesorefs/campaign.hpp new file mode 100644 index 00000000..d9c2859f --- /dev/null +++ b/src/experiments/kesorefs/campaign.hpp @@ -0,0 +1,19 @@ +#ifndef __KESOREFCAMPAIGN_HPP__ + #define __KESOREFCAMPAIGN_HPP__ + +#include "cpn/Campaign.hpp" +#include "comm/ExperimentData.hpp" +#include "kesoref.pb.h" + +class KesoRefExperimentData : public fail::ExperimentData { +public: + KesoRefProtoMsg msg; + KesoRefExperimentData() : fail::ExperimentData(&msg) {} +}; + +class KesoRefCampaign : public fail::Campaign { +public: + virtual bool run(); +}; + +#endif // __KESOREFCAMPAIGN_HPP__ diff --git a/src/experiments/kesorefs/experiment.cc b/src/experiments/kesorefs/experiment.cc index 37a6e879..6f8907b6 100644 --- a/src/experiments/kesorefs/experiment.cc +++ b/src/experiments/kesorefs/experiment.cc @@ -18,6 +18,9 @@ #include #include +#include "campaign.hpp" +#include "kesoref.pb.h" + using namespace std; using namespace fail; @@ -33,72 +36,47 @@ void KESOrefs::printEIP() { m_log << "EIP = 0x" << hex << simulator.getCPU(0).getInstructionPointer() <<" "<< m_elf.getNameByAddress(simulator.getCPU(0).getInstructionPointer()) << endl; } -static vector mg_exitbps; - -void KESOrefs::setupExitBPs(const string& funcname){ - BPSingleListener* bp = new BPSingleListener(); - bp->setWatchInstructionPointer(m_elf.getAddressByName(funcname)); - - mg_exitbps.push_back(bp); -} - -void KESOrefs::enableBPs(){ - vector::const_iterator it; - // add all BPs - for(it = mg_exitbps.begin(); it != mg_exitbps.end(); ++it){ - simulator.addListener(*it); - } -} - -void KESOrefs::clearExitBPs(){ - for( size_t i = 0; i < mg_exitbps.size(); i++){ - delete mg_exitbps[i]; - } - mg_exitbps.clear(); -} - -const unsigned KESO_NUM_STATIC_REFS = 36; // from KESO globals.h - -address_t rev_byte(address_t dword){ - return ((dword>>24)&0x000000FF) | ((dword>>8)&0x0000FF00) | ((dword<<8)&0x00FF0000) | ((dword<<24)&0xFF000000); -} - -void KESOrefs::showStaticRefs(){ - address_t sref_start = m_elf.getAddressByName("__CIAO_APPDATA_cdx_det__heap"); // guest_address_t -> uint32_t - MemoryManager& mm = simulator.getMemoryManager(); - address_t value = 0; - m_log << "__CIAO_APPDATA_cdx_det__heap : 0x" << hex << setw(8) << setfill('0') << sref_start << endl; - - for(unsigned i = 0; i < KESO_NUM_STATIC_REFS; ++i){ - mm.getBytes(sref_start+(i*4), 4, (void*)&value); - value = rev_byte(value); - cout << "0x" << hex << setw(8) << setfill('0') << value << " | "; - if ((i+1) % 8 == 0) cout << "" << endl; - } - cout << "" << endl; -} - -void KESOrefs::injectStaticRefs(unsigned referenceoffset, unsigned bitpos){ - address_t sref_start = m_elf.getAddressByName("__CIAO_APPDATA_cdx_det__heap"); // guest_address_t -> uint32_t +unsigned KESOrefs::injectBitFlip(address_t data_address, unsigned bitpos){ MemoryManager& mm = simulator.getMemoryManager(); - address_t value = 0, injectedval =0; + unsigned value, injectedval; - sref_start += (referenceoffset*4); - - if(referenceoffset > KESO_NUM_STATIC_REFS){ - m_log << "WARNING: reference offset to large!" << endl; - } - mm.getBytes(sref_start, 4, (void*)&value); + mm.getBytes(data_address, 4, (void*)&value); injectedval = value ^ bitpos; - mm.setBytes(sref_start, 4, (void*)&injectedval); + mm.setBytes(data_address, 4, (void*)&injectedval); - m_log << "INJECTION at: __CIAO_APPDATA_cdx_det__heap + " << referenceoffset << " : 0x" << hex << setw(8) << setfill('0') << sref_start; + m_log << "INJECTION at: 0x" << hex << setw(8) << setfill('0') << data_address; cout << " value: 0x" << setw(8) << setfill('0') << value << " -> 0x" << setw(8) << setfill('0') << injectedval << endl; + return value; } +void handleEvent(KesoRefExperimentData& param, KesoRefProtoMsg_ResultType restype, const std::string &msg){ + cout << msg << endl; + param.msg.set_resulttype(restype); + param.msg.set_details(msg); +} + +void handleMemoryAccessEvent(KesoRefExperimentData& param, const fail::MemAccessListener& l_mem){ + stringstream sstr; + sstr << "mem access ("; + switch (l_mem.getTriggerAccessType()) { + case MemAccessEvent::MEM_READ: + sstr << "r"; + break; + case MemAccessEvent::MEM_WRITE: + sstr << "w"; + break; + default: break; + } + sstr << ") @ 0x" << hex << l_mem.getTriggerAddress(); + + sstr << " ip @ 0x" << hex << l_mem.getTriggerInstructionPointer(); + + handleEvent(param, param.msg.MEMACCESS, sstr.str()); +} + bool KESOrefs::run() { @@ -108,7 +86,7 @@ bool KESOrefs::run() #if SAFESTATE // define SS (SafeState) when building: make -DSS #warning "Building safe state variant" - m_log << "Booting, and saving state at "; + m_log << "Booting, and saving state at main"; BPSingleListener bp; // STEP 1: run until interesting function starts, and save state bp.setWatchInstructionPointer(m_elf.getAddressByName("main")); @@ -123,36 +101,85 @@ bool KESOrefs::run() //******* Fault injection *******// #warning "Building restore state variant" + + for (int experiment_count = 0; experiment_count < 200 || (m_jc.getNumberOfUndoneJobs() != 0) ; ) { // only do 200 sequential experiments, to prevent swapping + + m_log << "asking jobserver for parameters" << endl; + KesoRefExperimentData param; + if(!m_jc.getParam(param)){ + m_log << "Dying." << endl; // We were told to die. + simulator.terminate(1); + } + + // Get input data from Jobserver + address_t injectionPC = param.msg.pc_address(); + address_t data_address = param.msg.ram_address(); + unsigned bitpos = param.msg.bit_offset(); + + simulator.restore("keso.state"); - - // Goto injection point BPSingleListener injBP; - injBP.setWatchInstructionPointer(m_elf.getAddressByName("c23_PersistentDetectorScopeEntry_m5_run")); + m_log << "Trying to inject @ " << hex << m_elf.getNameByAddress(injectionPC) << endl; + + injBP.setWatchInstructionPointer(injectionPC); + simulator.addListenerAndResume(&injBP); - printEIP(); m_log << "Lets inject some stuff..." << endl; - showStaticRefs(); + printEIP(); /// INJECT BITFLIP: - injectStaticRefs(9, 9); - showStaticRefs(); + param.msg.set_original_value(injectBitFlip(data_address, bitpos)); // Setup exit points - setupExitBPs("keso_throw_error"); - setupExitBPs("keso_throw_parity"); - setupExitBPs("keso_throw_nullpointer"); - setupExitBPs("keso_throw_index_out_of_bounds"); - setupExitBPs("c17_Main_m4_dumpResults_console"); - setupExitBPs("os::krn::OSControl::shutdownOS"); - - enableBPs(); + BPSingleListener l_error(m_elf.getAddressByName("keso_throw_error")); + BPSingleListener l_nullp(m_elf.getAddressByName("keso_throw_nullpointer")); + BPSingleListener l_parity(m_elf.getAddressByName("keso_throw_parity")); + BPSingleListener l_oobounds(m_elf.getAddressByName("keso_throw_index_out_of_bounds")); + BPSingleListener l_dump(m_elf.getAddressByName("c17_Main_m4_dumpResults_console")); + MemAccessListener l_memtext(99999); l_memtext.setWatchWidth(2); + TrapListener l_trap(ANY_TRAP); + simulator.addListener(&l_trap); + simulator.addListener(&l_error); + simulator.addListener(&l_nullp); + simulator.addListener(&l_oobounds); + simulator.addListener(&l_dump); + simulator.addListener(&l_parity); // resume and wait for results - /* fail::BaseListener* l =*/ simulator.resume(); + fail::BaseListener* l = simulator.resume(); printEIP(); - showStaticRefs(); - // cleanup - clearExitBPs(); + + // Evaluate result + if(l == &l_error) { + handleEvent(param, param.msg.EXC_ERROR, "exc error"); + + } else if ( l == &l_nullp ) { + handleEvent(param, param.msg.EXC_NULLPOINTER, "exc nullpointer"); + + } else if ( l == &l_oobounds ) { + handleEvent(param, param.msg.EXC_OOBOUNDS, "exc out of bounds"); + + } else if (l == &l_dump) { + handleEvent(param, param.msg.CALCDONE, "calculation done"); + + } else if (l == &l_parity) { + handleEvent(param, param.msg.EXC_PARITY, "exc parity"); + + } else if (l == &l_trap) { + stringstream sstr; + sstr << "trap #" << l_trap.getTriggerNumber(); + handleEvent(param, param.msg.TRAP, sstr.str()); + + } else if (l == &l_memtext){ + handleMemoryAccessEvent(param, l_memtext); + + } else { + handleEvent(param, param.msg.UNKNOWN, "UNKNOWN event"); + } + simulator.clearListeners(); + m_jc.sendResult(param); +} // end while (1) // Explicitly terminate, or the simulator will continue to run. #endif simulator.terminate(); } + diff --git a/src/experiments/kesorefs/experiment.hpp b/src/experiments/kesorefs/experiment.hpp index 6e2a60aa..4977dfea 100644 --- a/src/experiments/kesorefs/experiment.hpp +++ b/src/experiments/kesorefs/experiment.hpp @@ -1,6 +1,8 @@ #ifndef __KESO_REFS_EXPERIMENT_HPP__ #define __KESO_REFS_EXPERIMENT_HPP__ + +#include "sal/SALInst.hpp" #include "efw/ExperimentFlow.hpp" #include "efw/JobClient.hpp" #include "util/Logger.hpp" @@ -18,7 +20,9 @@ class KESOrefs : public fail::ExperimentFlow { void enableBPs(); void clearExitBPs(); void showStaticRefs(); - void injectStaticRefs(unsigned referenceoffset, unsigned bitpos); + + unsigned injectBitFlip(fail::address_t data_address, unsigned bitpos); + public: KESOrefs() : m_log("KESOrefs", false), m_mm(fail::simulator.getMemoryManager()) {}; bool run(); diff --git a/src/experiments/kesorefs/kesoref.proto b/src/experiments/kesorefs/kesoref.proto new file mode 100644 index 00000000..f65c5154 --- /dev/null +++ b/src/experiments/kesorefs/kesoref.proto @@ -0,0 +1,27 @@ +message KesoRefProtoMsg { + // parameters + required int32 pc_address = 1; + required int32 ram_address = 2; + required int32 bit_offset = 3; + + // results + // make these optional to reduce overhead for server->client communication + enum ResultType { + CALCDONE = 1; + TIMEOUT = 2; + TRAP = 3; + EXC_ERROR = 4; + EXC_PARITY = 5; + EXC_NULLPOINTER = 6; + EXC_OOBOUNDS = 7; + MEMACCESS = 8; + UNKNOWN = 9; + } + // result type, see above + optional ResultType resulttype = 4; + optional uint32 original_value = 5; + // did ECC correct the fault? + //optional int32 error_corrected = 6; + // optional textual description of what happened + optional string details = 7; +} diff --git a/src/experiments/kesorefs/main.cc b/src/experiments/kesorefs/main.cc index 16605ac5..4af91718 100644 --- a/src/experiments/kesorefs/main.cc +++ b/src/experiments/kesorefs/main.cc @@ -6,7 +6,7 @@ int main(int argc, char **argv) { - ChecksumOOStuBSCampaign c; + KesoRefCampaign c; if (fail::campaignmanager.runCampaign(&c)) { return 0; } else {