diff --git a/debuggers/t32/api/CMakeLists.txt b/debuggers/t32/api/CMakeLists.txt index 15ac93e6..9907f578 100644 --- a/debuggers/t32/api/CMakeLists.txt +++ b/debuggers/t32/api/CMakeLists.txt @@ -1 +1 @@ -add_library(t32api hlinknet.cc hremote.cc) +add_library(t32api hlinknet.c hremote.c) diff --git a/debuggers/t32/api/hlinknet.cc b/debuggers/t32/api/hlinknet.c similarity index 100% rename from debuggers/t32/api/hlinknet.cc rename to debuggers/t32/api/hlinknet.c diff --git a/debuggers/t32/api/hremote.cc b/debuggers/t32/api/hremote.c similarity index 99% rename from debuggers/t32/api/hremote.cc rename to debuggers/t32/api/hremote.c index fdced808..d9ee1c42 100644 --- a/debuggers/t32/api/hremote.cc +++ b/debuggers/t32/api/hremote.c @@ -1110,7 +1110,7 @@ int T32_Break(void) /* Stop Realtime */ * NAME commandline */ -int T32_Cmd(char *name) /* Executes a command line */ +int T32_Cmd(const char *name) /* Executes a command line */ { word wlen; int len; diff --git a/debuggers/t32/include/T32TraceFormat.hpp b/debuggers/t32/include/T32TraceFormat.hpp new file mode 100644 index 00000000..4fdde483 --- /dev/null +++ b/debuggers/t32/include/T32TraceFormat.hpp @@ -0,0 +1,76 @@ +#ifndef __T32TRACEFORMAT_H__ +#define __T32TRACEFORMAT_H__ +#include +#include +namespace fail { + + struct T32TraceHeader { + uint8_t export_file_header_string[32]; + uint8_t reserved_32; + uint8_t cpu_code; + uint8_t timestamp_available; + uint8_t prestore_mode; + uint8_t trigger_unit_available; + uint8_t port_analyzer_avaiable_mode; + uint8_t analyzer_type; + uint8_t reserved_39; + + uint32_t record_length; // in bytes + uint32_t number_of_records; // in the file + uint32_t last_record; + uint32_t referenced_record; + uint8_t reserved_56_63[8]; + }; + + struct T32TraceRecord { + struct { + uint32_t data_cycle :1; // bit 0 + uint32_t program_cycle :1; // bit 1 + uint32_t reserved_2_5 : 4; // bits 2-5 + uint32_t write_cycle : 1; // bit 6 + uint32_t reserved_7_20 : 14 ;// bits 7-20 + uint32_t flow_error : 1; // bit 21 + uint32_t reserved_22_24 : 3; //bits 22-24 + uint32_t fifo_overflow : 1; // bit 25 + uint32_t reserved_26_30 : 5; // bits 26-30 + uint32_t ownership_cycle :1; // bit 31 + } cycle_information; + + // data byte enable mask + uint8_t data_byte_valid; // bit0 : byte0 valid, ... + + struct { + uint8_t exec_signal : 1; + uint8_t thumb_mode : 1; + uint8_t arm_mode : 1; + uint8_t reserved_3_4 : 2; + uint8_t not_executed : 1; + uint8_t executed : 1; + uint8_t reserved_6_7 : 1; + } cpu_info; + + uint8_t reserved_6; + + uint8_t core_number; // only on SMP targets + uint32_t bus_data_address; // bus/data + uint32_t pflow_address; // or upper part + uint64_t data; + uint64_t timestamp; // relative to ZERO in ns + + bool isDataAccess(void) const { return cycle_information.data_cycle == 1; }; + bool isProgram(void) const { return cycle_information.program_cycle == 1; }; + bool isDataRead(void) const { return cycle_information.data_cycle && !cycle_information.write_cycle; }; + bool isDataWrite(void) const { return cycle_information.data_cycle && cycle_information.write_cycle; }; + uint32_t getAddress(void) const { return bus_data_address; }; + uint32_t getData(void) const { return data; }; + + + }; + + // +#include +#include "T32TraceFormat.hpp" +#include "util/Logger.hpp" + +namespace fail { + +class T32Tracer { + private: + typedef std::vector record_vector_t; + + bool avail; + std::string path; + std::string exportcmd; + record_vector_t rvec; + fail::Logger m_log; + + public: + typedef record_vector_t::const_reverse_iterator const_record_iterator; + + T32Tracer( const std::string& tracefile ); + + void setup(void) const; + int evaluate(); + + bool wasDataAccess(void) const ; + const T32TraceRecord & getLatestRecord(void) const { return rvec.back(); }; + void dump(void); + + bool available(void) const { return avail; }; + + // We return a reverse operator, as the trace list begins with the oldest record. + // We just let it look like a "normal" iterator and traverse backwards starting + // with most recent record. (Rbegin/Rend!) + const_record_iterator begin() const { return rvec.rbegin(); }; + const_record_iterator end() const { return rvec.rend(); }; +}; + +}; // end of namespace +#endif // __T32TRACER_HPP__ + diff --git a/debuggers/t32/include/t32.h b/debuggers/t32/include/t32.h index a3519d99..5b26e99f 100644 --- a/debuggers/t32/include/t32.h +++ b/debuggers/t32/include/t32.h @@ -315,7 +315,7 @@ T32EXTERN int T32_SetMode(int); T32EXTERN int T32_Go(void); T32EXTERN int T32_Break(void); T32EXTERN int T32_Terminate(int retval); -T32EXTERN int T32_Cmd( char * ); +T32EXTERN int T32_Cmd( const char * ); T32EXTERN int T32_CmdWin( dword, char * ); T32EXTERN int T32_EvalGet ( dword * ); T32EXTERN int T32_GetMessage ( char *, word * ); diff --git a/debuggers/t32/sim/CMakeLists.txt b/debuggers/t32/sim/CMakeLists.txt index 4677665d..888e7b76 100644 --- a/debuggers/t32/sim/CMakeLists.txt +++ b/debuggers/t32/sim/CMakeLists.txt @@ -1,4 +1,3 @@ include_directories(include) add_subdirectory(${T32_ARCHITECTURE}) -add_subdirectory(memlogger) diff --git a/debuggers/t32/sim/memlogger/memlogger.c b/debuggers/t32/sim/memlogger/memlogger.c index b60cd083..4c55dd51 100644 --- a/debuggers/t32/sim/memlogger/memlogger.c +++ b/debuggers/t32/sim/memlogger/memlogger.c @@ -9,21 +9,31 @@ typedef struct { + simulWord infoBase; int bustype; int data; } MemLog_t; - - static int SIMULAPI readCB(simulProcessor processor, simulCallbackStruct * cbs, simulPtr private) { - - // simulWord address = cbs->x.bus.address; + simulWord address = cbs->x.bus.address; MemLog_t * memlog = (MemLog_t*)private; cbs->x.bus.data = memlog->data; - //int width = cbs->x.bus.width; - SIMUL_Printf(processor, "MEM Read *0x%x - 0x%x\n", cbs->x.bus.address, memlog->data); + simulWord width = cbs->x.bus.width; + SIMUL_Printf(processor, "MEM Read *0x%x - 0x%x\n", address, memlog->data); + + simulWord data = memlog->data; + simulWord writeAccess = 0; + simulWord iadr = memlog->infoBase; + SIMUL_WriteMemory(processor, memlog->bustype, &iadr, 4, SIMUL_MEMORY_HIDDEN, &address); + iadr += 4; + SIMUL_WriteMemory(processor, memlog->bustype, &iadr, 4, SIMUL_MEMORY_HIDDEN, &data); + iadr += 4; + SIMUL_WriteMemory(processor, memlog->bustype, &iadr, 4, SIMUL_MEMORY_HIDDEN, &width); + iadr += 4; + SIMUL_WriteMemory(processor, memlog->bustype, &iadr, 4, SIMUL_MEMORY_HIDDEN, &writeAccess); + return SIMUL_MEMORY_OK; } @@ -31,11 +41,23 @@ static int SIMULAPI readCB(simulProcessor processor, simulCallbackStruct * cbs, static int SIMULAPI writeCB(simulProcessor processor, simulCallbackStruct * cbs, simulPtr private) { simulWord data = cbs->x.bus.data; - //simulWord address = cbs->x.bus.address; + simulWord address = cbs->x.bus.address; MemLog_t * memlog = (MemLog_t*)private; memlog->data = cbs->x.bus.data; - //int width = cbs->x.bus.width; - SIMUL_Printf(processor, "MEM Write *0x%x - 0x%x\n", cbs->x.bus.address, data); + simulWord width = cbs->x.bus.width; + SIMUL_Printf(processor, "MEM Write *0x%x - 0x%x\n", address, data); + + simulWord writeAccess = 1; + simulWord iadr = memlog->infoBase; + SIMUL_WriteMemory(processor, memlog->bustype, &iadr, 4, SIMUL_MEMORY_HIDDEN, &address); + iadr += 4; + SIMUL_WriteMemory(processor, memlog->bustype, &iadr, 4, SIMUL_MEMORY_HIDDEN, &data); + iadr += 4; + SIMUL_WriteMemory(processor, memlog->bustype, &iadr, 4, SIMUL_MEMORY_HIDDEN, &width); + iadr += 4; + SIMUL_WriteMemory(processor, memlog->bustype, &iadr, 4, SIMUL_MEMORY_HIDDEN, &writeAccess); + + return SIMUL_MEMORY_OK; } @@ -66,6 +88,7 @@ int SIMULAPI SIMUL_Init(simulProcessor processor, simulCallbackStruct * cbs) // return SIMUL_INIT_FAIL; // } pmemlog->bustype = cbs->x.init.argpbustype[1]; + pmemlog->infoBase = 0x60000000; // placed at "external RAM" simulWord from, to; from = 0x20002074; diff --git a/debuggers/t32/src/CMakeLists.txt b/debuggers/t32/src/CMakeLists.txt index 9c68398b..5fb78754 100644 --- a/debuggers/t32/src/CMakeLists.txt +++ b/debuggers/t32/src/CMakeLists.txt @@ -1,6 +1,8 @@ set(SRCS main.cc T32Connector.cc + T32TraceFormat.cc + T32Tracer.cc ) add_executable(fail-client ${SRCS}) @@ -10,3 +12,4 @@ install(TARGETS fail-client RUNTIME DESTINATION bin) add_executable(t32cli t32cli.cc) target_link_libraries(t32cli t32api) + diff --git a/debuggers/t32/src/T32Connector.cc b/debuggers/t32/src/T32Connector.cc index 75bc2bb1..b0220d1d 100644 --- a/debuggers/t32/src/T32Connector.cc +++ b/debuggers/t32/src/T32Connector.cc @@ -78,7 +78,7 @@ int T32Connector::getState() const { void T32Connector::showMemoryRegions(const memory_map_t& map) const { - for(int i = 0; i < map.size(); i++){ + for(unsigned int i = 0; i < map.size(); i++){ std::cout << "[" << i << "] 0x" << std::hex << map[i].first << " - 0x" << std::hex << map[i].second << std::endl; } } diff --git a/debuggers/t32/src/T32TraceFormat.cc b/debuggers/t32/src/T32TraceFormat.cc new file mode 100644 index 00000000..48b1d00d --- /dev/null +++ b/debuggers/t32/src/T32TraceFormat.cc @@ -0,0 +1,25 @@ + +#include "T32TraceFormat.hpp" +#include + +using namespace std; + +namespace fail { + + std::ostream& operator <<(std::ostream & os, const fail::T32TraceRecord & r) { +#ifndef __puma + if(r.isDataWrite()){ + os << "WRITE"; + } else if (r.isDataRead()) { + os << "READ"; + } else if( r.isProgram()) { + os << "PROGRAM"; + } else { + os << "UNKNOWN"; + } + os << "\t" << hex << (int)(r.getAddress()) << "\t" << r.getData() << "\t"; +#endif + return os; + } + +}; // end of namespace diff --git a/debuggers/t32/src/T32Tracer.cc b/debuggers/t32/src/T32Tracer.cc new file mode 100644 index 00000000..6281ea3f --- /dev/null +++ b/debuggers/t32/src/T32Tracer.cc @@ -0,0 +1,66 @@ +#include "T32Tracer.hpp" +#include "T32TraceFormat.hpp" +#include +#include +#include "t32.h" + +using namespace std; + +namespace fail { + + T32Tracer::T32Tracer( const std::string& tfile ) : path(tfile), m_log("T32Tracer", false) { + // TODO Check if tracing is available: + avail = true; + exportcmd = "Trace.export " + path; + m_log << "Trace file: " << path.c_str() << endl; + } + + + void T32Tracer::setup() const { + T32_Cmd("Trace.SIZE 16."); // trace 16 records + T32_Cmd("Trace.METHOD Analyzer"); + T32_Cmd("Trace.autoarm on"); + T32_Cmd("Trace.autoinit on"); + T32_Cmd("Trace.state"); + } + + int T32Tracer::evaluate(){ + // clear old records + rvec.clear(); + + // export trace to file + //T32_Cmd(static_cast(exportcmd.c_str())); + T32_Cmd((char*)(exportcmd.c_str())); + // open trace file. + ifstream tracefile; + tracefile.open(path.c_str(), ios::in | ios::binary); + + if(tracefile.is_open()){ + // evaluate trace. + T32TraceHeader hdr; + tracefile.seekg(0, ios::beg); + tracefile.read(reinterpret_cast(&hdr), sizeof(T32TraceHeader)); + + T32TraceRecord r; + for(size_t i = 0; i < hdr.number_of_records; ++i) { + tracefile.read(reinterpret_cast(&r), sizeof(T32TraceRecord)); + rvec.push_back(r); // add trace record to vector + } + return rvec.size(); + } + return -1; + } + + bool T32Tracer::wasDataAccess(void) const { + // TODO if rvec.size() != 0 !! + return rvec.back().isDataAccess(); + } + + + void T32Tracer::dump(void){ + for(size_t i = 0; i < rvec.size(); ++i) { + m_log << "[" << dec << i << "] " << rvec[i] << endl; + } + } + +}; // end of namespace fail diff --git a/debuggers/t32/src/main.cc b/debuggers/t32/src/main.cc index 27271b87..22c86f75 100644 --- a/debuggers/t32/src/main.cc +++ b/debuggers/t32/src/main.cc @@ -22,6 +22,7 @@ #include "util/optionparser/optionparser_ext.hpp" #include "T32Connector.hpp" +#include "T32Tracer.hpp" #include "t32config.hpp" #include "sal/MemoryInstruction.hpp" #include "util/Disassembler.hpp" @@ -54,7 +55,6 @@ int main(int argc, char** argv){ option::Option options[stats.options_max], buffer[stats.buffer_max]; option::Parser parse(usage, argc, argv, options, buffer); - return 0; if (parse.error()){ cerr << "Error parsing arguments." << endl; return 1; @@ -101,18 +101,27 @@ int main(int argc, char** argv){ MemoryInstruction mem; address_t ip; + // Enable T32 Tracer (if available) + T32Tracer tr("/tmp/tr.x"); // TODO configurable trace file path + tr.setup(); // enable and configure tracing. + while(1) { // Start execution (with next timeout, if any) t32.go(); // Wait for debugger to stop. while( t32.isRunning() ) {} - // Evaluate state. - t32.test();// TODO + // Call appropriate callback of the SimulatorController. ip = fail::simulator.getCPU(0).getInstructionPointer(); fail::simulator.onBreakpoint(&fail::simulator.getCPU(0), ip , fail::ANY_ADDR); - if( meminstruction.eval(ip, mem) ) { - fail::simulator.onMemoryAccess(&fail::simulator.getCPU(0), mem.getAddress(), mem.getWidth(), mem.isWriteAccess(), ip ); + + // Evaluate tracing result, handle memory access event.. + if((tr.evaluate() > 0) && (tr.wasDataAccess())){ + // TODO: step back in trace and find program counter of the according instruction. + // ip = XXX; + fail::simulator.onMemoryAccess(&fail::simulator.getCPU(0), tr.getLatestRecord().getAddress(), /* TODO access width: */ 4, tr.getLatestRecord().isDataWrite(), ip ); + + tr.dump(); } } diff --git a/scripts/t32cmm/CMakeLists.txt b/scripts/t32cmm/CMakeLists.txt index 59e0c850..8e7334b9 100644 --- a/scripts/t32cmm/CMakeLists.txt +++ b/scripts/t32cmm/CMakeLists.txt @@ -14,7 +14,7 @@ else() message(FATAL_ERROR "Please set the FAIL_ELF_PATH enviroment variable to the binary under test.") endif() -OPTION( T32_SIMULATOR "Start LAuterbach as instruction set simulator. No hardware needed." OFF) +OPTION( T32_SIMULATOR "Start LAuterbach as instruction set simulator. No hardware needed." ON) if(T32_SIMULATOR) set(T32_USB_OR_SIM "SIM") diff --git a/scripts/t32cmm/armm3/init.cmm.in b/scripts/t32cmm/armm3/init.cmm.in index 92613b8c..b49ca49e 100644 --- a/scripts/t32cmm/armm3/init.cmm.in +++ b/scripts/t32cmm/armm3/init.cmm.in @@ -12,7 +12,6 @@ IF (SIMULATOR()) SYS.DOWN AREA.view SIM.UNLOAD - SIM.LOAD @T32_MEMLOGGER_LIB@ SIM.LOAD @T32_NVIC_LIB@ SIM.LIST SYS.CPU cortexm3 diff --git a/src/core/sal/arm/ArmMemoryInstruction.cc b/src/core/sal/arm/ArmMemoryInstruction.cc index ae9e9a9f..69979e0f 100644 --- a/src/core/sal/arm/ArmMemoryInstruction.cc +++ b/src/core/sal/arm/ArmMemoryInstruction.cc @@ -83,7 +83,7 @@ namespace fail { bool ArmMemoryInstructionAnalyzer::eval(address_t address, MemoryInstruction & result){ #ifdef CORTEXM3 -#warning "Memory Accesses cannot be evaluated completedly!" +#warning "Memory Accesses cannot be evaluated completely!" return eval_cm3(address, result); #elif defined CORTEXA9 return eval_ca9(address, result); diff --git a/src/experiments/vezs-example/experiment.cc b/src/experiments/vezs-example/experiment.cc index 12e7a0ee..db65e159 100644 --- a/src/experiments/vezs-example/experiment.cc +++ b/src/experiments/vezs-example/experiment.cc @@ -41,18 +41,18 @@ bool VEZSExperiment::run() address_t pfoo = m_elf.getSymbol("foo").getAddress(); //BPSingleListener bp(address); //BPRangeListener bp(address-32, address + 32); - //MemWriteListener l_foo( pfoo ); - MemAccessListener l_foo( 0x20002018 ); l_foo.setWatchWidth(0x20); + MemWriteListener l_foo( pfoo ); + //MemAccessListener l_foo( 0x20002074 ); l_foo.setWatchWidth(0x4); reg = simulator.getCPU(0).getRegister(RI_R4); - unsigned foo = 23; + //unsigned foo = 23; for(int i = 0; i < 15; i++){ simulator.addListenerAndResume(&l_foo); //if(i == 0) mm.setBytes(pfoo, 4, (void*)&foo); m_log << " Breakpoint hit! @ 0x" << std::hex << simulator.getCPU(0).getInstructionPointer() << std::endl; //m_log << " Register R3: 0x" << hex << simulator.getCPU(0).getRegisterContent(reg) << endl; //mm.getBytes(pfoo, 4, (void*)&foo); - m_log << " foo @ 0x"<< std::hex << pfoo << " = " << foo << std::endl; + //m_log << " foo @ 0x"<< std::hex << pfoo << " = " << foo << std::endl; } /*