T32SIM: Integrating Tracing feature of the T32SIM.
After each simulator break, T32Tracer retrieves the latest (16) trace records from the T32. Memory address and value can now be evaluated easily from the trace record. TODO:Nevertheless we still have to traverse the trace to find the instruction causing the access.
This commit is contained in:
@ -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)
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
25
debuggers/t32/src/T32TraceFormat.cc
Normal file
25
debuggers/t32/src/T32TraceFormat.cc
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
#include "T32TraceFormat.hpp"
|
||||
#include <iostream>
|
||||
|
||||
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
|
||||
66
debuggers/t32/src/T32Tracer.cc
Normal file
66
debuggers/t32/src/T32Tracer.cc
Normal file
@ -0,0 +1,66 @@
|
||||
#include "T32Tracer.hpp"
|
||||
#include "T32TraceFormat.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#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<char*>(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<char*>(&hdr), sizeof(T32TraceHeader));
|
||||
|
||||
T32TraceRecord r;
|
||||
for(size_t i = 0; i < hdr.number_of_records; ++i) {
|
||||
tracefile.read(reinterpret_cast<char*>(&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
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user