This change makes all C++-based tools in tools/ abort when they encounter an unknown commandline parameter (both option or non-option). This has already caused some confusion, as in some cases unexpected behaviour can be the result. For example, "prune-trace -t mytrace.tc -d database" up to now ignored the "-t" parameter, took "mytrace.tc" as the first non-option parameter (and ignored it); as no option parameter may follow the non-option parameters, all other options were ignored as well. Change-Id: Ia0812a518c4760fa28ed54979c81f43fa7aa096e
169 lines
4.6 KiB
C++
169 lines
4.6 KiB
C++
#include <iostream>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include "comm/TracePlugin.pb.h"
|
|
#include "util/ProtoStream.hpp"
|
|
#include "../../src/core/util/Logger.hpp"
|
|
#include "../../src/core/util/gzstream/gzstream.h"
|
|
#include "util/CommandLine.hpp"
|
|
|
|
using namespace fail;
|
|
using std::stringstream;
|
|
using std::endl;
|
|
using std::cout;
|
|
using std::cerr;
|
|
using std::hex;
|
|
using std::dec;
|
|
|
|
Logger LOG("dump-trace", true);
|
|
|
|
std::istream& openStream(const char *input_file,
|
|
std::ifstream& normal_stream, igzstream& gz_stream) {
|
|
normal_stream.open(input_file);
|
|
if (!normal_stream) {
|
|
LOG << "couldn't open " << input_file << endl;
|
|
exit(-1);
|
|
}
|
|
unsigned char b1, b2;
|
|
normal_stream >> b1 >> b2;
|
|
|
|
if (b1 == 0x1f && b2 == 0x8b) {
|
|
normal_stream.close();
|
|
gz_stream.open(input_file);
|
|
if (!gz_stream) {
|
|
LOG << "couldn't open " << input_file << endl;
|
|
exit(-1);
|
|
}
|
|
//LOG << "opened file " << input_file << " in GZip mode" << endl;
|
|
return gz_stream;
|
|
}
|
|
|
|
normal_stream.seekg(0);
|
|
|
|
//LOG << "opened file " << input_file << " in normal mode" << endl;
|
|
return normal_stream;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
Trace_Event ev;
|
|
|
|
CommandLine &cmd = CommandLine::Inst();
|
|
CommandLine::option_handle UNKNOWN =
|
|
cmd.addOption("", "", Arg::None, "usage: dump-trace [options] tracefile.tc");
|
|
CommandLine::option_handle HELP =
|
|
cmd.addOption("h", "help", Arg::None, "-h/--help \tPrint usage and exit");
|
|
CommandLine::option_handle STATS =
|
|
cmd.addOption("s", "stats", Arg::None,
|
|
"-s/--stats \tShow trace stats");
|
|
CommandLine::option_handle EXTENDED_TRACE =
|
|
cmd.addOption("", "extended-trace", Arg::None,
|
|
"--extended-trace \tDump extended trace information if available");
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
cmd.add_args(argv[i]);
|
|
}
|
|
if (!cmd.parse()) {
|
|
std::cerr << "Error parsing arguments." << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
if (cmd[HELP] || cmd[UNKNOWN] || cmd.parser()->nonOptionsCount() != 1) {
|
|
for (option::Option* opt = cmd[UNKNOWN]; opt; opt = opt->next()) {
|
|
std::cerr << "Unknown option: " << opt->name << "\n";
|
|
}
|
|
for (int i = 1; i < cmd.parser()->nonOptionsCount(); ++i) {
|
|
std::cerr << "Unknown non-option: " << cmd.parser()->nonOption(i) << "\n";
|
|
}
|
|
cmd.printUsage();
|
|
if (cmd[HELP]) {
|
|
exit(0);
|
|
} else {
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
bool stats_only = cmd[STATS];
|
|
bool extended = cmd[EXTENDED_TRACE];
|
|
|
|
std::ifstream normal_stream;
|
|
igzstream gz_stream;
|
|
ProtoIStream ps(&openStream(cmd.parser()->nonOption(0), normal_stream, gz_stream));
|
|
|
|
uint64_t acctime = 0;
|
|
uint64_t stats_instr = 0, stats_reads = 0, stats_writes = 0;
|
|
uint64_t stats_read_b = 0, stats_write_b = 0, starttime = 0;
|
|
|
|
while (ps.getNext(&ev)) {
|
|
if (ev.has_time_delta()) {
|
|
if (!acctime) {
|
|
starttime = ev.time_delta();
|
|
}
|
|
acctime += ev.time_delta();
|
|
}
|
|
if (!ev.has_memaddr()) {
|
|
++stats_instr;
|
|
if (!stats_only) {
|
|
cout << "IP " << hex << ev.ip() << dec << " t=" << acctime << "\n";
|
|
}
|
|
} else {
|
|
stringstream ext;
|
|
if (ev.has_trace_ext() && !stats_only && extended) {
|
|
const Trace_Event_Extended& temp_ext = ev.trace_ext();
|
|
ext << " DATA " << std::hex;
|
|
ext << (uint64_t) temp_ext.data();
|
|
for (int i = 0; i < temp_ext.registers_size(); i++) {
|
|
const Trace_Event_Extended_Registers& temp_reg = temp_ext.registers(i);
|
|
ext << " REG "
|
|
<< (unsigned) temp_reg.id() << " = ";
|
|
if (temp_reg.has_value()) {
|
|
ext << (uint32_t) temp_reg.value();
|
|
} else {
|
|
ext << "??";
|
|
}
|
|
ext << " -> ";
|
|
if (temp_reg.has_value_deref()) {
|
|
ext << (uint32_t) temp_reg.value_deref();
|
|
} else {
|
|
ext << "??";
|
|
}
|
|
}
|
|
if (temp_ext.stack_size() > 0 ) {
|
|
ext << " STACK:";
|
|
for (int i = 0; i < temp_ext.stack_size(); i++) {
|
|
const Trace_Event_Extended_Stack& temp_stack = temp_ext.stack(i);
|
|
ext << " " << (uint32_t) temp_stack.value();
|
|
}
|
|
}
|
|
}
|
|
if (!stats_only) {
|
|
cout << "MEM "
|
|
<< (ev.accesstype() == Trace_Event_AccessType_READ ? "R" : "W") << " "
|
|
<< hex << ev.memaddr()
|
|
<< dec << " width " << ev.width()
|
|
<< hex << " IP " << ev.ip()
|
|
<< dec << " t=" << acctime
|
|
<< ext.str() << "\n";
|
|
}
|
|
if (ev.accesstype() == Trace_Event_AccessType_READ) {
|
|
stats_reads++;
|
|
stats_read_b += ev.width();
|
|
} else {
|
|
stats_writes++;
|
|
stats_write_b += ev.width();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (stats_only) {
|
|
cout << "#instructions: " << stats_instr << "\n"
|
|
<< "#memR: " << stats_reads << "\n"
|
|
<< "#memR_bytes " << stats_read_b << "\n"
|
|
<< "#memW: " << stats_writes << "\n"
|
|
<< "#memW_bytes " << stats_write_b << "\n"
|
|
<< "duration: " << (acctime - starttime + 1) << endl;
|
|
}
|
|
|
|
return 0;
|
|
}
|