Merge "core/sal: dependency checks moved to listener classes"

This commit is contained in:
Adrian Böckenkamp
2013-06-05 15:36:33 +02:00
committed by Gerrit Code Review

View File

@ -13,11 +13,16 @@
#include "perf/BufferInterface.hpp" #include "perf/BufferInterface.hpp"
#include "util/ElfReader.hpp" #include "util/ElfReader.hpp"
#include "config/FailConfig.hpp"
namespace fail { namespace fail {
class ExperimentFlow; class ExperimentFlow;
// Warning: Inheriting from these listeners breaks the (static) dependency check for
// derived classes. One should therefore deploy a check for derived classes in
// the same way.
/** /**
* \class BaseListener * \class BaseListener
* This is the base class for all listener types. * This is the base class for all listener types.
@ -199,6 +204,14 @@ public:
virtual bool isMatching(const BPEvent* pEv) const = 0; virtual bool isMatching(const BPEvent* pEv) const = 0;
}; };
#if defined CONFIG_EVENT_BREAKPOINTS
#define BP_CTOR_SCOPE public
#else
#define BP_CTOR_SCOPE protected
// This prevents an experiment from instantiating an object of BPSingleListener
// without having enabled the appropriate configuration flag, i.e.,
// CONFIG_EVENT_BREAKPOINTS = ON.
#endif
/** /**
* \class BPSingleListener * \class BPSingleListener
* A Breakpoint listener to observe specific instruction pointers. * A Breakpoint listener to observe specific instruction pointers.
@ -206,7 +219,7 @@ public:
class BPSingleListener : public BPListener { class BPSingleListener : public BPListener {
protected: protected:
address_t m_WatchInstrPtr; address_t m_WatchInstrPtr;
public: BP_CTOR_SCOPE:
/** /**
* Creates a new breakpoint listener. * Creates a new breakpoint listener.
* @param ip the instruction pointer of the breakpoint. If the control * @param ip the instruction pointer of the breakpoint. If the control
@ -218,6 +231,7 @@ public:
*/ */
BPSingleListener(address_t ip = 0, address_t address_space = ANY_ADDR, ConcreteCPU* cpu = NULL) BPSingleListener(address_t ip = 0, address_t address_space = ANY_ADDR, ConcreteCPU* cpu = NULL)
: BPListener(address_space, cpu), m_WatchInstrPtr(ip) { } : BPListener(address_space, cpu), m_WatchInstrPtr(ip) { }
public: // reset scope in order to allow compiling the various other Fail* sources
/** /**
* Returns the instruction pointer this listener waits for. * Returns the instruction pointer this listener waits for.
* @return the instruction pointer specified in the constructor or by * @return the instruction pointer specified in the constructor or by
@ -237,6 +251,11 @@ public:
bool isMatching(const BPEvent* pEv) const; bool isMatching(const BPEvent* pEv) const;
}; };
#if defined CONFIG_EVENT_BREAKPOINTS_RANGE
#define BPRANGE_CTOR_SCOPE public
#else
#define BPRANGE_CTOR_SCOPE protected
#endif
/** /**
* \class BPRangeListener * \class BPRangeListener
* A listener type to observe ranges of instruction pointers. * A listener type to observe ranges of instruction pointers.
@ -245,7 +264,7 @@ class BPRangeListener : public BPListener {
protected: protected:
address_t m_WatchStartAddr; address_t m_WatchStartAddr;
address_t m_WatchEndAddr; address_t m_WatchEndAddr;
public: BPRANGE_CTOR_SCOPE:
/** /**
* Creates a new breakpoint-range listener. The range's ends are both * Creates a new breakpoint-range listener. The range's ends are both
* inclusive, i.e. an address matches if start <= addr <= end. * inclusive, i.e. an address matches if start <= addr <= end.
@ -256,6 +275,7 @@ public:
ConcreteCPU* cpu = NULL) ConcreteCPU* cpu = NULL)
: BPListener(address_space, cpu), m_WatchStartAddr(start), m_WatchEndAddr(end) : BPListener(address_space, cpu), m_WatchStartAddr(start), m_WatchEndAddr(end)
{ } { }
public:
/** /**
* Returns the instruction pointer watch range of this listener. * Returns the instruction pointer watch range of this listener.
* @return the listener's range * @return the listener's range
@ -279,6 +299,14 @@ public:
bool isMatching(const BPEvent* pEv) const; bool isMatching(const BPEvent* pEv) const;
}; };
#if defined CONFIG_EVENT_MEMREAD || defined CONFIG_EVENT_MEMWRITE
#define WP_CTOR_SCOPE public
#else
#define WP_CTOR_SCOPE protected
// Note: "private" works only in case of a "final class" (a leaf class) because when using
// "private", the derived classes wouldn't compile anymore (even if they are not used anyway).
// Clearly, MemAccessListener is *not* a leaf class.
#endif
/** /**
* \class MemAccessListener * \class MemAccessListener
* Observes memory read/write accesses. * Observes memory read/write accesses.
@ -295,7 +323,7 @@ protected:
*/ */
MemAccessEvent::access_type_t m_WatchType; MemAccessEvent::access_type_t m_WatchType;
MemAccessEvent m_Data; MemAccessEvent m_Data;
public: WP_CTOR_SCOPE:
MemAccessListener(MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE, MemAccessListener(MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
ConcreteCPU* cpu = NULL) ConcreteCPU* cpu = NULL)
: BaseListener(cpu), m_WatchAddr(ANY_ADDR), m_WatchWidth(1), m_WatchType(type) { } : BaseListener(cpu), m_WatchAddr(ANY_ADDR), m_WatchWidth(1), m_WatchType(type) { }
@ -307,7 +335,7 @@ public:
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE, MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
ConcreteCPU* cpu = NULL) ConcreteCPU* cpu = NULL)
: BaseListener(cpu), m_WatchAddr(symbol.getAddress()), m_WatchWidth(symbol.getSize()), m_WatchType(type) { } : BaseListener(cpu), m_WatchAddr(symbol.getAddress()), m_WatchWidth(symbol.getSize()), m_WatchType(type) { }
public:
/** /**
* Returns the physical memory address to be observed. * Returns the physical memory address to be observed.
*/ */
@ -384,30 +412,45 @@ public:
bool isMatching(const MemAccessEvent* pEv) const; bool isMatching(const MemAccessEvent* pEv) const;
}; };
#ifdef CONFIG_EVENT_MEMREAD
#define WPREAD_CTOR_SCOPE public
#else
#define WPREAD_CTOR_SCOPE protected
#endif
/** /**
* \class MemReadListener * \class MemReadListener
* Observes memory read accesses. * Observes memory read accesses.
*/ */
class MemReadListener : public MemAccessListener { class MemReadListener : public MemAccessListener {
public: WPREAD_CTOR_SCOPE:
MemReadListener(ConcreteCPU* cpu = NULL) MemReadListener(ConcreteCPU* cpu = NULL)
: MemAccessListener(MemAccessEvent::MEM_READ, cpu) { } : MemAccessListener(MemAccessEvent::MEM_READ, cpu) { }
MemReadListener(address_t addr, ConcreteCPU* cpu = NULL) MemReadListener(address_t addr, ConcreteCPU* cpu = NULL)
: MemAccessListener(addr, MemAccessEvent::MEM_READ, cpu) { } : MemAccessListener(addr, MemAccessEvent::MEM_READ, cpu) { }
}; };
#ifdef CONFIG_EVENT_MEMWRITE
#define WPWRITE_CTOR_SCOPE public
#else
#define WPWRITE_CTOR_SCOPE protected
#endif
/** /**
* \class MemWriteListener * \class MemWriteListener
* Observes memory write accesses. * Observes memory write accesses.
*/ */
class MemWriteListener : public MemAccessListener { class MemWriteListener : public MemAccessListener {
public: WPWRITE_CTOR_SCOPE:
MemWriteListener(ConcreteCPU* cpu = NULL) MemWriteListener(ConcreteCPU* cpu = NULL)
: MemAccessListener(MemAccessEvent::MEM_READ, cpu) { } : MemAccessListener(MemAccessEvent::MEM_READ, cpu) { }
MemWriteListener(address_t addr, ConcreteCPU* cpu = NULL) MemWriteListener(address_t addr, ConcreteCPU* cpu = NULL)
: MemAccessListener(addr, MemAccessEvent::MEM_WRITE, cpu) { } : MemAccessListener(addr, MemAccessEvent::MEM_WRITE, cpu) { }
}; };
#if defined CONFIG_EVENT_INTERRUPT || defined CONFIG_EVENT_TRAP
#define TROUBLE_CTOR_SCOPE public
#else
#define TROUBLE_CTOR_SCOPE protected
#endif
/** /**
* \class TroubleListener * \class TroubleListener
* Observes interrupt/trap activties. * Observes interrupt/trap activties.
@ -420,10 +463,11 @@ protected:
* or ANY_INTERRUPT/ANY_TRAP. * or ANY_INTERRUPT/ANY_TRAP.
*/ */
std::vector<unsigned> m_WatchNumbers; std::vector<unsigned> m_WatchNumbers;
public: TROUBLE_CTOR_SCOPE:
TroubleListener(ConcreteCPU* cpu = NULL) : BaseListener(cpu) { } TroubleListener(ConcreteCPU* cpu = NULL) : BaseListener(cpu) { }
TroubleListener(unsigned troubleNumber, ConcreteCPU* cpu = NULL) : BaseListener(cpu) TroubleListener(unsigned troubleNumber, ConcreteCPU* cpu = NULL) : BaseListener(cpu)
{ addWatchNumber(troubleNumber); } { addWatchNumber(troubleNumber); }
public:
/** /**
* Add an interrupt/trap-number which should be observed. * Add an interrupt/trap-number which should be observed.
* @param troubleNumber number of an interrupt or trap * @param troubleNumber number of an interrupt or trap
@ -468,6 +512,11 @@ public:
unsigned getTriggerNumber() const { return m_Data.getTriggerNumber(); } unsigned getTriggerNumber() const { return m_Data.getTriggerNumber(); }
}; };
#ifdef CONFIG_EVENT_INTERRUPT
#define INT_CTOR_SCOPE public
#else
#define INT_CTOR_SCOPE protected
#endif
/** /**
* \class InterruptListener * \class InterruptListener
* Observes interrupts of the guest system. * Observes interrupts of the guest system.
@ -475,10 +524,11 @@ public:
class InterruptListener : public TroubleListener { class InterruptListener : public TroubleListener {
protected: protected:
InterruptEvent m_Data; //!< event related data, e.g. NMI flag InterruptEvent m_Data; //!< event related data, e.g. NMI flag
public: INT_CTOR_SCOPE:
InterruptListener(ConcreteCPU* cpu = NULL) : TroubleListener(cpu) { } InterruptListener(ConcreteCPU* cpu = NULL) : TroubleListener(cpu) { }
InterruptListener(unsigned interrupt, ConcreteCPU* cpu = NULL) : TroubleListener(cpu) InterruptListener(unsigned interrupt, ConcreteCPU* cpu = NULL) : TroubleListener(cpu)
{ addWatchNumber(interrupt); } { addWatchNumber(interrupt); }
public:
/** /**
* Returns \c true if the interrupt is non maskable, \c false otherwise. * Returns \c true if the interrupt is non maskable, \c false otherwise.
*/ */
@ -489,17 +539,27 @@ public:
void setNMI(bool enabled) { m_Data.setNMI(enabled); } void setNMI(bool enabled) { m_Data.setNMI(enabled); }
}; };
#ifdef CONFIG_EVENT_TRAP
#define TRAP_CTOR_SCOPE public
#else
#define TRAP_CTOR_SCOPE protected
#endif
/** /**
* \class TrapListener * \class TrapListener
* Observes traps of the guest system. * Observes traps of the guest system.
*/ */
class TrapListener : public TroubleListener { class TrapListener : public TroubleListener {
public: TRAP_CTOR_SCOPE:
TrapListener(ConcreteCPU* cpu = NULL) : TroubleListener(cpu) { } TrapListener(ConcreteCPU* cpu = NULL) : TroubleListener(cpu) { }
TrapListener(unsigned trap, ConcreteCPU* cpu = NULL) : TroubleListener(cpu) TrapListener(unsigned trap, ConcreteCPU* cpu = NULL) : TroubleListener(cpu)
{ addWatchNumber(trap); } { addWatchNumber(trap); }
}; };
#ifdef CONFIG_EVENT_GUESTSYS
#define GUESTSYS_CTOR_SCOPE public
#else
#define GUESTSYS_CTOR_SCOPE protected
#endif
/** /**
* \class GuestListener * \class GuestListener
* Used to receive data from the guest system. * Used to receive data from the guest system.
@ -510,8 +570,9 @@ public:
class GuestListener : public BaseListener { class GuestListener : public BaseListener {
protected: protected:
GuestEvent m_Data; GuestEvent m_Data;
public: GUESTSYS_CTOR_SCOPE:
GuestListener() { } GuestListener() { }
public:
/** /**
* Returns the data, transmitted by the guest system. * Returns the data, transmitted by the guest system.
*/ */
@ -530,6 +591,11 @@ public:
void setPort(unsigned port) { m_Data.setPort(port); } void setPort(unsigned port) { m_Data.setPort(port); }
}; };
#ifdef CONFIG_EVENT_IOPORT
#define IOPORT_CTOR_SCOPE public
#else
#define IOPORT_CTOR_SCOPE protected
#endif
/** /**
* \class IOPortListener * \class IOPortListener
* Observes I/O access on architectures with a separate I/O access mechanism (e.g. IA-32) * Observes I/O access on architectures with a separate I/O access mechanism (e.g. IA-32)
@ -539,7 +605,7 @@ protected:
IOPortEvent m_Data; IOPortEvent m_Data;
unsigned m_Port; unsigned m_Port;
bool m_Out; bool m_Out;
public: IOPORT_CTOR_SCOPE:
/** /**
* Initialises an IOPortListener * Initialises an IOPortListener
* *
@ -550,6 +616,7 @@ public:
*/ */
IOPortListener(unsigned port, bool out, ConcreteCPU* cpu = NULL) IOPortListener(unsigned port, bool out, ConcreteCPU* cpu = NULL)
: BaseListener(cpu), m_Port(port), m_Out(out) { } : BaseListener(cpu), m_Port(port), m_Out(out) { }
public:
/** /**
* Returns the data sent to the specified port * Returns the data sent to the specified port
*/ */
@ -593,6 +660,11 @@ public:
void setOut(bool out) { m_Out = out; } void setOut(bool out) { m_Out = out; }
}; };
#ifdef CONFIG_EVENT_JUMP
#define JUMP_CTOR_SCOPE public
#else
#define JUMP_CTOR_SCOPE protected
#endif
/** /**
* \class JumpListener * \class JumpListener
* JumpListeners are used to observe conditional jumps (if...else if...else). * JumpListeners are used to observe conditional jumps (if...else if...else).
@ -600,7 +672,7 @@ public:
class JumpListener : public BaseListener { class JumpListener : public BaseListener {
protected: protected:
JumpEvent m_Data; JumpEvent m_Data;
public: JUMP_CTOR_SCOPE:
/** /**
* Constructs a new listener object. * Constructs a new listener object.
* @param opcode the opcode of the jump-instruction to be observed * @param opcode the opcode of the jump-instruction to be observed
@ -608,6 +680,7 @@ public:
*/ */
JumpListener(unsigned opcode = ANY_INSTR, ConcreteCPU* cpu = NULL) JumpListener(unsigned opcode = ANY_INSTR, ConcreteCPU* cpu = NULL)
: BaseListener(cpu), m_Data(opcode) { } : BaseListener(cpu), m_Data(opcode) { }
public:
/** /**
* Retrieves the opcode of the jump-instruction. * Retrieves the opcode of the jump-instruction.
*/ */