diff --git a/src/experiments/generic-tracing/experiment.cc b/src/experiments/generic-tracing/experiment.cc index 96c80310..37a2fb78 100644 --- a/src/experiments/generic-tracing/experiment.cc +++ b/src/experiments/generic-tracing/experiment.cc @@ -21,200 +21,210 @@ using namespace std; using namespace fail; void GenericTracing::parseOptions() { - CommandLine &cmd = CommandLine::Inst(); - CommandLine::option_handle IGNORE = cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... \n\n"); - CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help\t Print usage and exit"); - CommandLine::option_handle ELF_FILE = cmd.addOption("", "elf-file", Arg::Required, - "--elf-file\t ELF Binary File (default: $FAIL_ELF_PATH)"); - CommandLine::option_handle START_SYMBOL = cmd.addOption("s", "start-symbol", Arg::Required, - "-s,--start-symbol\t ELF symbol to start tracing (default: main)"); - CommandLine::option_handle STOP_SYMBOL = cmd.addOption("e", "end-symbol", Arg::Required, - "-e,--end-symbol\t ELF symbol to end tracing"); - CommandLine::option_handle SAVE_SYMBOL = cmd.addOption("S", "save-symbol", Arg::Required, - "-S,--save-symbol\t ELF symbol to save the state of the machine (default: main)\n"); - CommandLine::option_handle STATE_FILE = cmd.addOption("f", "state-file", Arg::Required, - "-f,--state-file\t File/dir to save the state to (default state)"); - CommandLine::option_handle TRACE_FILE = cmd.addOption("t", "trace-file", Arg::Required, - "-t,--trace-file\t File to save the execution trace to\n"); + CommandLine &cmd = CommandLine::Inst(); + CommandLine::option_handle IGNORE = cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... \n\n"); + CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help\t Print usage and exit"); - CommandLine::option_handle MEM_SYMBOL = cmd.addOption("m", "memory-symbol", Arg::Required, - "-m,--memory-symbol\t ELF symbol(s) to trace accesses (without specifiying all mem read/writes are traced)"); - CommandLine::option_handle MEM_REGION = cmd.addOption("M", "memory-region", Arg::Required, - "-M,--memory-region\t restrict memory region which is traced" - " Possible formats: 0x
, 0x
:0x
, 0x
:"); - if(!cmd.parse()) { - cerr << "Error parsing arguments." << endl; - exit(-1); - } + CommandLine::option_handle ELF_FILE = cmd.addOption("", "elf-file", Arg::Required, + "--elf-file\t ELF Binary File (default: $FAIL_ELF_PATH)"); + CommandLine::option_handle START_SYMBOL = cmd.addOption("s", "start-symbol", Arg::Required, + "-s,--start-symbol\t ELF symbol to start tracing (default: main)"); + CommandLine::option_handle STOP_SYMBOL = cmd.addOption("e", "end-symbol", Arg::Required, + "-e,--end-symbol\t ELF symbol to end tracing"); + CommandLine::option_handle SAVE_SYMBOL = cmd.addOption("S", "save-symbol", Arg::Required, + "-S,--save-symbol\t ELF symbol to save the state of the machine (default: main)\n"); + CommandLine::option_handle STATE_FILE = cmd.addOption("f", "state-file", Arg::Required, + "-f,--state-file\t File/dir to save the state to (default state)"); + CommandLine::option_handle TRACE_FILE = cmd.addOption("t", "trace-file", Arg::Required, + "-t,--trace-file\t File to save the execution trace to\n"); - if (cmd[HELP]) { - cmd.printUsage(); - exit(0); - } + CommandLine::option_handle FULL_TRACE = cmd.addOption("", "full-trace", Arg::None, "--full-trace\t Do a full trace (more data, default: off)"); + CommandLine::option_handle MEM_SYMBOL = cmd.addOption("m", "memory-symbol", Arg::Required, + "-m,--memory-symbol\t ELF symbol(s) to trace accesses (without specifiying all mem read/writes are traced)"); + CommandLine::option_handle MEM_REGION = cmd.addOption("M", "memory-region", Arg::Required, + "-M,--memory-region\t restrict memory region which is traced" + " Possible formats: 0x
, 0x
:0x
, 0x
:"); - if (cmd[ELF_FILE].count() > 0) - elf_file = cmd[ELF_FILE].first()->arg; - else { - char * elfpath = getenv("FAIL_ELF_PATH"); - if(elfpath == NULL){ - m_log << "FAIL_ELF_PATH not set :( (alternative: --elf-file) " << std::endl; - exit(-1); - } + if(!cmd.parse()) { + cerr << "Error parsing arguments." << endl; + exit(-1); + } - elf_file = elfpath; - } - m_elf = new ElfReader(elf_file.c_str()); + if (cmd[HELP]) { + cmd.printUsage(); + exit(0); + } - if (cmd[START_SYMBOL].count() > 0) - start_symbol = cmd[START_SYMBOL].first()->arg; - else - start_symbol = "main"; + if (cmd[ELF_FILE].count() > 0) + elf_file = cmd[ELF_FILE].first()->arg; + else { + char * elfpath = getenv("FAIL_ELF_PATH"); + if(elfpath == NULL){ + m_log << "FAIL_ELF_PATH not set :( (alternative: --elf-file) " << std::endl; + exit(-1); + } - if (cmd[STOP_SYMBOL].count() > 0) - stop_symbol = std::string(cmd[STOP_SYMBOL].first()->arg); - else { - m_log << "You have to give an end symbol (-e,--end-symbol)!" << std::endl; - exit(EXIT_FAILURE); - } + elf_file = elfpath; + } + m_elf = new ElfReader(elf_file.c_str()); - if (cmd[SAVE_SYMBOL].count() > 0) - save_symbol = std::string(cmd[SAVE_SYMBOL].first()->arg); - else - save_symbol = "main"; + if (cmd[START_SYMBOL].count() > 0) + start_symbol = cmd[START_SYMBOL].first()->arg; + else + start_symbol = "main"; - if (cmd[STATE_FILE].count() > 0) - state_file = std::string(cmd[STATE_FILE].first()->arg); - else - state_file = "state"; + if (cmd[STOP_SYMBOL].count() > 0) + stop_symbol = std::string(cmd[STOP_SYMBOL].first()->arg); + else { + m_log << "You have to give an end symbol (-e,--end-symbol)!" << std::endl; + exit(EXIT_FAILURE); + } - if (cmd[TRACE_FILE].count() > 0) - trace_file = std::string(cmd[TRACE_FILE].first()->arg); - else - trace_file = "trace.pb"; + if (cmd[SAVE_SYMBOL].count() > 0) + save_symbol = std::string(cmd[SAVE_SYMBOL].first()->arg); + else + save_symbol = "main"; - use_memory_map = false; + if (cmd[STATE_FILE].count() > 0) + state_file = std::string(cmd[STATE_FILE].first()->arg); + else + state_file = "state"; - if (cmd[MEM_SYMBOL].count() > 0) { - use_memory_map = true; - option::Option *opt = cmd[MEM_SYMBOL].first(); + if (cmd[TRACE_FILE].count() > 0) + trace_file = std::string(cmd[TRACE_FILE].first()->arg); + else + trace_file = "trace.pb"; - while(opt != 0) { - const ElfSymbol &symbol = m_elf->getSymbol(opt->arg); - assert(symbol.isValid()); + use_memory_map = false; - m_log << "Adding '" << opt->arg << "' == 0x" << std::hex << symbol.getAddress() - << "+" << std::dec << symbol.getSize() << " to trace map" << std::endl; - traced_memory_map.add(symbol.getAddress(), symbol.getSize()); + if (cmd[MEM_SYMBOL].count() > 0) { + use_memory_map = true; + option::Option *opt = cmd[MEM_SYMBOL].first(); - opt = opt->next(); - } - } + while(opt != 0) { + const ElfSymbol &symbol = m_elf->getSymbol(opt->arg); + assert(symbol.isValid()); - if (cmd[MEM_REGION].count() > 0) { - use_memory_map = true; - option::Option *opt = cmd[MEM_REGION].first(); + m_log << "Adding '" << opt->arg << "' == 0x" << std::hex << symbol.getAddress() + << "+" << std::dec << symbol.getSize() << " to trace map" << std::endl; + traced_memory_map.add(symbol.getAddress(), symbol.getSize()); - while(opt != 0) { - char *endptr; - guest_address_t begin = strtol(opt->arg, &endptr, 16); - guest_address_t size; - if (endptr == opt->arg) { - m_log << "Couldn't parse " << opt->arg << std::endl; - exit(-1); - } + opt = opt->next(); + } + } - char delim = *endptr; - if (delim == 0) { - size = 1; - } else if(delim == ':') { - char *p = endptr +1; - size = strtol(p, &endptr, 16) - begin; - if (p == endptr || *endptr != 0) { - m_log << "Couldn't parse " << opt->arg << std::endl; - exit(-1); - } - } else if(delim == '+') { - char *p = endptr +1; - size = strtol(p, &endptr, 10); - if (p == endptr || *endptr != 0) { - m_log << "Couldn't parse " << opt->arg << std::endl; - exit(-1); - } - } else { - m_log << "Couldn't parse " << opt->arg << std::endl; - exit(-1); - } + if (cmd[MEM_REGION].count() > 0) { + use_memory_map = true; + option::Option *opt = cmd[MEM_REGION].first(); - traced_memory_map.add(begin, size); + while(opt != 0) { + char *endptr; + guest_address_t begin = strtol(opt->arg, &endptr, 16); + guest_address_t size; + if (endptr == opt->arg) { + m_log << "Couldn't parse " << opt->arg << std::endl; + exit(-1); + } - m_log << "Adding " << opt->arg << " 0x" << std::hex << begin - << "+" << std::dec << size << " to trace map" << std::endl; + char delim = *endptr; + if (delim == 0) { + size = 1; + } else if(delim == ':') { + char *p = endptr +1; + size = strtol(p, &endptr, 16) - begin; + if (p == endptr || *endptr != 0) { + m_log << "Couldn't parse " << opt->arg << std::endl; + exit(-1); + } + } else if(delim == '+') { + char *p = endptr +1; + size = strtol(p, &endptr, 10); + if (p == endptr || *endptr != 0) { + m_log << "Couldn't parse " << opt->arg << std::endl; + exit(-1); + } + } else { + m_log << "Couldn't parse " << opt->arg << std::endl; + exit(-1); + } - opt = opt->next(); - } - } + traced_memory_map.add(begin, size); - assert(m_elf->getSymbol(start_symbol).isValid()); - assert(m_elf->getSymbol(stop_symbol).isValid()); - assert(m_elf->getSymbol(save_symbol).isValid()); + m_log << "Adding " << opt->arg << " 0x" << std::hex << begin + << "+" << std::dec << size << " to trace map" << std::endl; - m_log << "start symbol: " << start_symbol << " 0x" << std::hex << m_elf->getSymbol(start_symbol).getAddress() << std::endl; - m_log << "save symbol: " << save_symbol << " 0x" << std::hex << m_elf->getSymbol(save_symbol).getAddress() << std::endl; - m_log << "stop symbol: " << stop_symbol << " 0x" << std::hex << m_elf->getSymbol(stop_symbol).getAddress() << std::endl; + opt = opt->next(); + } + } + + if (cmd[FULL_TRACE]) { + this->full_trace = true; + } + + assert(m_elf->getSymbol(start_symbol).isValid()); + assert(m_elf->getSymbol(stop_symbol).isValid()); + assert(m_elf->getSymbol(save_symbol).isValid()); + + m_log << "start symbol: " << start_symbol << " 0x" << std::hex << m_elf->getSymbol(start_symbol).getAddress() << std::endl; + m_log << "save symbol: " << save_symbol << " 0x" << std::hex << m_elf->getSymbol(save_symbol).getAddress() << std::endl; + m_log << "stop symbol: " << stop_symbol << " 0x" << std::hex << m_elf->getSymbol(stop_symbol).getAddress() << std::endl; + + m_log << "state file: " << state_file << std::endl; + m_log << "trace file: " << trace_file << std::endl; + m_log << "full-trace: " << this->full_trace << std::endl; - m_log << "state file: " << state_file << std::endl; - m_log << "trace file: " << trace_file << std::endl; } bool GenericTracing::run() { - parseOptions(); + parseOptions(); - BPSingleListener l_start_symbol(m_elf->getSymbol(start_symbol).getAddress()); - BPSingleListener l_save_symbol (m_elf->getSymbol(save_symbol).getAddress()); - BPSingleListener l_stop_symbol (m_elf->getSymbol(stop_symbol).getAddress()); + BPSingleListener l_start_symbol(m_elf->getSymbol(start_symbol).getAddress()); + BPSingleListener l_save_symbol (m_elf->getSymbol(save_symbol).getAddress()); + BPSingleListener l_stop_symbol (m_elf->getSymbol(stop_symbol).getAddress()); - //////////////////////////////////////////////////////////////// - // STEP 1: run until interesting function starts, start the tracing - simulator.addListenerAndResume(&l_start_symbol); - m_log << start_symbol << " reached, start tracing" << std::endl; + //////////////////////////////////////////////////////////////// + // STEP 1: run until interesting function starts, start the tracing + simulator.addListenerAndResume(&l_start_symbol); + m_log << start_symbol << " reached, start tracing" << std::endl; - // restrict memory access logging to injection target - TracingPlugin tp; + // restrict memory access logging to injection target + TracingPlugin tp; + tp.setFullTrace(this->full_trace); - if (use_memory_map) { - m_log << "Use restricted memory map for tracing" << std::endl; - tp.restrictMemoryAddresses(&traced_memory_map); - } + if (use_memory_map) { + m_log << "Use restricted memory map for tracing" << std::endl; + tp.restrictMemoryAddresses(&traced_memory_map); + } - ogzstream of(trace_file.c_str()); - if (of.bad()) { - m_log << "Couldn't open trace file: " << trace_file << std::endl; - exit(-1); - } - tp.setTraceFile(&of); + ogzstream of(trace_file.c_str()); + if (of.bad()) { + m_log << "Couldn't open trace file: " << trace_file << std::endl; + exit(-1); + } + tp.setTraceFile(&of); - // this must be done *after* configuring the plugin: - simulator.addFlow(&tp); + // this must be done *after* configuring the plugin: + simulator.addFlow(&tp); - //////////////////////////////////////////////////////////////// - // STEP 2: continue to the save point, and save state - if (start_symbol != save_symbol) { - simulator.addListenerAndResume(&l_save_symbol); - } - m_log << start_symbol << " reached, save state" << std::endl; - simulator.save(state_file); + //////////////////////////////////////////////////////////////// + // STEP 2: continue to the save point, and save state + if (start_symbol != save_symbol) { + simulator.addListenerAndResume(&l_save_symbol); + } + m_log << start_symbol << " reached, save state" << std::endl; + simulator.save(state_file); - //////////////////////////////////////////////////////////////// - // Step 3: Continue to the stop point - simulator.addListener(&l_stop_symbol); - simulator.resume(); + //////////////////////////////////////////////////////////////// + // Step 3: Continue to the stop point + simulator.addListener(&l_stop_symbol); + simulator.resume(); - //////////////////////////////////////////////////////////////// - // Step 4: tear down the tracing + //////////////////////////////////////////////////////////////// + // Step 4: tear down the tracing simulator.removeFlow(&tp); // serialize trace to file @@ -222,7 +232,7 @@ bool GenericTracing::run() m_log << "failed to write " << trace_file << std::endl; return false; } - of.close(); + of.close(); simulator.clearListeners(); simulator.terminate(); diff --git a/src/experiments/generic-tracing/experiment.hpp b/src/experiments/generic-tracing/experiment.hpp index 270f5d19..6c08d12f 100644 --- a/src/experiments/generic-tracing/experiment.hpp +++ b/src/experiments/generic-tracing/experiment.hpp @@ -11,25 +11,27 @@ class GenericTracing : public fail::ExperimentFlow { - std::string start_symbol; - std::string stop_symbol; - std::string save_symbol; + std::string start_symbol; + std::string stop_symbol; + std::string save_symbol; - std::string state_file; - std::string trace_file; - std::string elf_file; + std::string state_file; + std::string trace_file; + std::string elf_file; - bool use_memory_map; - fail::MemoryMap traced_memory_map; + bool use_memory_map; + fail::MemoryMap traced_memory_map; - fail::Logger m_log; - fail::ElfReader *m_elf; + bool full_trace; + + fail::Logger m_log; + fail::ElfReader *m_elf; public: - void parseOptions(); + void parseOptions(); bool run(); - GenericTracing() : m_log("GenericTracing", false) {}; + GenericTracing() : full_trace(false), m_log("GenericTracing", false) {}; }; #endif // __TRACING_TEST_HPP__ diff --git a/src/plugins/tracing/TracingPlugin.cc b/src/plugins/tracing/TracingPlugin.cc index 56754deb..dc2b8af6 100644 --- a/src/plugins/tracing/TracingPlugin.cc +++ b/src/plugins/tracing/TracingPlugin.cc @@ -1,7 +1,9 @@ #include +#include #include "sal/SALInst.hpp" #include "sal/Register.hpp" +#include "sal/Memory.hpp" #include "sal/Listener.hpp" #include "TracingPlugin.hpp" @@ -10,6 +12,8 @@ using namespace fail; bool TracingPlugin::run() { + MemoryManager& mm = simulator.getMemoryManager(); + MemAccessListener ev_mem(ANY_ADDR); BPSingleListener ev_step(ANY_ADDR); BaseListener *ev; @@ -23,13 +27,24 @@ bool TracingPlugin::run() if(m_protoStreamFile) { ps = new ProtoOStream(m_protoStreamFile); } - + +#ifdef BUILD_X86 + size_t ids[] = {RID_CSP, RID_CBP, RID_FLAGS}; +#else + size_t ids[] = {}; +#endif + + Register *regs[sizeof(ids)/sizeof(*ids)]; + for (unsigned i = 0; i < sizeof(ids)/sizeof(*ids); ++i) + regs[i] = simulator.getCPU(0).getRegister(ids[i]); + + while (true) { ev = simulator.resume(); if (ev == &ev_step) { simulator.addListener(&ev_step); - + address_t ip = ev_step.getTriggerInstructionPointer(); if (m_ipMap && !m_ipMap->isMatching(ip)) { continue; @@ -49,15 +64,15 @@ bool TracingPlugin::run() address_t addr = ev_mem.getTriggerAddress(); size_t width = ev_mem.getTriggerWidth(); if ((m_ipMap && !m_ipMap->isMatching(ip)) || - (m_memMap && !m_memMap->isMatching(addr, width))) { + (m_memMap && !m_memMap->isMatching(addr, width))) { continue; } if (m_os) *m_os << hex << "[Tracing] MEM " - << ((ev_mem.getTriggerAccessType() & - MemAccessEvent::MEM_READ) ? "R " : "W ") - << addr << " width " << width << " IP " << ip << "\n"; + << ((ev_mem.getTriggerAccessType() & + MemAccessEvent::MEM_READ) ? "R " : "W ") + << addr << " width " << width << " IP " << ip << "\n"; if (m_protoStreamFile) { Trace_Event e; e.set_ip(ip); @@ -66,6 +81,29 @@ bool TracingPlugin::run() e.set_accesstype( (ev_mem.getTriggerAccessType() & MemAccessEvent::MEM_READ) ? e.READ : e.WRITE); + + /* When we're doing a full trace, we log more data in + the case of a memory event */ + if (m_full_trace) { + Trace_Event_Extended &ext = *e.mutable_trace_ext(); + // Read the accessed data + assert(width <= 8); + uint64_t data = 0; + mm.getBytes(addr, width, &data); + ext.set_data(data); + + for (unsigned i = 0; i < sizeof(ids)/sizeof(*ids); ++i) { + Trace_Event_Extended_Registers *er = ext.add_registers(); + er->set_id(ids[i]); + er->set_value(simulator.getCPU(0).getRegisterContent(regs[i])); + if (er->value() <= mm.getPoolSize() - width) { + uint32_t value_deref; + mm.getBytes(er->value(), 4, &value_deref); + er->set_value_deref(value_deref); + } + } + } + ps->writeMessage(&e); } } else { diff --git a/src/plugins/tracing/TracingPlugin.hpp b/src/plugins/tracing/TracingPlugin.hpp index a13eb430..4cafa8b2 100644 --- a/src/plugins/tracing/TracingPlugin.hpp +++ b/src/plugins/tracing/TracingPlugin.hpp @@ -21,7 +21,7 @@ * \brief Plugin to record instruction traces and memory accesses. * * This plugin is supposed to be instantiated, configured and run by - * experiments needing instruction or memory access traces. Tracing can be + * experiments needing instruction or memory access traces. Tracing can be * restricted to a memory or instruction address map; the restrictions are * applied together, i.e., a memory access is only logged if neither its * instruction address nor its memory address is restricted. @@ -29,10 +29,10 @@ * TODO: document usage by example * FIXME: handle configuration changes after tracing start properly * FIXME: more explicit startup/shutdown; listener-based event interface needed? - * -> should simulator.removeFlow make sure all remaining active events - * are delivered? + * -> should simulator.removeFlow make sure all remaining active events + * are delivered? * FIXME: trace a sequence of pb messages, not a giant single one (pb weren't - * made for huge messages) + * made for huge messages) * FIXME: destructor -> removeFlow? */ class TracingPlugin : public fail::ExperimentFlow @@ -42,18 +42,19 @@ private: fail::MemoryMap *m_ipMap; //!< instruction address restriction bool m_memonly; //!< log instructions only if they are memory accesses bool m_iponly; //!< log instruction addresses only + bool m_full_trace; //!< do a full trace (more information for the events) std::ostream *m_protoStreamFile; std::ostream *m_os; //!< ostream to write human-readable trace into fail::ProtoOStream *ps; public: - TracingPlugin() + TracingPlugin(bool full_trace = false) : m_memMap(0), m_ipMap(0), m_memonly(false), m_iponly(false), - m_protoStreamFile(0), m_os(0) { } + m_full_trace(full_trace), m_protoStreamFile(0), m_os(0) { } bool run(); /** - * Restricts tracing to memory addresses listed in this MemoryMap. An + * Restricts tracing to memory addresses listed in this MemoryMap. An * access wider than 8 bit *is* logged if *one* of the bytes it * reads/writes is listed. */ @@ -75,6 +76,10 @@ public: * If invoked with iponly=true, only instruction addresses are logged. */ void setLogIPOnly(bool iponly) { m_iponly = iponly; } + /** + * If invoked with fulltrace=true, a extended (full) trace is done. + */ + void setFullTrace(bool fulltrace) { m_full_trace = fulltrace; } /** * ostream to trace into (human-readable) */ diff --git a/src/plugins/tracing/trace.proto b/src/plugins/tracing/trace.proto index 33ff84c7..a5032f24 100644 --- a/src/plugins/tracing/trace.proto +++ b/src/plugins/tracing/trace.proto @@ -1,3 +1,21 @@ +message Trace_Event_Extended { + // data value read/written + optional uint64 data = 5; + // register contents + repeated group Registers = 6 { + // register ID + required uint32 id = 1; + // register value + optional uint64 value = 2; + // data register points to + optional uint32 value_deref = 3; + } + // selected stack content + repeated group Stack = 7 { + required uint32 value = 1; + } +} + message Trace_Event { required uint64 ip = 1; optional uint64 memaddr = 2; @@ -7,4 +25,7 @@ message Trace_Event { WRITE = 2; } optional AccessType accesstype = 4; + + optional Trace_Event_Extended trace_ext = 5; } + diff --git a/tools/dump-trace/Makefile b/tools/dump-trace/Makefile new file mode 100644 index 00000000..8e1ead58 --- /dev/null +++ b/tools/dump-trace/Makefile @@ -0,0 +1,4 @@ +all: trace_pb2.py + +trace_pb2.py: ../../src/plugins/tracing/trace.proto + protoc --python_out=. --proto_path `dirname $<` $< diff --git a/src/plugins/tracing/dump-trace.py b/tools/dump-trace/dump-trace.py similarity index 52% rename from src/plugins/tracing/dump-trace.py rename to tools/dump-trace/dump-trace.py index b3f017df..3a071290 100755 --- a/src/plugins/tracing/dump-trace.py +++ b/tools/dump-trace/dump-trace.py @@ -6,6 +6,7 @@ import trace_pb2 import sys import struct +from gzip import GzipFile if len(sys.argv) != 2: print "Usage:", sys.argv[0], "tracefile.pb" @@ -13,14 +14,21 @@ if len(sys.argv) != 2: trace_event = trace_pb2.Trace_Event() +def open_trace(filename): + f = open(filename, "rb") + if ord(f.read(1)) == 0x1f and ord(f.read(1)) == 0x8b: + f.seek(0,0) + return GzipFile(fileobj = f) + f.seek(0,0) + return f try: - f = open(sys.argv[1], "rb") + f = open_trace(sys.argv[1]) except IOError: print sys.argv[1] + ": Could not open file." sys.exit(-1) -while 1: +while True: # Read trace length try: lengthNO = f.read(4) @@ -34,14 +42,21 @@ while 1: trace_event.ParseFromString(f.read(length)) # This works for any type of pb message: - #print trace_event + # print trace_event # More compact dump for traces: if not trace_event.HasField("memaddr"): print "IP {0:x}".format(trace_event.ip) else: - print "MEM {0} {1:x} width {2:d} IP {3:x}".format( + ext = "" + if trace_event.HasField("trace_ext"): + ext = "DATA {0:x}".format(trace_event.trace_ext.data) + for reg in trace_event.trace_ext.registers: + ext += " REG: {0} *{1:x}={2:x}".format(reg.id, reg.value, reg.value_deref) + if len(trace_event.trace_ext.stack) > 0: + ext += " STACK: " + "".join(["%x"%x for x in trace_event.trace_ext.stack]) + print "MEM {0} {1:x} width {2:d} IP {3:x} {4}".format( "R" if trace_event.accesstype == trace_pb2.Trace_Event.READ else "W", - trace_event.memaddr, trace_event.width, trace_event.ip) + trace_event.memaddr, trace_event.width, trace_event.ip, ext) f.close()