diff --git a/core/experiments/weathermonitor/CMakeLists.txt b/core/experiments/weathermonitor/CMakeLists.txt new file mode 100644 index 00000000..cb92ba57 --- /dev/null +++ b/core/experiments/weathermonitor/CMakeLists.txt @@ -0,0 +1,32 @@ +set(EXPERIMENT_NAME weathermonitor) +set(EXPERIMENT_TYPE WeathermonitorExperiment) +configure_file(../instantiate-experiment.ah.in + ${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY +) + +## Setup desired protobuf descriptions HERE ## +set(MY_PROTOS + weathermonitor.proto +) + +set(MY_CAMPAIGN_SRCS + experimentInfo.hpp + 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(${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS}) + +## This is the example's campaign server distributing experiment parameters +add_executable(${EXPERIMENT_NAME}-server main.cc) +target_link_libraries(${EXPERIMENT_NAME}-server ${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY}) diff --git a/core/experiments/weathermonitor/campaign.cc b/core/experiments/weathermonitor/campaign.cc new file mode 100644 index 00000000..3218e3ba --- /dev/null +++ b/core/experiments/weathermonitor/campaign.cc @@ -0,0 +1,51 @@ +#include +#include +#include + +#include "campaign.hpp" +#include "experimentInfo.hpp" +#include "controller/CampaignManager.hpp" +#include "util/Logger.hpp" +#include "util/MemoryMap.hpp" + +#include "vptr_map.hpp" + +#include "plugins/tracing/TracingPlugin.hpp" +char const * const trace_filename = "trace.pb"; + +using namespace fi; +using std::endl; + +char const * const results_csv = "weathermonitor.csv"; + +// equivalence class type: addr, [i1, i2] +// addr: byte to inject a bit-flip into +// [i1, i2]: interval of instruction numbers, counted from experiment +// begin +struct equivalence_class { + sal::address_t data_address; + int instr1, instr2; + sal::address_t instr2_absolute; +}; + +bool WeathermonitorCampaign::run() +{ + Logger log("Weathermonitor Campaign"); + + 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; + } + + log << "startup" << endl; + + // XXX + + return true; +} diff --git a/core/experiments/weathermonitor/campaign.hpp b/core/experiments/weathermonitor/campaign.hpp new file mode 100644 index 00000000..310d8d60 --- /dev/null +++ b/core/experiments/weathermonitor/campaign.hpp @@ -0,0 +1,19 @@ +#ifndef __WEATHERMONITOR_CAMPAIGN_HPP__ +#define __WEATHERMONITOR_CAMPAIGN_HPP__ + +#include "controller/Campaign.hpp" +#include "controller/ExperimentData.hpp" +#include "weathermonitor.pb.h" + +class WeathermonitorExperimentData : public fi::ExperimentData { +public: + WeathermonitorProtoMsg msg; + WeathermonitorExperimentData() : fi::ExperimentData(&msg) {} +}; + +class WeathermonitorCampaign : public fi::Campaign { +public: + virtual bool run(); +}; + +#endif diff --git a/core/experiments/weathermonitor/experiment.cc b/core/experiments/weathermonitor/experiment.cc new file mode 100644 index 00000000..a00df6f1 --- /dev/null +++ b/core/experiments/weathermonitor/experiment.cc @@ -0,0 +1,63 @@ +#include + +// getpid +#include +#include + +#include "util/Logger.hpp" + +#include "experiment.hpp" +#include "experimentInfo.hpp" +#include "campaign.hpp" + +#include "SAL/SALConfig.hpp" +#include "SAL/SALInst.hpp" +#include "SAL/Memory.hpp" +#include "SAL/bochs/BochsRegister.hpp" +#include "controller/Event.hpp" + +// you need to have the tracing plugin enabled for this +#include "plugins/tracing/TracingPlugin.hpp" + +#include "vptr_map.hpp" + +#define LOCAL 1 + +using std::endl; + +bool WeathermonitorExperiment::run() +{ + char const *statename = "bochs.state"; + Logger log("Weathermonitor", false); + fi::BPEvent bp; + + log << "startup" << endl; + +#if 1 + // STEP 0: record memory map with vptr addresses + fi::GuestEvent g; + while (true) { + sal::simulator.addEventAndWait(&g); + std::cout << g.getData() << std::flush; + } +#elif 0 + // STEP 1: run until interesting function starts, and save state + bp.setWatchInstructionPointer(WEATHER_FUNC_MAIN); + sal::simulator.addEventAndWait(&bp); + log << "test function entry reached, saving state" << endl; + log << "EIP = " << std::hex << bp.getTriggerInstructionPointer() << endl; + sal::simulator.save(statename); + assert(bp.getTriggerInstructionPointer() == WEATHER_FUNC_MAIN); + assert(sal::simulator.getRegisterManager().getInstructionPointer() == WEATHER_FUNC_MAIN); +#elif 0 + // STEP 2: record trace for fault-space pruning + // XXX + +#elif 0 + // STEP 3: The actual experiment. + // XXX + +#endif + // Explicitly terminate, or the simulator will continue to run. + sal::simulator.terminate(); +} diff --git a/core/experiments/weathermonitor/experiment.hpp b/core/experiments/weathermonitor/experiment.hpp new file mode 100644 index 00000000..1acc3fda --- /dev/null +++ b/core/experiments/weathermonitor/experiment.hpp @@ -0,0 +1,14 @@ +#ifndef __WEATHERMONITOR_EXPERIMENT_HPP__ +#define __WEATHERMONITOR_EXPERIMENT_HPP__ + +#include "controller/ExperimentFlow.hpp" +#include "jobserver/JobClient.hpp" + +class WeathermonitorExperiment : public fi::ExperimentFlow { + fi::JobClient m_jc; +public: + WeathermonitorExperiment() : m_jc("ios.cs.tu-dortmund.de") {} + bool run(); +}; + +#endif diff --git a/core/experiments/weathermonitor/experimentInfo.hpp b/core/experiments/weathermonitor/experimentInfo.hpp new file mode 100644 index 00000000..6664d761 --- /dev/null +++ b/core/experiments/weathermonitor/experimentInfo.hpp @@ -0,0 +1,37 @@ +#ifndef __WEATHERMONITOR_EXPERIMENT_INFO_HPP__ +#define __WEATHERMONITOR_EXPERIMENT_INFO_HPP__ + +// FIXME autogenerate this + +#define GUARDED_WEATHERMONITOR 0 + +#if !GUARDED_WEATHERMONITOR // without vptr guards + +// main() address: +// nm -C vanilla.elf|fgrep main +#define WEATHER_FUNC_MAIN 0x001010f0 +// Temperature::measure() address: +// nm -C vanilla.elf|fgrep 'Temperature::measure()' +#define WEATHER_FUNC_TEMP_MEASURE 0x001010f0 +// number of instructions we want to observe +#define WEATHER_NUMINSTR 10000 +// data/BSS begin: +// nm -C vanilla.elf|fgrep ___DATA_START__ +#define WEATHER_DATA_START 0x00101c34 +// data/BSS end: +// nm -C vanilla.elf|fgrep ___BSS_END__ +#define WEATHER_DATA_END 0x00103529 +// text begin: +// nm -C vanilla.elf|fgrep ___TEXT_START__ +#define WEATHER_TEXT_START 0x00100000 +// text end: +// nm -C vanilla.elf|fgrep ___TEXT_END__ +#define WEATHER_TEXT_END 0x00101a5b + +#else // with guards + +// XXX + +#endif + +#endif diff --git a/core/experiments/weathermonitor/main.cc b/core/experiments/weathermonitor/main.cc new file mode 100644 index 00000000..a6f4dfdd --- /dev/null +++ b/core/experiments/weathermonitor/main.cc @@ -0,0 +1,11 @@ +#include +#include + +#include "controller/CampaignManager.hpp" +#include "experiments/checksum-oostubs/campaign.hpp" + +int main(int argc, char **argv) +{ + WeathermonitorCampaign c; + return !fi::campaignmanager.runCampaign(&c); +} diff --git a/core/experiments/weathermonitor/vptr_map.hpp b/core/experiments/weathermonitor/vptr_map.hpp new file mode 100644 index 00000000..f14b46ea --- /dev/null +++ b/core/experiments/weathermonitor/vptr_map.hpp @@ -0,0 +1,2 @@ +// will be generated from STEP 0 output with region2array.sh +// XXX diff --git a/core/experiments/weathermonitor/weathermonitor.proto b/core/experiments/weathermonitor/weathermonitor.proto new file mode 100644 index 00000000..0ed8ca0e --- /dev/null +++ b/core/experiments/weathermonitor/weathermonitor.proto @@ -0,0 +1,42 @@ +message WeathermonitorProtoMsg { + // Input: experiment parameters + required int32 instr_offset = 1; + optional int32 instr_address = 2; // for sanity checks + required int32 mem_addr = 3; + required int32 bit_offset = 4; + + // ---------------------------------------------------- + + // Output: experiment results + // (make these optional to reduce overhead for server->client communication) + + // instruction pointer where injection was done + optional uint32 injection_ip = 5; + + // result type: + // FINISHED = planned number of instructions were executed + // TRAP = premature guest "crash" + enum ResultType { + FINISHED = 1; + TRAP = 2; + HALT = 3; + UNKNOWN = 4; + } + optional ResultType resulttype = 6; + + // result details: + // resultdata = result[0-2] + repeated uint32 resultdata = 7 [packed=true]; + + // was finish() ever reached? + optional bool finish_reached = 8; + + // especially interesting for TRAP/ UNKNOWN: latest IP + optional uint32 latest_ip = 9; + + // did ECC correct the fault? + optional int32 error_corrected = 10; + + // optional textual description of what happened + optional string details = 11; +}