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:
@ -51,7 +51,8 @@ elseif(BUILD_OVP)
|
|||||||
elseif(BUILD_QEMU)
|
elseif(BUILD_QEMU)
|
||||||
include_directories(simulators)
|
include_directories(simulators)
|
||||||
elseif(BUILD_T32)
|
elseif(BUILD_T32)
|
||||||
add_subdirectory(hwdebuggers/t32)
|
include_directories(debuggers/t32/include src/core)
|
||||||
|
add_subdirectory(debuggers/t32)
|
||||||
endif(BUILD_BOCHS)
|
endif(BUILD_BOCHS)
|
||||||
|
|
||||||
## Additional compiler and linker flags ##
|
## Additional compiler and linker flags ##
|
||||||
|
|||||||
1
debuggers/gdb/README
Normal file
1
debuggers/gdb/README
Normal file
@ -0,0 +1 @@
|
|||||||
|
TODO: a nice GDB backend.
|
||||||
@ -91,7 +91,7 @@ extern struct hostent * gethostbyaddr();
|
|||||||
# define FD_ISSET(fd,fdset) (*fdset & (1<<(fd)))
|
# define FD_ISSET(fd,fdset) (*fdset & (1<<(fd)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DEC_VMS) || defined(MS_WINDOWS) || defined(OS_9) || defined(LINUX)
|
#if defined(DEC_VMS) || defined(MS_WINDOWS) || defined(OS_9) || defined(LINUX)
|
||||||
# define RECEIVEADDR (&ReceiveSocketAddress)
|
# define RECEIVEADDR (&ReceiveSocketAddress)
|
||||||
static struct sockaddr ReceiveSocketAddress;
|
static struct sockaddr ReceiveSocketAddress;
|
||||||
#else
|
#else
|
||||||
@ -106,7 +106,7 @@ struct LineStruct {
|
|||||||
unsigned short ReceivePort; /* Receiver Port */
|
unsigned short ReceivePort; /* Receiver Port */
|
||||||
unsigned short TransmitPort; /* Transmitter Port in T32 */
|
unsigned short TransmitPort; /* Transmitter Port in T32 */
|
||||||
int PacketSize; /* Max. size of UDP-packet data */
|
int PacketSize; /* Max. size of UDP-packet data */
|
||||||
int PollTimeSec;
|
int PollTimeSec;
|
||||||
int ReceiveToggleBit;
|
int ReceiveToggleBit;
|
||||||
unsigned char MessageId;
|
unsigned char MessageId;
|
||||||
int LineUp;
|
int LineUp;
|
||||||
@ -227,28 +227,28 @@ int LINE_LineConfig(char * in)
|
|||||||
}
|
}
|
||||||
if (!strncmp((char *) in, "PORT=", 5)) {
|
if (!strncmp((char *) in, "PORT=", 5)) {
|
||||||
x = str2dec (in+5);
|
x = str2dec (in+5);
|
||||||
if (x == -1)
|
if (x == -1)
|
||||||
return -1;
|
return -1;
|
||||||
line->TransmitPort = x;
|
line->TransmitPort = x;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!strncmp((char *) in, "HOSTPORT=", 9)) {
|
if (!strncmp((char *) in, "HOSTPORT=", 9)) {
|
||||||
x = str2dec (in+9);
|
x = str2dec (in+9);
|
||||||
if (x == -1)
|
if (x == -1)
|
||||||
return -1;
|
return -1;
|
||||||
line->HostPort = x;
|
line->HostPort = x;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!strncmp((char *) in, "PACKLEN=", 8)) {
|
if (!strncmp((char *) in, "PACKLEN=", 8)) {
|
||||||
x = str2dec (in+8);
|
x = str2dec (in+8);
|
||||||
if (x == -1)
|
if (x == -1)
|
||||||
return -1;
|
return -1;
|
||||||
line->PacketSize = x;
|
line->PacketSize = x;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!strncmp((char *) in, "TIMEOUT=", 8)) {
|
if (!strncmp((char *) in, "TIMEOUT=", 8)) {
|
||||||
x = str2dec (in+8);
|
x = str2dec (in+8);
|
||||||
if (x == -1)
|
if (x == -1)
|
||||||
return -1;
|
return -1;
|
||||||
line->PollTimeSec = x;
|
line->PollTimeSec = x;
|
||||||
return 1;
|
return 1;
|
||||||
@ -353,7 +353,7 @@ void LINE_LineExit(void)
|
|||||||
|
|
||||||
if (line->CommSocket != -1) {
|
if (line->CommSocket != -1) {
|
||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
sendto(line->CommSocket, (char *) discon, 16, 0,
|
sendto(line->CommSocket, (char *) discon, 16, 0,
|
||||||
(struct sockaddr *) &(line->SocketAddress), sizeof(line->SocketAddress));
|
(struct sockaddr *) &(line->SocketAddress), sizeof(line->SocketAddress));
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
@ -516,7 +516,7 @@ void T32_UnInstallAsyncSelect(HWND hwnd)
|
|||||||
/**
|
/**
|
||||||
Sends a message to T32. Handles segmentation of _message_ into (one
|
Sends a message to T32. Handles segmentation of _message_ into (one
|
||||||
or multiple) _packages_.
|
or multiple) _packages_.
|
||||||
|
|
||||||
@param in pointer to outgoing message (already includes 5 byte message header)
|
@param in pointer to outgoing message (already includes 5 byte message header)
|
||||||
@param size size of message
|
@param size size of message
|
||||||
@note the message must be allocated such that there is space in
|
@note the message must be allocated such that there is space in
|
||||||
@ -533,11 +533,11 @@ int LINE_LineTransmit(unsigned char * in, int size)
|
|||||||
line->LastTransmitSize = size;
|
line->LastTransmitSize = size;
|
||||||
line->LastTransmitSeq = line->TransmitSeq;
|
line->LastTransmitSeq = line->TransmitSeq;
|
||||||
in -= 4; /* space for packet header */
|
in -= 4; /* space for packet header */
|
||||||
|
|
||||||
do {
|
do {
|
||||||
packetSize = (size > line->PacketSize - 4) ? line->PacketSize - 4 : size;
|
packetSize = (size > line->PacketSize - 4) ? line->PacketSize - 4 : size;
|
||||||
|
|
||||||
/* When sending multiple packets, the packet header is written inside the
|
/* When sending multiple packets, the packet header is written inside the
|
||||||
message's payload. Original contents needs to be saved/restored */
|
message's payload. Original contents needs to be saved/restored */
|
||||||
|
|
||||||
SETLONGVAR(tmpl, in[0]); /* save */
|
SETLONGVAR(tmpl, in[0]); /* save */
|
||||||
@ -547,7 +547,7 @@ int LINE_LineTransmit(unsigned char * in, int size)
|
|||||||
SETWORDVAR(in[2], line->TransmitSeq); /* packet sequence ID */
|
SETWORDVAR(in[2], line->TransmitSeq); /* packet sequence ID */
|
||||||
|
|
||||||
if (sendto(line->CommSocket,
|
if (sendto(line->CommSocket,
|
||||||
(char *) in,
|
(char *) in,
|
||||||
packetSize + 4, 0,
|
packetSize + 4, 0,
|
||||||
(struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)
|
(struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress)
|
||||||
) != packetSize + 4) {
|
) != packetSize + 4) {
|
||||||
@ -576,9 +576,9 @@ static int ReceiveWithTimeout(struct timeval *tim, unsigned char *dest, int size
|
|||||||
socklen_t length;
|
socklen_t length;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
LineStruct* line = pLineParams;
|
LineStruct* line = pLineParams;
|
||||||
|
|
||||||
timeout = *tim;
|
timeout = *tim;
|
||||||
|
|
||||||
#ifdef POLL_NET
|
#ifdef POLL_NET
|
||||||
DWORD endpoll;
|
DWORD endpoll;
|
||||||
static struct timeval tival = {0};
|
static struct timeval tival = {0};
|
||||||
@ -657,11 +657,11 @@ retry:
|
|||||||
|
|
||||||
/* multiple packets are merged in-place: backup data that is
|
/* multiple packets are merged in-place: backup data that is
|
||||||
overwritten package aby header */
|
overwritten package aby header */
|
||||||
SETLONGVAR(tmpl, dest[0]);
|
SETLONGVAR(tmpl, dest[0]);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct timeval PollTime = {0, 0};
|
struct timeval PollTime = {0, 0};
|
||||||
PollTime.tv_sec = line->PollTimeSec;
|
PollTime.tv_sec = line->PollTimeSec;
|
||||||
if ((i = ReceiveWithTimeout(&PollTime, dest, line->PacketSize)) <= 0) {
|
if ((i = ReceiveWithTimeout(&PollTime, dest, line->PacketSize)) <= 0) {
|
||||||
if (i == -2)
|
if (i == -2)
|
||||||
goto retry;
|
goto retry;
|
||||||
@ -670,17 +670,17 @@ retry:
|
|||||||
if (i <= 4) {
|
if (i <= 4) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Detect and enqeue async notification that slipped into a request/reply pair */
|
/* Detect and enqeue async notification that slipped into a request/reply pair */
|
||||||
if (dest[0] == T32_API_NOTIFICATION)
|
if (dest[0] == T32_API_NOTIFICATION)
|
||||||
{
|
{
|
||||||
T32_NotificationPackage *newPackage, *oldHead;
|
T32_NotificationPackage *newPackage, *oldHead;
|
||||||
|
|
||||||
newPackage = reinterpret_cast<T32_NotificationPackage*>( malloc(sizeof(T32_NotificationPackage)) );
|
newPackage = reinterpret_cast<T32_NotificationPackage*>( malloc(sizeof(T32_NotificationPackage)) );
|
||||||
if (newPackage==NULL)
|
if (newPackage==NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
memcpy(newPackage, dest, i); /* in theory i should always be the package size, at least for ethernet */
|
memcpy(newPackage, dest, i); /* in theory i should always be the package size, at least for ethernet */
|
||||||
oldHead = T32_NotificationHead;
|
oldHead = T32_NotificationHead;
|
||||||
newPackage->prev = NULL;
|
newPackage->prev = NULL;
|
||||||
@ -693,12 +693,12 @@ retry:
|
|||||||
}
|
}
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dest[0] != T32_API_RECEIVE) {
|
if (dest[0] != T32_API_RECEIVE) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
SETWORDVAR(tmpw, dest[2]);
|
SETWORDVAR(tmpw, dest[2]);
|
||||||
|
|
||||||
if (tmpw == line->LastReceiveSeq && line->LastTransmitSize) {
|
if (tmpw == line->LastReceiveSeq && line->LastTransmitSize) {
|
||||||
line->TransmitSeq = line->LastTransmitSeq;
|
line->TransmitSeq = line->LastTransmitSeq;
|
||||||
LINE_LineTransmit(line->LastTransmitBuffer, line->LastTransmitSize);
|
LINE_LineTransmit(line->LastTransmitBuffer, line->LastTransmitSize);
|
||||||
@ -736,7 +736,7 @@ retry:
|
|||||||
function until it returns -1.
|
function until it returns -1.
|
||||||
|
|
||||||
@param package output buffer of size T32_PCKLEN_MAX for the package
|
@param package output buffer of size T32_PCKLEN_MAX for the package
|
||||||
@return -1 no notification pending,
|
@return -1 no notification pending,
|
||||||
>=0 notificataion type T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG
|
>=0 notificataion type T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@ -746,7 +746,7 @@ int LINE_ReceiveNotifyMessage(unsigned char* package)
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
static struct timeval LongTime = {0, 0};
|
static struct timeval LongTime = {0, 0};
|
||||||
|
|
||||||
/* Check for asynchronous notifications */
|
/* Check for asynchronous notifications */
|
||||||
if (T32_NotificationTail) {
|
if (T32_NotificationTail) {
|
||||||
T32_NotificationPackage *prev = T32_NotificationTail->prev;
|
T32_NotificationPackage *prev = T32_NotificationTail->prev;
|
||||||
@ -762,10 +762,10 @@ int LINE_ReceiveNotifyMessage(unsigned char* package)
|
|||||||
if (len < 2)
|
if (len < 2)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (package[0] != T32_API_NOTIFICATION)
|
if (package[0] != T32_API_NOTIFICATION)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return package[1]; /* type of notification: T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG */
|
return package[1]; /* type of notification: T32_E_BREAK, T32_E_EDIT, T32_E_BREAKPOINTCONFIG */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,7 +811,7 @@ retry:
|
|||||||
line->LastReceiveSeq = line->ReceiveSeq - 100;
|
line->LastReceiveSeq = line->ReceiveSeq - 100;
|
||||||
|
|
||||||
|
|
||||||
packet[0] = T32_API_SYNCBACK;
|
packet[0] = T32_API_SYNCBACK;
|
||||||
packet[1] = 0;
|
packet[1] = 0;
|
||||||
SETWORDVAR(packet[2], line->TransmitSeq);
|
SETWORDVAR(packet[2], line->TransmitSeq);
|
||||||
SETWORDCONST(packet[4], 0);
|
SETWORDCONST(packet[4], 0);
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
#ifndef __T32_H__
|
||||||
|
#define __T32_H__
|
||||||
|
|
||||||
#include <config/VariantConfig.hpp>
|
#include <config/VariantConfig.hpp>
|
||||||
|
|
||||||
@ -120,14 +122,14 @@ typedef unsigned int dword;
|
|||||||
|
|
||||||
/* Callbacks should have the following protoypes */
|
/* Callbacks should have the following protoypes */
|
||||||
/************************* WARNING *****************************/
|
/************************* WARNING *****************************/
|
||||||
/*
|
/*
|
||||||
* If you add more callback functions here, make sure you ONLY
|
* If you add more callback functions here, make sure you ONLY
|
||||||
* use 'int', 'unsigned int', 'integral-type *' or 'float-type *' as parameters.
|
* use 'int', 'unsigned int', 'integral-type *' or 'float-type *' as parameters.
|
||||||
*
|
*
|
||||||
* No 'long', no 'long long', no 'short', no 'char', no floats, no typedefs
|
* No 'long', no 'long long', no 'short', no 'char', no floats, no typedefs
|
||||||
* and no function pointers!
|
* and no function pointers!
|
||||||
* This is because we absolutely need to avoid portability problems here.
|
* This is because we absolutely need to avoid portability problems here.
|
||||||
*
|
*
|
||||||
* Explanation:
|
* Explanation:
|
||||||
* The T32_NotificationCallback_t typedef'd below has an empty parameter list,
|
* The T32_NotificationCallback_t typedef'd below has an empty parameter list,
|
||||||
* which we can't change anymore to a va_list because of backwards compatibility.
|
* which we can't change anymore to a va_list because of backwards compatibility.
|
||||||
@ -360,3 +362,5 @@ extern void* T32_GetChannel0(void);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
set(SRCS
|
set(SRCS
|
||||||
t32connector.cc
|
T32Connector.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(fail-client ${SRCS})
|
add_executable(fail-client ${SRCS})
|
||||||
@ -7,3 +7,5 @@ target_link_libraries(fail-client -Wl,-whole-archive t32api -Wl,-no-whole-archiv
|
|||||||
|
|
||||||
install(TARGETS fail-client RUNTIME DESTINATION bin)
|
install(TARGETS fail-client RUNTIME DESTINATION bin)
|
||||||
|
|
||||||
|
add_executable(t32cli t32cli.cc)
|
||||||
|
target_link_libraries(t32cli -Wl,-whole-archive t32api -Wl,-no-whole-archive)
|
||||||
61
debuggers/t32/src/T32Connector.cc
Normal file
61
debuggers/t32/src/T32Connector.cc
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
#include "config/VariantConfig.hpp"
|
||||||
|
#include "sal/SALInst.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
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 the SimulatorController do the dirty work.
|
||||||
|
fail::simulator.startup();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
24
debuggers/t32/src/T32Connector.hpp
Normal file
24
debuggers/t32/src/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__
|
||||||
BIN
doc/t32_remote_api.pdf
Normal file
BIN
doc/t32_remote_api.pdf
Normal file
Binary file not shown.
@ -60,8 +60,12 @@ elseif(BUILD_T32)
|
|||||||
Register.cc
|
Register.cc
|
||||||
SimulatorController.cc
|
SimulatorController.cc
|
||||||
t32/T32Controller.cc
|
t32/T32Controller.cc
|
||||||
t32/wrappers.cc
|
|
||||||
)
|
)
|
||||||
|
if(BUILD_ARM)
|
||||||
|
set(SRCS ${SRCS}
|
||||||
|
t32/T32ArmCPU.cc
|
||||||
|
)
|
||||||
|
endif(BUILD_ARM)
|
||||||
endif(BUILD_BOCHS)
|
endif(BUILD_BOCHS)
|
||||||
|
|
||||||
if(BUILD_X86)
|
if(BUILD_X86)
|
||||||
|
|||||||
@ -15,6 +15,11 @@
|
|||||||
#include "qemu/QEMUConfig.hpp"
|
#include "qemu/QEMUConfig.hpp"
|
||||||
#elif defined BUILD_T32
|
#elif defined BUILD_T32
|
||||||
#include "t32/T32Config.hpp"
|
#include "t32/T32Config.hpp"
|
||||||
|
#if defined BUILD_ARM
|
||||||
|
#include "t32/T32ArmCPU.hpp"
|
||||||
|
#else
|
||||||
|
#error Active config currently not supported!
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error SAL Config Target not defined
|
#error SAL Config Target not defined
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -10,7 +10,7 @@ namespace fail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class Gem5ArmCPU
|
* \class Gem5ArmCPU
|
||||||
*
|
*
|
||||||
* \c Gem5ArmCPU is the concrete CPU implementation for the gem5 ARM simulator. It
|
* \c Gem5ArmCPU is the concrete CPU implementation for the gem5 ARM simulator. It
|
||||||
* implements the CPU interfaces \c ArmArchitecture and \c ArmCPUState.
|
* implements the CPU interfaces \c ArmArchitecture and \c ArmCPUState.
|
||||||
* \c ArmArchitecture refers to architectural information (e.g. register \a count)
|
* \c ArmArchitecture refers to architectural information (e.g. register \a count)
|
||||||
|
|||||||
@ -10,7 +10,7 @@ namespace fail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \class Gem5Controller
|
* \class Gem5Controller
|
||||||
*
|
*
|
||||||
* Gem5-specific implementation of a SimulatorController.
|
* Gem5-specific implementation of a SimulatorController.
|
||||||
*/
|
*/
|
||||||
class Gem5Controller : public SimulatorController {
|
class Gem5Controller : public SimulatorController {
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace fail {
|
|||||||
class Gem5MemoryManager : public MemoryManager {
|
class Gem5MemoryManager : public MemoryManager {
|
||||||
public:
|
public:
|
||||||
Gem5MemoryManager(System* system) : m_System(system), m_Mem(&system->getPhysMem()) { }
|
Gem5MemoryManager(System* system) : m_System(system), m_Mem(&system->getPhysMem()) { }
|
||||||
|
|
||||||
size_t getPoolSize() const { return m_Mem->totalSize(); }
|
size_t getPoolSize() const { return m_Mem->totalSize(); }
|
||||||
host_address_t getStartAddr() const { return 0; }
|
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
|
* \brief Type definitions and configuration settings for the
|
||||||
* T32 target backend.
|
* T32 target backend.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __T32_CONFIG_HPP__
|
#ifndef __T32_CONFIG_HPP__
|
||||||
@ -13,7 +13,8 @@ namespace fail {
|
|||||||
typedef uint32_t guest_address_t; //!< the guest memory address type
|
typedef uint32_t guest_address_t; //!< the guest memory address type
|
||||||
typedef unsigned char* host_address_t; //!< the host 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 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
|
} // 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 "T32Controller.hpp"
|
||||||
#include "T32Memory.hpp"
|
#include "T32Connector.hpp"
|
||||||
#include "T32Register.hpp"
|
|
||||||
#include "../Register.hpp"
|
#include "../Listener.hpp"
|
||||||
#include "../SALInst.hpp"
|
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
T32Controller::T32Controller()
|
void T32Controller::startup(){
|
||||||
: SimulatorController(new T32RegisterManager(), new T32MemoryManager())
|
// Do some T32-specific startup
|
||||||
{
|
addCPU(new ConcreteCPU(0));
|
||||||
// TODO: probably do additional RegisterManager initializations
|
// Startup generic SimulatorController
|
||||||
|
SimulatorController::startup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
T32Controller::~T32Controller()
|
T32Controller::~T32Controller()
|
||||||
{
|
{
|
||||||
delete m_Regs;
|
std::vector<ConcreteCPU*>::iterator it = m_CPUs.begin();
|
||||||
delete m_Mem;
|
while (it != m_CPUs.end()) {
|
||||||
|
delete *it;
|
||||||
|
it = m_CPUs.erase(it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,18 @@
|
|||||||
#ifndef __T32_CONTROLLER_HPP__
|
#ifndef __T32_CONTROLLER_HPP__
|
||||||
#define __T32_CONTROLLER_HPP__
|
#define __T32_CONTROLLER_HPP__
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "../SimulatorController.hpp"
|
#include "../SimulatorController.hpp"
|
||||||
|
#include "T32Memory.hpp"
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
class ExperimentFlow;
|
|
||||||
class TimerListener;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class T32Controller
|
* \class T32Controller
|
||||||
* Very rudimentary, T32-specific implementation of a SimulatorController.
|
* Very rudimentary, T32-specific implementation of a SimulatorController.
|
||||||
*/
|
*/
|
||||||
class T32Controller : public SimulatorController {
|
class T32Controller : public SimulatorController {
|
||||||
public:
|
public:
|
||||||
// Initialize the controller.
|
void startup();
|
||||||
T32Controller();
|
|
||||||
~T32Controller();
|
~T32Controller();
|
||||||
|
|
||||||
|
|
||||||
@ -29,8 +20,7 @@ public:
|
|||||||
* Simulator Controller & Access API:
|
* Simulator Controller & Access API:
|
||||||
* ********************************************************************/
|
* ********************************************************************/
|
||||||
/**
|
/**
|
||||||
* Save simulator state. Quite hard on real hardware! Also safe all
|
* Save simulator state. Quite hard on real hardware! Also safe all HW registers! TODO
|
||||||
* HW registers!
|
|
||||||
* @param path Location to store state information
|
* @param path Location to store state information
|
||||||
* @return \c true if the state has been successfully saved, \c false otherwise
|
* @return \c true if the state has been successfully saved, \c false otherwise
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
#ifndef __T32LISTENER_AH__
|
#ifndef __T32LISTENER_AH__
|
||||||
#define __T32LISTENER_AH__
|
#define __T32LISTENER_AH__
|
||||||
|
|
||||||
#include "config/VariantConfig.hpp"
|
|
||||||
#include "config/FailConfig.hpp"
|
#include "config/FailConfig.hpp"
|
||||||
|
#include "config/VariantConfig.hpp"
|
||||||
|
|
||||||
#if defined(BUILD_T32) && defined(CONFIG_EVENT_BREAKPOINTS)
|
#if defined(BUILD_T32) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||||
|
|
||||||
@ -10,23 +10,22 @@
|
|||||||
|
|
||||||
aspect T32Listener
|
aspect T32Listener
|
||||||
|
|
||||||
advice "fail::MemWriteListener" : slice class
|
advice "fail::BPSingleListener" : slice class
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool onAddition()
|
bool onAddition()
|
||||||
{
|
{
|
||||||
//std::cout << "T32MemWriteListener::onAddition" << std::endl;
|
|
||||||
//if (failqemu_add_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1) != 0) {
|
// Setup Breakpoint in T32
|
||||||
// std::cout << "adding watchpoint failed!" << std::endl;
|
std::cout << "T32Listener::onAddition" << std::endl;
|
||||||
return false;
|
|
||||||
//}
|
|
||||||
//return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDeletion()
|
void onDeletion()
|
||||||
{
|
{
|
||||||
//std::cout << "T32MemWriteListener::onDeletion" << std::endl;
|
// Delete Breakpoint in T32
|
||||||
//failqemu_remove_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "../Memory.hpp"
|
#include "../Memory.hpp"
|
||||||
|
|
||||||
|
#include <t32.h>
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,29 +13,44 @@ namespace fail {
|
|||||||
* MemoryManager to provide access to T32's memory pool.
|
* MemoryManager to provide access to T32's memory pool.
|
||||||
*/
|
*/
|
||||||
class T32MemoryManager : public MemoryManager {
|
class T32MemoryManager : public MemoryManager {
|
||||||
|
|
||||||
|
enum ACCESS_CLASS {
|
||||||
|
data_access = 0,
|
||||||
|
program_access = 1,
|
||||||
|
AD_access = 12,
|
||||||
|
AP_access = 13,
|
||||||
|
USR_access = 15,
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
size_t getPoolSize() const { return 0; /* TODO */ }
|
size_t getPoolSize() const { return 0; /* TODO */ }
|
||||||
|
|
||||||
host_address_t getStartAddr() const { return 0; }
|
host_address_t getStartAddr() const { return 0; }
|
||||||
|
|
||||||
byte_t getByte(guest_address_t addr)
|
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)
|
void getBytes(guest_address_t addr, size_t cnt, void *dest)
|
||||||
{
|
{
|
||||||
char *d = static_cast<char *>(dest);
|
int access = data_access; // TODO what access class do we need?!
|
||||||
for (size_t i = 0; i < cnt; ++i)
|
T32_ReadMemory( addr, access, (byte*)(dest), cnt);
|
||||||
d[i] = 0; //getByte(addr + i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setByte(guest_address_t addr, byte_t data)
|
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)
|
void setBytes(guest_address_t addr, size_t cnt, void const *src)
|
||||||
{
|
{
|
||||||
//char const *s = static_cast<char const *>(src);
|
int access = data_access; // TODO what access class do we really need?!
|
||||||
for (size_t i = 0; i < cnt; ++i)
|
T32_WriteMemory(addr, access, (byte*)(src), cnt);
|
||||||
; //setByte(addr + i, s[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // 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/Memory.hpp"
|
||||||
#include "sal/Listener.hpp"
|
#include "sal/Listener.hpp"
|
||||||
|
|
||||||
#include "sal/bochs/BochsListener.hpp"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace fail;
|
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()
|
bool VEZSExperiment::run()
|
||||||
{
|
{
|
||||||
m_log << "STARTING EXPERIMENT" << endl;
|
m_log << "STARTING EXPERIMENT" << endl;
|
||||||
printEIP();
|
m_log << "Instruction Pointer: 0x" << hex << simulator.getCPU(0).getInstructionPointer() << endl;
|
||||||
|
|
||||||
#if(SAVESTATE)
|
Register* reg = simulator.getCPU(0).getRegister(RI_R1);
|
||||||
m_log << "Booting, and saving state at ";
|
m_log << "Register R2: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
||||||
BPSingleListener bp;
|
|
||||||
// STEP 1: run until interesting function starts, and save state
|
reg = simulator.getCPU(0).getRegister(RI_R2);
|
||||||
bp.setWatchInstructionPointer(m_elf.getAddressByName("main"));
|
m_log << "Register R1: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl;
|
||||||
if(simulator.addListenerAndResume(&bp) == &bp){
|
|
||||||
m_log << "test function entry reached, saving state" << endl;
|
simulator.getCPU(0).setRegisterContent(reg, 0x23);
|
||||||
}
|
// Explicitly terminate, or the simulator will continue to run.
|
||||||
printEIP();
|
|
||||||
//simulator.terminate();
|
|
||||||
simulator.save("vezs.state");
|
|
||||||
simulator.terminate();
|
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__
|
#ifndef __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
||||||
#define __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
#define __CHECKSUM_OOSTUBS_EXPERIMENT_HPP__
|
||||||
|
|
||||||
#include "efw/ExperimentFlow.hpp"
|
#include "efw/ExperimentFlow.hpp"
|
||||||
#include "efw/JobClient.hpp"
|
#include "efw/JobClient.hpp"
|
||||||
#include "util/Logger.hpp"
|
#include "util/Logger.hpp"
|
||||||
#include "util/ElfReader.hpp"
|
|
||||||
|
|
||||||
class VEZSExperiment : public fail::ExperimentFlow {
|
class VEZSExperiment : public fail::ExperimentFlow {
|
||||||
|
|
||||||
fail::JobClient m_jc;
|
fail::JobClient m_jc;
|
||||||
fail::ElfReader m_elf;
|
|
||||||
fail::Logger m_log;
|
fail::Logger m_log;
|
||||||
|
|
||||||
void printEIP();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VEZSExperiment() : m_log("VEZS-example", false) {};
|
VEZSExperiment() : m_log("VEZS-example", false) {};
|
||||||
bool run();
|
bool run();
|
||||||
|
|||||||
Reference in New Issue
Block a user