From 946da143b5fa8b5babddd5668743e4048bf08e7d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Sun, 11 Dec 2011 14:32:50 +0000 Subject: [PATCH] Move trace dumping to a separate module. Add option to not dump arg names. --- CMakeLists.txt | 1 + cli/cli_dump.cpp | 18 ++- common/trace_dump.cpp | 260 +++++++++++++++++++++++++++++++++++++++++ common/trace_dump.hpp | 72 ++++++++++++ common/trace_model.cpp | 219 ---------------------------------- common/trace_model.hpp | 20 +--- retrace.cpp | 1 + scripts/tracediff.sh | 2 +- 8 files changed, 352 insertions(+), 241 deletions(-) create mode 100644 common/trace_dump.cpp create mode 100644 common/trace_dump.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 09386aa..177c82b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -267,6 +267,7 @@ else () endif () add_library (common STATIC + common/trace_dump.cpp common/trace_file.cpp common/trace_file_read.cpp common/trace_file_write.cpp diff --git a/cli/cli_dump.cpp b/cli/cli_dump.cpp index ebb92d8..f6c5129 100644 --- a/cli/cli_dump.cpp +++ b/cli/cli_dump.cpp @@ -1,5 +1,6 @@ /************************************************************************** * + * Copyright 2011 Jose Fonseca * Copyright 2010 VMware, Inc. * All Rights Reserved. * @@ -23,12 +24,15 @@ * **************************************************************************/ + #include #include "cli.hpp" #include "cli_pager.hpp" #include "trace_parser.hpp" +#include "trace_dump.hpp" + enum ColorOption { COLOR_OPTION_NEVER = 0, @@ -52,12 +56,16 @@ usage(void) " -v, --verbose verbose output\n" " --color=\n" " --colour= Colored syntax highlighting\n" - " WHEN is 'auto', 'always', or 'never'\n"; + " WHEN is 'auto', 'always', or 'never'\n" + " --no-arg-names Don't dump argument names\n" + ; } static int command(int argc, char *argv[]) { + trace::DumpFlags dumpFlags = 0; + int i; for (i = 0; i < argc; ++i) { @@ -88,6 +96,8 @@ command(int argc, char *argv[]) !strcmp(arg, "--no-color") || !strcmp(arg, "--no-colour")) { color = COLOR_OPTION_NEVER; + } else if (!strcmp(arg, "--no-arg-names")) { + dumpFlags |= trace::DUMP_FLAG_NO_ARG_NAMES; } else { std::cerr << "error: unknown option " << arg << "\n"; usage(); @@ -104,6 +114,10 @@ command(int argc, char *argv[]) #endif } + if (color == COLOR_OPTION_NEVER) { + dumpFlags |= trace::DUMP_FLAG_NO_COLOR; + } + for (; i < argc; ++i) { trace::Parser p; @@ -116,7 +130,7 @@ command(int argc, char *argv[]) while ((call = p.parse_call())) { if (verbose || !(call->flags & trace::CALL_FLAG_VERBOSE)) { - call->dump(std::cout, color); + trace::dump(*call, std::cout, dumpFlags); } delete call; } diff --git a/common/trace_dump.cpp b/common/trace_dump.cpp new file mode 100644 index 0000000..6a0e6a7 --- /dev/null +++ b/common/trace_dump.cpp @@ -0,0 +1,260 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include "formatter.hpp" +#include "trace_dump.hpp" + + +namespace trace { + + +class Dumper : public Visitor +{ +protected: + std::ostream &os; + DumpFlags flags; + formatter::Formatter *formatter; + formatter::Attribute *normal; + formatter::Attribute *bold; + formatter::Attribute *italic; + formatter::Attribute *strike; + formatter::Attribute *red; + formatter::Attribute *pointer; + formatter::Attribute *literal; + +public: + Dumper(std::ostream &_os, DumpFlags _flags) : + os(_os), + flags(_flags) + { + bool color = !(flags & DUMP_FLAG_NO_COLOR); + formatter = formatter::defaultFormatter(color); + normal = formatter->normal(); + bold = formatter->bold(); + italic = formatter->italic(); + strike = formatter->strike(); + red = formatter->color(formatter::RED); + pointer = formatter->color(formatter::GREEN); + literal = formatter->color(formatter::BLUE); + } + + ~Dumper() { + delete normal; + delete bold; + delete italic; + delete strike; + delete red; + delete pointer; + delete literal; + delete formatter; + } + + void visit(Null *) { + os << "NULL"; + } + + void visit(Bool *node) { + os << literal << (node->value ? "true" : "false") << normal; + } + + void visit(SInt *node) { + os << literal << node->value << normal; + } + + void visit(UInt *node) { + os << literal << node->value << normal; + } + + void visit(Float *node) { + os << literal << node->value << normal; + } + + void visit(Double *node) { + os << literal << node->value << normal; + } + + void visit(String *node) { + os << literal << "\""; + for (const char *it = node->value; *it; ++it) { + unsigned char c = (unsigned char) *it; + if (c == '\"') + os << "\\\""; + else if (c == '\\') + os << "\\\\"; + else if (c >= 0x20 && c <= 0x7e) + os << c; + else if (c == '\t') { + os << "\t"; + } else if (c == '\r') { + // Ignore carriage-return + } else if (c == '\n') { + // Reset formatting so that it looks correct with 'less -R' + os << normal << '\n' << literal; + } else { + unsigned octal0 = c & 0x7; + unsigned octal1 = (c >> 3) & 0x7; + unsigned octal2 = (c >> 3) & 0x7; + os << "\\"; + if (octal2) + os << octal2; + if (octal1) + os << octal1; + os << octal0; + } + } + os << "\"" << normal; + } + + void visit(Enum *node) { + const EnumSig *sig = node->sig; + for (const EnumValue *it = sig->values; it != sig->values + sig->num_values; ++it) { + if (it->value == node->value) { + os << literal << it->name << normal; + return; + } + } + os << literal << node->value << normal; + } + + void visit(Bitmask *bitmask) { + unsigned long long value = bitmask->value; + const BitmaskSig *sig = bitmask->sig; + bool first = true; + for (const BitmaskFlag *it = sig->flags; value != 0 && it != sig->flags + sig->num_flags; ++it) { + if ((it->value && (value & it->value) == it->value) || + (!it->value && value == 0)) { + if (!first) { + os << " | "; + } + os << literal << it->name << normal; + value &= ~it->value; + first = false; + } + } + if (value || first) { + if (!first) { + os << " | "; + } + os << literal << "0x" << std::hex << value << std::dec << normal; + } + } + + void visit(Struct *s) { + const char *sep = ""; + os << "{"; + for (unsigned i = 0; i < s->members.size(); ++i) { + os << sep << italic << s->sig->member_names[i] << normal << " = "; + _visit(s->members[i]); + sep = ", "; + } + os << "}"; + } + + void visit(Array *array) { + if (array->values.size() == 1) { + os << "&"; + _visit(array->values[0]); + } + else { + const char *sep = ""; + os << "{"; + for (std::vector::iterator it = array->values.begin(); it != array->values.end(); ++it) { + os << sep; + _visit(*it); + sep = ", "; + } + os << "}"; + } + } + + void visit(Blob *blob) { + os << pointer << "blob(" << blob->size << ")" << normal; + } + + void visit(Pointer *p) { + os << pointer << "0x" << std::hex << p->value << std::dec << normal; + } + + void visit(Call *call) { + CallFlags flags = call->flags; + + if (flags & CALL_FLAG_NON_REPRODUCIBLE) { + os << strike; + } else if (flags & (CALL_FLAG_FAKE | CALL_FLAG_NO_SIDE_EFFECTS)) { + os << normal; + } else { + os << bold; + } + os << call->sig->name << normal; + + os << "("; + const char *sep = ""; + for (unsigned i = 0; i < call->args.size(); ++i) { + os << sep; + if (!(flags = DUMP_FLAG_NO_ARG_NAMES)) { + os << italic << call->sig->arg_names[i] << normal << " = "; + } + if (call->args[i]) { + _visit(call->args[i]); + } else { + os << "?"; + } + sep = ", "; + } + os << ")"; + + if (call->ret) { + os << " = "; + _visit(call->ret); + } + + if (flags & CALL_FLAG_INCOMPLETE) { + os << " // " << red << "incomplete" << normal; + } + + os << "\n"; + + if (flags & CALL_FLAG_END_FRAME) { + os << "\n"; + } + } +}; + + +void dump(Value *value, std::ostream &os, DumpFlags flags) { + Dumper d(os, flags); + value->visit(d); +} + + +void dump(Call &call, std::ostream &os, DumpFlags flags) { + Dumper d(os, flags); + os << call.no << " "; + d.visit(&call); +} + + +} /* namespace trace */ diff --git a/common/trace_dump.hpp b/common/trace_dump.hpp new file mode 100644 index 0000000..4ffe65a --- /dev/null +++ b/common/trace_dump.hpp @@ -0,0 +1,72 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + +/* + * Human-readible dumping. + */ + +#ifndef _TRACE_DUMP_HPP_ +#define _TRACE_DUMP_HPP_ + + +#include + +#include "trace_model.hpp" + + +namespace trace { + + +typedef unsigned DumpFlags; + +enum { + DUMP_FLAG_NO_COLOR = (1 << 0), + DUMP_FLAG_NO_ARG_NAMES = (1 << 1), +}; + + +void dump(Value *value, std::ostream &os, DumpFlags flags = 0); + + +inline std::ostream & operator <<(std::ostream &os, Value *value) { + if (value) { + dump(value, os); + } + return os; +} + + +void dump(Call &call, std::ostream &os, DumpFlags flags = 0); + + +inline std::ostream & operator <<(std::ostream &os, Call &call) { + dump(call, os); + return os; +} + + +} /* namespace trace */ + +#endif /* _TRACE_DUMP_HPP_ */ diff --git a/common/trace_model.cpp b/common/trace_model.cpp index 2ceb810..e05ca27 100644 --- a/common/trace_model.cpp +++ b/common/trace_model.cpp @@ -24,7 +24,6 @@ **************************************************************************/ -#include "formatter.hpp" #include "trace_model.hpp" @@ -183,217 +182,6 @@ void Visitor::visit(Blob *) { assert(0); } void Visitor::visit(Pointer *) { assert(0); } -class Dumper : public Visitor -{ -protected: - std::ostream &os; - formatter::Formatter *formatter; - formatter::Attribute *normal; - formatter::Attribute *bold; - formatter::Attribute *italic; - formatter::Attribute *strike; - formatter::Attribute *red; - formatter::Attribute *pointer; - formatter::Attribute *literal; - -public: - Dumper(std::ostream &_os, bool color) : os(_os) { - formatter = formatter::defaultFormatter(color); - normal = formatter->normal(); - bold = formatter->bold(); - italic = formatter->italic(); - strike = formatter->strike(); - red = formatter->color(formatter::RED); - pointer = formatter->color(formatter::GREEN); - literal = formatter->color(formatter::BLUE); - } - - ~Dumper() { - delete normal; - delete bold; - delete italic; - delete strike; - delete red; - delete pointer; - delete literal; - delete formatter; - } - - void visit(Null *) { - os << "NULL"; - } - - void visit(Bool *node) { - os << literal << (node->value ? "true" : "false") << normal; - } - - void visit(SInt *node) { - os << literal << node->value << normal; - } - - void visit(UInt *node) { - os << literal << node->value << normal; - } - - void visit(Float *node) { - os << literal << node->value << normal; - } - - void visit(Double *node) { - os << literal << node->value << normal; - } - - void visit(String *node) { - os << literal << "\""; - for (const char *it = node->value; *it; ++it) { - unsigned char c = (unsigned char) *it; - if (c == '\"') - os << "\\\""; - else if (c == '\\') - os << "\\\\"; - else if (c >= 0x20 && c <= 0x7e) - os << c; - else if (c == '\t') { - os << "\t"; - } else if (c == '\r') { - // Ignore carriage-return - } else if (c == '\n') { - // Reset formatting so that it looks correct with 'less -R' - os << normal << '\n' << literal; - } else { - unsigned octal0 = c & 0x7; - unsigned octal1 = (c >> 3) & 0x7; - unsigned octal2 = (c >> 3) & 0x7; - os << "\\"; - if (octal2) - os << octal2; - if (octal1) - os << octal1; - os << octal0; - } - } - os << "\"" << normal; - } - - void visit(Enum *node) { - const EnumSig *sig = node->sig; - for (const EnumValue *it = sig->values; it != sig->values + sig->num_values; ++it) { - if (it->value == node->value) { - os << literal << it->name << normal; - return; - } - } - os << literal << node->value << normal; - } - - void visit(Bitmask *bitmask) { - unsigned long long value = bitmask->value; - const BitmaskSig *sig = bitmask->sig; - bool first = true; - for (const BitmaskFlag *it = sig->flags; value != 0 && it != sig->flags + sig->num_flags; ++it) { - if ((it->value && (value & it->value) == it->value) || - (!it->value && value == 0)) { - if (!first) { - os << " | "; - } - os << literal << it->name << normal; - value &= ~it->value; - first = false; - } - } - if (value || first) { - if (!first) { - os << " | "; - } - os << literal << "0x" << std::hex << value << std::dec << normal; - } - } - - void visit(Struct *s) { - const char *sep = ""; - os << "{"; - for (unsigned i = 0; i < s->members.size(); ++i) { - os << sep << italic << s->sig->member_names[i] << normal << " = "; - _visit(s->members[i]); - sep = ", "; - } - os << "}"; - } - - void visit(Array *array) { - if (array->values.size() == 1) { - os << "&"; - _visit(array->values[0]); - } - else { - const char *sep = ""; - os << "{"; - for (std::vector::iterator it = array->values.begin(); it != array->values.end(); ++it) { - os << sep; - _visit(*it); - sep = ", "; - } - os << "}"; - } - } - - void visit(Blob *blob) { - os << pointer << "blob(" << blob->size << ")" << normal; - } - - void visit(Pointer *p) { - os << pointer << "0x" << std::hex << p->value << std::dec << normal; - } - - void visit(Call *call) { - CallFlags flags = call->flags; - - if (flags & CALL_FLAG_NON_REPRODUCIBLE) { - os << strike; - } else if (flags & (CALL_FLAG_FAKE | CALL_FLAG_NO_SIDE_EFFECTS)) { - os << normal; - } else { - os << bold; - } - os << call->sig->name << normal; - - os << "("; - const char *sep = ""; - for (unsigned i = 0; i < call->args.size(); ++i) { - os << sep << italic << call->sig->arg_names[i] << normal << " = "; - if (call->args[i]) { - _visit(call->args[i]); - } else { - os << "?"; - } - sep = ", "; - } - os << ")"; - - if (call->ret) { - os << " = "; - _visit(call->ret); - } - - if (flags & CALL_FLAG_INCOMPLETE) { - os << " // " << red << "incomplete" << normal; - } - - os << "\n"; - - if (flags & CALL_FLAG_END_FRAME) { - os << "\n"; - } - } -}; - - -void Value::dump(std::ostream &os, bool color) { - Dumper d(os, color); - visit(d); -} - - static Null null; const Value & Value::operator[](size_t index) const { @@ -406,11 +194,4 @@ const Value & Value::operator[](size_t index) const { return null; } -void Call::dump(std::ostream &os, bool color) { - Dumper d(os, color); - os << no << " "; - d.visit(this); -} - - } /* namespace trace */ diff --git a/common/trace_model.hpp b/common/trace_model.hpp index 1b2e1f2..4f150bc 100644 --- a/common/trace_model.hpp +++ b/common/trace_model.hpp @@ -32,10 +32,10 @@ #include +#include #include #include -#include namespace trace { @@ -107,8 +107,6 @@ public: virtual const char *toString(void) const; const Value & operator[](size_t index) const; - - void dump(std::ostream &os, bool color=true); }; @@ -332,14 +330,6 @@ protected: }; -inline std::ostream & operator <<(std::ostream &os, Value *value) { - if (value) { - value->dump(os); - } - return os; -} - - typedef unsigned CallFlags; /** @@ -444,17 +434,9 @@ public: assert(index < args.size()); return *(args[index]); } - - void dump(std::ostream &os, bool color=true); }; -inline std::ostream & operator <<(std::ostream &os, Call &call) { - call.dump(os); - return os; -} - - } /* namespace trace */ #endif /* _TRACE_MODEL_HPP_ */ diff --git a/retrace.cpp b/retrace.cpp index 795d039..849c597 100644 --- a/retrace.cpp +++ b/retrace.cpp @@ -27,6 +27,7 @@ #include #include +#include "trace_dump.hpp" #include "retrace.hpp" diff --git a/scripts/tracediff.sh b/scripts/tracediff.sh index 57d59f8..9f9633d 100755 --- a/scripts/tracediff.sh +++ b/scripts/tracediff.sh @@ -31,7 +31,7 @@ APITRACE=${APITRACE:-apitrace} $APITRACE dump stripdump () { - $APITRACE dump --color=never "$1" \ + $APITRACE dump --color=never --no-arg-names "$1" \ | sed \ -e 's/\r$//g' \ -e 's/^[0-9]\+ //' \ -- 2.43.0