Changes I made in the l4-sys experiment recently, plus one minor style fix
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1584 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -164,19 +164,16 @@ void JobServer::run()
|
||||
// Spawn a thread for further communication,
|
||||
// and add this thread to a list threads
|
||||
// We can limit the generation of threads here.
|
||||
if (m_threadlist.size() < m_maxThreads) {
|
||||
th = new boost::thread(CommThread(cs, *this));
|
||||
m_threadlist.push_back(th);
|
||||
} else {
|
||||
if (m_threadlist.size() >= m_maxThreads) {
|
||||
// Run over list with a timed_join,
|
||||
// removing finished threads.
|
||||
do {
|
||||
m_threadlist.remove_if(timed_join_successful(m_threadtimeout));
|
||||
} while(m_threadlist.size() == m_maxThreads);
|
||||
}
|
||||
// Start new thread
|
||||
th = new boost::thread(CommThread(cs, *this));
|
||||
m_threadlist.push_back(th);
|
||||
}
|
||||
|
||||
}
|
||||
close(s);
|
||||
|
||||
@ -1,22 +1,26 @@
|
||||
#if 0
|
||||
// temporarily disabled to make the code in the repository compile - will soon be fixed
|
||||
#include "sal/bochs/BochsController.hpp"
|
||||
#include "UDIS86.hpp"
|
||||
|
||||
using namespace fail;
|
||||
|
||||
Udis86::Udis86(const unsigned char *instr, size_t size) {
|
||||
Udis86::Udis86(const unsigned char *instr, size_t size, address_t ip) {
|
||||
// initialise the buffer
|
||||
unsigned char *udis_instr = static_cast<unsigned char*>(malloc(size));
|
||||
memcpy(udis_instr, instr, size);
|
||||
udis_instr_size = size;
|
||||
udis_instr = static_cast<unsigned char*>(malloc(udis_instr_size));
|
||||
memcpy(udis_instr, instr, udis_instr_size);
|
||||
|
||||
// initialise the internal data structure
|
||||
memset(&ud_obj, 0, sizeof(ud_t));
|
||||
ud_init(&ud_obj);
|
||||
ud_set_mode(&ud_obj, 32);
|
||||
ud_set_syntax(&ud_obj, UD_SYN_ATT);
|
||||
ud_set_pc(&ud_obj, ip);
|
||||
|
||||
// assign the buffer to the data structure
|
||||
ud_set_input_buffer(&ud_obj, udis_instr, size);
|
||||
ud_set_input_buffer(&ud_obj, udis_instr, udis_instr_size);
|
||||
}
|
||||
|
||||
Udis86::~Udis86() {
|
||||
// free the buffer
|
||||
free(udis_instr);
|
||||
}
|
||||
@ -60,4 +64,3 @@ GPRegisterId Udis86::udisGPRToFailBochsGPR(ud_type_t udisReg) {
|
||||
}
|
||||
#undef REG_CASE
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
#if 0
|
||||
// temporarily disabled to make the code in the repository compile - will soon be fixed
|
||||
#ifndef __UDIS86_HPP__
|
||||
#define __UDIS86_HPP__
|
||||
|
||||
@ -19,8 +17,11 @@ class Udis86
|
||||
{
|
||||
private:
|
||||
ud_t ud_obj; //<! the ud object of udis86
|
||||
unsigned char *udis_instr; //<! the instruction buffer for UDIs86
|
||||
size_t udis_instr_size; //<! the size of the instruction buffer
|
||||
public:
|
||||
Udis86(const unsigned char *instr, size_t size);
|
||||
Udis86(const unsigned char *instr, size_t size, fail::address_t ip);
|
||||
~Udis86();
|
||||
/**
|
||||
* retrieves the private ud structure of udis86
|
||||
* @returns a reference pointer to a ud_t variable
|
||||
@ -41,4 +42,3 @@ public:
|
||||
};
|
||||
|
||||
#endif // __UDIS86_HPP__
|
||||
#endif
|
||||
|
||||
@ -11,10 +11,11 @@ using namespace std;
|
||||
using namespace fail;
|
||||
|
||||
char const * const results_csv = "l4sys.csv";
|
||||
const char *l4sys_output_strings[] = { "Unknown", "Done", "Timeout", "Trap", "Interrupt", "Wrong output", "Error" };
|
||||
const char *l4sys_output_result_strings[] = { "Unknown", "Done", "Timeout", "Trap", "Interrupt", "Wrong output", "Error" };
|
||||
const char *l4sys_output_experiment_strings[] = { "Unknown", "GPR Flip", "RAT Flip", "Instr Flip", "ALU Instr Flip" };
|
||||
|
||||
#define OUTPUT_CASE(OUTPUT) case L4SysProtoMsg::OUTPUT: return l4sys_output_result_strings[L4SysProtoMsg::OUTPUT];
|
||||
std::string L4SysCampaign::output_result(L4SysProtoMsg_ResultType res) {
|
||||
#define OUTPUT_CASE(OUTPUT) case L4SysProtoMsg::OUTPUT: return l4sys_output_strings[L4SysProtoMsg::OUTPUT];
|
||||
switch (res) {
|
||||
OUTPUT_CASE(DONE);
|
||||
OUTPUT_CASE(TIMEOUT);
|
||||
@ -23,10 +24,22 @@ std::string L4SysCampaign::output_result(L4SysProtoMsg_ResultType res) {
|
||||
OUTPUT_CASE(WRONG);
|
||||
OUTPUT_CASE(UNKNOWN);
|
||||
default:
|
||||
return l4sys_output_strings[0];
|
||||
return l4sys_output_result_strings[0];
|
||||
}
|
||||
#undef OUTPUT_CASE
|
||||
}
|
||||
#undef OUTPUT_CASE
|
||||
#define OUTPUT_CASE(OUTPUT) case L4SysProtoMsg::OUTPUT: return l4sys_output_experiment_strings[L4SysProtoMsg::OUTPUT];
|
||||
std::string L4SysCampaign::output_experiment(L4SysProtoMsg_ExperimentType res) {
|
||||
switch (res) {
|
||||
OUTPUT_CASE(GPRFLIP)
|
||||
OUTPUT_CASE(RATFLIP)
|
||||
OUTPUT_CASE(IDCFLIP)
|
||||
OUTPUT_CASE(ALUINSTR)
|
||||
default:
|
||||
return l4sys_output_experiment_strings[0];
|
||||
}
|
||||
}
|
||||
#undef OUTPUT_CASE
|
||||
|
||||
bool L4SysCampaign::run() {
|
||||
Logger log("L4SysCampaign");
|
||||
@ -48,17 +61,46 @@ bool L4SysCampaign::run() {
|
||||
|
||||
int count = 0;
|
||||
srand(time(NULL));
|
||||
for (int i = 0; i < 3000; ++i) {
|
||||
for (int i = 0; i < 25; ++i) {
|
||||
L4SysExperimentData *d = new L4SysExperimentData;
|
||||
d->msg.set_exp_type(d->msg.RATFLIP);
|
||||
d->msg.set_instr_offset(rand() % L4SYS_NUMINSTR);
|
||||
// 15 bytes (120 bits) are the longest instruction Bochs still executes
|
||||
int bit_offset = rand() % 120;
|
||||
d->msg.set_exp_type(d->msg.GPRFLIP);
|
||||
// modify for a random instruction
|
||||
int instr_offset = rand() % L4SYS_NUMINSTR;
|
||||
d->msg.set_instr_offset(instr_offset);
|
||||
// modify a random bit
|
||||
int bit_offset = rand() % 32;
|
||||
d->msg.set_bit_offset(bit_offset);
|
||||
|
||||
campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
#if 0
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
L4SysExperimentData *d = new L4SysExperimentData;
|
||||
d->msg.set_exp_type(d->msg.RATFLIP);
|
||||
// modify for a random instruction
|
||||
int instr_offset = rand() % L4SYS_NUMINSTR;
|
||||
d->msg.set_instr_offset(instr_offset);
|
||||
// this value is not required for this experiment, so set it to an arbitrary value
|
||||
d->msg.set_bit_offset(0);
|
||||
|
||||
campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
L4SysExperimentData *d = new L4SysExperimentData;
|
||||
d->msg.set_exp_type(d->msg.IDCFLIP);
|
||||
// modify for a random instruction
|
||||
int instr_offset = rand() % L4SYS_NUMINSTR;
|
||||
d->msg.set_instr_offset(instr_offset);
|
||||
// modify a random bit - Bochs supports at most 15 bytes of instruction
|
||||
int bit_offset = rand() % 125;
|
||||
d->msg.set_bit_offset(bit_offset);
|
||||
|
||||
campaignmanager.addParam(d);
|
||||
++count;
|
||||
}
|
||||
#endif
|
||||
campaignmanager.noMoreParameters();
|
||||
log << "done enqueueing parameter sets (" << count << ")." << endl;
|
||||
|
||||
@ -66,12 +108,12 @@ bool L4SysCampaign::run() {
|
||||
L4SysExperimentData *res;
|
||||
int rescount = 0;
|
||||
results
|
||||
<< "injection_ip,instr_offset,injection_bit,resulttype,resultdata,output,details"
|
||||
<< "exp_type,injection_ip,instr_offset,injection_bit,resulttype,resultdata,output,details"
|
||||
<< endl;
|
||||
while ((res = static_cast<L4SysExperimentData *>(campaignmanager.getDone()))) {
|
||||
rescount++;
|
||||
|
||||
results << hex << res->msg.injection_ip() << "," << dec
|
||||
results << output_experiment(res->msg.exp_type()) << "," << hex << res->msg.injection_ip() << "," << dec
|
||||
<< res->msg.instr_offset() << "," << res->msg.bit_offset()
|
||||
<< "," << output_result(res->msg.resulttype()) << ","
|
||||
<< res->msg.resultdata();
|
||||
|
||||
@ -16,6 +16,7 @@ public:
|
||||
virtual bool run();
|
||||
private:
|
||||
std::string output_result(L4SysProtoMsg_ResultType res);
|
||||
std::string output_experiment(L4SysProtoMsg_ExperimentType res);
|
||||
};
|
||||
|
||||
#endif // __L4SYS_CAMPAIGN_HPP__
|
||||
|
||||
@ -56,7 +56,8 @@ string L4SysExperiment::sanitised(const string &in_str) {
|
||||
for (int idx = 0; idx < in_str_size; idx++) {
|
||||
char cur_char = in_str[idx];
|
||||
unsigned cur_char_value = static_cast<unsigned>(cur_char);
|
||||
if (cur_char_value < 0x20 || cur_char_value > 0x7E) {
|
||||
// also exclude the delimiter (',')
|
||||
if (cur_char_value < 0x20 || cur_char_value > 0x7E || cur_char_value == ',') {
|
||||
char str_nr[5];
|
||||
sprintf(str_nr, "\\%03o", cur_char_value);
|
||||
result += str_nr;
|
||||
@ -145,21 +146,11 @@ void L4SysExperiment::readFromFileToVector(std::ifstream &file,
|
||||
file.close();
|
||||
}
|
||||
|
||||
void L4SysExperiment::changeBochsInstruction(bxInstruction_c *dest,
|
||||
bxInstruction_c *src) {
|
||||
// backup the current and insert the faulty instruction
|
||||
bxInstruction_c old_instr;
|
||||
memcpy(&old_instr, dest, sizeof(bxInstruction_c));
|
||||
memcpy(dest, src, sizeof(bxInstruction_c));
|
||||
|
||||
// execute the faulty instruction, then return
|
||||
void L4SysExperiment::singleStep() {
|
||||
BPSingleListener singlestepping_event(ANY_ADDR, L4SYS_ADDRESS_SPACE);
|
||||
simulator.addListener(&singlestepping_event);
|
||||
waitIOOrOther(false);
|
||||
simulator.removeListener(&singlestepping_event);
|
||||
|
||||
//restore the old instruction
|
||||
memcpy(dest, &old_instr, sizeof(bxInstruction_c));
|
||||
}
|
||||
|
||||
bool L4SysExperiment::run() {
|
||||
@ -183,6 +174,31 @@ bool L4SysExperiment::run() {
|
||||
}
|
||||
|
||||
// STEP 2: determine instructions executed
|
||||
#ifdef PREPARE_EXPERIMENT
|
||||
log << "restoring state" << endl;
|
||||
simulator.restore(L4SYS_STATE_FOLDER);
|
||||
log << "EIP = " << hex
|
||||
<< simulator.getRegisterManager().getInstructionPointer()
|
||||
<< endl;
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
simulator.addSuppressedInterrupt(0);
|
||||
|
||||
int count;
|
||||
int ul = 0, kernel = 0;
|
||||
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||
for (count = 0; bp.getTriggerInstructionPointer() != L4SYS_FUNC_EXIT; ++count) {
|
||||
simulator.addListenerAndResume(&bp);
|
||||
if(bp.getTriggerInstructionPointer() < 0xC0000000) {
|
||||
ul++;
|
||||
} else {
|
||||
kernel++;
|
||||
}
|
||||
// log << "EIP = " << hex << simulator.getRegisterManager().getInstructionPointer() << endl;
|
||||
}
|
||||
log << "test function calculation position reached after " << dec << count << " instructions; "
|
||||
<< "ul: " << ul << ", kernel: " << kernel << endl;
|
||||
#else
|
||||
#if 0
|
||||
// the files currently get too big.
|
||||
/* I do not really have a clever idea to solve this.
|
||||
@ -197,7 +213,7 @@ bool L4SysExperiment::run() {
|
||||
<< endl;
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
simulator.addSuppressedInterrupt(32);
|
||||
simulator.addSuppressedInterrupt(0);
|
||||
|
||||
ofstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::out | ios::binary);
|
||||
ofstream alu_instr_file(L4SYS_ALU_INSTRUCTIONS, ios::out | ios::binary);
|
||||
@ -253,7 +269,7 @@ bool L4SysExperiment::run() {
|
||||
<< endl;
|
||||
|
||||
// make sure the timer interrupt doesn't disturb us
|
||||
simulator.addSuppressedInterrupt(32);
|
||||
simulator.addSuppressedInterrupt(0);
|
||||
|
||||
ofstream golden_run_file(L4SYS_CORRECT_OUTPUT);
|
||||
bp.setWatchInstructionPointer(L4SYS_FUNC_EXIT);
|
||||
@ -306,7 +322,7 @@ bool L4SysExperiment::run() {
|
||||
int exp_type = param.msg.exp_type();
|
||||
|
||||
bp.setWatchInstructionPointer(ANY_ADDR);
|
||||
bp.setCounter(instr_offset);
|
||||
bp.setCounter(instr_offset + 1);
|
||||
simulator.addListener(&bp);
|
||||
//and log the output
|
||||
waitIOOrOther(true);
|
||||
@ -350,7 +366,7 @@ bool L4SysExperiment::run() {
|
||||
// this is a twisted one
|
||||
|
||||
// initial definitions
|
||||
bxICacheEntry_c *cache_entry = simulator.getICacheEntry();
|
||||
bxICacheEntry_c *cache_entry = simulator.getCPUContext()->getICacheEntry();
|
||||
unsigned length_in_bits = cache_entry->i->ilen() << 3;
|
||||
|
||||
// get the instruction in plain text in inject the error there
|
||||
@ -380,15 +396,22 @@ bool L4SysExperiment::run() {
|
||||
&bochs_instr);
|
||||
|
||||
// inject it
|
||||
changeBochsInstruction(cache_entry->i, &bochs_instr);
|
||||
// backup the current and insert the faulty instruction
|
||||
bxInstruction_c old_instr;
|
||||
memcpy(&old_instr, cache_entry->i, sizeof(bxInstruction_c));
|
||||
memcpy(cache_entry->i, &bochs_instr, sizeof(bxInstruction_c));
|
||||
|
||||
// execute the faulty instruction, then return
|
||||
singleStep();
|
||||
|
||||
//restore the old instruction
|
||||
memcpy(cache_entry->i, &old_instr, sizeof(bxInstruction_c));
|
||||
|
||||
// do the logging
|
||||
logInjection(log, param);
|
||||
} else if (exp_type == param.msg.RATFLIP) {
|
||||
#if 0
|
||||
// temporarily disabled to make the code in the repository compile - will soon be fixed
|
||||
bxICacheEntry_c *cache_entry = simulator.getICacheEntry();
|
||||
Udis86 udis(calculateInstructionAddress(), cache_entry->i->ilen());
|
||||
bxICacheEntry_c *cache_entry = simulator.getCPUContext()->getICacheEntry();
|
||||
Udis86 udis(calculateInstructionAddress(), cache_entry->i->ilen(), injection_ip);
|
||||
if (udis.fetchNextInstruction()) {
|
||||
ud_t _ud = udis.getCurrentState();
|
||||
|
||||
@ -422,7 +445,12 @@ bool L4SysExperiment::run() {
|
||||
}
|
||||
|
||||
ud_type_t which;
|
||||
unsigned rnd = random() % opcount;
|
||||
unsigned rnd;
|
||||
if(opcount == 0)
|
||||
rnd = 0;
|
||||
else
|
||||
rnd = rand() % opcount;
|
||||
|
||||
if (operands[rnd] > RAT_IDX_OFFSET) {
|
||||
which = _ud.operand[operands[rnd] - RAT_IDX_OFFSET].index;
|
||||
} else {
|
||||
@ -464,30 +492,23 @@ bool L4SysExperiment::run() {
|
||||
}
|
||||
|
||||
// execute the instruction
|
||||
BPSingleListener execute_single_instr(ANY_INSTR, L4SYS_ADDRESS_SPACE);
|
||||
simulator.addListener(&execute_single_instr);
|
||||
waitIOOrOther(false);
|
||||
simulator.removeListener(&execute_single_instr);
|
||||
singleStep();
|
||||
|
||||
// restore
|
||||
if (rnd > 0) {
|
||||
// restore input register
|
||||
rm.getRegister(bochs_reg)->setData(data);
|
||||
} else if (rnd == 0) {
|
||||
if (rnd == 0) {
|
||||
// output register - do the fault injection here
|
||||
if(exchg_reg >= 0) {
|
||||
// write the result into the wrong local register
|
||||
regdata_t newdata = rm.getRegister(bochs_reg)->getData();
|
||||
rm.getRegister(exchg_reg)->setData(newdata);
|
||||
}
|
||||
// restore the value of the actual output register
|
||||
// in reality, it would never have been overwritten
|
||||
rm.getRegister(bochs_reg)->setData(data);
|
||||
}
|
||||
// restore the actual value of the register
|
||||
// in reality, it would never have been overwritten
|
||||
rm.getRegister(bochs_reg)->setData(data);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
} else if (exp_type == param.msg.ALUINSTR) {
|
||||
}
|
||||
|
||||
@ -560,7 +581,7 @@ bool L4SysExperiment::run() {
|
||||
|
||||
simulator.clearListeners();
|
||||
m_jc.sendResult(param);
|
||||
|
||||
#endif
|
||||
#ifdef HEADLESS_EXPERIMENT
|
||||
simulator.terminate(0);
|
||||
#endif
|
||||
|
||||
@ -59,15 +59,13 @@ private:
|
||||
*/
|
||||
void logInjection(fail::Logger &log, const L4SysExperimentData ¶m);
|
||||
/**
|
||||
* May be obsolete. Not supplying docu until I am sure whether I need to
|
||||
* May be obsolete. Not supplying doc until I am sure whether I need to
|
||||
*/
|
||||
void readFromFileToVector(std::ifstream &file, std::vector<struct __trace_instr_type> &instr_list);
|
||||
/**
|
||||
* Overwrites one Bochs instruction with another.
|
||||
* @param dest the instruction to copy to
|
||||
* @param src the instruction to copy from
|
||||
* Proceeds by one single instruction.
|
||||
*/
|
||||
void changeBochsInstruction(bxInstruction_c *dest, bxInstruction_c *src);
|
||||
void singleStep();
|
||||
};
|
||||
|
||||
#endif // __L4SYS_EXPERIMENT_HPP__
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#define L4SYS_ADDRESS_SPACE 0x203d000
|
||||
#define L4SYS_FUNC_ENTRY 0x1000400
|
||||
#define L4SYS_FUNC_EXIT 0x10005b0
|
||||
#define L4SYS_NUMINSTR 56052772
|
||||
#define L4SYS_NUMINSTR 56052774
|
||||
|
||||
#define L4SYS_ITERATION_COUNT 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user