From 41cf5e1352f9a06f2296bd05b5d6b5ae701acf40 Mon Sep 17 00:00:00 2001 From: hsc Date: Mon, 22 Oct 2012 15:36:18 +0000 Subject: [PATCH] nanojpeg: campaign's fault-space pruning works now git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1795 8c4709b5-6ec9-48aa-a5cd-a96041d1645a --- src/experiments/nanojpeg/campaign.cc | 85 +++++++++++++++++++++++-- src/experiments/nanojpeg/campaign.hpp | 3 + src/experiments/nanojpeg/nanojpeg.proto | 14 ++-- 3 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/experiments/nanojpeg/campaign.cc b/src/experiments/nanojpeg/campaign.cc index f7881a9f..6a51f212 100644 --- a/src/experiments/nanojpeg/campaign.cc +++ b/src/experiments/nanojpeg/campaign.cc @@ -84,6 +84,20 @@ bool NanoJPEGCampaign::run() Udis86Helper udis_helper; Udis86Helper::UDRegisterSet in_regs, out_regs; + // register cascade for equivalence class generation + // map: register -> list of latest accesses (front = newest access) + // list: latest accesses (instr offset | bit mask) + map > > reg_cascade; + // open up an equivalence class for all bits in all GPRs + reg_cascade[RID_EAX].push_front(std::pair(0, 0xffffffffffffffffULL)); + reg_cascade[RID_EBX].push_front(std::pair(0, 0xffffffffffffffffULL)); + reg_cascade[RID_ECX].push_front(std::pair(0, 0xffffffffffffffffULL)); + reg_cascade[RID_EDX].push_front(std::pair(0, 0xffffffffffffffffULL)); + reg_cascade[RID_ESP].push_front(std::pair(0, 0xffffffffffffffffULL)); + reg_cascade[RID_EBP].push_front(std::pair(0, 0xffffffffffffffffULL)); + reg_cascade[RID_ESI].push_front(std::pair(0, 0xffffffffffffffffULL)); + reg_cascade[RID_EDI].push_front(std::pair(0, 0xffffffffffffffffULL)); + // load trace ifstream tracef(NANOJPEG_TRACE); if (tracef.fail()) { @@ -124,13 +138,15 @@ bool NanoJPEGCampaign::run() ud_t& ud = udis.getCurrentState(); udis_helper.setUd(&ud); - // for now: debug output - m_log << "0x" << hex << ev.ip() << " " << ::ud_insn_asm(&ud) << endl; - for (int i = 0; i < 3; ++i) { - cout << udis_helper.operandTypeToChar(ud.operand[i].type) << " "; - } - cout << endl; + //m_log << "0x" << hex << ev.ip() << " " << ::ud_insn_asm(&ud) << endl; + //for (int i = 0; i < 3; ++i) { + // cout << udis_helper.operandTypeToChar(ud.operand[i].type) << " "; + //} + //cout << endl; + + // determine input/output registers udis_helper.inOutRegisters(in_regs, out_regs); +#if 0 cout << "IN: "; for (Udis86Helper::UDRegisterSet::const_iterator it = in_regs.begin(); it != in_regs.end(); ++it) { @@ -142,7 +158,64 @@ bool NanoJPEGCampaign::run() cout << udis_helper.typeToString(*it) << " "; } cout << endl; +#endif + + // all IN registers close an equivalence class and generate experiments + for (Udis86Helper::UDRegisterSet::const_iterator it = in_regs.begin(); + it != in_regs.end(); ++it) { + // determine Fail* register ID and bitmask + uint64_t access_mask; + fail::GPRegisterId reg = udis_helper.udisGPRToFailBochsGPR(*it, access_mask); + uint64_t remaining_access_mask = access_mask; + + // iterate over latest accesses to register, newest to oldest + for (std::list >::iterator acc = reg_cascade[reg].begin(); + acc != reg_cascade[reg].end() && remaining_access_mask; ) { + uint64_t curr_mask = acc->second; + uint64_t common_mask = curr_mask & remaining_access_mask; + if (!common_mask) { + ++acc; + continue; + } + + remaining_access_mask &= ~common_mask; + acc->second &= ~common_mask; + + // new EC with experiments: acc->first -- instr, common_mask + count += add_experiment_ec(acc->first, instr, 0 /*todo*/, reg, common_mask); + + // new memory access EC in access cascade + reg_cascade[reg].push_front(std::pair(instr + 1, common_mask)); + + // old access completely shadowed by newer accesses? + if (acc->second == 0) { + acc = reg_cascade[reg].erase(acc); + } else { + ++acc; + } + } + assert(remaining_access_mask == 0); + } + + // all OUT registers close an equivalence class and generate known results + // TODO + // special case: empty EC! } + cout << "experiments planned: " << dec << count << endl; return true; } + +int NanoJPEGCampaign::add_experiment_ec(unsigned instr_ecstart, unsigned instr_offset, + unsigned instr_address, fail::GPRegisterId register_id, uint64_t bitmask) +{ + uint64_t v = bitmask; // count the number of bits set in v + int c; // c accumulates the total bits set in v + + for (c = 0; v; v >>= 1) { + c += v & 1; + } + + // TODO really enqueue jobs + return c; +} diff --git a/src/experiments/nanojpeg/campaign.hpp b/src/experiments/nanojpeg/campaign.hpp index 85e81713..0662cb62 100644 --- a/src/experiments/nanojpeg/campaign.hpp +++ b/src/experiments/nanojpeg/campaign.hpp @@ -4,6 +4,7 @@ #include "cpn/Campaign.hpp" #include "comm/ExperimentData.hpp" #include "util/Logger.hpp" +#include "sal/bochs/BochsRegisterIDs.hpp" #include "nanojpeg.pb.h" class NanoJPEGExperimentData : public fail::ExperimentData { @@ -14,6 +15,8 @@ public: class NanoJPEGCampaign : public fail::Campaign { fail::Logger m_log; + int add_experiment_ec(unsigned instr_ecstart, unsigned instr_offset, + unsigned instr_address, fail::GPRegisterId register_id, uint64_t bitmask); public: NanoJPEGCampaign() : m_log("nJPEG Campaign") {} virtual bool run(); diff --git a/src/experiments/nanojpeg/nanojpeg.proto b/src/experiments/nanojpeg/nanojpeg.proto index ad4aec12..ed15a115 100644 --- a/src/experiments/nanojpeg/nanojpeg.proto +++ b/src/experiments/nanojpeg/nanojpeg.proto @@ -2,16 +2,16 @@ message NanoJPEGProtoMsg { // Input: experiment parameters // (client executes one experiment for every specified bit in the target register) + // equivalence class start + required int32 instr_ecstart = 1; // FI at #instructions from experiment start - required int32 instr_offset = 1; + required int32 instr_offset = 2; // the exact IP value at this point in time (from golden run) - optional int32 instr_address = 2; // for sanity checks + optional int32 instr_address = 3; // for sanity checks // ID of the register to inject faults into - required int32 register_id = 3; - // first bit to inject a flip into - required int32 bit_start = 4; - // last bit to inject a flip into (inclusive) - required int32 bit_end = 5; + required int32 register_id = 4; + // bits to inject a bit flip into + required int64 bitmask = 5; // timeout in ms required int32 timeout = 6;