diff options
author | Jose Fonseca <jfonseca@vmware.com> | 2016-02-19 11:17:49 +0000 |
---|---|---|
committer | Jose Fonseca <jfonseca@vmware.com> | 2016-02-19 11:17:49 +0000 |
commit | 5b1d901228eb137e4883c1b58db7e9237f123fb3 (patch) | |
tree | 81197f359f92f0f6a5bc95a0b009a3e596478a1f /cli | |
parent | b3236dd0ac5322332bbdb7bfce073ec96be21d14 (diff) |
cli: Add support to dump blobs to files.
Many people asked something like this. I finally felt the urge myself and
implemented it.
One can see the blobs with an ordinary hex editor.
Diffstat (limited to 'cli')
-rw-r--r-- | cli/cli_dump.cpp | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/cli/cli_dump.cpp b/cli/cli_dump.cpp index d674c83d..c6163950 100644 --- a/cli/cli_dump.cpp +++ b/cli/cli_dump.cpp @@ -32,11 +32,14 @@ #include <unistd.h> // for isatty() #endif +#include <memory> +#include <fstream> + #include "cli.hpp" #include "cli_pager.hpp" #include "trace_parser.hpp" -#include "trace_dump.hpp" +#include "trace_dump_internal.hpp" #include "trace_callset.hpp" #include "trace_option.hpp" @@ -71,6 +74,7 @@ usage(void) " --thread-ids=[=BOOL] dump thread ids [default: no]\n" " --call-nos[=BOOL] dump call numbers[default: yes]\n" " --arg-names[=BOOL] dump argument names [default: yes]\n" + " --blobs dump blobs into files\n" "\n" ; } @@ -81,6 +85,7 @@ enum { THREAD_IDS_OPT, CALL_NOS_OPT, ARG_NAMES_OPT, + BLOBS_OPT, }; const static char * @@ -96,14 +101,53 @@ longOptions[] = { {"thread-ids", optional_argument, 0, THREAD_IDS_OPT}, {"call-nos", optional_argument, 0, CALL_NOS_OPT}, {"arg-names", optional_argument, 0, ARG_NAMES_OPT}, + {"blobs", no_argument, 0, BLOBS_OPT}, {0, 0, 0, 0} }; + +class BlobDumper : public trace::Dumper +{ + unsigned callNo = 0; + unsigned blobNo = 0; +public: + BlobDumper(std::ostream &_os, trace::DumpFlags _flags) : + Dumper(_os, _flags) + { + } + + void visit(trace::Blob *blob) { + std::string fileName = "blob_call" + std::to_string(callNo); + if (blobNo) { + fileName += "_"; + fileName += std::to_string(blobNo); + } + fileName += ".bin"; + + { + std::ofstream stream(fileName, std::ofstream::binary); + stream.write((const char *)blob->buf, blob->size); + stream.close(); + } + + os << pointer << "blob(\"" << fileName << "\")" << normal; + ++blobNo; + } + + void visit(trace::Call *call) { + callNo = call->no; + blobNo = 0; + Dumper::visit(call); + } +}; + + static int command(int argc, char *argv[]) { trace::DumpFlags dumpFlags = 0; - + bool blobs = false; + int opt; while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) { switch (opt) { @@ -150,6 +194,9 @@ command(int argc, char *argv[]) dumpFlags |= trace::DUMP_FLAG_NO_ARG_NAMES; } break; + case BLOBS_OPT: + blobs = true; + break; default: std::cerr << "error: unexpected option `" << (char)opt << "`\n"; usage(); @@ -170,6 +217,14 @@ command(int argc, char *argv[]) dumpFlags |= trace::DUMP_FLAG_NO_COLOR; } + std::unique_ptr<trace::Dumper> dumper; + + if (blobs) { + dumper = std::unique_ptr<trace::Dumper>(new BlobDumper(std::cout, dumpFlags)); + } else { + dumper = std::unique_ptr<trace::Dumper>(new trace::Dumper(std::cout, dumpFlags)); + } + for (int i = optind; i < argc; ++i) { trace::Parser p; @@ -182,7 +237,7 @@ command(int argc, char *argv[]) if (calls.contains(*call)) { if (verbose || !(call->flags & trace::CALL_FLAG_VERBOSE)) { - trace::dump(*call, std::cout, dumpFlags); + dumper->visit(call); } } delete call; |