diff --git a/src/core/comm/DatabaseCampaignMessage.proto b/src/core/comm/DatabaseCampaignMessage.proto index f2c80455..ae1e3d09 100644 --- a/src/core/comm/DatabaseCampaignMessage.proto +++ b/src/core/comm/DatabaseCampaignMessage.proto @@ -5,9 +5,10 @@ extend google.protobuf.FieldOptions { } message DatabaseCampaignMessage { - required int32 pilot_id = 1 [(sql_primary_key) = true]; - required int32 variant_id = 2 [(sql_ignore) = true]; - required int32 fspmethod_id = 3 [(sql_ignore) = true]; - required int32 instr2 = 4 [(sql_ignore) = true]; - required int32 data_address = 5 [(sql_ignore) = true]; + required int32 pilot_id = 1 [(sql_primary_key) = true]; + required int32 variant_id = 2 [(sql_ignore) = true]; + required int32 fspmethod_id = 3 [(sql_ignore) = true]; + required int32 injection_instr = 4 [(sql_ignore) = true]; + optional int32 injection_instr_absolute = 5 [(sql_ignore) = true]; + required int32 data_address = 6 [(sql_ignore) = true]; } \ No newline at end of file diff --git a/src/core/cpn/DatabaseCampaign.cc b/src/core/cpn/DatabaseCampaign.cc index 64f22794..9e9003bd 100644 --- a/src/core/cpn/DatabaseCampaign.cc +++ b/src/core/cpn/DatabaseCampaign.cc @@ -82,15 +82,15 @@ bool DatabaseCampaign::run() { /* Gather all unfinished jobs */ int experiment_count; - std::string sql_select = "SELECT pilot_id, fspgroup.fspmethod_id, fspgroup.variant_id, fspgroup.instr2, fspgroup.data_address "; + std::string sql_select = "SELECT pilot_id, g.fspmethod_id, g.variant_id, g.injection_instr, g.injection_instr_absolute, g.data_address"; std::stringstream ss; - ss << " FROM fspgroup INNER JOIN fsppilot ON fsppilot.id = fspgroup.pilot_id " - << " WHERE known_outcome = 0 " - << " AND fspgroup.fspmethod_id = " << fspmethod_id - << " AND fspgroup.variant_id = " << variant_id - // << " AND fsppilot.data_address = 1346688" - << " AND (SELECT COUNT(*) FROM " + db_connect.result_table() + " as r WHERE r.pilot_id = fspgroup.pilot_id) = 0" - << " ORDER BY fspgroup.instr2"; + ss << " FROM fspgroup g" + << " INNER JOIN fsppilot p ON p.id = g.pilot_id " + << " WHERE p.known_outcome = 0 " + << " AND g.fspmethod_id = " << fspmethod_id + << " AND g.variant_id = " << variant_id + << " AND (SELECT COUNT(*) FROM " + db_connect.result_table() + " as r WHERE r.pilot_id = g.pilot_id) = 0" + << " ORDER BY g.injection_instr"; std::string sql_body = ss.str(); /* Get the number of unfinished experiments */ @@ -105,15 +105,19 @@ bool DatabaseCampaign::run() { sent_pilots = 0; while ((row = mysql_fetch_row(pilots)) != 0) { - unsigned pilot_id = atoi(row[0]); - unsigned instr2 = atoi(row[3]); - unsigned data_address = atoi(row[4]); + unsigned pilot_id = atoi(row[0]); + unsigned injection_instr = atoi(row[3]); + unsigned data_address = atoi(row[5]); DatabaseCampaignMessage pilot; pilot.set_pilot_id(pilot_id); pilot.set_fspmethod_id(fspmethod_id); pilot.set_variant_id(variant_id); - pilot.set_instr2(instr2); + pilot.set_injection_instr(injection_instr); + if (row[4]) { + unsigned injection_instr_absolute = atoi(row[4]); + pilot.set_injection_instr_absolute(injection_instr_absolute); + } pilot.set_data_address(data_address); this->cb_send_pilot(pilot); diff --git a/src/experiments/dciao-kernelstructs/CMakeLists.txt b/src/experiments/dciao-kernelstructs/CMakeLists.txt new file mode 100644 index 00000000..d45e26e8 --- /dev/null +++ b/src/experiments/dciao-kernelstructs/CMakeLists.txt @@ -0,0 +1,35 @@ +set(EXPERIMENT_NAME dciao-kernelstructs) +set(EXPERIMENT_TYPE DCIAOKernelStructs) +configure_file(../instantiate-experiment.ah.in + ${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY +) + +## Setup desired protobuf descriptions HERE ## +set(MY_PROTOS + dciao_kernel.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(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS}) +add_dependencies(fail-${EXPERIMENT_NAME} fail-comm) +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} -lmysqlclient) +install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin) + diff --git a/src/experiments/dciao-kernelstructs/campaign.cc b/src/experiments/dciao-kernelstructs/campaign.cc new file mode 100644 index 00000000..101d12d8 --- /dev/null +++ b/src/experiments/dciao-kernelstructs/campaign.cc @@ -0,0 +1,20 @@ +#include +#include + +#include "campaign.hpp" +#include "cpn/CampaignManager.hpp" +#include "util/Logger.hpp" +#include "util/ElfReader.hpp" +#include "util/ProtoStream.hpp" +#include "sal/SALConfig.hpp" + +using namespace std; +using namespace fail; +using namespace google::protobuf; + +void DCIAOKernelCampaign::cb_send_pilot(DatabaseCampaignMessage pilot) { + DCIAOKernelExperimentData *data = new DCIAOKernelExperimentData; + data->msg.mutable_fsppilot()->CopyFrom(pilot); + campaignmanager.addParam(data); +} + diff --git a/src/experiments/dciao-kernelstructs/campaign.hpp b/src/experiments/dciao-kernelstructs/campaign.hpp new file mode 100644 index 00000000..9df5e29d --- /dev/null +++ b/src/experiments/dciao-kernelstructs/campaign.hpp @@ -0,0 +1,23 @@ +#ifndef __DCIAOCAMPAIGN_HPP__ +#define __DCIAOCAMPAIGN_HPP__ + +#include "cpn/DatabaseCampaign.hpp" +#include "comm/ExperimentData.hpp" +#include "dciao_kernel.pb.h" +#include "util/ElfReader.hpp" +#include + +class DCIAOKernelExperimentData : public fail::ExperimentData { +public: + DCIAOKernelProtoMsg msg; + DCIAOKernelExperimentData() : fail::ExperimentData(&msg) {} +}; + +class DCIAOKernelCampaign : public fail::DatabaseCampaign { + virtual const google::protobuf::Descriptor * cb_result_message() + { return google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName("DCIAOKernelProtoMsg"); } + + virtual void cb_send_pilot(DatabaseCampaignMessage pilot); +}; + +#endif // __KESOREFCAMPAIGN_HPP__ diff --git a/src/experiments/dciao-kernelstructs/dciao_kernel.proto b/src/experiments/dciao-kernelstructs/dciao_kernel.proto new file mode 100644 index 00000000..c9728013 --- /dev/null +++ b/src/experiments/dciao-kernelstructs/dciao_kernel.proto @@ -0,0 +1,29 @@ +import "DatabaseCampaignMessage.proto"; + +message DCIAOKernelProtoMsg { + required DatabaseCampaignMessage fsppilot = 1; + + repeated group Result = 2 { + enum ResultType { + OK = 1; + TIMEOUT = 2; + TRAP = 3; + ERR_ERROR_HOOK = 4; + ERR_DIFFERENT_ACTIVATION = 5; + ERR_DIFFERENT_KERNEL_TRANSITIONS = 6; + + ERR_MEMACCESS = 7; + ERR_OUTSIDE_TEXT = 8; + + UNKNOWN = 9; + NOINJECTION = 10; + } + + required int32 bitoffset = 1 [(sql_primary_key) = true]; + required ResultType resulttype = 2; + optional uint32 original_value = 3; + + repeated uint32 activation_scheme = 4; + optional string details = 5; + } +} diff --git a/src/experiments/dciao-kernelstructs/experiment.cc b/src/experiments/dciao-kernelstructs/experiment.cc new file mode 100644 index 00000000..3999f7be --- /dev/null +++ b/src/experiments/dciao-kernelstructs/experiment.cc @@ -0,0 +1,378 @@ +#include +#include + +// getpid +#include +#include + + +#include +#include "experiment.hpp" +#include "sal/SALConfig.hpp" +#include "sal/SALInst.hpp" +#include "sal/Memory.hpp" +#include "sal/Listener.hpp" + +#include "sal/bochs/BochsListener.hpp" +#include +#include +#include + + +#include "campaign.hpp" +#include "dciao_kernel.pb.h" + +using namespace std; +using namespace fail; + +#define SAFESTATE (1) + +// Check if configuration dependencies are satisfied: +#if !defined(CONFIG_EVENT_BREAKPOINTS) || !defined(CONFIG_SR_RESTORE) || \ + !defined(CONFIG_SR_SAVE) +#error This experiment needs: breakpoints, traps, save, and restore. Enable these in the configuration. +#endif + +unsigned DCIAOKernelStructs::injectBitFlip(address_t data_address, unsigned bitpos){ + + MemoryManager& mm = simulator.getMemoryManager(); + unsigned int value, injectedval; + + value = mm.getByte(data_address); + injectedval = value ^ (1 << bitpos); + mm.setByte(data_address, injectedval); + + m_log << "INJECTION at: 0x" << hex << setw(2) << setfill('0') << data_address + << " value: 0x" << setw(2) << setfill('0') << value << " -> 0x" << setw(2) << setfill('0') << injectedval << endl; + + return value; +} + + +void handleEvent(DCIAOKernelProtoMsg_Result& result, DCIAOKernelProtoMsg_Result_ResultType restype, const std::string &msg) { + cout << msg << endl; + result.set_resulttype(restype); + result.set_details(msg); +} + +// void handleMemoryAccessEvent(DCIAOKernelExperimentData& 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.ERR_MEMACCESS, sstr.str()); +// } + +DCIAOKernelStructs::time_markers_t *DCIAOKernelStructs::getTimeMarkerList() { + const ElfSymbol & sym_time_marker_index = m_elf.getSymbol("time_marker_index"); + const ElfSymbol & sym_time_markers = m_elf.getSymbol("time_markers"); + + assert(sym_time_marker_index.isValid()); + assert(sym_time_markers.isValid()); + + + unsigned int time_marker_index; + + simulator.getMemoryManager().getBytes(sym_time_marker_index.getAddress(), + sym_time_marker_index.getSize(), + &time_marker_index); + if (time_marker_index > 500) { + time_marker_index = 500; + } + time_markers_t *time_markers = new time_markers_t(time_marker_index); + + simulator.getMemoryManager().getBytes(sym_time_markers.getAddress(), + time_marker_index * sizeof(time_marker), + time_markers->data()); + return time_markers; +} + +int DCIAOKernelStructs::time_markers_compare(const time_markers_t &a, const time_markers_t &b) { + int pos = -1; + unsigned max_index = std::min(a.size(), b.size()); + for (unsigned i = 0; i < max_index; i++) { + if (a[i].time != b[i].time + || a[i].at != b[i].at) { + pos = i; + break; + } + } + if (pos == -1 && (a.size() != b.size())) { + pos = max_index; + } + return pos; +} + + + +bool DCIAOKernelStructs::run() { + //******* Boot, and store state *******// + m_log << "STARTING EXPERIMENT" << endl; + + char * statedir = getenv("FAIL_STATEDIR"); + if(statedir == NULL){ + m_log << "FAIL_STATEDIR not set :(" << std::endl; + simulator.terminate(1); + } + + address_t minimal_ip = 0x100000; // 1 Mbyte + address_t minimal_data = 0x100000; // 1 Mbyte + address_t maximal_ip = 0; + address_t maximal_data = 0; + for (ElfReader::symbol_iterator it = m_elf.sym_begin(); + it != m_elf.sym_end(); ++it) { + const ElfSymbol &symbol = *it; + if (symbol.getSymbolType() == STT_FUNC + || symbol.getSymbolType() == STT_GNU_IFUNC /*indirect codeasm object */) { + maximal_ip = std::max(maximal_ip, symbol.getEnd()); + } + maximal_data = std::max(maximal_data, symbol.getEnd()); + } + + std::cout << "Code section from " << hex << minimal_ip << " to " << maximal_ip << std::endl; + std::cout << "Data section from " << hex << minimal_ip << " to " << maximal_data << std::endl; + + m_log << "Booting, and saving state at main"; + BPSingleListener bp; + + // STEP 1: run until interesting function starts, and save state + bp.setWatchInstructionPointer(m_elf.getSymbol("main").getAddress()); + if(simulator.addListenerAndResume(&bp) == &bp){ + m_log << "main function entry reached, saving state" << endl; + } else { + m_log << "Couldn't reach entry function. Dying" << std::endl; + simulator.terminate(1); + } + + simulator.save(statedir); + guest_address_t enter_kernel_address = m_elf.getSymbol("os::dep::KernelStructs::correct").getAddress(); + BPSingleListener l_enter_kernel(enter_kernel_address); + BPSingleListener l_time_marker_print(m_elf.getSymbol("time_marker_print").getAddress()); + + + simulator.clearListeners(); + simulator.addListener(&l_enter_kernel); + simulator.addListener(&l_time_marker_print); + + bool in_kernelspace = false; + unsigned kernel_activations = 0; + while (1) { + fail::BaseListener *l = simulator.resume(); + simulator.addListener(l); + + if (l == &l_time_marker_print) { + break; + } else if (l == &l_enter_kernel) { + kernel_activations ++; + } else { + m_log << "THIS SHOULD'T HAPPEN" << std::endl; + simulator.terminate(1); + } + + } + + correct.time_markers = getTimeMarkerList(); + correct.kernel_activation_count = kernel_activations; + + assert(kernel_activations > 0); + assert(correct.time_markers->size() > 0); + + m_log << "correct run is done:" << dec << std::endl; + m_log << " kernel_transitions " << correct.kernel_activation_count << std::endl; + m_log << " time_markers " << correct.time_markers->size() << std::endl; + + // //******* Fault injection *******// + // // #warning "Building restore state variant" + + unsigned executed_jobs = 0; + + while (executed_jobs < 25 || m_jc.getNumberOfUndoneJobs() > 0) { + m_log << "asking jobserver for parameters" << endl; + DCIAOKernelExperimentData param; + if(!m_jc.getParam(param)){ + m_log << "Dying." << endl; // We were told to die. + simulator.terminate(1); + } + + // Get input data from Jobserver + unsigned injection_instr = param.msg.fsppilot().injection_instr(); + address_t data_address = param.msg.fsppilot().data_address(); + + for (int bit_offset = 0; bit_offset < 8; ++bit_offset) { + // 8 results in one job + DCIAOKernelProtoMsg_Result *result = param.msg.add_result(); + result->set_bitoffset(bit_offset); + + m_log << "restoring state" << endl; + + // Restore to the image, which starts at address(main) + simulator.restore(statedir); + executed_jobs ++; + + kernel_activations = 0; + + m_log << "Trying to inject @ instr #" << dec << injection_instr << endl; + + + if (injection_instr > 0) { + simulator.clearListeners(); + // XXX could be improved with intermediate states (reducing runtime until injection) + simulator.addListener(&l_time_marker_print); + simulator.addListener(&l_enter_kernel); + + bp.setWatchInstructionPointer(ANY_ADDR); + bp.setCounter(injection_instr); + simulator.addListener(&bp); + + bool inject = true; + while (1) { + fail::BaseListener * listener = simulator.resume(); + // finish() before FI? + if (listener == &l_time_marker_print) { + m_log << "experiment reached finish() before FI" << endl; + handleEvent(*result, result->NOINJECTION, "time_marker reached before instr2"); + inject = false; + break; + } else if (listener == &l_enter_kernel) { + // Count all kernel activations + simulator.addListener(&l_enter_kernel); + kernel_activations++; + } else if (listener == &bp) { + break; + } else { + inject = false; + handleEvent(*result, result->NOINJECTION, "WTF"); + break; + } + } + + // Next experiment + if (!inject) + continue; + } + + // Not a working sanitiy check. Because of instruction + // offsets! + // + // if (simulator.getCPU(0).getInstructionPointer() != param.msg.fsppilot().instr2_absolute()) { + // m_log << "Invalid Injection address EIP=0x" + // << std::hex << simulator.getCPU(0).getInstructionPointer() + // << " != enter_kernel=0x" << param.msg.fsppilot().instr2_absolute() << std::endl; + // simulator.terminate(1); + // } + + /// INJECT BITFLIP: + result->set_original_value(injectBitFlip(data_address, bit_offset)); + + // // Setup exit points + BPSingleListener l_error_hook(m_elf.getSymbol("copter_mock_panic").getAddress()); + + TrapListener l_trap(ANY_TRAP); + TimerListener l_timeout(1000 * 1000); // 1 second in microseconds + + simulator.clearListeners(); + simulator.addListener(&l_enter_kernel); + simulator.addListener(&l_timeout); + simulator.addListener(&l_trap); + simulator.addListener(&l_time_marker_print); + simulator.addListener(&l_error_hook); + + // jump outside text segment + BPRangeListener ev_below_text(ANY_ADDR, minimal_ip - 1); + BPRangeListener ev_beyond_text(maximal_ip + 1, ANY_ADDR); + simulator.addListener(&ev_below_text); + simulator.addListener(&ev_beyond_text); + + // memory access outside of bound determined in the golden run [lowest_addr, highest_addr] + MemAccessListener ev_mem_low(0x0, MemAccessEvent::MEM_READWRITE); + ev_mem_low.setWatchWidth(minimal_data); + MemAccessListener ev_mem_high(maximal_data + 1, MemAccessEvent::MEM_READWRITE); + ev_mem_high.setWatchWidth(0xFFFFFFFFU - (maximal_data + 1)); + simulator.addListener(&ev_mem_low); + simulator.addListener(&ev_mem_high); + + + // resume and wait for results while counting kernel + // activations + fail::BaseListener* l; + while (1) { + l = simulator.resume(); + + // Evaluate result + if (l == &l_enter_kernel) { + kernel_activations++; + simulator.addListener(&l_enter_kernel); + // continue experiment + } else if (l == &l_time_marker_print) { + m_log << "experiment ran to the end" << std::endl; + DCIAOKernelStructs::time_markers_t * time_markers = getTimeMarkerList(); + int pos = time_markers_compare(*time_markers, *correct.time_markers); + if (pos != -1) { + m_log << "Different activation scheme" << std::endl; + m_log << " size " << std::dec << time_markers->size() << std::endl; + m_log << " at " << std::dec << pos << std::endl; + + stringstream sstr; + sstr << "diff after #" << pos; + handleEvent(*result, result->ERR_DIFFERENT_ACTIVATION, sstr.str()); + /* In case of an error append the activation scheme */ + for (unsigned i = pos; i < time_markers->size(); ++i) { + result->add_activation_scheme( (*time_markers)[i].time ); + result->add_activation_scheme( (*time_markers)[i].at ); + } + } else if (kernel_activations != correct.kernel_activation_count) { + stringstream sstr; + sstr << "kernel activations " << kernel_activations << " (expt: " << correct.kernel_activation_count << ")"; + handleEvent(*result, result->ERR_DIFFERENT_KERNEL_TRANSITIONS, sstr.str()); + } else { + stringstream sstr; + sstr << "calc done (kernel #" << kernel_activations << ")"; + handleEvent(*result, result->OK, sstr.str()); + } + delete time_markers; + // End of experiment + break; + } else if (l == &l_trap) { + stringstream sstr; + sstr << "trap #" << l_trap.getTriggerNumber(); + handleEvent(*result, result->TRAP, sstr.str()); + break; // EOExperiment + } else if (l == &l_timeout){ + handleEvent(*result, result->TIMEOUT, "timeout: 1 second"); + break; // EOExperiment + } else if (l == &l_error_hook){ + handleEvent(*result, result->ERR_ERROR_HOOK, "called error hook"); + break; // EOExperiment + } else if (l == &ev_below_text || l == &ev_beyond_text) { + handleEvent(*result, result->ERR_OUTSIDE_TEXT, (l == &ev_below_text) ? "< .text" : ">.text"); + break; // EOExperiment + } else if (l == &ev_mem_low || l == &ev_mem_high) { + handleEvent(*result, result->ERR_MEMACCESS, (l == &ev_mem_low) ? "< .data" : ">.data"); + break; // EOFExperiment + } else { + handleEvent(*result, result->UNKNOWN, "UNKNOWN event"); + break; // EOExperiment + } + } + + simulator.clearListeners(); + } // injection done, continue with next bit + + m_jc.sendResult(param); + } // end while (1) + + // Explicitly terminate, or the simulator will continue to run. + simulator.terminate(); +} + diff --git a/src/experiments/dciao-kernelstructs/experiment.hpp b/src/experiments/dciao-kernelstructs/experiment.hpp new file mode 100644 index 00000000..8d62f275 --- /dev/null +++ b/src/experiments/dciao-kernelstructs/experiment.hpp @@ -0,0 +1,50 @@ +#ifndef __DCIAO_KERNEL_EXPERIMENT_HPP__ +#define __DCIAO_KERNEL_EXPERIMENT_HPP__ + + +#include "sal/SALInst.hpp" +#include "efw/ExperimentFlow.hpp" +#include "efw/JobClient.hpp" +#include "util/Logger.hpp" +#include "util/ElfReader.hpp" +#include +#include + +class DCIAOKernelStructs : public fail::ExperimentFlow { +public: + /** timer_markers indicate the activation flow inside the + coper_mock application. For a correct run the activation flow + is deterministic. Therefore we can say wheter a the + application had a correct control flow */ + struct time_marker { + uint32_t time; + uint32_t at; + }; + + typedef std::vector time_markers_t; + +private: + fail::JobClient m_jc; + fail::Logger m_log; + fail::MemoryManager& m_mm; + fail::ElfReader m_elf; + + struct correct_run { + time_markers_t *time_markers; + unsigned int kernel_activation_count; + }; + + correct_run correct; + + unsigned injectBitFlip(fail::address_t data_address, unsigned bitpos); + time_markers_t *getTimeMarkerList(); + static int time_markers_compare(const time_markers_t &, const time_markers_t &); + + +public: + DCIAOKernelStructs() : m_log("DCIAOKernelStructs", false), m_mm(fail::simulator.getMemoryManager()) {} + + bool run(); +}; + +#endif // __KESO_REFS_EXPERIMENT_HPP__ diff --git a/src/experiments/dciao-kernelstructs/main.cc b/src/experiments/dciao-kernelstructs/main.cc new file mode 100644 index 00000000..a27edfa1 --- /dev/null +++ b/src/experiments/dciao-kernelstructs/main.cc @@ -0,0 +1,20 @@ +#include +#include + +#include "cpn/CampaignManager.hpp" +#include "util/CommandLine.hpp" +#include "campaign.hpp" + +int main(int argc, char **argv) +{ + fail::CommandLine &cmd = fail::CommandLine::Inst(); + for (int i = 1; i < argc; ++i) + cmd.add_args(argv[i]); + + DCIAOKernelCampaign c; + if (fail::campaignmanager.runCampaign(&c)) { + return 0; + } else { + return 1; + } +} diff --git a/tools/import-trace/DCiAOKernelImporter.cc b/tools/import-trace/DCiAOKernelImporter.cc index a21dbcd6..82587c59 100644 --- a/tools/import-trace/DCiAOKernelImporter.cc +++ b/tools/import-trace/DCiAOKernelImporter.cc @@ -11,9 +11,9 @@ using namespace fail; bool DCiAOKernelImporter::inDynamicKernelMemory(fail::address_t addr) { const std::string &name = m_elf->getSymbol(addr).getDemangledName(); bool dynamic = name.find("os::data::dynamic", 0) != std::string::npos; - bool stack = name.find("_stack") != std::string::npos; - - return dynamic && !stack; + // bool stack = name.find("_stack") != std::string::npos; + // return dynamic && !stack; + return dynamic; } bool DCiAOKernelImporter::copy_to_database(fail::ProtoIStream &ps) { diff --git a/tools/prune-trace/BasicPruner.cc b/tools/prune-trace/BasicPruner.cc index c6946c8f..38c4c639 100644 --- a/tools/prune-trace/BasicPruner.cc +++ b/tools/prune-trace/BasicPruner.cc @@ -7,8 +7,8 @@ static fail::Logger LOG ("BasicPruner"); bool BasicPruner::prune_all() { std::stringstream ss; - ss << "INSERT INTO fsppilot (known_outcome, variant_id, instr2, data_address, fspmethod_id) " - "SELECT 0, variant_id, instr2, data_address, " << m_method_id << " " + ss << "INSERT INTO fsppilot (known_outcome, variant_id, instr1, instr2, data_address, fspmethod_id) " + "SELECT 0, variant_id, instr1, instr2, data_address, " << m_method_id << " " "FROM trace " "WHERE variant_id = " << m_variant_id << " AND accesstype = 'R'"; if (!db->query(ss.str().c_str())) return false; @@ -16,8 +16,8 @@ bool BasicPruner::prune_all() { int rows = db->affected_rows(); // single entry for known outcome (write access) - ss << "INSERT INTO fsppilot (known_outcome, variant_id, instr2, data_address, fspmethod_id) " - "SELECT 1, variant_id, instr2, data_address, " << m_method_id << " " + ss << "INSERT INTO fsppilot (known_outcome, variant_id, instr1, instr2, data_address, fspmethod_id) " + "SELECT 1, variant_id, instr1, instr2, data_address, " << m_method_id << " " "FROM trace " "WHERE variant_id = " << m_variant_id << " AND accesstype = 'W' " "LIMIT 1"; @@ -27,19 +27,30 @@ bool BasicPruner::prune_all() { LOG << "created " << rows << " fsppilot entries" << std::endl; - ss << "INSERT INTO fspgroup (variant_id, instr2, data_address, fspmethod_id, pilot_id) " - "SELECT variant_id, instr2, data_address, fspmethod_id, id " - "FROM fsppilot " - "WHERE known_outcome = 0 AND fspmethod_id = " << m_method_id << " AND variant_id = " << m_variant_id; + /* When we are in basic-left mode we use the left boundary of the + equivalence interval. Sine the current database scheme has no + instr2_absolute, we set this to NULL in the basic-left mode. */ + std::string injection_instr = this->use_instr1 ? "t.instr1" : "t.instr2"; + std::string injection_instr_absolute = this->use_instr1 ? "NULL" : "t.instr2_absolute"; + + ss << "INSERT INTO fspgroup (variant_id, injection_instr, injection_instr_absolute, " + << " data_address, fspmethod_id, pilot_id) " + << "SELECT p.variant_id, " << injection_instr << ", " << injection_instr_absolute << ", p.data_address, p.fspmethod_id, p.id " + << "FROM fsppilot p " + << " JOIN trace t ON t.variant_id = p.variant_id AND t.instr2 = p.instr2" + << " AND t.data_address = p.data_address " + << "WHERE known_outcome = 0 AND p.fspmethod_id = " << m_method_id << " AND p.variant_id = " << m_variant_id; + if (!db->query(ss.str().c_str())) return false; ss.str(""); + rows = db->affected_rows(); - ss << "INSERT INTO fspgroup (variant_id, instr2, data_address, fspmethod_id, pilot_id) " - "SELECT t.variant_id, t.instr2, t.data_address, p.fspmethod_id, p.id " - "FROM trace t " - "JOIN fsppilot p " - "ON t.variant_id = p.variant_id AND p.fspmethod_id = " << m_method_id << " AND p.known_outcome = 1 " - "WHERE t.variant_id = " << m_variant_id << " AND t.accesstype = 'W'"; + ss << "INSERT INTO fspgroup (variant_id, injection_instr, injection_instr_absolute, data_address, fspmethod_id, pilot_id) " + "SELECT t.variant_id, "<< injection_instr << ", " << injection_instr_absolute <<", t.data_address, p.fspmethod_id, p.id " + "FROM trace t " + "JOIN fsppilot p " + "ON t.variant_id = p.variant_id AND p.fspmethod_id = " << m_method_id << " AND p.known_outcome = 1 " + "WHERE t.variant_id = " << m_variant_id << " AND t.accesstype = 'W'"; if (!db->query(ss.str().c_str())) return false; ss.str(""); rows += db->affected_rows(); diff --git a/tools/prune-trace/BasicPruner.hpp b/tools/prune-trace/BasicPruner.hpp index 730f955b..435d47d0 100644 --- a/tools/prune-trace/BasicPruner.hpp +++ b/tools/prune-trace/BasicPruner.hpp @@ -4,7 +4,10 @@ #include "Pruner.hpp" class BasicPruner : public Pruner { - virtual std::string method_name() { return "basic"; } + bool use_instr1; +public: + BasicPruner(bool use_instr1 = false) : Pruner(), use_instr1(use_instr1) {} + virtual std::string method_name() { return std::string("basic") + (use_instr1 ? "-left" : ""); } virtual bool prune_all(); }; diff --git a/tools/prune-trace/Pruner.cc b/tools/prune-trace/Pruner.cc index 7a00a589..5708ae36 100644 --- a/tools/prune-trace/Pruner.cc +++ b/tools/prune-trace/Pruner.cc @@ -28,22 +28,24 @@ bool Pruner::create_database() { " id int(11) NOT NULL AUTO_INCREMENT," " known_outcome tinyint(4) NOT NULL," " variant_id int(11) NOT NULL," + " instr1 int(10) unsigned NOT NULL," " instr2 int(10) unsigned NOT NULL," " data_address int(10) unsigned NOT NULL," " fspmethod_id int(11) NOT NULL," " PRIMARY KEY (id)," - " KEY fspmethod_id (fspmethod_id,variant_id,instr2,data_address)" + " KEY fspmethod_id (fspmethod_id,variant_id,instr1,instr2,data_address)" ") engine=MyISAM "; bool success = (bool) db->query(create_statement.c_str()); if (!success) return false; create_statement = "CREATE TABLE IF NOT EXISTS fspgroup (" - " variant_id int(11) NOT NULL," - " instr2 int(10) unsigned NOT NULL," - " data_address int(10) unsigned NOT NULL," - " fspmethod_id int(11) NOT NULL," - " pilot_id int(11) NOT NULL," - " PRIMARY KEY (variant_id, instr2, data_address, fspmethod_id, pilot_id)," + " variant_id int(11) NOT NULL," + " injection_instr int(10) unsigned NOT NULL," + " injection_instr_absolute int(10) unsigned," + " data_address int(10) unsigned NOT NULL," + " fspmethod_id int(11) NOT NULL," + " pilot_id int(11) NOT NULL," + " PRIMARY KEY (variant_id, injection_instr, data_address, fspmethod_id, pilot_id)," " KEY joinresults (pilot_id,fspmethod_id))"; return db->query(create_statement.c_str()); diff --git a/tools/prune-trace/main.cc b/tools/prune-trace/main.cc index 8d1023d9..98309c43 100644 --- a/tools/prune-trace/main.cc +++ b/tools/prune-trace/main.cc @@ -43,6 +43,10 @@ int main(int argc, char *argv[]) { if (imp == "basic") { LOG << "Using BasicPruner" << endl; pruner = new BasicPruner(); + } else if (imp == "basic-left") { + LOG << "Using BasicPruner (use left border, instr1)" << endl; + pruner = new BasicPruner(true); + } else { LOG << "Unkown import method: " << imp << endl; exit(-1);