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:
unzner
2012-09-01 16:05:22 +00:00
parent 1e53a7c0de
commit d9b24a7c60
8 changed files with 130 additions and 68 deletions

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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__

View File

@ -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

View File

@ -59,15 +59,13 @@ private:
*/
void logInjection(fail::Logger &log, const L4SysExperimentData &param);
/**
* 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__

View File

@ -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