Files
fail/src/experiments/l4-sys/experiment.hpp
Björn Döbel 560860cb99 L4Sys: consult instruction list for breakpoints
Change-Id: Ic8163cc84bad9b0074a9d6489127d0ef09eb3c21
2013-09-11 18:02:03 +02:00

169 lines
5.6 KiB
C++

#ifndef __L4SYS_EXPERIMENT_HPP__
#define __L4SYS_EXPERIMENT_HPP__
#include <string>
#include "efw/ExperimentFlow.hpp"
#include "efw/JobClient.hpp"
#include "util/Logger.hpp"
#include "sal/Listener.hpp"
class L4SysExperimentData;
/**
* A data type containing an instruction trace entry.
*/
typedef struct TraceInstrType {
fail::address_t trigger_addr; //!< the instruction pointer of the observed instruction
/**
* counts how often this instruction has been called
* if you want to call exactly this instruction, e.g. in a loop,
* you need to ignore the breakpoint \c bp_counter - 1 times
*/
unsigned bp_counter;
} TraceInstr;
typedef std::vector<TraceInstr> TraceVector;
class L4SysExperiment : public fail::ExperimentFlow {
private:
fail::JobClient m_jc; //!< the job client connecting to the campaign server
fail::Logger log; //<! the logger
L4SysExperimentData *param; //<! the parameter set currently in use by the client
std::string currentOutput; //<! output for the current experiment run
public:
L4SysExperiment();
~L4SysExperiment();
bool run();
protected:
/**
* Frees all attached resources and terminates the simulator.
* @param reason the exit reason, i.e. exit code, passed on to simulator::terminate
*/
void terminate(int reason);
/**
* Frees all resources allocated by this object.
* This function is called by terminate as well as the destructor.
*/
inline void destroy();
private:
/**
* Sanitises the output string of the serial device monitored.
* @param a string containing special ASCII characters
* @returns a byte-stuffed version of the given string
*/
std::string sanitised(const std::string &in_str);
/**
* Waits for events and simultaneously logs output from the serial console
* @param clear_output if true, the output logged so far is deleted, thus the buffer is reset (cleared)
* @returns the event returned by waitAny, as long as it did not log output
*/
fail::BaseListener* waitIOOrOther(bool clear_output);
/**
* Calculates the address where Bochs will read the current instruction from.
* This code is copied from various Bochs methods and should be reviewed as
* soon as a new Bochs version is introduced.
* @returns a pointer to the memory region containing the current Bochs instruction
*/
const Bit8u *calculateInstructionAddress();
/**
* A function necessary for Bochs internal address translation
* @returns a value for Bochs' eipBiased variable
*/
Bit32u eipBiased();
/**
* Parses a raw instruction into a bxInstruction_c structure.
* This simple version of the function is taken from Bochs
* where it is currently disabled due to the TRACE_CACHE option,
* and has been modified to fit the needs of instruction modification.
* @param instance a pointer to the current Bochs CPU
* @param instr a pointer to the address the instruction is fetched from
* @param iStorage an outgoing value which contains the parsed instruction
* @returns \a false if the instruction continued on the following page in memory
*/
bx_bool fetchInstruction(BX_CPU_C *instance, const Bit8u *instr, bxInstruction_c *iStorage);
/**
* Write out the injection parameters to the logger.
*/
void logInjection();
/**
* Proceeds by one single instruction.
* @param preserveAddressSpace if set, the address space of the next instruction
* must match with the current address space
* (for example, this is important when debugging in the kernel)
* @returns the listener that was triggered, in case there were more than one
*/
fail::BaseListener *singleStep(bool preserveAddressSpace);
/**
* Injects a new instruction into the Bochs instruction stream and restores the previous one
* @param oldInstr address of the instruction to be replaced
* @param newInstr address of the instruction to replace it with
*/
void injectInstruction(bxInstruction_c *oldInstr, bxInstruction_c *newInstr);
/**
* Calculate the timeout of the current workload in milliseconds.
*/
unsigned calculateTimeout(unsigned instr_left);
/**
* Send back the experiment parameter set with a description of the error.
*/
void terminateWithError(std::string details, int reason);
/**
* Run until L4SYS_FUNC_ENTRY and save state (experiment preparation,
* phase 1)
*/
void startAndSaveInitState(fail::BPSingleListener* bp);
/**
* Collect list of executed instructions, considering instruction
* filtering if configured (experiment preparation, phase 2).
*/
void collectInstructionTrace(fail::BPSingleListener* bp);
/**
* Perform the golden run (experiment preparation, phase 3)
*/
void goldenRun(fail::BPSingleListener* bp);
/**
* Check that all required setup has been done before an experiment run.
*/
void validatePrerequisites();
/**
* Load job parameters for an experiment.
*/
void getJobParameters();
/**
* Read the golden run output into the target string.
*/
void readGoldenRun(std::string& target);
/*
* Prepare memory experiment. Creates a breakpoint to run until the
* injection location.
*/
fail::BPSingleListener* prepareMemoryExperiment(int ip, int offset, int dataAddress);
/*
* Prepare register experiment. Creates a breakpoint to run until the
* injection location.
*/
fail::BPSingleListener* prepareRegisterExperiment(int ip, int offset, int dataAddress);
/**
* Perform memory bit flip at (address, bit).
*/
void doMemoryInjection(int address, int bit);
/**
* Perform register bit flip in the specified (register, bit)
* combination.
*/
void doRegisterInjection(int regDesc, int bit);
void setupFilteredBreakpoint(fail::BPSingleListener* bp, int instOffset);
};
#endif // __L4SYS_EXPERIMENT_HPP__