Simulator specific listener are now implemented using aspects instead of an additional inheritance level
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1706 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -7,7 +7,6 @@ if(BUILD_BOCHS)
|
||||
SimulatorController.cc
|
||||
perf/BreakpointBuffer.cc
|
||||
bochs/BochsController.cc
|
||||
bochs/BochsListener.cc
|
||||
)
|
||||
elseif(BUILD_GEM5)
|
||||
set(SRCS
|
||||
@ -17,7 +16,6 @@ elseif(BUILD_GEM5)
|
||||
Register.cc
|
||||
SimulatorController.cc
|
||||
gem5/Gem5Controller.cc
|
||||
gem5/Gem5Listener.cc
|
||||
gem5/Gem5PCEvent.cc
|
||||
)
|
||||
elseif(BUILD_OVP)
|
||||
@ -39,7 +37,6 @@ elseif(BUILD_QEMU)
|
||||
perf/BreakpointBuffer.cc
|
||||
SimulatorController.cc
|
||||
qemu/QEMUController.cc
|
||||
qemu/QEMUListener.cc
|
||||
qemu/wrappers.cc
|
||||
)
|
||||
endif(BUILD_BOCHS)
|
||||
|
||||
@ -74,7 +74,7 @@ bool BPRangeListener::isMatching(const BPEvent* pEv) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GenericBPSingleListener::isMatching(const BPEvent* pEv) const
|
||||
bool BPSingleListener::isMatching(const BPEvent* pEv) const
|
||||
{
|
||||
if (aspaceIsMatching(pEv->getCR3())) {
|
||||
if (m_WatchInstrPtr == ANY_ADDR || m_WatchInstrPtr == pEv->getTriggerInstructionPointer())
|
||||
|
||||
@ -173,7 +173,7 @@ public:
|
||||
* \class BPSingleListener
|
||||
* A Breakpoint listener to observe specific instruction pointers.
|
||||
*/
|
||||
class GenericBPSingleListener : public BPListener {
|
||||
class BPSingleListener : public BPListener {
|
||||
protected:
|
||||
address_t m_WatchInstrPtr;
|
||||
public:
|
||||
@ -189,7 +189,7 @@ public:
|
||||
* Here, too, ANY_ADDR is a placeholder to allow debugging
|
||||
* in a random address space.
|
||||
*/
|
||||
GenericBPSingleListener(address_t ip = 0, address_t address_space = ANY_ADDR)
|
||||
BPSingleListener(address_t ip = 0, address_t address_space = ANY_ADDR)
|
||||
: BPListener(address_space), m_WatchInstrPtr(ip) { }
|
||||
/**
|
||||
* Returns the instruction pointer this listener waits for.
|
||||
@ -353,14 +353,14 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* \class GenericMemWriteListener
|
||||
* \class MemWriteListener
|
||||
* Observes memory write accesses.
|
||||
*/
|
||||
class GenericMemWriteListener : public MemAccessListener {
|
||||
class MemWriteListener : public MemAccessListener {
|
||||
public:
|
||||
GenericMemWriteListener()
|
||||
MemWriteListener()
|
||||
: MemAccessListener(MemAccessEvent::MEM_READ) { }
|
||||
GenericMemWriteListener(address_t addr)
|
||||
MemWriteListener(address_t addr)
|
||||
: MemAccessListener(addr, MemAccessEvent::MEM_WRITE) { }
|
||||
};
|
||||
|
||||
@ -568,16 +568,16 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* \class GenericTimerListener
|
||||
* \class TimerListener
|
||||
* This listener type is used to create timeouts within in an experiment.
|
||||
*
|
||||
* Depending on your simulator backend, a concrete class needs to be derived from
|
||||
* \c GenericTimerListener. \c onAddition should be used to register and \c onDeletion
|
||||
* \c TimerListener. \c onAddition should be used to register and \c onDeletion
|
||||
* to unregister the timer. \c onTrigger can be used to re-register the timer if a
|
||||
* repetitive timer is requested and the back-end doesn't support such timer types
|
||||
* natively.
|
||||
*/
|
||||
class GenericTimerListener : public BaseListener {
|
||||
class TimerListener : public BaseListener {
|
||||
protected:
|
||||
unsigned m_Timeout; //!< timeout interval in milliseconds
|
||||
GenericTimerEvent m_Data;
|
||||
@ -589,8 +589,8 @@ public:
|
||||
* @param timeout the time interval in milliseconds (ms)
|
||||
* @see SimulatorController::addListener
|
||||
*/
|
||||
GenericTimerListener(unsigned timeout) : m_Timeout(timeout) { }
|
||||
~GenericTimerListener() { }
|
||||
TimerListener(unsigned timeout) : m_Timeout(timeout) { }
|
||||
~TimerListener() { }
|
||||
/**
|
||||
* Retrieves the internal timer id. Maybe useful for debug output.
|
||||
* @return the timer id
|
||||
@ -610,16 +610,4 @@ public:
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
#if defined BUILD_BOCHS
|
||||
#include "bochs/BochsListener.hpp"
|
||||
#elif defined BUILD_GEM5
|
||||
#include "gem5/Gem5Listener.hpp"
|
||||
#elif defined BUILD_OVP
|
||||
// #include "ovp/OVPListener.hpp"
|
||||
#elif defined BUILD_QEMU
|
||||
#include "qemu/QEMUListener.hpp"
|
||||
#else
|
||||
#error SAL Config Target not defined
|
||||
#endif
|
||||
|
||||
#endif // __LISTENER_HPP__
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#include "ListenerManager.hpp"
|
||||
#include "SALInst.hpp"
|
||||
|
||||
#include "Listener.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
void ListenerManager::add(BaseListener* li, ExperimentFlow* pExp)
|
||||
|
||||
@ -6,11 +6,12 @@
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Listener.hpp"
|
||||
#include "perf/BufferInterface.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
class ExperimentFlow;
|
||||
class BaseListener;
|
||||
|
||||
/**
|
||||
* Buffer-list for a specific experiment; acts as a simple storage container
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "SimulatorController.hpp"
|
||||
#include "SALInst.hpp"
|
||||
#include "Event.hpp"
|
||||
#include "Listener.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
#include "efw/CoroutineManager.hpp"
|
||||
#include "ListenerManager.hpp"
|
||||
#include "SALConfig.hpp"
|
||||
#include "Listener.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "BochsRegister.hpp"
|
||||
#include "../Register.hpp"
|
||||
#include "../SALInst.hpp"
|
||||
#include "../Listener.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
|
||||
@ -8,10 +8,8 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "FailBochsGlobals.hpp"
|
||||
#include "BochsListener.hpp"
|
||||
|
||||
#include "../SimulatorController.hpp"
|
||||
#include "../Listener.hpp"
|
||||
|
||||
#include "bochs.h"
|
||||
#include "cpu/cpu.h"
|
||||
|
||||
51
src/core/sal/bochs/BochsListener.ah
Normal file
51
src/core/sal/bochs/BochsListener.ah
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef __BOCHSLISTENER_AH__
|
||||
#define __BOCHSLISTENER_AH__
|
||||
|
||||
#include "config/VariantConfig.hpp"
|
||||
#include "config/FailConfig.hpp"
|
||||
|
||||
#if defined(BUILD_BOCHS) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||
|
||||
#include "bochs.h"
|
||||
#include "BochsController.hpp"
|
||||
|
||||
aspect BochsListener
|
||||
{
|
||||
advice "fail::TimerListener" : slice class
|
||||
{
|
||||
public:
|
||||
bool onAddition()
|
||||
{
|
||||
// Register the timer listener in the Bochs simulator:
|
||||
setId(m_registerTimer(this));
|
||||
if(getId() == -1)
|
||||
return false; // unable to register the timer (error in Bochs' function call)
|
||||
return true;
|
||||
}
|
||||
|
||||
void onDeletion()
|
||||
{
|
||||
// Unregister the time listener:
|
||||
m_unregisterTimer(this);
|
||||
}
|
||||
|
||||
private:
|
||||
timer_id_t m_registerTimer(TimerListener* pev)
|
||||
{
|
||||
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
||||
return static_cast<timer_id_t>(
|
||||
bx_pc_system.register_timer(pev, BochsController::onTimerTrigger, pev->getTimeout(),
|
||||
false, 1/*start immediately*/, "Fail*: BochsController"/*name*/));
|
||||
}
|
||||
|
||||
bool m_unregisterTimer(TimerListener* pev)
|
||||
{
|
||||
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
||||
bx_pc_system.deactivate_timer(static_cast<unsigned>(pev->getId()));
|
||||
return bx_pc_system.unregisterTimer(static_cast<unsigned>(pev->getId()));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // BUILD_BOCHS && CONFIG_EVENT_BREAKPOINTS
|
||||
#endif // __BOCHSLISTENER_AH__
|
||||
@ -1,36 +0,0 @@
|
||||
#include "BochsListener.hpp"
|
||||
#include "../SALInst.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
bool TimerListener::onAddition()
|
||||
{
|
||||
// Register the timer listener in the Bochs simulator:
|
||||
setId(m_registerTimer(this));
|
||||
if(getId() == -1)
|
||||
return false; // unable to register the timer (error in Bochs' function call)
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimerListener::onDeletion()
|
||||
{
|
||||
// Unregister the time listener:
|
||||
m_unregisterTimer(this);
|
||||
}
|
||||
|
||||
timer_id_t TimerListener::m_registerTimer(TimerListener* pev)
|
||||
{
|
||||
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
||||
return static_cast<timer_id_t>(
|
||||
bx_pc_system.register_timer(pev, BochsController::onTimerTrigger, pev->getTimeout(),
|
||||
false, 1/*start immediately*/, "Fail*: BochsController"/*name*/));
|
||||
}
|
||||
|
||||
bool TimerListener::m_unregisterTimer(TimerListener* pev)
|
||||
{
|
||||
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
||||
bx_pc_system.deactivate_timer(static_cast<unsigned>(pev->getId()));
|
||||
return bx_pc_system.unregisterTimer(static_cast<unsigned>(pev->getId()));
|
||||
}
|
||||
|
||||
} // end-of-namespace: fail
|
||||
@ -1,81 +0,0 @@
|
||||
#ifndef __BOCHS_LISTENER_HPP__
|
||||
#define __BOCHS_LISTENER_HPP__
|
||||
|
||||
#include "../Listener.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
typedef GenericBPSingleListener BPSingleListener;
|
||||
typedef GenericMemWriteListener MemWriteListener;
|
||||
|
||||
/**
|
||||
* \class TimerListener
|
||||
* Concrete TimerListener implementation of GenericTimerListener for the Bochs
|
||||
* simulator backend. A (Fail)Bochs bug currently leads to the consequence that
|
||||
* timers cannot be added/enabled at boot time (see BochsController.hpp for
|
||||
* further details).
|
||||
*/
|
||||
class TimerListener : public GenericTimerListener {
|
||||
private:
|
||||
/**
|
||||
* Registers a timer in the Bochs simulator. This timer triggers \a TimerListeners
|
||||
* to inform the corresponding experiment-flow. Note that the number of timers
|
||||
* (in Bochs) is limited to \c BX_MAX_TIMERS (defaults to 64 in v2.4.6).
|
||||
* @param pli a pointer to the (experiment flow-) allocated TimerListener object,
|
||||
* providing all required information to start the timer (e.g. the
|
||||
* timeout value).
|
||||
* @return The unique id of the timer recently created. This id is carried
|
||||
* along with the TimerListener. On errors, -1 is returned (e.g. because
|
||||
* a timer with the same id is already existing)
|
||||
* @see TimerListener::getId()
|
||||
*/
|
||||
static timer_id_t m_registerTimer(TimerListener* pli);
|
||||
/**
|
||||
* Deletes a timer. No further events will be triggered by the timer.
|
||||
* @param pli a pointer to the TimerListener-object to be removed
|
||||
* @return \c true if the timer with \a pli->getId() has been removed
|
||||
* successfully, \c false otherwise
|
||||
*/
|
||||
static bool m_unregisterTimer(TimerListener* pli);
|
||||
public:
|
||||
/**
|
||||
* Creates a new timer event. This can be used to implement a timeout-
|
||||
* mechanism in the experiment-flow. The timer starts automatically when
|
||||
* added to FailBochs.
|
||||
* @param timeout the time intervall in milliseconds (ms)
|
||||
* @see SimulatorController::addListener
|
||||
*/
|
||||
TimerListener(unsigned timeout)
|
||||
: GenericTimerListener(timeout) { }
|
||||
~TimerListener() { onDeletion(); } // FIXME ~BaseListener should automatically dequeue a Listener, and then indirectly calls onDeletion. In the current implementation, no dequeueing happens at all.
|
||||
|
||||
/**
|
||||
* This method is called when an experiment flow adds a new event by
|
||||
* calling \c simulator.addListener() or \c simulator.addListenerAndResume().
|
||||
* More specifically, the event will be added to the event-list first
|
||||
* (buffer-list, to be precise) and then this event handler is called.
|
||||
* @return You should return \c true to continue and \c false to prevent
|
||||
* the addition of the event \a pev, yielding an error in the
|
||||
* experiment flow (i.e. -1 is returned).
|
||||
*/
|
||||
bool onAddition();
|
||||
/**
|
||||
* This method is called when an experiment flow removes an event from
|
||||
* the event-management by calling \c removeListener(prev), \c clearListeners()
|
||||
* or by deleting a complete flow (\c removeFlow). More specifically, this
|
||||
* event handler will be called *before* the event is actually deleted.
|
||||
*/
|
||||
void onDeletion();
|
||||
/**
|
||||
* This method is called when an previously added event is about to be
|
||||
* triggered by the simulator-backend. More specifically, this event handler
|
||||
* will be called *before* the event is actually triggered, i.e. before the
|
||||
* corresponding coroutine is toggled.
|
||||
*/
|
||||
void onTrigger() { onDeletion(); } // FIXME It should NOT be a Listener's job to call its own onDeletion. ListenerManager should call onDeletion when it deletes a Listener from a queue.
|
||||
// TODO/FIXME: bei neuer impl. anpassen
|
||||
};
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
#endif // __BOCHS_LISTENER_HPP__
|
||||
@ -35,18 +35,21 @@ void Gem5Controller::reboot()
|
||||
void Gem5Controller::onBreakpoint(address_t instrPtr, address_t address_space)
|
||||
{
|
||||
bool do_fire = false;
|
||||
BPEvent tmp(instrPtr, address_space);
|
||||
// Check for active breakpoint-events:
|
||||
for (ListenerManager::iterator it = m_LstList.begin(); it != m_LstList.end(); it++) {
|
||||
ListenerManager::iterator it = m_LstList.begin();
|
||||
BPEvent tmp(instrPtr, address_space);
|
||||
while (it != m_LstList.end()) {
|
||||
BaseListener* pLi = *it;
|
||||
BPListener* pBreakpt = dynamic_cast<BPListener*>(pLi);
|
||||
if(pBreakpt != NULL && pBreakpt->isMatching(&tmp)) {
|
||||
if (pBreakpt != NULL && pBreakpt->isMatching(&tmp)) {
|
||||
pBreakpt->setTriggerInstructionPointer(instrPtr);
|
||||
it = m_LstList.makeActive(it);
|
||||
do_fire = true;
|
||||
// "it" has already been set to the next element (by calling makeActive()):
|
||||
// "it" has already been set to the next element (by calling
|
||||
// makeActive()):
|
||||
continue; // -> skip iterator increment
|
||||
}
|
||||
it++;
|
||||
}
|
||||
if (do_fire)
|
||||
m_LstList.triggerActiveListeners();
|
||||
|
||||
39
src/core/sal/gem5/Gem5Listener.ah
Normal file
39
src/core/sal/gem5/Gem5Listener.ah
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef __GEM5LISTENER_AH__
|
||||
#define __GEM5LISTENER_AH__
|
||||
|
||||
#include "config/VariantConfig.hpp"
|
||||
#include "config/FailConfig.hpp"
|
||||
|
||||
#if defined(BUILD_GEM5) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||
|
||||
#include "Gem5PCEvent.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
aspect Gem5Listener
|
||||
{
|
||||
advice "fail::BPSingleListener" : slice class
|
||||
{
|
||||
private:
|
||||
Gem5PCEvent* m_Breakpoint;
|
||||
public:
|
||||
virtual bool onAddition()
|
||||
{
|
||||
System* sys = *System::systemList.begin();
|
||||
m_Breakpoint = new Gem5PCEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void onDeletion()
|
||||
{
|
||||
if(m_Breakpoint)
|
||||
{
|
||||
delete m_Breakpoint;
|
||||
m_Breakpoint = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // BUILD_GEM5 && CONFIG_EVENT_BREAKPOINTS
|
||||
#endif // __GEM5LISTENER_AH__
|
||||
@ -1,33 +0,0 @@
|
||||
#include "Gem5Listener.hpp"
|
||||
#include "../SALInst.hpp"
|
||||
|
||||
#include "sim/system.hh"
|
||||
|
||||
namespace fail {
|
||||
|
||||
Gem5BPSingleListener::Gem5BPSingleListener(address_t ip)
|
||||
: GenericBPSingleListener(ip)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Gem5BPSingleListener::onAddition()
|
||||
{
|
||||
if(!m_Breakpoint)
|
||||
{
|
||||
System* sys = *System::systemList.begin();
|
||||
m_Breakpoint = new Gem5PCEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Gem5BPSingleListener::~Gem5BPSingleListener()
|
||||
{
|
||||
if(m_Breakpoint)
|
||||
{
|
||||
delete m_Breakpoint;
|
||||
}
|
||||
}
|
||||
|
||||
} // end-of-namespace: fail
|
||||
@ -1,25 +0,0 @@
|
||||
#ifndef __GEM5_LISTENER_HPP__
|
||||
#define __GEM5_LISTENER_HPP__
|
||||
|
||||
#include "../Listener.hpp"
|
||||
#include "Gem5PCEvent.hh"
|
||||
|
||||
namespace fail {
|
||||
|
||||
typedef GenericMemWriteListener MemWriteListener;
|
||||
|
||||
class Gem5BPSingleListener : public GenericBPSingleListener
|
||||
{
|
||||
public:
|
||||
Gem5BPSingleListener(address_t ip = 0);
|
||||
virtual bool onAddition();
|
||||
~Gem5BPSingleListener();
|
||||
private:
|
||||
Gem5PCEvent* m_Breakpoint;
|
||||
};
|
||||
|
||||
typedef Gem5BPSingleListener BPSingleListener;
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
#endif // __GEM5_LISTENER_HPP__
|
||||
@ -8,13 +8,13 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "../SimulatorController.hpp"
|
||||
#include "../Listener.hpp"
|
||||
|
||||
struct CPUX86State;
|
||||
|
||||
namespace fail {
|
||||
|
||||
class ExperimentFlow;
|
||||
class TimerListener;
|
||||
|
||||
/**
|
||||
* \class QEMUController
|
||||
|
||||
60
src/core/sal/qemu/QEMUListener.ah
Normal file
60
src/core/sal/qemu/QEMUListener.ah
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef __QEMULISTENER_AH__
|
||||
#define __QEMULISTENER_AH__
|
||||
|
||||
#include "config/VariantConfig.hpp"
|
||||
#include "config/FailConfig.hpp"
|
||||
|
||||
#if defined(BUILD_QEMU) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||
|
||||
#include "../SALInst.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "qemu/failqemu.h"
|
||||
}
|
||||
|
||||
aspect QEMUListener
|
||||
{
|
||||
advice "fail::TimerListener" : slice class
|
||||
{
|
||||
public:
|
||||
bool onAddition()
|
||||
{
|
||||
//std::cout << "QEMUTimerListener::onAddition" << std::endl;
|
||||
setId(failqemu_register_timer(getTimeout(), (void *)this));
|
||||
//std::cout << "this = " << std::hex << (unsigned) this << std::endl;
|
||||
//std::cout << "id = " << std::hex << (unsigned) getId() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void onDeletion()
|
||||
{
|
||||
//std::cout << "QEMUTimerListener::onDeletion" << std::endl;
|
||||
//std::cout << "this = " << std::hex << (unsigned) this << std::endl;
|
||||
//std::cout << "id = " << std::hex << (unsigned) getId() << std::endl;
|
||||
failqemu_unregister_timer(getId());
|
||||
}
|
||||
};
|
||||
|
||||
advice "fail::MemWriteListener" : slice class
|
||||
{
|
||||
public:
|
||||
bool onAddition()
|
||||
{
|
||||
//std::cout << "QEMUMemWriteListener::onAddition" << std::endl;
|
||||
if (failqemu_add_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1) != 0) {
|
||||
std::cout << "adding watchpoint failed!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void onDeletion()
|
||||
{
|
||||
//std::cout << "QEMUMemWriteListener::onDeletion" << std::endl;
|
||||
failqemu_remove_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // BUILD_QEMU && CONFIG_EVENT_BREAKPOINTS
|
||||
#endif // __QEMULISTENER_AH__
|
||||
@ -1,45 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "QEMUListener.hpp"
|
||||
#include "../SALInst.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "qemu/failqemu.h"
|
||||
}
|
||||
|
||||
namespace fail {
|
||||
|
||||
bool QEMUMemWriteListener::onAddition()
|
||||
{
|
||||
//std::cout << "QEMUMemWriteListener::onAddition" << std::endl;
|
||||
if (failqemu_add_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1) != 0) {
|
||||
std::cout << "adding watchpoint failed!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void QEMUMemWriteListener::onDeletion()
|
||||
{
|
||||
//std::cout << "QEMUMemWriteListener::onDeletion" << std::endl;
|
||||
failqemu_remove_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1);
|
||||
}
|
||||
|
||||
bool QEMUTimerListener::onAddition()
|
||||
{
|
||||
//std::cout << "QEMUTimerListener::onAddition" << std::endl;
|
||||
setId(failqemu_register_timer(getTimeout(), (void *)this));
|
||||
//std::cout << "this = " << std::hex << (unsigned) this << std::endl;
|
||||
//std::cout << "id = " << std::hex << (unsigned) getId() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void QEMUTimerListener::onDeletion()
|
||||
{
|
||||
//std::cout << "QEMUTimerListener::onDeletion" << std::endl;
|
||||
//std::cout << "this = " << std::hex << (unsigned) this << std::endl;
|
||||
//std::cout << "id = " << std::hex << (unsigned) getId() << std::endl;
|
||||
failqemu_unregister_timer(getId());
|
||||
}
|
||||
|
||||
} // end-of-namespace: fail
|
||||
@ -1,40 +0,0 @@
|
||||
#ifndef __QEMU_LISTENER_HPP__
|
||||
#define __QEMU_LISTENER_HPP__
|
||||
|
||||
#include "../Listener.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
typedef GenericBPSingleListener BPSingleListener;
|
||||
|
||||
/**
|
||||
* \class QEMUTimerListener
|
||||
* Concrete TimerListener implementation of GenericTimerListener for QEMU.
|
||||
*/
|
||||
class QEMUTimerListener : public GenericTimerListener {
|
||||
private:
|
||||
public:
|
||||
QEMUTimerListener(unsigned timeout)
|
||||
: GenericTimerListener(timeout) { }
|
||||
~QEMUTimerListener() { onDeletion(); } // FIXME ~BaseListener should automatically dequeue a Listener, and then indirectly calls onDeletion. In the current implementation, no dequeueing happens at all.
|
||||
bool onAddition();
|
||||
void onDeletion();
|
||||
};
|
||||
typedef QEMUTimerListener TimerListener;
|
||||
|
||||
class QEMUMemWriteListener : public GenericMemWriteListener {
|
||||
public:
|
||||
QEMUMemWriteListener()
|
||||
: GenericMemWriteListener() { }
|
||||
QEMUMemWriteListener(address_t addr)
|
||||
: GenericMemWriteListener(addr) { }
|
||||
|
||||
virtual bool onAddition();
|
||||
virtual void onDeletion();
|
||||
};
|
||||
|
||||
typedef QEMUMemWriteListener MemWriteListener;
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
#endif // __QEMU_LISTENER_HPP__
|
||||
Reference in New Issue
Block a user