Rework instruction filtering
Add a new instruction filter that allows filtering a list of ranges read from a file. This allows us to specify multiple ranges, e.g., to leave out instructions or to focus on multiple functions Change-Id: Iba13cda00d0a73edaef270b3cd9100afe3e4668b
This commit is contained in:
@ -1,4 +1,44 @@
|
||||
#include "InstructionFilter.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include <fstream>
|
||||
|
||||
// for more complex filters yet to come
|
||||
|
||||
/**
|
||||
* Determine how many bytes are left in this file.
|
||||
*/
|
||||
static inline unsigned
|
||||
getFileBytesLeft(std::ifstream& f)
|
||||
{
|
||||
// get pos, seek to end, return difference
|
||||
std::streampos pos = f.tellg();
|
||||
f.seekg(0, std::ios::end);
|
||||
std::streampos end = f.tellg();
|
||||
|
||||
// and don't forget to reset the seek pos
|
||||
f.seekg(pos, std::ios::beg);
|
||||
|
||||
return end - pos;
|
||||
}
|
||||
|
||||
|
||||
RangeSetInstructionFilter::RangeSetInstructionFilter(char const *filename)
|
||||
: _filters()
|
||||
{
|
||||
fail::Logger log("RangeSet", false);
|
||||
|
||||
std::ifstream filterFile(filename, std::ios::in);
|
||||
if (!filterFile.is_open()) {
|
||||
log << filename << " not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
while (getFileBytesLeft(filterFile) > 1) {
|
||||
address_t start, end;
|
||||
filterFile >> std::hex >> start;
|
||||
filterFile >> std::hex >> end;
|
||||
log << "new filter range: " << std::hex
|
||||
<< start << " - " << end << std::endl;
|
||||
addFilter(start, end);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "sal/SALConfig.hpp"
|
||||
#include "cpu/instr.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace fail;
|
||||
|
||||
@ -54,4 +55,34 @@ private:
|
||||
address_t endAddress; //<! the end of the address range
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class RangeSetInstructionFilter
|
||||
*
|
||||
* Collects a list of filter ranges from an input file.
|
||||
*/
|
||||
class RangeSetInstructionFilter : public InstructionFilter {
|
||||
private:
|
||||
std::vector<RangeInstructionFilter> _filters;
|
||||
|
||||
public:
|
||||
RangeSetInstructionFilter(char const *filename);
|
||||
~RangeSetInstructionFilter() {}
|
||||
|
||||
bool isValidInstr(address_t ip, char const *instr) const
|
||||
{
|
||||
std::vector<RangeInstructionFilter>::const_iterator it;
|
||||
for (it = _filters.begin(); it != _filters.end(); ++it) {
|
||||
if (it->isValidInstr(ip, instr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void addFilter(address_t startAddr, address_t endAddr)
|
||||
{
|
||||
_filters.push_back(RangeInstructionFilter(startAddr, endAddr));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __L4SYS_INSTRUCTIONFILTER_HPP__ */
|
||||
|
||||
@ -228,14 +228,12 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener& bp)
|
||||
|
||||
#ifdef L4SYS_FILTER_INSTRUCTIONS
|
||||
ofstream instr_list_file(L4SYS_INSTRUCTION_LIST, ios::binary);
|
||||
RangeSetInstructionFilter rsif(L4SYS_FILTER);
|
||||
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++;
|
||||
@ -249,9 +247,8 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener& bp)
|
||||
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,
|
||||
reinterpret_cast<char const*>(calculateInstructionAddress()))) {
|
||||
if (rsif.isValidInstr(curr_addr,
|
||||
reinterpret_cast<char const*>(calculateInstructionAddress()))) {
|
||||
accepted++;
|
||||
TraceInstr new_instr;
|
||||
log << "writing IP " << hex << curr_addr << " counter "
|
||||
@ -262,7 +259,6 @@ void L4SysExperiment::collectInstructionTrace(fail::BPSingleListener& bp)
|
||||
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 "
|
||||
|
||||
@ -5,20 +5,16 @@
|
||||
#define MAX_INSTR_BYTES 15
|
||||
|
||||
// the bounds of the program (space, instructions and time)
|
||||
#define L4SYS_ADDRESS_SPACE 0x1fd6e000
|
||||
#define L4SYS_FUNC_ENTRY 0x01000200
|
||||
#define L4SYS_FUNC_EXIT 0x01000245
|
||||
#define L4SYS_ADDRESS_SPACE 0x1fd4c000
|
||||
#define L4SYS_FUNC_ENTRY 0x010002a0
|
||||
#define L4SYS_FUNC_EXIT 0x01000380
|
||||
|
||||
// Instruction filtering: Allows to specify a range within
|
||||
// which to perform injection experiments. If in doubt, set
|
||||
// to the whole user-addressable area (0, 0xC0000000)
|
||||
// select instruction filtering
|
||||
#define L4SYS_FILTER_INSTRUCTIONS 1
|
||||
#define L4SYS_ADDRESS_LBOUND 0
|
||||
#define L4SYS_ADDRESS_UBOUND 0xC0000000
|
||||
|
||||
// kernel: 2377547, userland: 79405472
|
||||
#define L4SYS_NUMINSTR 3281
|
||||
#define L4SYS_TOTINSTR 228218
|
||||
#define L4SYS_NUMINSTR 15099
|
||||
#define L4SYS_TOTINSTR 60214
|
||||
#define L4SYS_BOCHS_IPS 5000000
|
||||
|
||||
// several file names used
|
||||
@ -26,10 +22,11 @@
|
||||
#define L4SYS_INSTRUCTION_LIST "ip.list"
|
||||
#define L4SYS_ALU_INSTRUCTIONS "alu.list"
|
||||
#define L4SYS_CORRECT_OUTPUT "golden.out"
|
||||
#define L4SYS_FILTER "filter.list"
|
||||
|
||||
// flags
|
||||
// 0 - preparation complete
|
||||
// >0 - next step to execute
|
||||
#define PREPARATION_STEP 0
|
||||
#define PREPARATION_STEP 2
|
||||
|
||||
#endif // __L4SYS_EXPERIMENT_INFO_HPP__
|
||||
|
||||
Reference in New Issue
Block a user