another directory rename: failstar -> fail
"failstar" sounds like a name for a cruise liner from the 80s. As "*" isn't a desirable part of directory names, just name the whole thing "fail/", the core parts being stored in "fail/core/". Additionally fixing two build system dependency issues: - missing jobserver -> protomessages dependency - broken bochs -> fail dependency (add_custom_target DEPENDS only allows plain file dependencies ... cmake for the win) git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@956 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
6
core/experiments/CMakeLists.txt
Normal file
6
core/experiments/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# Note that we're allowing *multiple* experiments to be enabled at once.
|
||||
set(EXPERIMENTS_ACTIVATED coolchecksum CACHE STRING "Activated experiments (a semicolon-separated list of fail/experiments/ subdirectories)")
|
||||
|
||||
foreach(experiment_name ${EXPERIMENTS_ACTIVATED})
|
||||
add_subdirectory(${experiment_name})
|
||||
endforeach(experiment_name)
|
||||
18
core/experiments/FaultCoverageExperiment/CMakeLists.txt
Normal file
18
core/experiments/FaultCoverageExperiment/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
#FaultCoverage experiment
|
||||
set(EXPERIMENT_NAME FaultCoverageExperiment)
|
||||
set(EXPERIMENT_TYPE FaultCoverageExperiment)
|
||||
configure_file(../instantiate-experiment.ah.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
|
||||
)
|
||||
|
||||
#experiment sources
|
||||
set(MY_EXPERIMENT_SRCS
|
||||
experiment.cc
|
||||
experiment.hpp
|
||||
)
|
||||
|
||||
#### include directories ####
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
## build library
|
||||
add_library(${EXPERIMENT_NAME} ${MY_EXPERIMENT_SRCS})
|
||||
140
core/experiments/FaultCoverageExperiment/experiment.cc
Normal file
140
core/experiments/FaultCoverageExperiment/experiment.cc
Normal file
@ -0,0 +1,140 @@
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <time.h>
|
||||
|
||||
#include "experiment.hpp"
|
||||
#include "SAL/SALInst.hpp"
|
||||
#include "SAL/bochs/BochsRegister.hpp"
|
||||
#include "../../util/Logger.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace sal;
|
||||
using namespace fi;
|
||||
using namespace sal;
|
||||
|
||||
bool FaultCoverageExperiment::run()
|
||||
{
|
||||
/*
|
||||
Experimentskizze:
|
||||
- starte Gastsystem
|
||||
- setze Breakpoint auf Beginn der betrachteten Funktion; warte darauf
|
||||
- sichere Zustand
|
||||
- iteriere über alle Register
|
||||
-- iteriere über alle 32 Bit in diesem Register
|
||||
--- iteriere über alle Instruktionsadressen innerhalb der betrachteten Funktion
|
||||
---- setze Breakpoint auf diese Adresse; warte darauf
|
||||
---- flippe Bit x in Register y
|
||||
---- setze Breakpoint auf Verlassen der Funktion; warte darauf
|
||||
---- bei Erreichen des Breakpoint: sichere Funktionsergebnis (irgendein bestimmtes Register)
|
||||
---- lege Ergebnisdaten ab:
|
||||
a) Ergebnis korrekt (im Vergleich zum bekannt korrekten Ergebnis für die Eingabe)
|
||||
b) Ergebnis falsch
|
||||
c) Breakpoint wird nicht erreicht, Timeout (z.B. gefangen in Endlosschleife)
|
||||
d) Trap wurde ausgelöst
|
||||
---- stelle zuvor gesicherten Zustand wieder her
|
||||
*/
|
||||
|
||||
// set breakpoint at start address of the function to be analyzed ("observed");
|
||||
// wait until instruction pointer reaches that address
|
||||
cout << "[FaultCoverageExperiment] Setting up experiment. Allowing to start now." << endl;
|
||||
BPEvent ev_func_start(INST_ADDR_FUNC_START);
|
||||
simulator.addEvent(&ev_func_start);
|
||||
|
||||
cout << "[FaultCoverageExperiment] Waiting for function start address..." << endl;
|
||||
while(simulator.waitAny() != &ev_func_start)
|
||||
;
|
||||
|
||||
// store current state
|
||||
cout << "[FaultCoverageExperiment] Saving state in ./bochs_save_point ..."; cout.flush();
|
||||
simulator.save("./bochs_save_point");
|
||||
cout << "done!" << endl;
|
||||
|
||||
// log the results on std::cout
|
||||
Logger res;
|
||||
cout << "[FaultCoverageExperiment] Logging results on std::cout." << endl;
|
||||
|
||||
RegisterManager& regMan = simulator.getRegisterManager();
|
||||
// iterate over all registers
|
||||
for(RegisterManager::iterator it = regMan.begin(); it != regMan.end(); it++)
|
||||
{
|
||||
Register* pReg = *it; // get a ptr to the current register-object
|
||||
// loop over the 32 bits within this register
|
||||
for(regwidth_t bitnr = 0; bitnr < pReg->getWidth(); ++bitnr)
|
||||
{
|
||||
// loop over all instruction addresses of observed function
|
||||
for(int instr = 0; ; ++instr)
|
||||
{
|
||||
// clear event queues
|
||||
simulator.clearEvents();
|
||||
|
||||
// restore previously saved simulator state
|
||||
cout << "[FaultCoverageExperiment] Restoring previous simulator state..."; cout.flush();
|
||||
simulator.restore("./bochs_save_point");
|
||||
cout << "done!" << endl;
|
||||
|
||||
// breakpoint at function exit
|
||||
BPEvent ev_func_end(INST_ADDR_FUNC_END);
|
||||
simulator.addEvent(&ev_func_end);
|
||||
|
||||
// no need to continue simulation if we want to
|
||||
// inject *now*
|
||||
if (instr > 0) {
|
||||
// breakpoint $instr instructions in the future
|
||||
BPEvent ev_instr_reached(ANY_ADDR);
|
||||
ev_instr_reached.setCounter(instr);
|
||||
simulator.addEvent(&ev_instr_reached);
|
||||
|
||||
// if we reach the exit first, this round is done
|
||||
if (simulator.waitAny() == &ev_func_end)
|
||||
break;
|
||||
}
|
||||
|
||||
// inject bit-flip at bit $bitnr in register $reg
|
||||
regdata_t data = pReg->getData();
|
||||
data ^= 1 << bitnr;
|
||||
pReg->setData(data); // write back data to register
|
||||
|
||||
// catch traps and timeout
|
||||
TrapEvent ev_trap; // any traps
|
||||
simulator.addEvent(&ev_trap);
|
||||
BPEvent ev_timeout(ANY_ADDR);
|
||||
ev_timeout.setCounter(1000);
|
||||
simulator.addEvent(&ev_timeout);
|
||||
|
||||
// wait for function exit, trap or timeout
|
||||
BaseEvent* ev = simulator.waitAny();
|
||||
if(ev == &ev_func_end)
|
||||
{
|
||||
// log result
|
||||
#if BX_SUPPORT_X86_64
|
||||
const GPRegisterId targetreg = sal::RID_RAX;
|
||||
const size_t expected_size = sizeof(uint32_t)*8;
|
||||
#else
|
||||
const GPRegisterId targetreg = sal::RID_EAX;
|
||||
const size_t expected_size = sizeof(uint64_t)*8;
|
||||
#endif
|
||||
Register* pEAX = simulator.getRegisterManager().getSetOfType(RT_GP)->getRegister(targetreg);
|
||||
assert(expected_size == pEAX->getWidth()); // we assume to get 32(64) bits...
|
||||
regdata_t result = pEAX->getData();
|
||||
res << "[FaultCoverageExperiment] Reg: " << pReg->getName()
|
||||
<< ", #Bit: " << bitnr << ", Instr-Idx: " << instr
|
||||
<< ", Data: " << result;
|
||||
}
|
||||
else if(ev == &ev_trap)
|
||||
res << "[FaultCoverageExperiment] Reg: " << pReg->getName()
|
||||
<< ", #Bit: " << bitnr << ", Instr-Idx: " << instr
|
||||
<< ", Trap#: " << ev_trap.getTriggerNumber() << " (Trap)";
|
||||
else if(ev == &ev_timeout)
|
||||
res << "[FaultCoverageExperiment] Reg: " << pReg->getName()
|
||||
<< ", #Bit: " << bitnr << ", Instr-Idx: " << instr
|
||||
<< " (Timeout)";
|
||||
else
|
||||
cout << "We've received an unkown event! "
|
||||
<< "What the hell is going on?" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
32
core/experiments/FaultCoverageExperiment/experiment.hpp
Normal file
32
core/experiments/FaultCoverageExperiment/experiment.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef __FAULTCOVERAGE_EXPERIMENT_HPP__
|
||||
#define __FAULTCOVERAGE_EXPERIMENT_HPP__
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "AspectConfig.hpp"
|
||||
#include "controller/ExperimentFlow.hpp"
|
||||
|
||||
#define INST_ADDR_FUNC_START 0x4ae6
|
||||
#define INST_ADDR_FUNC_END 0x4be6
|
||||
|
||||
/*
|
||||
// Check if aspect dependencies are satisfied:
|
||||
#if CONFIG_EVENT_CPULOOP != 1 || CONFIG_EVENT_TRAP != 1 || \
|
||||
CONFIG_SR_RESTORE != 1 || CONFIG_SR_SAVE != 1
|
||||
#error At least one of the following aspect-dependencies are not satisfied: \
|
||||
cpu loop, traps, save/restore. Enable aspects first (see AspectConfig.hpp)!
|
||||
#endif
|
||||
// This is disabled because the AspectConfig.hpp-header disables
|
||||
// all aspects on default.
|
||||
*/
|
||||
using namespace fi;
|
||||
|
||||
class FaultCoverageExperiment : public ExperimentFlow
|
||||
{
|
||||
public:
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif // __FAULTCOVERAGE_EXPERIMENT_HPP__
|
||||
|
||||
31
core/experiments/MHTestCampaign/CMakeLists.txt
Normal file
31
core/experiments/MHTestCampaign/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
set(EXPERIMENT_NAME MHTestCampaign)
|
||||
set(EXPERIMENT_TYPE MHTestExperiment)
|
||||
configure_file(../instantiate-experiment.ah.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
|
||||
)
|
||||
|
||||
## Setup desired protobuf descriptions HERE ##
|
||||
set(MY_PROTOS
|
||||
MHTest.proto
|
||||
)
|
||||
|
||||
set(MY_CAMPAIGN_SRCS
|
||||
MHTestCampaign.hpp
|
||||
MHTestCampaign.cc
|
||||
experiment.hpp
|
||||
experiment.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 mhcampaign.cc)
|
||||
target_link_libraries(${EXPERIMENT_NAME}-server fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY})
|
||||
5
core/experiments/MHTestCampaign/MHTest.proto
Normal file
5
core/experiments/MHTestCampaign/MHTest.proto
Normal file
@ -0,0 +1,5 @@
|
||||
message MHTestData {
|
||||
optional string foo = 1;
|
||||
optional int32 input = 2;
|
||||
optional int32 output = 3;
|
||||
}
|
||||
42
core/experiments/MHTestCampaign/MHTestCampaign.cc
Normal file
42
core/experiments/MHTestCampaign/MHTestCampaign.cc
Normal file
@ -0,0 +1,42 @@
|
||||
#include "MHTestCampaign.hpp"
|
||||
#include <controller/CampaignManager.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace fi;
|
||||
|
||||
|
||||
bool MHTestCampaign::run()
|
||||
{
|
||||
|
||||
MHExperimentData* datas[m_parameter_count];
|
||||
cout << "[MHTestCampaign] Adding " << m_parameter_count << " values." << endl;
|
||||
for(int i = 1; i <= m_parameter_count; i++){
|
||||
datas[i] = new MHExperimentData;
|
||||
datas[i]->msg.set_input(i);
|
||||
|
||||
campaignmanager.addParam(datas[i]);
|
||||
usleep(100 * 1000); // 100 ms
|
||||
}
|
||||
campaignmanager.noMoreParameters();
|
||||
// test results.
|
||||
int f;
|
||||
int res = 0;
|
||||
int res2 = 0;
|
||||
MHExperimentData * exp;
|
||||
for(int i = 1; i <= m_parameter_count; i++){
|
||||
exp = static_cast<MHExperimentData*>( campaignmanager.getDone() );
|
||||
f = exp->msg.output();
|
||||
// cout << ">>>>>>>>>>>>>>> Output: " << i << "^2 = " << f << endl;
|
||||
res += f;
|
||||
res2 += (i*i);
|
||||
delete exp;
|
||||
}
|
||||
if (res == res2) {
|
||||
cout << "TEST SUCCESSFUL FINISHED! " << "[" << res << "==" << res2 << "]" << endl;
|
||||
}else{
|
||||
cout << "TEST FAILED!" << " [" << res << "!=" << res2 << "]" << endl;
|
||||
}
|
||||
cout << "thats all... " << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
27
core/experiments/MHTestCampaign/MHTestCampaign.hpp
Normal file
27
core/experiments/MHTestCampaign/MHTestCampaign.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __TESTCAMPAIGN_HPP__
|
||||
#define __TESTCAMPAIGN_HPP__
|
||||
|
||||
|
||||
#include <controller/Campaign.hpp>
|
||||
#include "controller/ExperimentData.hpp"
|
||||
#include <experiments/MHTestCampaign/MHTest.pb.h>
|
||||
|
||||
using namespace fi;
|
||||
|
||||
class MHExperimentData : public ExperimentData {
|
||||
public:
|
||||
MHTestData msg;
|
||||
public:
|
||||
MHExperimentData() : ExperimentData(&msg){ };
|
||||
};
|
||||
|
||||
|
||||
class MHTestCampaign : public Campaign {
|
||||
int m_parameter_count;
|
||||
public:
|
||||
MHTestCampaign(int parametercount) : m_parameter_count(parametercount){};
|
||||
virtual bool run();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
42
core/experiments/MHTestCampaign/experiment.cc
Normal file
42
core/experiments/MHTestCampaign/experiment.cc
Normal file
@ -0,0 +1,42 @@
|
||||
#include "experiment.hpp"
|
||||
#include "MHTestCampaign.hpp"
|
||||
#include "SAL/SALInst.hpp"
|
||||
#include "SAL/Register.hpp"
|
||||
#include "controller/Event.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool MHTestExperiment::run()
|
||||
{
|
||||
|
||||
cout << "[MHTestExperiment] Let's go" << endl;
|
||||
#if 0
|
||||
fi::BPEvent mainbp(0x00003c34);
|
||||
sal::simulator.addEventAndWait(&mainbp);
|
||||
cout << "[MHTestExperiment] breakpoint reached, saving" << endl;
|
||||
sal::simulator.save("hello.main");
|
||||
#else
|
||||
MHExperimentData par;
|
||||
if(m_jc.getParam(par)){
|
||||
|
||||
int num = par.msg.input();
|
||||
cout << "[MHExperiment] stepping " << num << " instructions" << endl;
|
||||
if (num > 0) {
|
||||
fi::BPEvent nextbp(fi::ANY_ADDR);
|
||||
nextbp.setCounter(num);
|
||||
sal::simulator.addEventAndWait(&nextbp);
|
||||
}
|
||||
sal::address_t instr = sal::simulator.getRegisterManager().getInstructionPointer();
|
||||
cout << "[MHTestExperiment] Reached instruction: "
|
||||
<< hex << instr
|
||||
<< endl;
|
||||
par.msg.set_output(instr);
|
||||
m_jc.sendResult(par);
|
||||
} else {
|
||||
cout << "No data for me? :(" << endl;
|
||||
}
|
||||
#endif
|
||||
sal::simulator.terminate();
|
||||
return true;
|
||||
}
|
||||
|
||||
17
core/experiments/MHTestCampaign/experiment.hpp
Normal file
17
core/experiments/MHTestCampaign/experiment.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef __TESTEXPERIMENT_HPP__
|
||||
#define __TESTEXPERIMENT_HPP__
|
||||
|
||||
#include "controller/ExperimentFlow.hpp"
|
||||
#include "jobserver/JobClient.hpp"
|
||||
|
||||
class MHTestExperiment : public fi::ExperimentFlow {
|
||||
fi::JobClient m_jc;
|
||||
public:
|
||||
MHTestExperiment(){};
|
||||
~MHTestExperiment(){};
|
||||
bool run();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
25
core/experiments/MHTestCampaign/mhcampaign.cc
Normal file
25
core/experiments/MHTestCampaign/mhcampaign.cc
Normal file
@ -0,0 +1,25 @@
|
||||
#include "controller/CampaignManager.hpp"
|
||||
#include "experiments/MHTestCampaign/MHTestCampaign.hpp"
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char**argv){
|
||||
|
||||
int paramcount = 0;
|
||||
if(argc == 2){
|
||||
paramcount = atoi(argv[1]);
|
||||
}else{
|
||||
paramcount = 10;
|
||||
}
|
||||
cout << "Running MHTestCampaign [" << paramcount << " parameter sets]" << endl;
|
||||
|
||||
MHTestCampaign mhc(paramcount);
|
||||
campaignmanager.runCampaign(&mhc);
|
||||
|
||||
cout << "Campaign complete." << endl;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
15
core/experiments/TracingTest/CMakeLists.txt
Normal file
15
core/experiments/TracingTest/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
set(EXPERIMENT_NAME TracingTest)
|
||||
set(EXPERIMENT_TYPE TracingTest)
|
||||
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(${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
|
||||
79
core/experiments/TracingTest/experiment.cc
Normal file
79
core/experiments/TracingTest/experiment.cc
Normal file
@ -0,0 +1,79 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "SAL/SALInst.hpp"
|
||||
#include "SAL/Register.hpp"
|
||||
#include "experiment.hpp"
|
||||
#include "plugins/tracing/TracingPlugin.hpp"
|
||||
|
||||
/*
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/io/gzip_stream.h>
|
||||
*/
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using namespace fi;
|
||||
using namespace sal;
|
||||
|
||||
bool TracingTest::run()
|
||||
{
|
||||
cout << "[TracingTest] Setting up experiment" << endl;
|
||||
|
||||
#if 1
|
||||
// STEP 1: run until interesting function starts, and save state
|
||||
BPEvent breakpoint(0x00101658);
|
||||
simulator.addEventAndWait(&breakpoint);
|
||||
cout << "[TracingTest] main() reached, saving" << endl;
|
||||
|
||||
simulator.save("state");
|
||||
#else
|
||||
// STEP 2: test tracing plugin
|
||||
simulator.restore("state");
|
||||
|
||||
cout << "[TracingTest] enabling tracing" << endl;
|
||||
|
||||
TracingPlugin tp;
|
||||
tp.setOstream(&cout);
|
||||
Trace trace;
|
||||
tp.setTraceMessage(&trace);
|
||||
// this must be done *after* configuring the plugin:
|
||||
simulator.addFlow(&tp);
|
||||
|
||||
cout << "[TracingTest] tracing 1000000 instructions" << endl;
|
||||
BPEvent timeout(fi::ANY_ADDR);
|
||||
timeout.setCounter(1000000);
|
||||
simulator.addEvent(&timeout);
|
||||
|
||||
InterruptEvent ie(fi::ANY_INTERRUPT);
|
||||
while (simulator.addEventAndWait(&ie) != &timeout) {
|
||||
cout << "INTERRUPT #" << ie.getTriggerNumber() << "\n";
|
||||
}
|
||||
|
||||
cout << "[TracingTest] disabling tracing (trace size: "
|
||||
<< std::dec << trace.ByteSize() << " bytes)\n";
|
||||
simulator.removeFlow(&tp);
|
||||
|
||||
/*
|
||||
// serialize trace to file
|
||||
std::ofstream of("trace.pb");
|
||||
if (of.fail()) { return false; }
|
||||
trace.SerializeToOstream(&of);
|
||||
of.close();
|
||||
|
||||
// serialize trace to gzip-compressed file
|
||||
int fd = open("trace.pb.gz", O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (!fd) { return false; }
|
||||
google::protobuf::io::FileOutputStream fo(fd);
|
||||
google::protobuf::io::GzipOutputStream::Options options;
|
||||
options.compression_level = 9;
|
||||
google::protobuf::io::GzipOutputStream go(&fo, options);
|
||||
trace.SerializeToZeroCopyStream(&go);
|
||||
go.Close();
|
||||
fo.Close();
|
||||
*/
|
||||
#endif
|
||||
cout << "[TracingTest] Finished." << endl;
|
||||
simulator.terminate();
|
||||
|
||||
return true;
|
||||
}
|
||||
12
core/experiments/TracingTest/experiment.hpp
Normal file
12
core/experiments/TracingTest/experiment.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef __TRACING_TEST_HPP__
|
||||
#define __TRACING_TEST_HPP__
|
||||
|
||||
#include "controller/ExperimentFlow.hpp"
|
||||
|
||||
class TracingTest : public fi::ExperimentFlow
|
||||
{
|
||||
public:
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif /* __TRACING_TEST_HPP__ */
|
||||
36
core/experiments/attic/DataRetrievalExperiment.cc
Normal file
36
core/experiments/attic/DataRetrievalExperiment.cc
Normal file
@ -0,0 +1,36 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "DataRetrievalExperiment.hpp"
|
||||
#include "../SAL/SALInst.hpp"
|
||||
#include "../controller/Event.hpp"
|
||||
#include "ExperimentDataExample/FaultCoverageExperiment.pb.h"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::hex;
|
||||
|
||||
#define MEMTEST86_BREAKPOINT 0x4EDC
|
||||
|
||||
bool DataRetrievalExperiment::run()
|
||||
{
|
||||
cout << "[getExperimentDataExperiment] Experiment start." << endl;
|
||||
|
||||
// Breakpoint address for Memtest86:
|
||||
fi::BPEvent mainbp(MEMTEST86_BREAKPOINT);
|
||||
sal::simulator.addEventAndWait(&mainbp);
|
||||
cout << "[getExperimentDataExperiment] Breakpoint reached." << endl;
|
||||
|
||||
FaultCoverageExperimentData* test = NULL;
|
||||
cout << "[getExperimentDataExperiment] Getting ExperimentData (FaultCoverageExperiment)..." << endl;
|
||||
test = sal::simulator.getExperimentData<FaultCoverageExperimentData>();
|
||||
cout << "[getExperimentDataExperiment] Content of ExperimentData (FaultCoverageExperiment):" << endl;
|
||||
|
||||
if(test->has_data_name())
|
||||
cout << "Name: "<< test->data_name() << endl;
|
||||
// m_instrptr1 augeben
|
||||
cout << "m_instrptr1: " << hex << test->m_instrptr1() << endl;
|
||||
// m_instrptr2 augeben
|
||||
cout << "m_instrptr2: " << hex << test->m_instrptr2() << endl;
|
||||
|
||||
return (true); // experiment successful
|
||||
}
|
||||
14
core/experiments/attic/DataRetrievalExperiment.hpp
Normal file
14
core/experiments/attic/DataRetrievalExperiment.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __DATA_RETRIEVAL_EXPERIMENT_HPP__
|
||||
#define __DATA_RETRIEVAL_EXPERIMENT_HPP__
|
||||
|
||||
#include "../controller/ExperimentFlow.hpp"
|
||||
|
||||
class DataRetrievalExperiment : public fi::ExperimentFlow
|
||||
{
|
||||
public:
|
||||
DataRetrievalExperiment() { }
|
||||
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif /* __DATA_RETRIEVAL_EXPERIMENT_HPP__ */
|
||||
19
core/experiments/attic/ExperimentDataExample/CMakeLists.txt
Normal file
19
core/experiments/attic/ExperimentDataExample/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
## Setup desired protobuf descriptions HERE ##
|
||||
set(MY_PROTOS
|
||||
FaultCoverageExperiment.proto
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
example.cc
|
||||
)
|
||||
|
||||
#### PROTOBUFS ####
|
||||
find_package(Protobuf REQUIRED)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_CURRNET_BINARY_DIR})
|
||||
|
||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS} )
|
||||
|
||||
## Build library
|
||||
add_library(fcexperimentmessage ${PROTO_SRCS} ${SRCS} )
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
message FaultCoverageExperimentData{
|
||||
|
||||
optional string data_name = 1;
|
||||
required int64 m_InstrPtr1 = 2;
|
||||
required int64 m_InstrPtr2 = 3;
|
||||
|
||||
}
|
||||
3
core/experiments/attic/ExperimentDataExample/build_example.sh
Executable file
3
core/experiments/attic/ExperimentDataExample/build_example.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd $(dirname $0)
|
||||
g++ ../../controller/JobServer.cc ../../controller/ExperimentDataQueue.cc example.cc FaultCoverageExperiment.pb.cc -o ./ExperimentData_example -l protobuf -pthread
|
||||
89
core/experiments/attic/ExperimentDataExample/example.cc
Normal file
89
core/experiments/attic/ExperimentDataExample/example.cc
Normal file
@ -0,0 +1,89 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "controller/ExperimentData.hpp"
|
||||
#include "controller/ExperimentDataQueue.hpp"
|
||||
#include "jobserver/JobServer.hpp"
|
||||
#include "FaultCoverageExperiment.pb.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char* argv[]){
|
||||
|
||||
|
||||
fi::ExperimentDataQueue exDaQu;
|
||||
fi::ExperimentData* readFromQueue;
|
||||
|
||||
|
||||
//Daten in Struktur schreiben und in Datei speichern
|
||||
|
||||
ofstream fileWrite;
|
||||
fileWrite.open("test.txt");
|
||||
|
||||
|
||||
FaultCoverageExperimentData faultCovExWrite;
|
||||
|
||||
//Namen setzen
|
||||
faultCovExWrite.set_data_name("Testfall 42");
|
||||
|
||||
//Instruktionpointer 1
|
||||
faultCovExWrite.set_m_instrptr1(0x4711);
|
||||
|
||||
|
||||
//Instruktionpointer 2
|
||||
faultCovExWrite.set_m_instrptr2(0x1122);
|
||||
|
||||
|
||||
//In ExperimentData verpacken
|
||||
fi::ExperimentData exDaWrite(&faultCovExWrite);
|
||||
|
||||
//In Queue einbinden
|
||||
exDaQu.addData(&exDaWrite);
|
||||
|
||||
//Aus Queue holen
|
||||
if(exDaQu.size() != 0)
|
||||
readFromQueue = exDaQu.getData();
|
||||
|
||||
//Serialisierung ueber Wrapper-Methode in ExperimentData
|
||||
readFromQueue->serialize(&fileWrite);
|
||||
|
||||
//cout << "Ausgabe: " << out << endl;
|
||||
|
||||
fileWrite.close();
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
//Daten aus Datei lesen und in Struktur schreiben
|
||||
|
||||
|
||||
ifstream fileRead;
|
||||
fileRead.open("test.txt");
|
||||
|
||||
|
||||
FaultCoverageExperimentData faultCovExRead;
|
||||
|
||||
fi::ExperimentData exDaRead(&faultCovExRead);
|
||||
|
||||
exDaRead.unserialize( &fileRead);
|
||||
|
||||
|
||||
//Wenn Name, dann ausgeben
|
||||
if(faultCovExRead.has_data_name()){
|
||||
cout << "Name: "<< faultCovExRead.data_name() << endl;
|
||||
}
|
||||
|
||||
//m_instrptr1 augeben
|
||||
cout << "m_instrptr1: " << faultCovExRead.m_instrptr1() << endl;
|
||||
|
||||
//m_instrptr2 augeben
|
||||
cout << "m_instrptr2: " << faultCovExRead.m_instrptr2() << endl;
|
||||
|
||||
fileRead.close();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
#ifndef __JUMP_AND_RUN_EXPERIMENT_HPP__
|
||||
#define __JUMP_AND_RUN_EXPERIMENT_HPP__
|
||||
|
||||
// Author: Adrian Böckenkamp
|
||||
// Date: 07.11.2011
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../controller/ExperimentFlow.hpp"
|
||||
#include "../SAL/SALInst.hpp"
|
||||
#include "../SAL/bochs/BochsRegister.hpp"
|
||||
#include "../AspectConfig.hpp"
|
||||
|
||||
// Check if aspect dependencies are satisfied:
|
||||
#if CONFIG_EVENT_CPULOOP != 1 || CONFIG_EVENT_JUMP != 1
|
||||
#error Breakpoint- and jump-events needed! Enable aspects first (see AspectConfig.hpp)!
|
||||
#endif
|
||||
|
||||
using namespace fi;
|
||||
using namespace std;
|
||||
using namespace sal;
|
||||
|
||||
class JumpAndRunExperiment : public fi::ExperimentFlow
|
||||
{
|
||||
public:
|
||||
bool run()
|
||||
{
|
||||
/************************************
|
||||
* Description of experiment flow. *
|
||||
************************************/
|
||||
// Wait for function entry adresss:
|
||||
cout << "[JumpAndRunExperiment] Setting up experiment. Allowing to "
|
||||
<< "start now." << endl;
|
||||
BPEvent mainFuncEntry(0x3c1f);
|
||||
simulator.addEvent(&mainFuncEntry);
|
||||
if(&mainFuncEntry != simulator.waitAny())
|
||||
{
|
||||
cerr << "[JumpAndRunExperiment] Now, we are completely lost! "
|
||||
<< "It's time to cry! :-(" << endl;
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
cout << "[JumpAndRunExperiment] Entry of main function reached! "
|
||||
<< " Let's see who's jumping around here..." << endl;
|
||||
|
||||
const unsigned COUNTER = 20000;
|
||||
unsigned i = 0;
|
||||
BxFlagsReg* pFlags = dynamic_cast<BxFlagsReg*>(simulator.
|
||||
getRegisterManager().getSetOfType(RT_ST).snatch());
|
||||
assert(pFlags != NULL && "FATAL ERROR: NULL ptr not expected!");
|
||||
JumpEvent ev;
|
||||
// Catch the next "counter" jumps:
|
||||
while(++i <= COUNTER)
|
||||
{
|
||||
ev.setWatchInstructionPointer(ANY_INSTR);
|
||||
simulator.addEvent(&ev);
|
||||
if(simulator.waitAny() != &ev)
|
||||
{
|
||||
cerr << "[JumpAndRunExperiment] Damn! Something went "
|
||||
<< "terribly wrong! Who added that event?! :-(" << endl;
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
cout << "[JumpAndRunExperiment] Jump detected. Instruction: "
|
||||
<< "0x" hex << ev.getTriggerInstructionPointer()
|
||||
<< " -- FLAGS [CF, ZF, OF, PF, SF] = ["
|
||||
<< pFlags->getCarryFlag() << ", "
|
||||
<< pFlags->getZeroFlag() << ", "
|
||||
<< pFlags->getOverflowFlag() << ", "
|
||||
<< pFlags->getParityFlag() << ", "
|
||||
<< pFlags->getSignFlag() << "]." << endl;
|
||||
}
|
||||
cout << "[JumpAndRunExperiment] " << dec << counter
|
||||
<< " jump(s) detected -- enough for today...exiting! :-)"
|
||||
<< endl;
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __JUMP_AND_RUN_EXPERIMENT_HPP__ */
|
||||
76
core/experiments/attic/MemWriteExperiment.hpp
Normal file
76
core/experiments/attic/MemWriteExperiment.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef __MEM_WRITE_EXPERIMENT_HPP__
|
||||
#define __MEM_WRITE_EXPERIMENT_HPP__
|
||||
|
||||
// Author: Adrian Böckenkamp
|
||||
// Date: 16.06.2011
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../controller/ExperimentFlow.hpp"
|
||||
#include "../SAL/SALInst.hpp"
|
||||
#include "../AspectConfig.hpp"
|
||||
|
||||
// Check aspect dependencies:
|
||||
#if CONFIG_EVENT_CPULOOP != 1 || CONFIG_EVENT_MEMACCESS != 1 || CONFIG_SR_SAVE != 1 || CONFIG_FI_MEM_ACCESS_BITFLIP != 1
|
||||
#error Event dependecies not satisfied! Enabled needed aspects in AspectConfig.hpp!
|
||||
#endif
|
||||
|
||||
using namespace fi;
|
||||
using namespace std;
|
||||
using sal::simulator;
|
||||
|
||||
class MemWriteExperiment : public ExperimentFlow
|
||||
{
|
||||
public:
|
||||
bool run() // Example experiment (defines "what we wanna do")
|
||||
{
|
||||
/************************************
|
||||
* Description of experiment flow. *
|
||||
************************************/
|
||||
|
||||
// 1. Add some events (set up the experiment):
|
||||
cout << "[MemWriteExperiment] Setting up experiment. Allowing to"
|
||||
<< " start now." << endl;
|
||||
MemWriteEvent mem1(0x000904F0), mem2(0x02ff0916), mem3(0x0050C8E8);
|
||||
BPEvent breakpt(0x4ae6);
|
||||
simulator.addEvent(&mem1);
|
||||
simulator.addEvent(&mem2);
|
||||
simulator.addEvent(&mem3);
|
||||
simulator.addEvent(&breakpt);
|
||||
|
||||
// 2. Wait for event condition "(id1 && id2) || id3" to become true:
|
||||
cout << "[MemWriteExperiment] Waiting for condition (1) (\"(id1 &&"
|
||||
<< " id2) || id3\") to become true..." << endl;
|
||||
bool f1 = false, f2 = false, f3 = false, f4 = false;
|
||||
while(!(f1 || f2 || f3 || f4))
|
||||
{
|
||||
BPEvent* pev = simulator.waitAny();
|
||||
cout << "[MemWriteExperiment] Received event id=" << id
|
||||
<< "." << endl;
|
||||
if(pev == &mem4)
|
||||
f4 = true;
|
||||
if(pev == &mem3)
|
||||
f3 = true;
|
||||
if(pev == &mem2)
|
||||
f2 = true;
|
||||
if(pev == &mem1)
|
||||
f1 = true;
|
||||
}
|
||||
cout << "[MemWriteExperiment] Condition (1) satisfied! Ready to "
|
||||
<< "add next event..." << endl;
|
||||
// 3. Add a new event now:
|
||||
cout << "[MemWriteExperiment] Adding new Event..."; cout.flush();
|
||||
simulator.clearEvents(); // remove residual events in the buffer
|
||||
// (we're just interested in the new event)
|
||||
simulator.save("./bochs_save_point");
|
||||
cout << "done!" << endl;
|
||||
|
||||
// 4. Continue simulation (waitAny) and inject bitflip:
|
||||
// ...
|
||||
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __MEM_WRITE_EXPERIMENT_HPP__ */
|
||||
|
||||
64
core/experiments/attic/MyExperiment.hpp
Normal file
64
core/experiments/attic/MyExperiment.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef __MY_EXPERIMENT_HPP__
|
||||
#define __MY_EXPERIMENT_HPP__
|
||||
|
||||
// Author: Adrian Böckenkamp
|
||||
// Date: 16.06.2011
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../controller/ExperimentFlow.hpp"
|
||||
#include "../SAL/SALInst.hpp"
|
||||
|
||||
using namespace fi;
|
||||
using namespace std;
|
||||
using sal::simulator;
|
||||
|
||||
class MyExperiment : public fi::ExperimentFlow
|
||||
{
|
||||
public:
|
||||
bool run() // Example experiment (defines "what we wanna do")
|
||||
{
|
||||
/************************************
|
||||
* Description of experiment flow. *
|
||||
************************************/
|
||||
|
||||
// 1. Add some events (set up the experiment):
|
||||
cout << "[MyExperiment] Setting up experiment. Allowing to start"
|
||||
<< " now." << endl;
|
||||
BPEvent ev1(0x8048A00), ev2(0x8048F01), ev3(0x3c1f);
|
||||
simulator.addEvent(&ev1);
|
||||
simulator.addEvent(&ev2);
|
||||
simulator.addEvent(&ev3);
|
||||
|
||||
// 2. Wait for event condition "(id1 && id2) || id3" to become true:
|
||||
BPEvent* pev;
|
||||
cout << "[MyExperiment] Waiting for condition (1) (\"(id1 && id2)"
|
||||
<< " || id3\") to become true..." << endl;
|
||||
bool f1 = false, f2 = false, f3 = false;
|
||||
while(!((f1 && f2) || f3))
|
||||
{
|
||||
pev = simulator.waitAny();
|
||||
cout << "[MyExperiment] Received event id=" << pev->getId()
|
||||
<< "." << endl;
|
||||
if(pev == &ev3)
|
||||
f3 = true;
|
||||
if(pev == &ev2)
|
||||
f2 = true;
|
||||
if(pev == &ev1)
|
||||
f1 = true;
|
||||
}
|
||||
cout << "[MyExperiment] Condition (1) satisfied! Ready..." << endl;
|
||||
// Remove residual (for all active experiments!)
|
||||
// events in the buffer:
|
||||
simulator.clearEvents();
|
||||
BPEvent foobar(ANY_ADDR);
|
||||
foobar.setCounter(400);
|
||||
cout << "[MyExperiment] Adding breakpoint-event, firing after the"
|
||||
<< " next 400 instructions..."; cout.flush();
|
||||
simulator.addEventAndWait(&foobar);
|
||||
cout << "cought! Exiting now." << endl;
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __MY_EXPERIMENT_HPP__ */
|
||||
64
core/experiments/attic/SingleSteppingExperiment.hpp
Normal file
64
core/experiments/attic/SingleSteppingExperiment.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef __SINGLE_STEPPING_EXPERIMENT_HPP__
|
||||
#define __SINGLE_STEPPING_EXPERIMENT_HPP__
|
||||
|
||||
// Author: Adrian Böckenkamp
|
||||
// Date: 09.11.2011
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../controller/ExperimentFlow.hpp"
|
||||
#include "../SAL/SALInst.hpp"
|
||||
#include "../AspectConfig.hpp"
|
||||
#include "../SAL/bochs/BochsRegister.hpp"
|
||||
|
||||
// Check if aspect dependency is satisfied:
|
||||
#if CONFIG_EVENT_CPULOOP != 1
|
||||
#error Breakpoint-events needed! Enable aspect first (see AspectConfig.hpp)!
|
||||
#endif
|
||||
|
||||
using namespace fi;
|
||||
using namespace std;
|
||||
using namespace sal;
|
||||
|
||||
#define FUNCTION_ENTRY_ADDRESS 0x3c1f
|
||||
|
||||
class SingleSteppingExperiment : public fi::ExperimentFlow
|
||||
{
|
||||
public:
|
||||
bool run()
|
||||
{
|
||||
/************************************
|
||||
* Description of experiment flow. *
|
||||
************************************/
|
||||
// Wait for function entry adresss:
|
||||
cout << "[SingleSteppingExperiment] Setting up experiment. Allowing"
|
||||
<< " to start now." << endl;
|
||||
BPEvent mainFuncEntry(FUNCTION_ENTRY_ADDRESS);
|
||||
simulator.addEvent(&mainFuncEntry);
|
||||
if(&mainFuncEntry != simulator.waitAny())
|
||||
{
|
||||
cerr << "[SingleSteppingExperiment] Now, we are completely lost!"
|
||||
<< " It's time to cry! :-(" << endl;
|
||||
return (false);
|
||||
}
|
||||
cout << "[SingleSteppingExperiment] Entry of main function reached!"
|
||||
<< " Beginning single-stepping..." << endl;
|
||||
char action;
|
||||
while(true)
|
||||
{
|
||||
BPEvent bp(ANY_ADDR);
|
||||
simulator.addEvent(&bp);
|
||||
simulator.waitAny();
|
||||
cout << "0x" << hex
|
||||
<< simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
cout << "Continue (y/n)? ";
|
||||
cin >> action; cin.sync(); cin.clear();
|
||||
if(action != 'y')
|
||||
break;
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __SINGLE_STEPPING_EXPERIMENT_HPP__ */
|
||||
16
core/experiments/attic/instantiate-experiment.ah.template
Normal file
16
core/experiments/attic/instantiate-experiment.ah.template
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __INSTANTIATE_EXPERIMENT_AH__
|
||||
#define __INSTANTIATE_EXPERIMENT_AH__
|
||||
|
||||
// copy this file to a .ah file and instantiate the experiment(s) you need
|
||||
|
||||
#include "hscsimple.hpp"
|
||||
#include "../SAL/SALInst.hpp"
|
||||
|
||||
aspect hscsimple {
|
||||
hscsimpleExperiment experiment;
|
||||
advice execution ("void sal::SimulatorController::initExperiments()") : after () {
|
||||
sal::simulator.addFlow(&experiment);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __INSTANTIATE_EXPERIMENT_AH__
|
||||
31
core/experiments/checksum-oostubs/CMakeLists.txt
Normal file
31
core/experiments/checksum-oostubs/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
set(EXPERIMENT_NAME checksum-oostubs)
|
||||
set(EXPERIMENT_TYPE CoolChecksumExperiment) # FIXME naming conflict
|
||||
configure_file(../instantiate-experiment.ah.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
|
||||
)
|
||||
|
||||
## Setup desired protobuf descriptions HERE ##
|
||||
set(MY_PROTOS
|
||||
checksum-oostubs.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(${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})
|
||||
1
core/experiments/checksum-oostubs/MemoryMap.hpp
Symbolic link
1
core/experiments/checksum-oostubs/MemoryMap.hpp
Symbolic link
@ -0,0 +1 @@
|
||||
../../util/MemoryMap.hpp
|
||||
140
core/experiments/checksum-oostubs/campaign.cc
Normal file
140
core/experiments/checksum-oostubs/campaign.cc
Normal file
@ -0,0 +1,140 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "campaign.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "controller/CampaignManager.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
|
||||
using namespace fi;
|
||||
using std::endl;
|
||||
|
||||
char const * const results_csv = "chksumoostubs.csv";
|
||||
|
||||
//TODO: generate new values for the updated experiment
|
||||
const unsigned memoryMap[49][2] = {
|
||||
{0x109134, 4},
|
||||
{0x10913c, 4},
|
||||
{0x109184, 4},
|
||||
{0x1091cc, 1},
|
||||
{0x109238, 256},
|
||||
{0x109344, 4},
|
||||
{0x109350, 4},
|
||||
{0x109354, 4},
|
||||
{0x109368, 1},
|
||||
{0x109374, 4},
|
||||
{0x109388, 1},
|
||||
{0x109398, 4},
|
||||
{0x1093a0, 4},
|
||||
{0x1093b4, 4},
|
||||
{0x1093b8, 4},
|
||||
{0x1093c0, 4},
|
||||
{0x1093d0, 4},
|
||||
{0x1093dc, 4},
|
||||
{0x1093e0, 4},
|
||||
{0x1093e8, 1},
|
||||
{0x1093f0, 4},
|
||||
{0x1093f4, 4},
|
||||
{0x10a460, 4},
|
||||
{0x10a468, 4},
|
||||
{0x10a470, 4},
|
||||
{0x10a478, 4},
|
||||
{0x10a480, 4},
|
||||
{0x10a488, 4},
|
||||
{0x10a494, 4},
|
||||
{0x10a498, 4},
|
||||
{0x10a4a8, 4},
|
||||
{0x10a4ad, 1},
|
||||
{0x10a4b4, 4},
|
||||
{0x10a4b8, 4},
|
||||
{0x10a4c8, 4},
|
||||
{0x10a4cd, 1},
|
||||
{0x10a4d4, 4},
|
||||
{0x10a4d8, 4},
|
||||
{0x10a4e8, 4},
|
||||
{0x10a4ed, 1},
|
||||
{0x10a4f4, 4},
|
||||
{0x10a4f8, 4},
|
||||
{0x10a500, 4},
|
||||
{0x10d350, 4},
|
||||
{0x10d358, 4},
|
||||
{0x10d37c, 4},
|
||||
{0x10d384, 4},
|
||||
{0x10d3a8, 4},
|
||||
{0x10d3b0, 4},
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool CoolChecksumCampaign::run()
|
||||
{
|
||||
Logger log("CoolChecksumCampaign");
|
||||
|
||||
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;
|
||||
|
||||
unsigned count = 0;
|
||||
|
||||
for(int member = 0; member < 49; ++member){ //TODO: 49 -> constant
|
||||
for (int bit_offset = 0; bit_offset < (memoryMap[member][1])*8; ++bit_offset) {
|
||||
for (int instr_offset = 0; instr_offset < OOSTUBS_NUMINSTR; ++instr_offset) {
|
||||
CoolChecksumExperimentData *d = new CoolChecksumExperimentData;
|
||||
d->msg.set_instr_offset(instr_offset);
|
||||
d->msg.set_mem_addr(memoryMap[member][0]);
|
||||
d->msg.set_bit_offset(bit_offset);
|
||||
|
||||
fi::campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (int bit_offset = 0; bit_offset < COOL_ECC_OBJUNDERTEST_SIZE*8; ++bit_offset) {
|
||||
for (int instr_offset = 0; instr_offset < OOSTUBS_NUMINSTR; ++instr_offset) {
|
||||
CoolChecksumExperimentData *d = new CoolChecksumExperimentData;
|
||||
d->msg.set_instr_offset(instr_offset);
|
||||
d->msg.set_mem_addr(0x0);
|
||||
d->msg.set_bit_offset(bit_offset);
|
||||
|
||||
fi::campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fi::campaignmanager.noMoreParameters();
|
||||
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
||||
|
||||
// collect results
|
||||
CoolChecksumExperimentData *res;
|
||||
int rescount = 0;
|
||||
results << "injection_ip\tinstr_offset\tinjection_bit\tresulttype\tresultdata\terror_corrected\tdetails" << endl;
|
||||
while ((res = static_cast<CoolChecksumExperimentData *>(fi::campaignmanager.getDone()))) {
|
||||
rescount++;
|
||||
|
||||
results
|
||||
<< res->msg.injection_ip() << "\t"
|
||||
<< res->msg.instr_offset() << "\t"
|
||||
<< res->msg.mem_addr() << "\t"
|
||||
<< res->msg.bit_offset() << "\t"
|
||||
<< res->msg.resulttype() << "\t"
|
||||
<< res->msg.resultdata() << "\t"
|
||||
<< res->msg.error_corrected() << "\t"
|
||||
<< res->msg.details() << "\n";
|
||||
delete res;
|
||||
}
|
||||
log << "done. sent " << count << " received " << rescount << endl;
|
||||
results.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
20
core/experiments/checksum-oostubs/campaign.hpp
Normal file
20
core/experiments/checksum-oostubs/campaign.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __COOLCAMPAIGN_HPP__
|
||||
#define __COOLCAMPAIGN_HPP__
|
||||
|
||||
#include "controller/Campaign.hpp"
|
||||
#include "controller/ExperimentData.hpp"
|
||||
#include "checksum-oostubs.pb.h"
|
||||
|
||||
class CoolChecksumExperimentData : public fi::ExperimentData {
|
||||
public:
|
||||
OOStuBSProtoMsg msg;
|
||||
CoolChecksumExperimentData() : fi::ExperimentData(&msg) {}
|
||||
};
|
||||
|
||||
|
||||
class CoolChecksumCampaign : public fi::Campaign {
|
||||
public:
|
||||
virtual bool run();
|
||||
};
|
||||
|
||||
#endif
|
||||
29
core/experiments/checksum-oostubs/checksum-oostubs.proto
Normal file
29
core/experiments/checksum-oostubs/checksum-oostubs.proto
Normal file
@ -0,0 +1,29 @@
|
||||
message OOStuBSProtoMsg {
|
||||
// parameters
|
||||
required int32 instr_offset = 1;
|
||||
required int32 mem_addr = 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;
|
||||
UNKNOWN = 4;
|
||||
}
|
||||
// instruction pointer where injection was done
|
||||
optional uint32 injection_ip = 4;
|
||||
// result type, see above
|
||||
optional ResultType resulttype = 5;
|
||||
// result data, depending on resulttype:
|
||||
// CALCDONE: resultdata = calculated value
|
||||
// TIMEOUT: resultdata = latest EIP
|
||||
// TRAP: resultdata = latest EIP
|
||||
// UNKNOWN: resultdata = latest EIP
|
||||
optional uint32 resultdata = 6;
|
||||
// did ECC correct the fault?
|
||||
optional int32 error_corrected = 7;
|
||||
// optional textual description of what happened
|
||||
optional string details = 8;
|
||||
}
|
||||
180
core/experiments/checksum-oostubs/experiment.cc
Normal file
180
core/experiments/checksum-oostubs/experiment.cc
Normal file
@ -0,0 +1,180 @@
|
||||
#include <iostream>
|
||||
|
||||
#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"
|
||||
|
||||
#include "checksum-oostubs.pb.h"
|
||||
|
||||
using std::endl;
|
||||
|
||||
bool CoolChecksumExperiment::run()
|
||||
{
|
||||
#if BX_SUPPORT_X86_64
|
||||
int targetreg = sal::RID_RDX;
|
||||
#else
|
||||
int targetreg = sal::RID_EDX;
|
||||
#endif
|
||||
Logger log("Checksum-OOStuBS", false);
|
||||
fi::BPEvent bp;
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
#if 1
|
||||
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(OOSTUBS_FUNC_ENTRY);
|
||||
sal::simulator.addEventAndWait(&bp);
|
||||
log << "test function entry reached, saving state" << endl;
|
||||
log << "EIP = " << std::hex << bp.getTriggerInstructionPointer() << " or " << sal::simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
log << "error_corrected = " << std::dec << ((int)sal::simulator.getMemoryManager().getByte(OOSTUBS_ERROR_CORRECTED)) << endl;
|
||||
sal::simulator.save("checksum-oostubs.state");
|
||||
#elif 1
|
||||
// STEP 2: determine # instructions from start to end
|
||||
log << "restoring state" << endl;
|
||||
sal::simulator.restore("checksum-oostubs.state");
|
||||
log << "EIP = " << std::hex << sal::simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
//sal::simulator.deactivateTimer(0); // leave it on, explicitly
|
||||
|
||||
unsigned count;
|
||||
bp.setWatchInstructionPointer(fi::ANY_ADDR);
|
||||
for (count = 0; bp.getTriggerInstructionPointer() != OOSTUBS_FUNC_DONE; ++count) {
|
||||
//for (count = 0; count < OOSTUBS_NUMINSTR; ++count) { //TODO?
|
||||
sal::simulator.addEventAndWait(&bp);
|
||||
//log << "EIP = " << std::hex << sal::simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
}
|
||||
log << "experiment finished after " << count << " instructions" << endl;
|
||||
|
||||
unsigned char results[OOSTUBS_RESULTS_BYTES];
|
||||
for(int i=0; i<OOSTUBS_RESULTS_BYTES; ++i){
|
||||
results[i] = (unsigned)sal::simulator.getMemoryManager().getByte(OOSTUBS_RESULTS_ADDR + i);
|
||||
}
|
||||
for(int i=0; i<OOSTUBS_RESULTS_BYTES/4; ++i){
|
||||
log << "results[" << i << "]: " << std::hex << *(((unsigned*)results)+i) << endl;
|
||||
}
|
||||
|
||||
#elif 1
|
||||
// FIXME consider moving experiment repetition into Fail* or even the
|
||||
// SAL -- whether and how this is possible with the chosen backend is
|
||||
// backend specific
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
|
||||
// STEP 3: The actual experiment.
|
||||
log << "restoring state" << endl;
|
||||
sal::simulator.restore("coolecc.state");
|
||||
|
||||
log << "asking job server for experiment parameters" << endl;
|
||||
CoolChecksumExperimentData param;
|
||||
if (!m_jc.getParam(param)) {
|
||||
log << "Dying." << endl;
|
||||
// communicate that we were told to die
|
||||
sal::simulator.terminate(1);
|
||||
}
|
||||
int id = param.getWorkloadID();
|
||||
int instr_offset = param.msg.instr_offset();
|
||||
int bit_offset = param.msg.bit_offset();
|
||||
log << "job " << id << " instr " << instr_offset << " bit " << bit_offset << endl;
|
||||
|
||||
// FIXME could be improved (especially for backends supporting
|
||||
// breakpoints natively) by utilizing a previously recorded instruction
|
||||
// trace
|
||||
bp.setWatchInstructionPointer(fi::ANY_ADDR);
|
||||
for (int count = 0; count < instr_offset; ++count) {
|
||||
sal::simulator.addEventAndWait(&bp);
|
||||
}
|
||||
|
||||
// inject
|
||||
sal::guest_address_t inject_addr = COOL_ECC_OBJUNDERTEST + bit_offset / 8;
|
||||
sal::MemoryManager& mm = sal::simulator.getMemoryManager();
|
||||
sal::byte_t data = mm.getByte(inject_addr);
|
||||
sal::byte_t newdata = data ^ (1 << (bit_offset % 8));
|
||||
mm.setByte(inject_addr, newdata);
|
||||
// note at what IP we did it
|
||||
int32_t injection_ip = sal::simulator.getRegisterManager().getInstructionPointer();
|
||||
param.msg.set_injection_ip(injection_ip);
|
||||
log << "inject @ ip " << injection_ip
|
||||
<< " offset " << std::dec << (bit_offset / 8)
|
||||
<< " (bit " << (bit_offset % 8) << ") 0x"
|
||||
<< std::hex << ((int)data) << " -> 0x" << ((int)newdata) << endl;
|
||||
|
||||
// aftermath
|
||||
fi::BPEvent ev_done(COOL_ECC_CALCDONE);
|
||||
sal::simulator.addEvent(&ev_done);
|
||||
fi::BPEvent ev_timeout(fi::ANY_ADDR);
|
||||
ev_timeout.setCounter(COOL_ECC_NUMINSTR + 3000);
|
||||
sal::simulator.addEvent(&ev_timeout);
|
||||
fi::TrapEvent ev_trap(fi::ANY_TRAP);
|
||||
sal::simulator.addEvent(&ev_trap);
|
||||
|
||||
fi::BaseEvent* ev = sal::simulator.waitAny();
|
||||
if (ev == &ev_done) {
|
||||
int32_t data = sal::simulator.getRegisterManager().getSetOfType(sal::RT_GP).getRegister(targetreg)->getData();
|
||||
log << std::dec << "Result EDX = " << data << endl;
|
||||
param.msg.set_resulttype(CoolChecksumProtoMsg_ResultType_CALCDONE);
|
||||
param.msg.set_resultdata(data);
|
||||
} else if (ev == &ev_timeout) {
|
||||
log << std::dec << "Result TIMEOUT" << endl;
|
||||
param.msg.set_resulttype(CoolChecksumProtoMsg_ResultType_TIMEOUT);
|
||||
param.msg.set_resultdata(sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
} else if (ev == &ev_trap) {
|
||||
log << std::dec << "Result TRAP #" << ev_trap.getTriggerNumber() << endl;
|
||||
param.msg.set_resulttype(CoolChecksumProtoMsg_ResultType_TRAP);
|
||||
param.msg.set_resultdata(sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
} else {
|
||||
log << std::dec << "Result WTF?" << endl;
|
||||
param.msg.set_resulttype(CoolChecksumProtoMsg_ResultType_UNKNOWN);
|
||||
param.msg.set_resultdata(sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "eventid " << ev << " EIP " << sal::simulator.getRegisterManager().getInstructionPointer();
|
||||
param.msg.set_details(ss.str());
|
||||
}
|
||||
int32_t error_corrected = sal::simulator.getMemoryManager().getByte(COOL_ECC_ERROR_CORRECTED);
|
||||
param.msg.set_error_corrected(error_corrected);
|
||||
m_jc.sendResult(param);
|
||||
|
||||
}
|
||||
#endif
|
||||
// FIXME We currently need to explicitly terminate. See below.
|
||||
sal::simulator.terminate();
|
||||
|
||||
// FIXME Simply returning currently fails, because afterwards
|
||||
// a) the ExperimentFlow base class cleans up this experiment's
|
||||
// remaining events,
|
||||
// b) the CoroutineManager deletes this coroutine and frees the
|
||||
// associated stack (and in particular the memory the event that
|
||||
// most recently activated us lies in),
|
||||
// c) BochsController tries to dynamic_cast<fi::BPRangeEvent*>(pBase)
|
||||
// this very event (bochs/Controller.cc:112).
|
||||
// This could be partially fixed by adding a "continue;" to the first
|
||||
// if() in this loop in BochsController, but it would still fail if
|
||||
// there were more events waiting to be fired. The general problem is
|
||||
// that we're removing events while we're in BochsController's (or
|
||||
// whose ever) event handling loop.
|
||||
//
|
||||
// Outline for a proper fix: Split all event handling loops into two
|
||||
// parts,
|
||||
// 1. collect all events to be fired in some kind of list data
|
||||
// structure,
|
||||
// 2. fire all collected events in a centralized SimulatorController
|
||||
// function.
|
||||
// The data structure and the centralized function should be chosen in
|
||||
// a way that this construct *can* deal with events being removed while
|
||||
// iterating over them.
|
||||
return true;
|
||||
}
|
||||
14
core/experiments/checksum-oostubs/experiment.hpp
Normal file
14
core/experiments/checksum-oostubs/experiment.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __COOLEXPERIMENT_HPP__
|
||||
#define __COOLEXPERIMENT_HPP__
|
||||
|
||||
#include "controller/ExperimentFlow.hpp"
|
||||
#include "jobserver/JobClient.hpp"
|
||||
|
||||
class CoolChecksumExperiment : public fi::ExperimentFlow {
|
||||
fi::JobClient m_jc;
|
||||
public:
|
||||
CoolChecksumExperiment() : m_jc("ios.cs.tu-dortmund.de") {}
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif
|
||||
48
core/experiments/checksum-oostubs/experimentInfo.hpp
Normal file
48
core/experiments/checksum-oostubs/experimentInfo.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef __EXPERIMENT_INFO_HPP__
|
||||
#define __EXPERIMENT_INFO_HPP__
|
||||
|
||||
// FIXME autogenerate this
|
||||
|
||||
#if 1 // with ECC
|
||||
|
||||
// the task function's entry address:
|
||||
// nm -C ecc.elf|fgrep main
|
||||
#define OOSTUBS_FUNC_ENTRY 0x00103f2c
|
||||
// empty function that is called explicitly when the experiment finished
|
||||
// nm -C ecc.elf|fgrep "finished()"
|
||||
#define OOSTUBS_FUNC_DONE 0x001093f0
|
||||
// number of instructions the target executes under non-error conditions from ENTRY to DONE:
|
||||
// (result of experiment's step #2)
|
||||
#define OOSTUBS_NUMINSTR 0x4a3401
|
||||
// number of instructions that are executed additionally for error corrections
|
||||
// (this is a rough guess ... TODO)
|
||||
#define OOSTUBS_RECOVERYINSTR 0x2000
|
||||
// the ECC protected object's address:
|
||||
// nm -C ecc.elf|fgrep objectUnderTest
|
||||
#define COOL_ECC_OBJUNDERTEST 0x002127a4 //FIXME
|
||||
// the ECC protected object's payload size:
|
||||
// (we know that from the object's definition and usual memory layout)
|
||||
#define COOL_ECC_OBJUNDERTEST_SIZE 10 //FIXME
|
||||
// the variable that's increased if ECC corrects an error:
|
||||
// nm -C ecc.elf|fgrep errors_corrected
|
||||
#define OOSTUBS_ERROR_CORRECTED 0x0010e3a4
|
||||
//
|
||||
// nm -C ecc.elf|fgrep results
|
||||
#define OOSTUBS_RESULTS_ADDR 0x0010d794
|
||||
#define OOSTUBS_RESULTS_BYTES 12
|
||||
#define OOSTUBS_RESULT0 0xab3566a9
|
||||
#define OOSTUBS_RESULT1 0x44889112
|
||||
#define OOSTUBS_RESULT2 0x10420844
|
||||
|
||||
#else // without ECC
|
||||
|
||||
#define COOL_ECC_FUNC_ENTRY 0x00200a90
|
||||
#define COOL_ECC_CALCDONE 0x00200ab7
|
||||
#define COOL_ECC_NUMINSTR 97
|
||||
#define COOL_ECC_OBJUNDERTEST 0x0021263c
|
||||
#define COOL_ECC_OBJUNDERTEST_SIZE 10
|
||||
#define COOL_ECC_ERROR_CORRECTED 0x002127b0 // dummy
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
15
core/experiments/checksum-oostubs/main.cc
Normal file
15
core/experiments/checksum-oostubs/main.cc
Normal file
@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "controller/CampaignManager.hpp"
|
||||
#include "experiments/checksum-oostubs/campaign.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CoolChecksumCampaign c;
|
||||
if (fi::campaignmanager.runCampaign(&c)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
31
core/experiments/coolchecksum/CMakeLists.txt
Normal file
31
core/experiments/coolchecksum/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
set(EXPERIMENT_NAME coolchecksum)
|
||||
set(EXPERIMENT_TYPE CoolChecksumExperiment)
|
||||
configure_file(../instantiate-experiment.ah.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
|
||||
)
|
||||
|
||||
## Setup desired protobuf descriptions HERE ##
|
||||
set(MY_PROTOS
|
||||
coolchecksum.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(${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})
|
||||
273
core/experiments/coolchecksum/campaign.cc
Normal file
273
core/experiments/coolchecksum/campaign.cc
Normal file
@ -0,0 +1,273 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "campaign.hpp"
|
||||
#include "experimentInfo.hpp"
|
||||
#include "controller/CampaignManager.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include "SAL/SALConfig.hpp"
|
||||
|
||||
#if COOL_FAULTSPACE_PRUNING
|
||||
#include "plugins/tracing/TracingPlugin.hpp"
|
||||
char const * const trace_filename = "trace.pb";
|
||||
#endif
|
||||
|
||||
using namespace fi;
|
||||
using std::endl;
|
||||
|
||||
char const * const results_csv = "coolcampaign.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 {
|
||||
unsigned byte_offset;
|
||||
int instr1, instr2;
|
||||
sal::address_t instr2_absolute; // FIXME we could record them all here
|
||||
};
|
||||
|
||||
bool CoolChecksumCampaign::run()
|
||||
{
|
||||
Logger log("CoolChecksumCampaign");
|
||||
|
||||
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;
|
||||
|
||||
#if !COOL_FAULTSPACE_PRUNING
|
||||
int count = 0;
|
||||
for (int bit_offset = 0; bit_offset < COOL_ECC_OBJUNDERTEST_SIZE*8; ++bit_offset) {
|
||||
for (int instr_offset = 0; instr_offset < COOL_ECC_NUMINSTR; ++instr_offset) {
|
||||
CoolChecksumExperimentData *d = new CoolChecksumExperimentData;
|
||||
d->msg.set_instr_offset(instr_offset);
|
||||
d->msg.set_bit_offset(bit_offset);
|
||||
|
||||
fi::campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
fi::campaignmanager.noMoreParameters();
|
||||
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
||||
|
||||
// collect results
|
||||
CoolChecksumExperimentData *res;
|
||||
int rescount = 0;
|
||||
results << "injection_ip\tinstr_offset\tinjection_bit\tresulttype\tresultdata\terror_corrected\tdetails" << endl;
|
||||
while ((res = static_cast<CoolChecksumExperimentData *>(fi::campaignmanager.getDone()))) {
|
||||
rescount++;
|
||||
|
||||
results
|
||||
<< res->msg.injection_ip() << "\t"
|
||||
<< res->msg.instr_offset() << "\t"
|
||||
<< res->msg.bit_offset() << "\t"
|
||||
<< res->msg.resulttype() << "\t"
|
||||
<< res->msg.resultdata() << "\t"
|
||||
<< res->msg.error_corrected() << "\t"
|
||||
<< res->msg.details() << "\n";
|
||||
delete res;
|
||||
}
|
||||
#else
|
||||
// load trace
|
||||
ifstream tracef(trace_filename);
|
||||
if (tracef.fail()) {
|
||||
log << "couldn't open " << trace_filename << endl;
|
||||
return false;
|
||||
}
|
||||
Trace trace;
|
||||
trace.ParseFromIstream(&tracef);
|
||||
tracef.close();
|
||||
|
||||
// set of equivalence classes that need one (rather: eight, one for
|
||||
// each bit in that byte) experiment to determine them all
|
||||
std::vector<equivalence_class> ecs_need_experiment;
|
||||
// set of equivalence classes that need no experiment, because we know
|
||||
// they'd be identical to the golden run
|
||||
std::vector<equivalence_class> ecs_no_effect;
|
||||
|
||||
Trace_Event end_event; // pseudo event
|
||||
equivalence_class current_ec;
|
||||
|
||||
// for every injection address ...
|
||||
// XXX in more complex cases we'll need to iterate over a MemoryMap here
|
||||
for (unsigned byte_offset = 0; byte_offset < COOL_ECC_OBJUNDERTEST_SIZE; ++byte_offset) {
|
||||
|
||||
current_ec.instr1 = 0;
|
||||
// for every section in the trace between subsequent memory
|
||||
// accesses to that address ...
|
||||
// XXX reorganizing the trace for efficient seeks could speed this up
|
||||
int instr = 0;
|
||||
sal::address_t instr_absolute = 0; // FIXME this one probably should also be recorded ...
|
||||
Trace_Event const *ev;
|
||||
for (int eventnr = 0; eventnr < trace.event_size(); ++eventnr) {
|
||||
ev = &trace.event(eventnr);
|
||||
|
||||
// only count instruction events
|
||||
if (!ev->has_memaddr()) {
|
||||
// new instruction
|
||||
instr++;
|
||||
instr_absolute = ev->ip();
|
||||
continue;
|
||||
|
||||
// skip accesses to other data
|
||||
} else if (ev->memaddr() != byte_offset + COOL_ECC_OBJUNDERTEST) {
|
||||
continue;
|
||||
|
||||
// skip zero-sized intervals: these can
|
||||
// occur when an instruction accesses a
|
||||
// memory location more than once
|
||||
// (e.g., INC, CMPXCHG)
|
||||
} else if (current_ec.instr1 > instr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// we now have an interval-terminating R/W
|
||||
// event to the memaddr we're currently looking
|
||||
// at:
|
||||
|
||||
// complete the equivalence interval
|
||||
current_ec.instr2 = instr;
|
||||
current_ec.instr2_absolute = instr_absolute;
|
||||
current_ec.byte_offset = byte_offset;
|
||||
|
||||
if (ev->accesstype() == ev->READ) {
|
||||
// a sequence ending with READ: we need
|
||||
// to do one experiment to cover it
|
||||
// completely
|
||||
ecs_need_experiment.push_back(current_ec);
|
||||
} else if (ev->accesstype() == ev->WRITE) {
|
||||
// a sequence ending with WRITE: an
|
||||
// injection anywhere here would have
|
||||
// no effect.
|
||||
ecs_no_effect.push_back(current_ec);
|
||||
} else {
|
||||
log << "WAT" << endl;
|
||||
}
|
||||
|
||||
// next interval must start at next
|
||||
// instruction; the aforementioned
|
||||
// skipping mechanism wouldn't work
|
||||
// otherwise
|
||||
current_ec.instr1 = instr + 1;
|
||||
}
|
||||
|
||||
// close the last interval:
|
||||
// Why -1? In most cases it does not make sense to inject before the
|
||||
// very last instruction, as we won't execute it anymore. This *only*
|
||||
// makes sense if we also inject into parts of the result vector. This
|
||||
// is not the case in this experiment, and with -1 we'll get a
|
||||
// result comparable to the non-pruned campaign.
|
||||
current_ec.instr2 = instr - 1;
|
||||
current_ec.instr2_absolute = 0; // won't be used
|
||||
current_ec.byte_offset = byte_offset;
|
||||
// zero-sized? skip.
|
||||
if (current_ec.instr1 > current_ec.instr2) {
|
||||
continue;
|
||||
}
|
||||
// as the experiment ends, this byte is a "don't care":
|
||||
ecs_no_effect.push_back(current_ec);
|
||||
}
|
||||
|
||||
log << "equivalence classes generated:"
|
||||
<< " need_experiment = " << ecs_need_experiment.size()
|
||||
<< " no_effect = " << ecs_no_effect.size() << endl;
|
||||
|
||||
// statistics
|
||||
int num_dumb_experiments = 0;
|
||||
for (std::vector<equivalence_class>::const_iterator it = ecs_need_experiment.begin();
|
||||
it != ecs_need_experiment.end(); ++it) {
|
||||
num_dumb_experiments += (*it).instr2 - (*it).instr1 + 1;
|
||||
}
|
||||
for (std::vector<equivalence_class>::const_iterator it = ecs_no_effect.begin();
|
||||
it != ecs_no_effect.end(); ++it) {
|
||||
num_dumb_experiments += (*it).instr2 - (*it).instr1 + 1;
|
||||
}
|
||||
log << "pruning: reduced " << num_dumb_experiments * 8 <<
|
||||
" experiments to " << ecs_need_experiment.size() * 8 << endl;
|
||||
|
||||
// map for efficient access when results come in
|
||||
std::map<CoolChecksumExperimentData *, equivalence_class *> experiment_ecs;
|
||||
int count = 0;
|
||||
for (std::vector<equivalence_class>::iterator it = ecs_need_experiment.begin();
|
||||
it != ecs_need_experiment.end(); ++it) {
|
||||
for (int bitnr = 0; bitnr < 8; ++bitnr) {
|
||||
CoolChecksumExperimentData *d = new CoolChecksumExperimentData;
|
||||
// we pick the rightmost instruction in that interval
|
||||
d->msg.set_instr_offset((*it).instr2);
|
||||
d->msg.set_instr_address((*it).instr2_absolute);
|
||||
d->msg.set_bit_offset((*it).byte_offset * 8 + bitnr);
|
||||
|
||||
experiment_ecs[d] = &(*it);
|
||||
|
||||
fi::campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
fi::campaignmanager.noMoreParameters();
|
||||
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
||||
|
||||
// CSV header
|
||||
results << "injection_ip\tinstr_offset\tinjection_bit\tresulttype\tresultdata\terror_corrected\tdetails" << endl;
|
||||
|
||||
// store no-effect "experiment" results
|
||||
// (for comparison reasons; we'll store that more compactly later)
|
||||
for (std::vector<equivalence_class>::const_iterator it = ecs_no_effect.begin();
|
||||
it != ecs_no_effect.end(); ++it) {
|
||||
for (int bitnr = 0; bitnr < 8; ++bitnr) {
|
||||
for (int instr = (*it).instr1; instr <= (*it).instr2; ++instr) {
|
||||
results
|
||||
<< (*it).instr2_absolute << "\t" // incorrect in all but one case!
|
||||
<< instr << "\t"
|
||||
<< ((*it).byte_offset * 8 + bitnr) << "\t"
|
||||
<< "1" << "\t"
|
||||
<< "45" << "\t"
|
||||
<< "0" << "\t"
|
||||
<< "" << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collect results
|
||||
CoolChecksumExperimentData *res;
|
||||
int rescount = 0;
|
||||
while ((res = static_cast<CoolChecksumExperimentData *>(fi::campaignmanager.getDone()))) {
|
||||
rescount++;
|
||||
|
||||
equivalence_class *ec = experiment_ecs[res];
|
||||
|
||||
// sanity check
|
||||
if (ec->instr2 != res->msg.instr_offset()) {
|
||||
results << "WTF" << endl;
|
||||
log << "WTF" << endl;
|
||||
delete res;
|
||||
continue;
|
||||
}
|
||||
|
||||
// explode equivalence class to single "experiments"
|
||||
// (for comparison reasons; we'll store that more compactly later)
|
||||
for (int instr = ec->instr1; instr <= ec->instr2; ++instr) {
|
||||
results
|
||||
<< res->msg.injection_ip() << "\t" // incorrect in all but one case!
|
||||
<< instr << "\t"
|
||||
<< res->msg.bit_offset() << "\t"
|
||||
<< res->msg.resulttype() << "\t"
|
||||
<< res->msg.resultdata() << "\t"
|
||||
<< res->msg.error_corrected() << "\t"
|
||||
<< res->msg.details() << "\n";
|
||||
}
|
||||
delete res;
|
||||
}
|
||||
#endif
|
||||
log << "done. sent " << count << " received " << rescount << endl;
|
||||
results.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
20
core/experiments/coolchecksum/campaign.hpp
Normal file
20
core/experiments/coolchecksum/campaign.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __COOLCAMPAIGN_HPP__
|
||||
#define __COOLCAMPAIGN_HPP__
|
||||
|
||||
#include "controller/Campaign.hpp"
|
||||
#include "controller/ExperimentData.hpp"
|
||||
#include "coolchecksum.pb.h"
|
||||
|
||||
class CoolChecksumExperimentData : public fi::ExperimentData {
|
||||
public:
|
||||
CoolChecksumProtoMsg msg;
|
||||
CoolChecksumExperimentData() : fi::ExperimentData(&msg) {}
|
||||
};
|
||||
|
||||
|
||||
class CoolChecksumCampaign : public fi::Campaign {
|
||||
public:
|
||||
virtual bool run();
|
||||
};
|
||||
|
||||
#endif
|
||||
29
core/experiments/coolchecksum/coolchecksum.proto
Normal file
29
core/experiments/coolchecksum/coolchecksum.proto
Normal file
@ -0,0 +1,29 @@
|
||||
message CoolChecksumProtoMsg {
|
||||
// parameters
|
||||
required int32 instr_offset = 1;
|
||||
optional int32 instr_address = 8; // for sanity checks
|
||||
required int32 bit_offset = 2;
|
||||
|
||||
// results
|
||||
// make these optional to reduce overhead for server->client communication
|
||||
enum ResultType {
|
||||
CALCDONE = 1;
|
||||
TIMEOUT = 2;
|
||||
TRAP = 3;
|
||||
UNKNOWN = 4;
|
||||
}
|
||||
// instruction pointer where injection was done
|
||||
optional uint32 injection_ip = 3;
|
||||
// result type, see above
|
||||
optional ResultType resulttype = 4;
|
||||
// result data, depending on resulttype:
|
||||
// CALCDONE: resultdata = calculated value
|
||||
// TIMEOUT: resultdata = latest EIP
|
||||
// TRAP: resultdata = latest EIP
|
||||
// UNKNOWN: resultdata = latest EIP
|
||||
optional uint32 resultdata = 5;
|
||||
// did ECC correct the fault?
|
||||
optional int32 error_corrected = 6;
|
||||
// optional textual description of what happened
|
||||
optional string details = 7;
|
||||
}
|
||||
197
core/experiments/coolchecksum/experiment.cc
Normal file
197
core/experiments/coolchecksum/experiment.cc
Normal file
@ -0,0 +1,197 @@
|
||||
#include <iostream>
|
||||
|
||||
#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"
|
||||
|
||||
#if COOL_FAULTSPACE_PRUNING
|
||||
#include "plugins/tracing/TracingPlugin.hpp"
|
||||
#endif
|
||||
|
||||
#include "coolchecksum.pb.h"
|
||||
|
||||
using std::endl;
|
||||
|
||||
bool CoolChecksumExperiment::run()
|
||||
{
|
||||
#if BX_SUPPORT_X86_64
|
||||
int targetreg = sal::RID_RDX;
|
||||
#else
|
||||
int targetreg = sal::RID_EDX;
|
||||
#endif
|
||||
Logger log("CoolChecksum", false);
|
||||
fi::BPEvent bp;
|
||||
|
||||
log << "startup" << endl;
|
||||
|
||||
#if 0
|
||||
// STEP 1: run until interesting function starts, and save state
|
||||
bp.setWatchInstructionPointer(COOL_ECC_FUNC_ENTRY);
|
||||
sal::simulator.addEventAndWait(&bp);
|
||||
log << "test function entry reached, saving state" << endl;
|
||||
log << "EIP = " << std::hex << bp.getTriggerInstructionPointer() << " or " << sal::simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
log << "error_corrected = " << std::dec << ((int)sal::simulator.getMemoryManager().getByte(COOL_ECC_ERROR_CORRECTED)) << endl;
|
||||
sal::simulator.save("coolecc.state");
|
||||
#elif 0
|
||||
|
||||
// STEP 2: determine # instructions from start to end
|
||||
log << "restoring state" << endl;
|
||||
sal::simulator.restore("coolecc.state");
|
||||
log << "EIP = " << std::hex << sal::simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
|
||||
#if COOL_FAULTSPACE_PRUNING
|
||||
// STEP 2.5: Additionally do a golden run with memory access tracing
|
||||
// for fault-space pruning. (optional!)
|
||||
log << "enabling tracing" << endl;
|
||||
TracingPlugin tp;
|
||||
|
||||
// restrict memory access logging to injection target
|
||||
MemoryMap mm;
|
||||
mm.add(COOL_ECC_OBJUNDERTEST, COOL_ECC_OBJUNDERTEST_SIZE);
|
||||
tp.restrictMemoryAddresses(&mm);
|
||||
|
||||
// record trace
|
||||
Trace trace;
|
||||
tp.setTraceMessage(&trace);
|
||||
|
||||
// this must be done *after* configuring the plugin:
|
||||
sal::simulator.addFlow(&tp);
|
||||
#endif
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
sal::simulator.addSuppressedInterrupt(32);
|
||||
|
||||
int count;
|
||||
bp.setWatchInstructionPointer(fi::ANY_ADDR);
|
||||
for (count = 0; bp.getTriggerInstructionPointer() != COOL_ECC_CALCDONE; ++count) {
|
||||
sal::simulator.addEventAndWait(&bp);
|
||||
// log << "EIP = " << std::hex << sal::simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
}
|
||||
log << "test function calculation position reached after " << std::dec << count << " instructions" << endl;
|
||||
log << std::dec << "EDX = " << sal::simulator.getRegisterManager().getRegister(targetreg)->getData() << endl;
|
||||
|
||||
#if COOL_FAULTSPACE_PRUNING
|
||||
sal::simulator.removeFlow(&tp);
|
||||
|
||||
// serialize trace to file
|
||||
std::ofstream of("trace.pb");
|
||||
if (of.fail()) {
|
||||
log << "failed to write trace.pb" << endl;
|
||||
return false;
|
||||
}
|
||||
trace.SerializeToOstream(&of);
|
||||
of.close();
|
||||
#endif
|
||||
|
||||
#elif 1
|
||||
// FIXME consider moving experiment repetition into Fail* or even the
|
||||
// SAL -- whether and how this is possible with the chosen backend is
|
||||
// backend specific
|
||||
for (int i = 0; i < 2000; ++i) {
|
||||
|
||||
// STEP 3: The actual experiment.
|
||||
log << "restoring state" << endl;
|
||||
sal::simulator.restore("coolecc.state");
|
||||
|
||||
log << "asking job server for experiment parameters" << endl;
|
||||
CoolChecksumExperimentData param;
|
||||
if (!m_jc.getParam(param)) {
|
||||
log << "Dying." << endl;
|
||||
// communicate that we were told to die
|
||||
sal::simulator.terminate(1); // "return (false);" ?
|
||||
}
|
||||
int id = param.getWorkloadID();
|
||||
int instr_offset = param.msg.instr_offset();
|
||||
int bit_offset = param.msg.bit_offset();
|
||||
log << "job " << id << " instr " << instr_offset << " bit " << bit_offset << endl;
|
||||
|
||||
// FIXME could be improved (especially for backends supporting
|
||||
// breakpoints natively) by utilizing a previously recorded instruction
|
||||
// trace
|
||||
bp.setWatchInstructionPointer(fi::ANY_ADDR);
|
||||
for (int count = 0; count < instr_offset; ++count) {
|
||||
sal::simulator.addEventAndWait(&bp);
|
||||
}
|
||||
|
||||
// inject
|
||||
sal::guest_address_t inject_addr = COOL_ECC_OBJUNDERTEST + bit_offset / 8;
|
||||
sal::MemoryManager& mm = sal::simulator.getMemoryManager();
|
||||
sal::byte_t data = mm.getByte(inject_addr);
|
||||
sal::byte_t newdata = data ^ (1 << (bit_offset % 8));
|
||||
mm.setByte(inject_addr, newdata);
|
||||
// note at what IP we did it
|
||||
int32_t injection_ip = sal::simulator.getRegisterManager().getInstructionPointer();
|
||||
param.msg.set_injection_ip(injection_ip);
|
||||
log << "inject @ ip " << injection_ip
|
||||
<< " (offset " << std::dec << instr_offset << ")"
|
||||
<< " bit " << bit_offset << ": 0x"
|
||||
<< std::hex << ((int)data) << " -> 0x" << ((int)newdata) << endl;
|
||||
// sanity check (only works if we're working with an instruction trace)
|
||||
if (param.msg.has_instr_address() &&
|
||||
injection_ip != param.msg.instr_address()) {
|
||||
std::stringstream ss;
|
||||
ss << "SANITY CHECK FAILED: " << injection_ip
|
||||
<< " != " << param.msg.instr_address() << endl;
|
||||
log << ss.str();
|
||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||
param.msg.set_resultdata(injection_ip);
|
||||
param.msg.set_details(ss.str());
|
||||
|
||||
sal::simulator.clearEvents();
|
||||
m_jc.sendResult(param);
|
||||
continue;
|
||||
}
|
||||
|
||||
// aftermath
|
||||
fi::BPEvent ev_done(COOL_ECC_CALCDONE);
|
||||
sal::simulator.addEvent(&ev_done);
|
||||
fi::BPEvent ev_timeout(fi::ANY_ADDR);
|
||||
ev_timeout.setCounter(COOL_ECC_NUMINSTR + 3000);
|
||||
sal::simulator.addEvent(&ev_timeout);
|
||||
fi::TrapEvent ev_trap(fi::ANY_TRAP);
|
||||
sal::simulator.addEvent(&ev_trap);
|
||||
|
||||
fi::BaseEvent* ev = sal::simulator.waitAny();
|
||||
if (ev == &ev_done) {
|
||||
int32_t data = sal::simulator.getRegisterManager().getRegister(targetreg)->getData();
|
||||
log << std::dec << "Result EDX = " << data << endl;
|
||||
param.msg.set_resulttype(param.msg.CALCDONE);
|
||||
param.msg.set_resultdata(data);
|
||||
} else if (ev == &ev_timeout) {
|
||||
log << std::dec << "Result TIMEOUT" << endl;
|
||||
param.msg.set_resulttype(param.msg.TIMEOUT);
|
||||
param.msg.set_resultdata(sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
} else if (ev == &ev_trap) {
|
||||
log << std::dec << "Result TRAP #" << ev_trap.getTriggerNumber() << endl;
|
||||
param.msg.set_resulttype(param.msg.TRAP);
|
||||
param.msg.set_resultdata(sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
} else {
|
||||
log << std::dec << "Result WTF?" << endl;
|
||||
param.msg.set_resulttype(param.msg.UNKNOWN);
|
||||
param.msg.set_resultdata(sal::simulator.getRegisterManager().getInstructionPointer());
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "eventid " << ev << " EIP " << sal::simulator.getRegisterManager().getInstructionPointer();
|
||||
param.msg.set_details(ss.str());
|
||||
}
|
||||
sal::simulator.clearEvents();
|
||||
int32_t error_corrected = sal::simulator.getMemoryManager().getByte(COOL_ECC_ERROR_CORRECTED);
|
||||
param.msg.set_error_corrected(error_corrected);
|
||||
m_jc.sendResult(param);
|
||||
}
|
||||
|
||||
// we do not want the simulator to continue running, especially for
|
||||
// headless and distributed experiments
|
||||
sal::simulator.terminate();
|
||||
#endif
|
||||
// simulator continues to run
|
||||
return true;
|
||||
}
|
||||
14
core/experiments/coolchecksum/experiment.hpp
Normal file
14
core/experiments/coolchecksum/experiment.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __COOLEXPERIMENT_HPP__
|
||||
#define __COOLEXPERIMENT_HPP__
|
||||
|
||||
#include "controller/ExperimentFlow.hpp"
|
||||
#include "jobserver/JobClient.hpp"
|
||||
|
||||
class CoolChecksumExperiment : public fi::ExperimentFlow {
|
||||
fi::JobClient m_jc;
|
||||
public:
|
||||
CoolChecksumExperiment() : m_jc("ios.cs.tu-dortmund.de") {}
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif
|
||||
40
core/experiments/coolchecksum/experimentInfo.hpp
Normal file
40
core/experiments/coolchecksum/experimentInfo.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __EXPERIMENT_INFO_HPP__
|
||||
#define __EXPERIMENT_INFO_HPP__
|
||||
|
||||
#define COOL_FAULTSPACE_PRUNING 0
|
||||
|
||||
// FIXME autogenerate this
|
||||
|
||||
#if 1 // with ECC
|
||||
|
||||
// the task function's entry address:
|
||||
// nm -C ecc.elf|fgrep Alpha::functionTaskTask0
|
||||
#define COOL_ECC_FUNC_ENTRY 0x00200b32
|
||||
// one of the last instructions before the task calls printf:
|
||||
// (objdump -Cd ecc.elf|less)
|
||||
#define COOL_ECC_CALCDONE 0x00200bdf
|
||||
// number of instructions the target executes under non-error conditions from ENTRY to CALCDONE:
|
||||
// (result of experiment's step #2)
|
||||
#define COOL_ECC_NUMINSTR 1995
|
||||
// the ECC protected object's address:
|
||||
// nm -C ecc.elf|fgrep objectUnderTest
|
||||
#define COOL_ECC_OBJUNDERTEST 0x002127a4
|
||||
// the ECC protected object's payload size:
|
||||
// (we know that from the object's definition and usual memory layout)
|
||||
#define COOL_ECC_OBJUNDERTEST_SIZE 10
|
||||
// the variable that's increased if ECC corrects an error:
|
||||
// nm -C ecc.elf|fgrep error_corrected
|
||||
#define COOL_ECC_ERROR_CORRECTED 0x002127b0
|
||||
|
||||
#else // without ECC
|
||||
|
||||
#define COOL_ECC_FUNC_ENTRY 0x00200a90
|
||||
#define COOL_ECC_CALCDONE 0x00200ab7
|
||||
#define COOL_ECC_NUMINSTR 97
|
||||
#define COOL_ECC_OBJUNDERTEST 0x0021263c
|
||||
#define COOL_ECC_OBJUNDERTEST_SIZE 10
|
||||
#define COOL_ECC_ERROR_CORRECTED 0x002127b0 // dummy
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
15
core/experiments/coolchecksum/main.cc
Normal file
15
core/experiments/coolchecksum/main.cc
Normal file
@ -0,0 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "controller/CampaignManager.hpp"
|
||||
#include "experiments/coolchecksum/campaign.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CoolChecksumCampaign c;
|
||||
if (fi::campaignmanager.runCampaign(&c)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
17
core/experiments/hscsimple/CMakeLists.txt
Normal file
17
core/experiments/hscsimple/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
set(EXPERIMENT_NAME hscsimple)
|
||||
set(EXPERIMENT_TYPE hscsimpleExperiment)
|
||||
configure_file(../instantiate-experiment.ah.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/instantiate-${EXPERIMENT_NAME}.ah @ONLY
|
||||
)
|
||||
|
||||
#experiment sources
|
||||
set(MY_EXPERIMENT_SRCS
|
||||
experiment.hpp
|
||||
experiment.cc
|
||||
)
|
||||
|
||||
#### include directories ####
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
## build library
|
||||
add_library(${EXPERIMENT_NAME} ${MY_EXPERIMENT_SRCS})
|
||||
49
core/experiments/hscsimple/experiment.cc
Normal file
49
core/experiments/hscsimple/experiment.cc
Normal file
@ -0,0 +1,49 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "experiment.hpp"
|
||||
#include "SAL/SALInst.hpp"
|
||||
#include "SAL/bochs/BochsRegister.hpp"
|
||||
#include "controller/Event.hpp"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
bool hscsimpleExperiment::run()
|
||||
{
|
||||
cout << "[HSC] experiment start" << endl;
|
||||
|
||||
// do funny things here...
|
||||
#if 0
|
||||
fi::BPEvent mainbp(0x00003c34);
|
||||
sal::simulator.addEventAndWait(&mainbp);
|
||||
cout << "[HSC] breakpoint reached, saving" << endl;
|
||||
sal::simulator.save("hello.main");
|
||||
#elif 1
|
||||
cout << "[HSC] restoring ..." << endl;
|
||||
sal::simulator.restore("hello.main");
|
||||
cout << "[HSC] restored!" << endl;
|
||||
|
||||
cout << "[HSC] waiting for last square() instruction" << endl;
|
||||
fi::BPEvent breakpoint(0x3c9e); // square(x) ret instruction
|
||||
sal::simulator.addEventAndWait(&breakpoint);
|
||||
cout << "[HSC] injecting hellish fault" << endl;
|
||||
#if BX_SUPPORT_X86_64
|
||||
int reg = sal::RID_RAX;
|
||||
#else
|
||||
int reg = sal::RID_EAX;
|
||||
#endif
|
||||
sal::simulator.getRegisterManager().getSetOfType(sal::RT_GP).getRegister(reg)->setData(666);
|
||||
cout << "[HSC] waiting for last main() instruction" << endl;
|
||||
breakpoint.setWatchInstructionPointer(0x3c92);
|
||||
sal::simulator.addEventAndWait(&breakpoint);
|
||||
|
||||
cout << "[HSC] reached" << endl;
|
||||
|
||||
// FIXME this shouldn't fail:
|
||||
sal::simulator.addEventAndWait(&breakpoint);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
14
core/experiments/hscsimple/experiment.hpp
Normal file
14
core/experiments/hscsimple/experiment.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __HSCSIMPLE_EXPERIMENT_HPP__
|
||||
#define __HSCSIMPLE_EXPERIMENT_HPP__
|
||||
|
||||
#include "controller/ExperimentFlow.hpp"
|
||||
|
||||
class hscsimpleExperiment : public fi::ExperimentFlow
|
||||
{
|
||||
public:
|
||||
hscsimpleExperiment() { }
|
||||
|
||||
bool run();
|
||||
};
|
||||
|
||||
#endif // __HSCSIMPLE_EXPERIMENT_HPP__
|
||||
19
core/experiments/instantiate-experiment.ah.in
Normal file
19
core/experiments/instantiate-experiment.ah.in
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef __INSTANTIATE_@EXPERIMENT_TYPE@_AH__
|
||||
#define __INSTANTIATE_@EXPERIMENT_TYPE@_AH__
|
||||
|
||||
// FIXME: cmake does not remove these .ah files when the user configures
|
||||
// another experiment (or even makes "clean"). Currently, this needs to be
|
||||
// worked around by manually removing $BUILDDIR/core/experiments/*/*.ah .
|
||||
|
||||
// Make sure your experiment declaration is in experiment.hpp:
|
||||
#include "experiments/@EXPERIMENT_NAME@/experiment.hpp"
|
||||
#include "SAL/SALInst.hpp"
|
||||
|
||||
aspect @EXPERIMENT_TYPE@ExperimentHook {
|
||||
@EXPERIMENT_TYPE@ experiment;
|
||||
advice execution ("void sal::SimulatorController::initExperiments()") : after () {
|
||||
sal::simulator.addFlow(&experiment);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __INSTANTIATE_@EXPERIMENT_TYPE@_AH__
|
||||
Reference in New Issue
Block a user