diff --git a/CMakeLists.txt b/CMakeLists.txt index e0d1e333..0bdb9fbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,8 @@ elseif(BUILD_OVP) elseif(BUILD_QEMU) include_directories(simulators) elseif(BUILD_T32) - add_subdirectory(hwdebuggers/t32) + include_directories(debuggers/t32/include src/core) + add_subdirectory(debuggers/t32) endif(BUILD_BOCHS) ## Additional compiler and linker flags ## diff --git a/debuggers/gdb/README b/debuggers/gdb/README new file mode 100644 index 00000000..c7225112 --- /dev/null +++ b/debuggers/gdb/README @@ -0,0 +1 @@ +TODO: a nice GDB backend. diff --git a/hwdebuggers/t32/CMakeLists.txt b/debuggers/t32/CMakeLists.txt similarity index 100% rename from hwdebuggers/t32/CMakeLists.txt rename to debuggers/t32/CMakeLists.txt diff --git a/hwdebuggers/t32/api/CMakeLists.txt b/debuggers/t32/api/CMakeLists.txt similarity index 100% rename from hwdebuggers/t32/api/CMakeLists.txt rename to debuggers/t32/api/CMakeLists.txt diff --git a/hwdebuggers/t32/api/hlinknet.cc b/debuggers/t32/api/hlinknet.cc similarity index 97% rename from hwdebuggers/t32/api/hlinknet.cc rename to debuggers/t32/api/hlinknet.cc index 067f729c..5f235cb7 100644 --- a/hwdebuggers/t32/api/hlinknet.cc +++ b/debuggers/t32/api/hlinknet.cc @@ -91,7 +91,7 @@ extern struct hostent * gethostbyaddr(); # define FD_ISSET(fd,fdset) (*fdset & (1<<(fd))) #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) static struct sockaddr ReceiveSocketAddress; #else @@ -106,7 +106,7 @@ struct LineStruct { unsigned short ReceivePort; /* Receiver Port */ unsigned short TransmitPort; /* Transmitter Port in T32 */ int PacketSize; /* Max. size of UDP-packet data */ - int PollTimeSec; + int PollTimeSec; int ReceiveToggleBit; unsigned char MessageId; int LineUp; @@ -227,28 +227,28 @@ int LINE_LineConfig(char * in) } if (!strncmp((char *) in, "PORT=", 5)) { x = str2dec (in+5); - if (x == -1) + if (x == -1) return -1; line->TransmitPort = x; return 1; } if (!strncmp((char *) in, "HOSTPORT=", 9)) { x = str2dec (in+9); - if (x == -1) + if (x == -1) return -1; line->HostPort = x; return 1; } if (!strncmp((char *) in, "PACKLEN=", 8)) { x = str2dec (in+8); - if (x == -1) + if (x == -1) return -1; line->PacketSize = x; return 1; } if (!strncmp((char *) in, "TIMEOUT=", 8)) { x = str2dec (in+8); - if (x == -1) + if (x == -1) return -1; line->PollTimeSec = x; return 1; @@ -353,7 +353,7 @@ void LINE_LineExit(void) if (line->CommSocket != -1) { 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)); #ifdef MS_WINDOWS @@ -516,7 +516,7 @@ void T32_UnInstallAsyncSelect(HWND hwnd) /** Sends a message to T32. Handles segmentation of _message_ into (one or multiple) _packages_. - + @param in pointer to outgoing message (already includes 5 byte message header) @param size size of message @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->LastTransmitSeq = line->TransmitSeq; in -= 4; /* space for packet header */ - + do { 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 */ 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 */ if (sendto(line->CommSocket, - (char *) in, + (char *) in, packetSize + 4, 0, (struct sockaddr *) & line->SocketAddress, sizeof(line->SocketAddress) ) != packetSize + 4) { @@ -576,9 +576,9 @@ static int ReceiveWithTimeout(struct timeval *tim, unsigned char *dest, int size socklen_t length; struct timeval timeout; LineStruct* line = pLineParams; - + timeout = *tim; - + #ifdef POLL_NET DWORD endpoll; static struct timeval tival = {0}; @@ -657,11 +657,11 @@ retry: /* multiple packets are merged in-place: backup data that is overwritten package aby header */ - SETLONGVAR(tmpl, dest[0]); + SETLONGVAR(tmpl, dest[0]); do { 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 == -2) goto retry; @@ -670,17 +670,17 @@ retry: if (i <= 4) { return -1; } - - + + /* 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; - + newPackage = reinterpret_cast( malloc(sizeof(T32_NotificationPackage)) ); if (newPackage==NULL) return -1; - + memcpy(newPackage, dest, i); /* in theory i should always be the package size, at least for ethernet */ oldHead = T32_NotificationHead; newPackage->prev = NULL; @@ -693,12 +693,12 @@ retry: } goto retry; } - + if (dest[0] != T32_API_RECEIVE) { return -1; } SETWORDVAR(tmpw, dest[2]); - + if (tmpw == line->LastReceiveSeq && line->LastTransmitSize) { line->TransmitSeq = line->LastTransmitSeq; LINE_LineTransmit(line->LastTransmitBuffer, line->LastTransmitSize); @@ -736,7 +736,7 @@ retry: function until it returns -1. @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 */ @@ -746,7 +746,7 @@ int LINE_ReceiveNotifyMessage(unsigned char* package) { int len; static struct timeval LongTime = {0, 0}; - + /* Check for asynchronous notifications */ if (T32_NotificationTail) { T32_NotificationPackage *prev = T32_NotificationTail->prev; @@ -762,10 +762,10 @@ int LINE_ReceiveNotifyMessage(unsigned char* package) if (len < 2) return -1; } - + if (package[0] != T32_API_NOTIFICATION) return -1; - + 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; - packet[0] = T32_API_SYNCBACK; + packet[0] = T32_API_SYNCBACK; packet[1] = 0; SETWORDVAR(packet[2], line->TransmitSeq); SETWORDCONST(packet[4], 0); diff --git a/hwdebuggers/t32/api/hremote.cc b/debuggers/t32/api/hremote.cc similarity index 100% rename from hwdebuggers/t32/api/hremote.cc rename to debuggers/t32/api/hremote.cc diff --git a/hwdebuggers/t32/include/t32.h b/debuggers/t32/include/t32.h similarity index 99% rename from hwdebuggers/t32/include/t32.h rename to debuggers/t32/include/t32.h index 0c9ea823..bcb872f4 100644 --- a/hwdebuggers/t32/include/t32.h +++ b/debuggers/t32/include/t32.h @@ -1,3 +1,5 @@ +#ifndef __T32_H__ +#define __T32_H__ #include @@ -120,14 +122,14 @@ typedef unsigned int dword; /* Callbacks should have the following protoypes */ /************************* WARNING *****************************/ -/* +/* * If you add more callback functions here, make sure you ONLY * 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! * This is because we absolutely need to avoid portability problems here. - * + * * Explanation: * 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. @@ -360,3 +362,5 @@ extern void* T32_GetChannel0(void); #ifdef __cplusplus } #endif +#endif + diff --git a/hwdebuggers/t32/src/CMakeLists.txt b/debuggers/t32/src/CMakeLists.txt similarity index 59% rename from hwdebuggers/t32/src/CMakeLists.txt rename to debuggers/t32/src/CMakeLists.txt index 757040d9..e84d7466 100644 --- a/hwdebuggers/t32/src/CMakeLists.txt +++ b/debuggers/t32/src/CMakeLists.txt @@ -1,5 +1,5 @@ set(SRCS - t32connector.cc + T32Connector.cc ) 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) +add_executable(t32cli t32cli.cc) +target_link_libraries(t32cli -Wl,-whole-archive t32api -Wl,-no-whole-archive) diff --git a/debuggers/t32/src/T32Connector.cc b/debuggers/t32/src/T32Connector.cc new file mode 100644 index 00000000..73d9ebb4 --- /dev/null +++ b/debuggers/t32/src/T32Connector.cc @@ -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 + * @date 15.02.2013 + */ + +#include +#include +#include +#include + +#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; +} diff --git a/debuggers/t32/src/T32Connector.hpp b/debuggers/t32/src/T32Connector.hpp new file mode 100644 index 00000000..1a60f38e --- /dev/null +++ b/debuggers/t32/src/T32Connector.hpp @@ -0,0 +1,24 @@ +#ifndef __T32_CONNECTOR_HPP__ + #define __T32_CONNECTOR_HPP__ + +#include + +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__ diff --git a/hwdebuggers/t32/src/t32connector.cc b/debuggers/t32/src/t32cli.cc similarity index 100% rename from hwdebuggers/t32/src/t32connector.cc rename to debuggers/t32/src/t32cli.cc diff --git a/doc/t32_remote_api.pdf b/doc/t32_remote_api.pdf new file mode 100644 index 00000000..590117bb Binary files /dev/null and b/doc/t32_remote_api.pdf differ diff --git a/src/core/sal/CMakeLists.txt b/src/core/sal/CMakeLists.txt index 025dac0d..631bb9ba 100644 --- a/src/core/sal/CMakeLists.txt +++ b/src/core/sal/CMakeLists.txt @@ -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) diff --git a/src/core/sal/ConcreteCPU.hpp b/src/core/sal/ConcreteCPU.hpp index f2931903..c77c6b32 100644 --- a/src/core/sal/ConcreteCPU.hpp +++ b/src/core/sal/ConcreteCPU.hpp @@ -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 diff --git a/src/core/sal/gem5/Gem5ArmCPU.hpp b/src/core/sal/gem5/Gem5ArmCPU.hpp index f6659402..edffd12a 100644 --- a/src/core/sal/gem5/Gem5ArmCPU.hpp +++ b/src/core/sal/gem5/Gem5ArmCPU.hpp @@ -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) diff --git a/src/core/sal/gem5/Gem5Controller.hpp b/src/core/sal/gem5/Gem5Controller.hpp index 82ba4ea0..2bdb117e 100644 --- a/src/core/sal/gem5/Gem5Controller.hpp +++ b/src/core/sal/gem5/Gem5Controller.hpp @@ -10,7 +10,7 @@ namespace fail { /** * \class Gem5Controller - * + * * Gem5-specific implementation of a SimulatorController. */ class Gem5Controller : public SimulatorController { diff --git a/src/core/sal/gem5/Gem5Memory.hpp b/src/core/sal/gem5/Gem5Memory.hpp index 7b2802e7..bad87f4e 100644 --- a/src/core/sal/gem5/Gem5Memory.hpp +++ b/src/core/sal/gem5/Gem5Memory.hpp @@ -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; } diff --git a/src/core/sal/t32/T32ArmCPU.cc b/src/core/sal/t32/T32ArmCPU.cc new file mode 100644 index 00000000..20b40003 --- /dev/null +++ b/src/core/sal/t32/T32ArmCPU.cc @@ -0,0 +1,53 @@ +#include "T32ArmCPU.hpp" +#include +#include + +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(mask & 0xffffffff), static_cast(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(mask & 0xffffffff), static_cast(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 + + diff --git a/src/core/sal/t32/T32ArmCPU.hpp b/src/core/sal/t32/T32ArmCPU.hpp new file mode 100644 index 00000000..a4464e88 --- /dev/null +++ b/src/core/sal/t32/T32ArmCPU.hpp @@ -0,0 +1,75 @@ +#ifndef __T32_ARM_CPU_HPP__ + #define __T32_ARM_CPU_HPP__ + +#include "../arm/Architecture.hpp" +#include "../arm/CPUState.hpp" +#include + +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__ diff --git a/src/core/sal/t32/T32Config.hpp b/src/core/sal/t32/T32Config.hpp index fe80cdbf..1f20333d 100644 --- a/src/core/sal/t32/T32Config.hpp +++ b/src/core/sal/t32/T32Config.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 diff --git a/src/core/sal/t32/T32Connector.cc b/src/core/sal/t32/T32Connector.cc new file mode 100644 index 00000000..b94165d7 --- /dev/null +++ b/src/core/sal/t32/T32Connector.cc @@ -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 + * @date 15.02.2013 + */ + +#include +#include +#include +#include + +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. + +} diff --git a/src/core/sal/t32/T32Connector.hpp b/src/core/sal/t32/T32Connector.hpp new file mode 100644 index 00000000..1a60f38e --- /dev/null +++ b/src/core/sal/t32/T32Connector.hpp @@ -0,0 +1,24 @@ +#ifndef __T32_CONNECTOR_HPP__ + #define __T32_CONNECTOR_HPP__ + +#include + +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__ diff --git a/src/core/sal/t32/T32Controller.cc b/src/core/sal/t32/T32Controller.cc index 425efceb..2035236c 100644 --- a/src/core/sal/t32/T32Controller.cc +++ b/src/core/sal/t32/T32Controller.cc @@ -1,23 +1,26 @@ -#include - #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::iterator it = m_CPUs.begin(); + while (it != m_CPUs.end()) { + delete *it; + it = m_CPUs.erase(it); + } } diff --git a/src/core/sal/t32/T32Controller.hpp b/src/core/sal/t32/T32Controller.hpp index b6712323..7ed6da9c 100644 --- a/src/core/sal/t32/T32Controller.hpp +++ b/src/core/sal/t32/T32Controller.hpp @@ -1,27 +1,18 @@ #ifndef __T32_CONTROLLER_HPP__ #define __T32_CONTROLLER_HPP__ -#include -#include -#include -#include -#include - #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 */ diff --git a/src/core/sal/t32/T32Listener.ah b/src/core/sal/t32/T32Listener.ah index d7e9e01e..b27cbc02 100644 --- a/src/core/sal/t32/T32Listener.ah +++ b/src/core/sal/t32/T32Listener.ah @@ -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 } }; }; diff --git a/src/core/sal/t32/T32Memory.hpp b/src/core/sal/t32/T32Memory.hpp index 17cf326e..7b397605 100644 --- a/src/core/sal/t32/T32Memory.hpp +++ b/src/core/sal/t32/T32Memory.hpp @@ -3,6 +3,8 @@ #include "../Memory.hpp" +#include + 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(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(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 diff --git a/src/core/sal/t32/T32Mock.ah b/src/core/sal/t32/T32Mock.ah new file mode 100644 index 00000000..eeed5b32 --- /dev/null +++ b/src/core/sal/t32/T32Mock.ah @@ -0,0 +1,26 @@ +#ifndef __T32MOCK_AH__ + #define __T32MOCK_AH__ + +#include + +#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__ diff --git a/src/core/sal/t32/T32Register.hpp b/src/core/sal/t32/T32Register.hpp deleted file mode 100644 index 06b1df18..00000000 --- a/src/core/sal/t32/T32Register.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __T32_REGISTER_HPP__ - #define __T32_REGISTER_HPP__ - -#include "../Register.hpp" - -#include -#include - -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(0); /* TODO */ - } - address_t getStackPointer() - { - return static_cast(0); /* TODO */ - } - address_t getBasePointer() - { - return static_cast(0); /* TODO */ - } -}; - -} // end-of-namespace: fail - -#endif // __T32_REGISTER_HPP__ diff --git a/src/experiments/vezs-example/experiment.cc b/src/experiments/vezs-example/experiment.cc index 28002cbe..f2ccb037 100644 --- a/src/experiments/vezs-example/experiment.cc +++ b/src/experiments/vezs-example/experiment.cc @@ -14,83 +14,24 @@ #include "sal/Memory.hpp" #include "sal/Listener.hpp" -#include "sal/bochs/BochsListener.hpp" #include 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 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(); } diff --git a/src/experiments/vezs-example/experiment.hpp b/src/experiments/vezs-example/experiment.hpp index f32d7733..b3eb8ad8 100644 --- a/src/experiments/vezs-example/experiment.hpp +++ b/src/experiments/vezs-example/experiment.hpp @@ -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();