T32: Integrated Register read/write calls
* Tested without connected Lauterbach. T32_* functions are mocked via aspect. * New target t32cli, for sending T32 command cia cli. (for testing) git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@2103 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -60,8 +60,12 @@ elseif(BUILD_T32)
|
||||
Register.cc
|
||||
SimulatorController.cc
|
||||
t32/T32Controller.cc
|
||||
t32/wrappers.cc
|
||||
)
|
||||
if(BUILD_ARM)
|
||||
set(SRCS ${SRCS}
|
||||
t32/T32ArmCPU.cc
|
||||
)
|
||||
endif(BUILD_ARM)
|
||||
endif(BUILD_BOCHS)
|
||||
|
||||
if(BUILD_X86)
|
||||
|
||||
@ -15,6 +15,11 @@
|
||||
#include "qemu/QEMUConfig.hpp"
|
||||
#elif defined BUILD_T32
|
||||
#include "t32/T32Config.hpp"
|
||||
#if defined BUILD_ARM
|
||||
#include "t32/T32ArmCPU.hpp"
|
||||
#else
|
||||
#error Active config currently not supported!
|
||||
#endif
|
||||
#else
|
||||
#error SAL Config Target not defined
|
||||
#endif
|
||||
|
||||
@ -10,7 +10,7 @@ namespace fail {
|
||||
|
||||
/**
|
||||
* \class Gem5ArmCPU
|
||||
*
|
||||
*
|
||||
* \c Gem5ArmCPU is the concrete CPU implementation for the gem5 ARM simulator. It
|
||||
* implements the CPU interfaces \c ArmArchitecture and \c ArmCPUState.
|
||||
* \c ArmArchitecture refers to architectural information (e.g. register \a count)
|
||||
|
||||
@ -10,7 +10,7 @@ namespace fail {
|
||||
|
||||
/**
|
||||
* \class Gem5Controller
|
||||
*
|
||||
*
|
||||
* Gem5-specific implementation of a SimulatorController.
|
||||
*/
|
||||
class Gem5Controller : public SimulatorController {
|
||||
|
||||
@ -19,7 +19,7 @@ namespace fail {
|
||||
class Gem5MemoryManager : public MemoryManager {
|
||||
public:
|
||||
Gem5MemoryManager(System* system) : m_System(system), m_Mem(&system->getPhysMem()) { }
|
||||
|
||||
|
||||
size_t getPoolSize() const { return m_Mem->totalSize(); }
|
||||
host_address_t getStartAddr() const { return 0; }
|
||||
|
||||
|
||||
53
src/core/sal/t32/T32ArmCPU.cc
Normal file
53
src/core/sal/t32/T32ArmCPU.cc
Normal file
@ -0,0 +1,53 @@
|
||||
#include "T32ArmCPU.hpp"
|
||||
#include <t32.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace fail {
|
||||
|
||||
regdata_t T32ArmCPU::getRegisterContent(Register* reg) const
|
||||
{
|
||||
// T32_ReadRegister wants a mask of bits representig the registers to read:
|
||||
// e.g., reading R1 and R4 and R63
|
||||
// mask1
|
||||
// 0000 0000 0000 0000 0001 0010 -> R1/R4
|
||||
// mask2
|
||||
// 1000 0000 0000 0000 0001 0010 -> R63
|
||||
uint64_t mask = (1 << reg->getIndex());
|
||||
|
||||
if(mask){
|
||||
if( T32_ReadRegister(static_cast<dword>(mask & 0xffffffff), static_cast<dword>(mask >> 32), m_regbuffer) == 0 ){
|
||||
// No error, return value.
|
||||
return m_regbuffer[reg->getIndex()];
|
||||
} else {
|
||||
/// TODO Error handling!
|
||||
}
|
||||
}
|
||||
return 0; // we should not come here.
|
||||
}
|
||||
|
||||
void T32ArmCPU::setRegisterContent(Register* reg, regdata_t value)
|
||||
{
|
||||
uint64_t mask = (1 << reg->getIndex());
|
||||
|
||||
if(mask){
|
||||
if( T32_WriteRegister(static_cast<dword>(mask & 0xffffffff), static_cast<dword>(mask >> 32), m_regbuffer) == 0 ){
|
||||
// No error, return value.
|
||||
return;
|
||||
} else {
|
||||
/// TODO Error handling!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
address_t T32ArmCPU::getInstructionPointer() const
|
||||
{
|
||||
// TODO: programpointer is only valid when Emulation is stopped! -> T32_GetState)
|
||||
address_t programpointer;
|
||||
T32_ReadPP( &programpointer );
|
||||
return programpointer;
|
||||
}
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
|
||||
75
src/core/sal/t32/T32ArmCPU.hpp
Normal file
75
src/core/sal/t32/T32ArmCPU.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef __T32_ARM_CPU_HPP__
|
||||
#define __T32_ARM_CPU_HPP__
|
||||
|
||||
#include "../arm/Architecture.hpp"
|
||||
#include "../arm/CPUState.hpp"
|
||||
#include <t32.h>
|
||||
|
||||
namespace fail {
|
||||
|
||||
/**
|
||||
* \class T32ArmCPU
|
||||
*
|
||||
* \c T32ArmCPU is the concrete CPU implementation for the T32 ARM debugger. It
|
||||
* implements the CPU interfaces \c ArmArchitecture and \c ArmCPUState.
|
||||
* \c ArmArchitecture refers to architectural information (e.g. register \a count)
|
||||
* while \c ArmCPUState encapsulates the CPU state (e.g. register \a content).
|
||||
*/
|
||||
class T32ArmCPU : public ArmArchitecture, public ArmCPUState {
|
||||
public:
|
||||
/**
|
||||
* Creates a new gem5 CPU for ARM based targets.
|
||||
* @param id the unique ID of the CPU to be created (the first CPU0 has ID 0)
|
||||
* @param system the gem5 system object
|
||||
*/
|
||||
T32ArmCPU(unsigned int id = 0) : m_Id(id) { }
|
||||
virtual ~T32ArmCPU() { }
|
||||
/**
|
||||
* Retrieves the register content from the current CPU.
|
||||
* @param reg the destination register whose content should be retrieved
|
||||
* @return the content of register \c reg
|
||||
*/
|
||||
regdata_t getRegisterContent(Register* reg) const;
|
||||
/**
|
||||
* Sets the register content for the \a current CPU.
|
||||
* @param reg the (initialized) register object whose content should be set
|
||||
* @param value the new content of the register \c reg
|
||||
*/
|
||||
void setRegisterContent(Register* reg, regdata_t value);
|
||||
/**
|
||||
* Retrieves the current instruction pointer (IP aka program counter, PC for short)
|
||||
* for the current CPU \c this.
|
||||
* @return the current instruction ptr address
|
||||
*/
|
||||
address_t getInstructionPointer() const;
|
||||
|
||||
/**
|
||||
* Retrieves the current stack pointer for the current CPU \c this.
|
||||
* @return the current stack ptr address
|
||||
*/
|
||||
address_t getStackPointer() const { return getRegisterContent(getRegister(RI_SP)); }
|
||||
/**
|
||||
* Retrieves the link register (return address when a function returns) for
|
||||
* the current CPU \c this. See
|
||||
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/ch02s08s01.html
|
||||
* for further information.
|
||||
* @return the current link register address
|
||||
*/
|
||||
address_t getLinkRegister() const { return getRegisterContent(getRegister(RI_LR)); }
|
||||
/**
|
||||
* Returns the ID of the current CPU.
|
||||
* @return the unique ID of \c this CPU object
|
||||
*/
|
||||
unsigned int getId() const { return m_Id; }
|
||||
private:
|
||||
unsigned int m_Id; //!< the unique ID of this CPU
|
||||
mutable dword m_regbuffer[64]; //!< internal buffer for reading/writing registers, wow mutable really makes sense sometimes.
|
||||
// char* cpuname? OMAP4430APP1 ??
|
||||
|
||||
};
|
||||
|
||||
typedef T32ArmCPU ConcreteCPU; //!< the concrete CPU type for ARM + T32
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
#endif // __T32_ARM_CPU_HPP__
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* \brief Type definitions and configuration settings for the
|
||||
* T32 target backend.
|
||||
* T32 target backend.
|
||||
*/
|
||||
|
||||
#ifndef __T32_CONFIG_HPP__
|
||||
@ -13,7 +13,8 @@ namespace fail {
|
||||
typedef uint32_t guest_address_t; //!< the guest memory address type
|
||||
typedef unsigned char* host_address_t; //!< the host memory address type
|
||||
typedef uint32_t register_data_t; //!< register data type (64 bit)
|
||||
typedef T32Timer* timer_t; //!< type of timer IDs
|
||||
typedef int timer_t; //!< type of timer IDs
|
||||
//typedef T32Timer* timer_t; //!< type of timer IDs
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
|
||||
56
src/core/sal/t32/T32Connector.cc
Normal file
56
src/core/sal/t32/T32Connector.cc
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* FailT32 -- Fault Injection on the Lauterbach Trace32 System
|
||||
*
|
||||
* 1. Invoke t32 executable with appropriate Lauterbach Skript
|
||||
* - Script has to load binary
|
||||
* - and let system run until entry point
|
||||
* -> Then we have a readily configured system
|
||||
*
|
||||
* @author Martin Hoffmann <hoffmann@cs.fau.de>
|
||||
* @date 15.02.2013
|
||||
*/
|
||||
|
||||
#include <t32.h>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* Default T32 error handler */
|
||||
void err(int ernum){
|
||||
if(err != 0){
|
||||
cerr << "Error: " << err << endl;
|
||||
//exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Here we go... */
|
||||
int main(int argc, char** argv){
|
||||
|
||||
// Evaluate arguments
|
||||
|
||||
// Setup connection to Lauterbach
|
||||
cout << "Lauterbach remote connection" << endl;
|
||||
int error;
|
||||
char hostname[] = "localhost";
|
||||
char packlen[] = "1024";
|
||||
char port[] = "20010";
|
||||
|
||||
cout << "[T32] Connecting to " << hostname << ":" << port << " Packlen: " << packlen << endl;
|
||||
T32_Config("NODE=", hostname);
|
||||
T32_Config("PACKLEN=", packlen);
|
||||
T32_Config("PORT=", port);
|
||||
|
||||
cout << "[T32] Init." << endl;
|
||||
err(T32_Init());
|
||||
|
||||
cout << "[T32] Attach." << endl;
|
||||
err(T32_Attach(T32_DEV_ICD));
|
||||
|
||||
|
||||
// Let simulatorcontroller do the work.
|
||||
|
||||
}
|
||||
24
src/core/sal/t32/T32Connector.hpp
Normal file
24
src/core/sal/t32/T32Connector.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __T32_CONNECTOR_HPP__
|
||||
#define __T32_CONNECTOR_HPP__
|
||||
|
||||
#include <t32.h>
|
||||
|
||||
namespace fail {
|
||||
|
||||
/**
|
||||
* \class T32Connector
|
||||
*/
|
||||
class T32Connector {
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Save simulator state. Quite hard on real hardware! Also safe all HW registers!
|
||||
* @param path Location to store state information
|
||||
* @return \c true if the state has been successfully saved, \c false otherwise
|
||||
*/
|
||||
};
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
#endif // __T32_CONNECTOR_HPP__
|
||||
@ -1,23 +1,26 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "T32Controller.hpp"
|
||||
#include "T32Memory.hpp"
|
||||
#include "T32Register.hpp"
|
||||
#include "../Register.hpp"
|
||||
#include "../SALInst.hpp"
|
||||
#include "T32Connector.hpp"
|
||||
|
||||
#include "../Listener.hpp"
|
||||
|
||||
|
||||
namespace fail {
|
||||
|
||||
T32Controller::T32Controller()
|
||||
: SimulatorController(new T32RegisterManager(), new T32MemoryManager())
|
||||
{
|
||||
// TODO: probably do additional RegisterManager initializations
|
||||
void T32Controller::startup(){
|
||||
// Do some T32-specific startup
|
||||
addCPU(new ConcreteCPU(0));
|
||||
// Startup generic SimulatorController
|
||||
SimulatorController::startup();
|
||||
}
|
||||
|
||||
|
||||
T32Controller::~T32Controller()
|
||||
{
|
||||
delete m_Regs;
|
||||
delete m_Mem;
|
||||
std::vector<ConcreteCPU*>::iterator it = m_CPUs.begin();
|
||||
while (it != m_CPUs.end()) {
|
||||
delete *it;
|
||||
it = m_CPUs.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,27 +1,18 @@
|
||||
#ifndef __T32_CONTROLLER_HPP__
|
||||
#define __T32_CONTROLLER_HPP__
|
||||
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string.h>
|
||||
|
||||
#include "../SimulatorController.hpp"
|
||||
#include "T32Memory.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
class ExperimentFlow;
|
||||
class TimerListener;
|
||||
|
||||
/**
|
||||
* \class T32Controller
|
||||
* Very rudimentary, T32-specific implementation of a SimulatorController.
|
||||
*/
|
||||
class T32Controller : public SimulatorController {
|
||||
public:
|
||||
// Initialize the controller.
|
||||
T32Controller();
|
||||
void startup();
|
||||
~T32Controller();
|
||||
|
||||
|
||||
@ -29,8 +20,7 @@ public:
|
||||
* Simulator Controller & Access API:
|
||||
* ********************************************************************/
|
||||
/**
|
||||
* Save simulator state. Quite hard on real hardware! Also safe all
|
||||
* HW registers!
|
||||
* Save simulator state. Quite hard on real hardware! Also safe all HW registers! TODO
|
||||
* @param path Location to store state information
|
||||
* @return \c true if the state has been successfully saved, \c false otherwise
|
||||
*/
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#ifndef __T32LISTENER_AH__
|
||||
#define __T32LISTENER_AH__
|
||||
|
||||
#include "config/VariantConfig.hpp"
|
||||
#include "config/FailConfig.hpp"
|
||||
#include "config/VariantConfig.hpp"
|
||||
|
||||
#if defined(BUILD_T32) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||
|
||||
@ -10,23 +10,22 @@
|
||||
|
||||
aspect T32Listener
|
||||
|
||||
advice "fail::MemWriteListener" : slice class
|
||||
advice "fail::BPSingleListener" : slice class
|
||||
{
|
||||
public:
|
||||
bool onAddition()
|
||||
{
|
||||
//std::cout << "T32MemWriteListener::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;
|
||||
|
||||
// Setup Breakpoint in T32
|
||||
std::cout << "T32Listener::onAddition" << std::endl;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void onDeletion()
|
||||
{
|
||||
//std::cout << "T32MemWriteListener::onDeletion" << std::endl;
|
||||
//failqemu_remove_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1);
|
||||
// Delete Breakpoint in T32
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
|
||||
#include "../Memory.hpp"
|
||||
|
||||
#include <t32.h>
|
||||
|
||||
namespace fail {
|
||||
|
||||
/**
|
||||
@ -11,29 +13,44 @@ namespace fail {
|
||||
* MemoryManager to provide access to T32's memory pool.
|
||||
*/
|
||||
class T32MemoryManager : public MemoryManager {
|
||||
|
||||
enum ACCESS_CLASS {
|
||||
data_access = 0,
|
||||
program_access = 1,
|
||||
AD_access = 12,
|
||||
AP_access = 13,
|
||||
USR_access = 15,
|
||||
};
|
||||
|
||||
public:
|
||||
size_t getPoolSize() const { return 0; /* TODO */ }
|
||||
|
||||
host_address_t getStartAddr() const { return 0; }
|
||||
|
||||
byte_t getByte(guest_address_t addr)
|
||||
{
|
||||
return 0; //failqemu_mem_read_byte(addr);
|
||||
}
|
||||
char b;
|
||||
getBytes(addr, 1, &b);
|
||||
return b;
|
||||
}
|
||||
|
||||
void getBytes(guest_address_t addr, size_t cnt, void *dest)
|
||||
{
|
||||
char *d = static_cast<char *>(dest);
|
||||
for (size_t i = 0; i < cnt; ++i)
|
||||
d[i] = 0; //getByte(addr + i);
|
||||
int access = data_access; // TODO what access class do we need?!
|
||||
T32_ReadMemory( addr, access, (byte*)(dest), cnt);
|
||||
}
|
||||
|
||||
void setByte(guest_address_t addr, byte_t data)
|
||||
{
|
||||
//failqemu_mem_write_byte(addr, data);
|
||||
setBytes(addr, 1, &data);
|
||||
}
|
||||
|
||||
void setBytes(guest_address_t addr, size_t cnt, void const *src)
|
||||
{
|
||||
//char const *s = static_cast<char const *>(src);
|
||||
for (size_t i = 0; i < cnt; ++i)
|
||||
; //setByte(addr + i, s[i]);
|
||||
int access = data_access; // TODO what access class do we really need?!
|
||||
T32_WriteMemory(addr, access, (byte*)(src), cnt);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
26
src/core/sal/t32/T32Mock.ah
Normal file
26
src/core/sal/t32/T32Mock.ah
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef __T32MOCK_AH__
|
||||
#define __T32MOCK_AH__
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BUILD_T32) // && defined(T32MOCK)
|
||||
|
||||
/* Mock aspect for testing without T32 HW attached. */
|
||||
aspect T32Mock
|
||||
{
|
||||
advice call("% T32_% (...)") : around ()
|
||||
{
|
||||
std::cout << "[T32 MOCK] " << JoinPoint::signature() << " (";
|
||||
|
||||
for(int i = 0; i < tjp->args(); i++) {
|
||||
std::cout << std::hex << *((int*)( tjp->arg(i) ) );
|
||||
if(i < tjp->args()-1) std::cout << ", ";
|
||||
}
|
||||
std::cout << ")" << std::endl;
|
||||
|
||||
*tjp->result() = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BUILD_T32 && CONFIG_EVENT_BREAKPOINTS
|
||||
#endif // __T32MOCK_AH__
|
||||
@ -1,45 +0,0 @@
|
||||
#ifndef __T32_REGISTER_HPP__
|
||||
#define __T32_REGISTER_HPP__
|
||||
|
||||
#include "../Register.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
namespace fail {
|
||||
|
||||
/**
|
||||
* \class T32Register
|
||||
* T32-specific implementation of ?? registers. TODO.
|
||||
*/
|
||||
class T32Register : public Register {
|
||||
public:
|
||||
T32Register(unsigned int id, regwidth_t width, regdata_t* link, RegisterType t)
|
||||
: Register(id, t, width) { }
|
||||
regdata_t getData() { return 0; /* TODO */ }
|
||||
void setData(regdata_t data) { /* TODO */ }
|
||||
};
|
||||
|
||||
/**
|
||||
* \class T32RegisterManager
|
||||
* T32-specific implementation of the RegisterManager. TODO.
|
||||
*/
|
||||
class T32RegisterManager : public RegisterManager {
|
||||
public:
|
||||
address_t getInstructionPointer()
|
||||
{
|
||||
return static_cast<address_t>(0); /* TODO */
|
||||
}
|
||||
address_t getStackPointer()
|
||||
{
|
||||
return static_cast<address_t>(0); /* TODO */
|
||||
}
|
||||
address_t getBasePointer()
|
||||
{
|
||||
return static_cast<address_t>(0); /* TODO */
|
||||
}
|
||||
};
|
||||
|
||||
} // end-of-namespace: fail
|
||||
|
||||
#endif // __T32_REGISTER_HPP__
|
||||
@ -14,83 +14,24 @@
|
||||
#include "sal/Memory.hpp"
|
||||
#include "sal/Listener.hpp"
|
||||
|
||||
#include "sal/bochs/BochsListener.hpp"
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using namespace fail;
|
||||
|
||||
// Check if configuration dependencies are satisfied:
|
||||
#if !defined(CONFIG_EVENT_BREAKPOINTS) || !defined(CONFIG_SR_RESTORE) || \
|
||||
!defined(CONFIG_SR_SAVE)
|
||||
#error This experiment needs: breakpoints, traps, save, and restore. Enable these in the configuration.
|
||||
#endif
|
||||
|
||||
#define SAVESTATE (0)
|
||||
|
||||
void VEZSExperiment::printEIP() {
|
||||
m_log << "EIP = 0x" << hex << simulator.getCPU(0).getInstructionPointer() <<" "<< m_elf.getNameByAddress(simulator.getCPU(0).getInstructionPointer()) << endl;
|
||||
}
|
||||
|
||||
std::vector<string> v;
|
||||
|
||||
bool VEZSExperiment::run()
|
||||
{
|
||||
m_log << "STARTING EXPERIMENT" << endl;
|
||||
printEIP();
|
||||
m_log << "Instruction Pointer: 0x" << hex << simulator.getCPU(0).getInstructionPointer() << endl;
|
||||
|
||||
#if(SAVESTATE)
|
||||
m_log << "Booting, and saving state at ";
|
||||
BPSingleListener bp;
|
||||
// STEP 1: run until interesting function starts, and save state
|
||||
bp.setWatchInstructionPointer(m_elf.getAddressByName("main"));
|
||||
if(simulator.addListenerAndResume(&bp) == &bp){
|
||||
m_log << "test function entry reached, saving state" << endl;
|
||||
}
|
||||
printEIP();
|
||||
//simulator.terminate();
|
||||
simulator.save("vezs.state");
|
||||
Register* reg = simulator.getCPU(0).getRegister(RI_R1);
|
||||
m_log << "Register R2: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
||||
|
||||
reg = simulator.getCPU(0).getRegister(RI_R2);
|
||||
m_log << "Register R1: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
||||
|
||||
simulator.getCPU(0).setRegisterContent(reg, 0x23);
|
||||
// Explicitly terminate, or the simulator will continue to run.
|
||||
simulator.terminate();
|
||||
#else
|
||||
simulator.restore("vezs.state");
|
||||
//m_elf.printDemangled();
|
||||
BPSingleListener bpt0;
|
||||
BPSingleListener bpt1;
|
||||
BPSingleListener bpt2;
|
||||
//BPSingleListener inst(ANY_ADDR);
|
||||
//bpt0.setWatchInstructionPointer(m_elf.getAddressByName("c17_Main_m4_dumpResults_console"));
|
||||
//bpt0.setWatchInstructionPointer(m_elf.getAddressByName("keso_throw_error"));
|
||||
//bpt1.setWatchInstructionPointer(m_elf.getAddressByName("c17_Main_m3_run"));
|
||||
bpt2.setWatchInstructionPointer(m_elf.getAddressByName("os::krn::OSControl::shutdownOS"));
|
||||
//simulator.addListener(&bpt0);
|
||||
//simulator.addListener(&bpt1);
|
||||
//simulator.addListener(&bpt2);
|
||||
simulator.addListener(&bpt2);
|
||||
fail::BaseListener* l = simulator.resume();
|
||||
printEIP();
|
||||
simulator.terminate();
|
||||
while(1){
|
||||
if(simulator.getCPU(0).getInstructionPointer() == m_elf.getAddressByName("os::krn::OSControl::shutdownOS")) {
|
||||
printEIP();
|
||||
break;
|
||||
}else{
|
||||
//std::string name = m_elf.getNameByAddress(simulator.getCPU(0).getInstructionPointer());
|
||||
//if(name != ElfReader::NOTFOUND){
|
||||
// v.push_back(name);
|
||||
//}
|
||||
printEIP();
|
||||
l = simulator.addListenerAndResume(l);
|
||||
}
|
||||
}
|
||||
|
||||
// simulator.clearListeners();
|
||||
// bpt1.setWatchInstructionPointer(m_elf.getAddressByName("os::krn::SchedImpl::superDispatch_impl"));
|
||||
// for(;;){
|
||||
// simulator.addListenerAndResume(&bpt1);
|
||||
// printEIP();
|
||||
// }
|
||||
|
||||
// Explicitly terminate, or the simulator will continue to run.
|
||||
#endif
|
||||
simulator.terminate();
|
||||
}
|
||||
|
||||
@ -1,19 +1,15 @@
|
||||
#ifndef __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
||||
#define __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
||||
|
||||
|
||||
#include "efw/ExperimentFlow.hpp"
|
||||
#include "efw/JobClient.hpp"
|
||||
#include "util/Logger.hpp"
|
||||
#include "util/ElfReader.hpp"
|
||||
|
||||
class VEZSExperiment : public fail::ExperimentFlow {
|
||||
|
||||
fail::JobClient m_jc;
|
||||
fail::ElfReader m_elf;
|
||||
fail::Logger m_log;
|
||||
|
||||
void printEIP();
|
||||
|
||||
public:
|
||||
VEZSExperiment() : m_log("VEZS-example", false) {};
|
||||
bool run();
|
||||
|
||||
Reference in New Issue
Block a user