diff --git a/src/experiments/lra-simple-panda/campaign.hpp b/src/experiments/lra-simple-panda/campaign.hpp index 333e3ac3..9364fca8 100644 --- a/src/experiments/lra-simple-panda/campaign.hpp +++ b/src/experiments/lra-simple-panda/campaign.hpp @@ -1,5 +1,5 @@ -#ifndef __DCIAOCAMPAIGN_HPP__ -#define __DCIAOCAMPAIGN_HPP__ +#ifndef __LRA_CAMPAIGN_HPP__ +#define __LRA_CAMPAIGN_HPP__ #include "cpn/DatabaseCampaign.hpp" #include "comm/ExperimentData.hpp" @@ -18,6 +18,9 @@ class LraSimpleCampaign : public fail::DatabaseCampaign { { return google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName("LraSimpleProtoMsg"); } virtual void cb_send_pilot(DatabaseCampaignMessage pilot); + virtual int expected_number_of_results(std::string variant, std::string benchmark) { + return 1; + } }; -#endif // __KESOREFCAMPAIGN_HPP__ +#endif // __LRA_CAMPAIGN_HPP__ diff --git a/src/experiments/lra-simple-panda/experiment.cc b/src/experiments/lra-simple-panda/experiment.cc index 97631ddb..199ab6b7 100644 --- a/src/experiments/lra-simple-panda/experiment.cc +++ b/src/experiments/lra-simple-panda/experiment.cc @@ -10,19 +10,21 @@ #include "util/WallclockTimer.hpp" #include "util/gzstream/gzstream.h" +#include "util/WallclockTimer.hpp" #include "efw/JobClient.hpp" #include "lra_simple.pb.h" #include "campaign.hpp" -#include "cpn/InjectionPoint.hpp" #include "config/FailConfig.hpp" #include #include +#include + // you need to have the tracing plugin enabled for this #include "../plugins/tracing/TracingPlugin.hpp" @@ -36,10 +38,26 @@ using namespace fail; #define PREPARATION 0 +int32_t correct_result[100] = { + 0, 6, 5, 1, 6, 2, 7, 3, + 8, 4, 1, 6, 5, 9, 5, 3, + 0, 6, 5, 3, 7, 1, 7, 2, + 8, 3, 9, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; + // ToDo: Move this functionality to SimulatorController -void LRASimplePandaExperiment::navigateToInjectionPoint(ConcreteInjectionPoint &ip) { - Logger log_nav("navigator"); +bool LRASimplePandaExperiment::navigateToInjectionPoint(ConcreteInjectionPoint &ip) { + Logger log_nav("navigator", false); #ifdef CONFIG_INJECTIONPOINT_HOPS // Hop nav @@ -60,6 +78,10 @@ void LRASimplePandaExperiment::navigateToInjectionPoint(ConcreteInjectionPoint & InjectionPointMessage_Hops h = ipm.hops(i); BaseListener *hop, *ev; + // Nav-fail-bp + BPSingleListener ev_func_end(elfReader->getSymbol("main").getEnd() - 4 - LRASP_MAIN_ENDOFFSET); + simulator.addListener(&ev_func_end); + if (h.accesstype() == h.EXECUTE) { log_nav << "BP at " << hex << h.address() << dec << endl; BPSingleListener bp (h.address()); @@ -76,56 +98,69 @@ void LRASimplePandaExperiment::navigateToInjectionPoint(ConcreteInjectionPoint & log_nav << "Halted" << endl; + if (ev == &ev_func_end) { + log_nav << "Navigational error..." << endl; + simulator.clearListeners(); + return false; + } else { + simulator.removeListener(&ev_func_end); + } + if (ev != hop) { log_nav << "FATAL ERROR: Unexpected event while navigating!" << endl; simulator.terminate(1); } + } #else // Step nav InjectionPointMessage ipm; ip.copyInjectionPointMessage(ipm); - log_nav << ipm.injection_instr() << endl; + log_nav << "Navigating to instruction " << ipm.injection_instr() << endl; + BPSingleListener step(ANY_ADDR); + step.setCounter(ipm.injection_instr()); + simulator.addListenerAndResume(&step); #endif + return true; } bool LRASimplePandaExperiment::run() { - Logger _log("lra-simpla-panda", false); - _log << "Startup" << endl; - - fail::ElfReader elfReader; - fail::JobClient jobClient; + Logger logger("lra-simpla-panda", false); + logger << "Startup" << endl; + elfReader = new ElfReader(); + fail::JobClient *jobClient = new JobClient(); #if PREPARATION == 1 - _log << "Preparation mode" << endl; + logger << "Preparation mode" << endl; + // STEP 1: run until main starts, save state, record trace - // TODO: store golden run output - BPSingleListener func_begin(elfReader.getSymbol("test_code_due").getAddress()); + BPSingleListener func_begin(elfReader->getSymbol("main").getStart()); simulator.addListenerAndResume(&func_begin); - _log << "test_func() reached, beginning trace recording" << endl; + logger << "test_func() reached, beginning trace recording" << endl; TracingPlugin tp; - // ogzstream of(LRASP_TRACE); - ofstream of(LRASP_TRACE); + ogzstream of(LRASP_TRACE); if (of.bad()) { - _log << "FATAL ERROR: Trace file could not be opened." << endl; + logger << "FATAL ERROR: Trace file could not be opened." << endl; simulator.terminate(); return false; } - tp.setTraceFile(&of); - //tp.setOstream(&of); + tp.setOstream(&of); // this must be done *after* configuring the plugin: simulator.addFlow(&tp); - BPSingleListener func_end(elfReader.getSymbol("test_code_due").getAddress() + elfReader.getSymbol("test_code_due").getSize() - 4); + BPSingleListener func_end(elfReader->getSymbol("main").getEnd() - 4 - 28); simulator.addListener(&func_end); BPSingleListener step(ANY_ADDR); + WallclockTimer timer; + timer.startTimer(); + // count instructions long counter = 0; while (true) { @@ -135,80 +170,207 @@ bool LRASimplePandaExperiment::run() } counter++; if ((counter % 1000) == 0) { - _log << "Traced " << counter << " insturctions" << endl; - of.flush(); + timer.stopTimer(); + logger << "Traced " << counter << " insturctions in " << timer << " seconds" << endl; + timer.reset(); + timer.startTimer(); } } - _log << "golden run took " << dec << counter << " instructions" << endl; + logger << "Traced " << counter << " insturctions in " << timer << " seconds" << endl << endl; + + logger << "golden run took " << dec << counter << " instructions" << endl; simulator.removeFlow(&tp); + of.flush(); // serialize trace to file if (of.fail()) { - _log << "failed to write to trace file"<< std::endl; + logger << "failed to write to trace file"<< std::endl; return false; } of.close(); -#else +#else // PREPARATION unsigned executed_jobs = 0; - _log << "Startup!" << endl; - - // std::ofstream exp_output ("exp.txt"); - - ConcreteCPU cpu = simulator.getCPU(0); - ConcreteCPU::iterator it = cpu.begin(); - it++; it++; - while (jobClient.getNumberOfUndoneJobs() > 0 || executed_jobs < 500) { - _log << "asking jobserver for parameters" << endl; + while (true) { + logger << "asking jobserver for parameters. Undone: "<getNumberOfUndoneJobs() << endl; LraSimpleExperimentData param; - if(!jobClient.getParam(param)){ - _log << "Dying." << endl; // We were told to die. + if(!jobClient->getParam(param)){ + logger << "Dying." << endl; // We were told to die. simulator.terminate(1); } + logger << "New param" << param.msg.DebugString() << endl; + // Get input data from Jobserver unsigned injection_instr = param.msg.fsppilot().injection_instr(); address_t data_address = param.msg.fsppilot().data_address(); - unsigned data_width = param.msg.fsppilot().data_width(); + // unsigned data_width = param.msg.fsppilot().data_width(); ConcreteInjectionPoint ip; ip.parseFromCampaignMessage(param.msg.fsppilot()); - // ToDo: Insert into all 8 Bits - for (int experiment_id = 0; experiment_id < 1; ++experiment_id) { - LraSimpleProtoMsg_Result *result = 0; + for (unsigned experiment_id = 0; experiment_id < LRASP_NUM_EXP_PER_PILOT; ++experiment_id) { + LraSimpleProtoMsg_Result *result = param.msg.add_result(); + executed_jobs ++; - _log << "rebooting device" << endl; + WallclockTimer timer; + timer.startTimer(); + + /******************** + * INITIALIZATION * + ********************/ + + logger << "rebooting device" << endl; // Restore to the image, which starts at address(main) simulator.reboot(); - executed_jobs ++; - // Fast forward to injection address - _log << "Trying to inject @ instr #" << dec << injection_instr << endl; + // In this case, no entry navigation is needed + // Otherwise we will have to navigate to the pre entry instruction!!! + BPSingleListener func_begin(elfReader->getSymbol("main").getStart()); + simulator.addListenerAndResume(&func_begin); - navigateToInjectionPoint(ip); + timer.stopTimer(); + result->set_time_init(float(timer)); + timer.reset(); - uint32_t iteration_counter; - simulator.getMemoryManager().getBytes(elfReader.getSymbol("test_code_idx").getAddress(), 4, (void*)(&iteration_counter)); + /**************** + * NAVIGATION * + ****************/ + logger << "Fastforwarding to instr #" << injection_instr << endl; - result = param.msg.add_result(); + timer.startTimer(); + if (!navigateToInjectionPoint(ip)) { + continue; + } + timer.stopTimer(); + result->set_time_nav(float(timer)); + timer.reset(); + + /*************** + * INJECTION * + ***************/ + // We do a 8-bit flip burst + + // Alternatively for single-bit-flips: + // data ^= 1 << experiment_id; + + + logger << "Injection bitflips at address " << hex << data_address << dec << endl; + + timer.startTimer(); + byte_t data = simulator.getMemoryManager().getByte(data_address); + data = ~data; + simulator.getMemoryManager().setByte(data_address, data); // write back data to register + timer.stopTimer(); + result->set_time_inject(float(timer)); + timer.reset(); + + /*************** + * AFTERMATH * + ***************/ + logger << "Aftermath: Checking for wrong mem access, traps, timeout, wrong result or success" << endl; + + timer.startTimer(); + + // Setup MMU + /* + * As the false positive rate is very high, if we watch a + * page with actively used memory and because of the high + * costs for a false positive (in the magnitude of seconds), + * we don't want to watch those areas. + * + * We must not watch the following areas: + * - UART I/O Port at 0x48020014 => don't watch page 0x48020000 + * - .text-, .bss- and .data-segment at 0x83000000 to 0x83411000 (exclusive) + * - Stack at 0xBFD00000 to 0xC0000000 + */ + + MemAccessListener ev_unauth_mem_acc_1(0x0); + ev_unauth_mem_acc_1.setWatchWidth(0x48020000); + simulator.addListener(&ev_unauth_mem_acc_1); + + MemAccessListener ev_unauth_mem_acc_2(0x48021000); + ev_unauth_mem_acc_2.setWatchWidth(0x83000000 - 0x48021000); + simulator.addListener(&ev_unauth_mem_acc_2); + + MemAccessListener ev_unauth_mem_acc_3(0x83411000); + ev_unauth_mem_acc_3.setWatchWidth(0xBFD00000 - 0x83411000); + simulator.addListener(&ev_unauth_mem_acc_3); + + MemAccessListener ev_unauth_mem_acc_4(0xC0000000); + ev_unauth_mem_acc_4.setWatchWidth(0xFFFFFFFF - 0xC0000000); + simulator.addListener(&ev_unauth_mem_acc_4); + + // Traps + + TrapListener ev_trap(fail::ANY_TRAP, NULL); + simulator.addListener(&ev_trap); + + // Timeout + + TimerListener ev_timeout(LRASP_TIMEOUT); + simulator.addListener(&ev_timeout); + + // Termination + + BPSingleListener ev_func_end(elfReader->getSymbol("main").getEnd() - 4 - LRASP_MAIN_ENDOFFSET); + simulator.addListener(&ev_func_end); + + logger << "waiting for function exit, trap or timeout(1 second)" << endl; + BaseListener* ev = simulator.resume(); + + if (ev == &ev_timeout) { + logger << "Timeout!" << endl; + result->set_resulttype(result->ERR_TIMEOUT); + } else if (ev == &ev_trap) { + logger << "Trap!" << endl; + result->set_resulttype(result->ERR_TRAP); + } else if (ev == &ev_unauth_mem_acc_1 || + ev == &ev_unauth_mem_acc_2 || + ev == &ev_unauth_mem_acc_3 || + ev == &ev_unauth_mem_acc_4) { + + result->set_resulttype(result->ERR_OUTSIDE_TEXT); + logger << hex << "Unauthorized memory access (" << ((((MemAccessListener*)ev)->getTriggerAccessType() == fail::MemAccessEvent::MEM_READ) ? "R" : "W") << + ") at instruction " << ((MemAccessListener*)ev)->getTriggerInstructionPointer() << " access address: " << + ((MemAccessListener*)ev)->getTriggerAddress() << dec << endl; + } else if (ev == &ev_func_end) { + logger << "Function terminated!" << endl; + + int32_t results[elfReader->getSymbol("result").getSize()/sizeof(int32_t)]; + simulator.getMemoryManager().getBytes(elfReader->getSymbol("result").getAddress(), + elfReader->getSymbol("result").getSize(), + (unsigned char*)results); + + result->set_resulttype(result->OK); + for (unsigned i = 0; i < sizeof(results) / sizeof(*results); ++i) { + if (correct_result[i] != results[i]) { + result->set_resulttype(result->ERR_WRONG_RESULT); + break; + } + } + } + + timer.stopTimer(); + result->set_time_aftermath(float(timer)); - result->set_bitoffset(experiment_id); - result->set_loop_iteration(iteration_counter); - result->set_resulttype(result->OK); result->set_experiment_number(executed_jobs); simulator.clearListeners(); } - jobClient.sendResult(param); + jobClient->sendResult(param); + logger << param.debugString(); } - _log << "jobClient.getNumberOfUndoneJobs() = " << jobClient.getNumberOfUndoneJobs() << "executed_jobs = " << executed_jobs << endl; + logger << "jobClient.getNumberOfUndoneJobs() = " << jobClient->getNumberOfUndoneJobs() << "executed_jobs = " << executed_jobs << endl; #endif // PREPARATION + delete elfReader; + delete jobClient; + simulator.terminate(); return true; } diff --git a/src/experiments/lra-simple-panda/experiment.hpp b/src/experiments/lra-simple-panda/experiment.hpp index e2c2f7af..463e7470 100644 --- a/src/experiments/lra-simple-panda/experiment.hpp +++ b/src/experiments/lra-simple-panda/experiment.hpp @@ -3,14 +3,17 @@ #include "efw/ExperimentFlow.hpp" #include "cpn/InjectionPoint.hpp" +#include "util/ElfReader.hpp" using namespace fail; class LRASimplePandaExperiment : public ExperimentFlow { +private: + fail::ElfReader *elfReader; public: LRASimplePandaExperiment() : ExperimentFlow() {} bool run(); - void navigateToInjectionPoint(ConcreteInjectionPoint &ip); + bool navigateToInjectionPoint(ConcreteInjectionPoint &ip); // void navigateToInjectionPoint(ConcreteInjectionPoint &ip, std::ostream &log); }; diff --git a/src/experiments/lra-simple-panda/experimentInfo.hpp b/src/experiments/lra-simple-panda/experimentInfo.hpp index 31937fad..113def05 100644 --- a/src/experiments/lra-simple-panda/experimentInfo.hpp +++ b/src/experiments/lra-simple-panda/experimentInfo.hpp @@ -2,12 +2,10 @@ #define __LRA_SIMPLE_PANDA_EXPERIMENT_INFO_HPP__ #define LRASP_TRACE "trace.tc" -#define LRASP_BIN_OFFSET 0x100000 -#define LRASP_RESULTS "LRASP.csv" -#define LRASP_TIMEOUT 1000000 // 1s -#define LRASP_ADDR_FUNC_BEGIN 0x83000978 -#define LRASP_ADDR_FUNC_END 0x83000a68 -#define LRASP_RESULT_ADDRESS 0x83016804 -#define LRASP_RESULTS_BYTES 4 +#define LRASP_TIMEOUT 3000000 // 1500ms +#define LRASP_RESULT_ADDRESS 0x834106b0 +#define LRASP_RESULTS_BYTES 1000 +#define LRASP_MAIN_ENDOFFSET 28 +#define LRASP_NUM_EXP_PER_PILOT 1 #endif diff --git a/src/experiments/lra-simple-panda/lra_simple.proto b/src/experiments/lra-simple-panda/lra_simple.proto index e3091e08..6e23cd1c 100644 --- a/src/experiments/lra-simple-panda/lra_simple.proto +++ b/src/experiments/lra-simple-panda/lra_simple.proto @@ -7,19 +7,24 @@ message LraSimpleProtoMsg { enum ResultType { OK = 1; - ERR_WRONG_RESULT = 4; + ERR_WRONG_RESULT = 2; - ERR_TRAP = 5; - ERR_TIMEOUT = 6; + ERR_TRAP = 3; + ERR_TIMEOUT = 4; - ERR_OUTSIDE_TEXT = 7; - - ERR_OUTSIDE_DATA = 8; + ERR_OUTSIDE_TEXT = 5; } - required int32 bitoffset = 1 [(sql_primary_key) = true]; + //required int32 bitoffset = 1 [(sql_primary_key) = true]; + + required uint32 experiment_number = 1 [(sql_primary_key) = true]; required ResultType resulttype = 2; - required uint32 experiment_number = 3; - required uint32 loop_iteration = 4; + + + // Times for evaluation + required float time_init = 3; + required float time_nav = 4; + required float time_inject = 5; + required float time_aftermath = 6; } } \ No newline at end of file