Introduces instruction filtering, e.g. to filter for kernel instructions

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1864 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
unzner
2012-10-30 09:14:33 +00:00
parent 247fed5aa7
commit 7ae8b6b09d
8 changed files with 151 additions and 96 deletions

View File

@ -9,6 +9,7 @@
#include "experiment.hpp"
#include "experimentInfo.hpp"
#include "UDIS86.hpp"
#include "InstructionFilter.hpp"
#include "aluinstr.hpp"
#include "campaign.hpp"
@ -32,16 +33,9 @@ using namespace fail;
save, and restore. Enable these in the configuration.
#endif
typedef struct __trace_instr_type {
fail::address_t trigger_addr;
unsigned bp_counter;
} trace_instr;
string output;
#if 0
//disabled (see "STEP 2" below)
vector<trace_instr> instr_list;
vector<trace_instr> alu_instr_list;
#ifdef L4SYS_FILTER_INSTRUCTIONS
TraceVector instr_list;
#endif
string golden_run;
@ -131,17 +125,6 @@ void L4SysExperiment::logInjection(Logger &log,
<< ")" << " bit " << bit_offset << endl;
}
void L4SysExperiment::readFromFileToVector(std::ifstream &file,
std::vector<trace_instr> &instr_list) {
file >> hex;
while (!file.eof()) {
trace_instr curr_instr;
file.read(reinterpret_cast<char*>(&curr_instr), sizeof(trace_instr));
instr_list.push_back(curr_instr);
}
file.close();
}
void L4SysExperiment::singleStep() {
BPSingleListener singlestepping_event(ANY_ADDR, L4SYS_ADDRESS_SPACE);
simulator.addListener(&singlestepping_event);
@ -195,6 +178,45 @@ bool L4SysExperiment::run() {
<< simulator.getRegisterManager().getInstructionPointer()
<< endl;
#ifdef L4SYS_FILTER_INSTRUCTIONS
ofstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::out | ios::binary);
bp.setWatchInstructionPointer(ANY_ADDR);
size_t count = 0, accepted = 0;
map<address_t, unsigned> times_called_map;
InstructionFilter *instrFilter = NULL;
#if defined(L4SYS_ADDRESS_LBOUND) && defined(L4SYS_ADDRESS_UBOUND)
instrFilter = new RangeInstructionFilter(L4SYS_ADDRESS_LBOUND, L4SYS_ADDRESS_UBOUND);
#endif
while (bp.getTriggerInstructionPointer() != L4SYS_FUNC_EXIT) {
simulator.addListenerAndResume(&bp);
count++;
//short sanity check
address_t curr_addr = bp.getTriggerInstructionPointer();
assert(
curr_addr == simulator.getRegisterManager().getInstructionPointer());
unsigned times_called = times_called_map[curr_addr];
times_called++;
times_called_map[curr_addr] = times_called;
// now check if we want to add the instruction for fault injection
if (instrFilter != NULL &&
instrFilter->isValidInstr(curr_addr, simulator.getCurrentInstruction())) {
accepted++;
TraceInstr new_instr;
new_instr.trigger_addr = curr_addr;
new_instr.bp_counter = times_called;
instr_list_file.write(reinterpret_cast<char*>(&new_instr), sizeof(TraceInstr));
}
}
delete instrFilter;
log << "saving instructions triggered during normal execution" << endl;
instr_list_file.close();
log << "test function calculation position reached after "
<< dec << count << " instructions; " << accepted << " accepted" << endl;
#else
int count = 0;
int ul = 0, kernel = 0;
bp.setWatchInstructionPointer(ANY_ADDR);
@ -211,6 +233,8 @@ bool L4SysExperiment::run() {
log << "test function calculation position reached after "
<< dec << count << " instructions; "
<< "ul: " << ul << ", kernel: " << kernel << endl;
#endif
#elif PREPARATION_STEP == 3
// STEP 3: determine the output of a "golden run"
log << "restoring state" << endl;
@ -239,68 +263,6 @@ bool L4SysExperiment::run() {
log << "saving output generated during normal execution" << endl;
golden_run_file.close();
#if 0
// the files currently get too big.
/* I do not really have a clever idea to solve this.
* You would probably need some kind of loop detection,
* but for the moment, I have to focus on different issues.
*/
if (stat(L4SYS_INSTRUCTION_LIST, &teststruct) == -1 ||
stat(L4SYS_ALU_INSTRUCTIONS, &teststruct) == -1) {
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);
ofstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::out | ios::binary);
ofstream alu_instr_file(L4SYS_ALU_INSTRUCTIONS, ios::out | ios::binary);
bp.setWatchInstructionPointer(ANY_ADDR);
map<address_t, unsigned> times_called_map;
while (bp.getTriggerInstructionPointer() != L4SYS_FUNC_EXIT) {
simulator.addListenerAndResume(&bp);
//short sanity check
address_t curr_addr = bp.getTriggerInstructionPointer();
assert(
curr_addr == simulator.getRegisterManager().getInstructionPointer());
unsigned times_called = times_called_map[curr_addr];
times_called++;
times_called_map[curr_addr] = times_called;
trace_instr new_instr;
new_instr.trigger_addr = curr_addr;
new_instr.bp_counter = times_called;
instr_list.push_back(new_instr);
instr_list_file.write(reinterpret_cast<char*>(&new_instr), sizeof(trace_instr));
// ALU instructions
// decode the instruction
bxInstruction_c instr;
fetchInstruction(simulator.getCPUContext(), calculateInstructionAddress(), &instr);
// add it to a second list if it is an ALU instruction
if (isALUInstruction(instr.getIaOpcode())) {
alu_instr_list.push_back(new_instr);
alu_instr_file.write(reinterpret_cast<char*>(&new_instr), sizeof(trace_instr));
}
}
log << "saving instructions triggered during normal execution" << endl;
alu_instr_file.close();
instr_list_file.close();
} else {
ifstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::in | ios::binary);
ifstream alu_instr_file(L4SYS_ALU_INSTRUCTIONS, ios::in | ios::binary);
readFromFileToVector(instr_list_file, instr_list);
readFromFileToVector(alu_instr_file, alu_instr_list);
}
#endif
#elif PREPARATION_STEP == 0
// LAST STEP: The actual experiment.
struct stat teststruct;
@ -322,6 +284,21 @@ bool L4SysExperiment::run() {
golden_run_file.close();
#ifdef L4SYS_FILTER_INSTRUCTIONS
ifstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::in | ios::binary);
if (!instr_list_file.good()) {
log << "Missing instruction trace" << endl;
simulator.terminate(21);
}
while (!instr_list_file.eof()) {
TraceInstr curr_instr;
instr_list_file.read(reinterpret_cast<char*>(&curr_instr), sizeof(TraceInstr));
instr_list.push_back(curr_instr);
}
instr_list_file.close();
#endif
//the generated output probably has a similar length
output.reserve(teststruct.st_size);
@ -340,8 +317,13 @@ bool L4SysExperiment::run() {
int bit_offset = param.msg.bit_offset();
int exp_type = param.msg.exp_type();
#ifdef L4SYS_FILTER_INSTRUCTIONS
bp.setWatchInstructionPointer(instr_list[instr_offset].trigger_addr);
bp.setCounter(instr_list[instr_offset].bp_counter);
#else
bp.setWatchInstructionPointer(ANY_ADDR);
bp.setCounter(instr_offset + 1);
bp.setCounter(instr_offset);
#endif
simulator.addListener(&bp);
//and log the output
waitIOOrOther(true);
@ -351,8 +333,8 @@ bool L4SysExperiment::run() {
simulator.getRegisterManager().getInstructionPointer();
param.msg.set_injection_ip(injection_ip);
#if 0
// temporarily out of order (see above)
#ifdef L4SYS_FILTER_INSTRUCTIONS
// only works if we filter instructions
// sanity check (only works if we're working with an instruction trace)
if (injection_ip != instr_list[instr_offset].trigger_addr) {
stringstream ss;