From 9c25e06ec2fd6cf84ac6f0e66c64ab8601a3ffef Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Mon, 6 May 2013 07:25:40 +0100 Subject: [PATCH] Use ids for frames. So that we don't need to send the same frames over and over again. --- common/trace_backtrace.cpp | 12 +++- common/trace_dump.cpp | 2 +- common/trace_format.hpp | 3 +- common/trace_model.hpp | 3 +- common/trace_parser.cpp | 113 ++++++++++++++++++++++------------ common/trace_parser.hpp | 7 ++- common/trace_writer.cpp | 47 +++++++------- common/trace_writer.hpp | 3 +- common/trace_writer_local.cpp | 2 +- gui/apitracecall.cpp | 22 +++---- 10 files changed, 135 insertions(+), 79 deletions(-) diff --git a/common/trace_backtrace.cpp b/common/trace_backtrace.cpp index 6807d3d..ef19aa9 100644 --- a/common/trace_backtrace.cpp +++ b/common/trace_backtrace.cpp @@ -176,8 +176,10 @@ private: size_t bufSize; void (*dumpBacktrace)(const DebugOutputTarget*, void*); DebugOutputTarget debugTarget; + Id nextFrameId; public: DalvikBacktraceProvider() { + nextFrameId = 0; FILE* (*open_memstream_exp)(char**, size_t*); void (*createDebugTarget)(DebugOutputTarget*, FILE*); void* handle = dlopen("/system/lib/libdvm.so", 0); @@ -240,6 +242,8 @@ public: char* rawBacktrace_it = rawBacktrace; while (*rawBacktrace_it != '\0') { RawStackFrame stackFrame; + // TODO: Keep a cache of stack frames + stackFrame->id = nextFrameId++; /* skip leading space */ while (*rawBacktrace_it == ' ') { rawBacktrace_it++; @@ -343,6 +347,7 @@ private: * functions on the stack to avoid recording these frames. */ int numOfNestedFunctions; + Id nextFrameId; private: /* * Parse a stack frame, expecting: @@ -357,6 +362,7 @@ private: char* frame_symbol_copy = new char[strlen(frame_symbol) + 1]; strcpy(frame_symbol_copy, frame_symbol); RawStackFrame* parsedFrame = new RawStackFrame; + parsedFrame->id = nextFrameId++; char* frame_it = frame_symbol_copy; parsedFrame->module = frame_it; char* offset = NULL; @@ -400,8 +406,10 @@ private: } public: GlibcBacktraceProvider() : - numOfNestedFunctions(0) { - } + numOfNestedFunctions(0), + nextFrameId(0) + {} + std::vector getParsedBacktrace() { std::vector parsedBacktrace; void *array[numOfNestedFunctions + BT_DEPTH]; diff --git a/common/trace_dump.cpp b/common/trace_dump.cpp index c757cb8..655b023 100644 --- a/common/trace_dump.cpp +++ b/common/trace_dump.cpp @@ -250,7 +250,7 @@ public: void visit(Backtrace & backtrace) { for (int i = 0; i < backtrace.size(); i ++) { - visit(&backtrace[i]); + visit(backtrace[i]); os << "\n"; } } diff --git a/common/trace_format.hpp b/common/trace_format.hpp index 21dbd55..4952ee3 100644 --- a/common/trace_format.hpp +++ b/common/trace_format.hpp @@ -108,7 +108,8 @@ namespace trace { * | OPAQUE int * | REPR value value * - * frame = frame_detail+ + * frame = id frame_detail+ + * | id * * frame_detail = MODULE string * | FUNCTION string diff --git a/common/trace_model.hpp b/common/trace_model.hpp index 531a79a..d04fe5e 100644 --- a/common/trace_model.hpp +++ b/common/trace_model.hpp @@ -349,6 +349,7 @@ public: }; struct RawStackFrame { + Id id; const char * module; const char * function; const char * filename; @@ -369,7 +370,7 @@ public: ~StackFrame(); }; -typedef std::vector Backtrace; +typedef std::vector Backtrace; class Visitor { diff --git a/common/trace_parser.cpp b/common/trace_parser.cpp index 5161663..f7a1f78 100644 --- a/common/trace_parser.cpp +++ b/common/trace_parser.cpp @@ -241,7 +241,7 @@ Parser::parse_function_sig(void) { } sig->arg_names = arg_names; sig->flags = lookupCallFlags(sig->name); - sig->offset = file->currentOffset(); + sig->fileOffset = file->currentOffset(); functions[id] = sig; /** @@ -279,7 +279,7 @@ Parser::parse_function_sig(void) { glGetErrorSig = sig; } - } else if (file->currentOffset() < sig->offset) { + } else if (file->currentOffset() < sig->fileOffset) { /* skip over the signature */ skip_string(); /* name */ unsigned num_args = read_uint(); @@ -309,9 +309,9 @@ StructSig *Parser::parse_struct_sig() { member_names[i] = read_string(); } sig->member_names = member_names; - sig->offset = file->currentOffset(); + sig->fileOffset = file->currentOffset(); structs[id] = sig; - } else if (file->currentOffset() < sig->offset) { + } else if (file->currentOffset() < sig->fileOffset) { /* skip over the signature */ skip_string(); /* name */ unsigned num_members = read_uint(); @@ -345,9 +345,9 @@ EnumSig *Parser::parse_old_enum_sig() { values->name = read_string(); values->value = read_sint(); sig->values = values; - sig->offset = file->currentOffset(); + sig->fileOffset = file->currentOffset(); enums[id] = sig; - } else if (file->currentOffset() < sig->offset) { + } else if (file->currentOffset() < sig->fileOffset) { /* skip over the signature */ skip_string(); /*name*/ scan_value(); @@ -374,9 +374,9 @@ EnumSig *Parser::parse_enum_sig() { it->value = read_sint(); } sig->values = values; - sig->offset = file->currentOffset(); + sig->fileOffset = file->currentOffset(); enums[id] = sig; - } else if (file->currentOffset() < sig->offset) { + } else if (file->currentOffset() < sig->fileOffset) { /* skip over the signature */ int num_values = read_uint(); for (int i = 0; i < num_values; ++i) { @@ -409,9 +409,9 @@ BitmaskSig *Parser::parse_bitmask_sig() { } } sig->flags = flags; - sig->offset = file->currentOffset(); + sig->fileOffset = file->currentOffset(); bitmasks[id] = sig; - } else if (file->currentOffset() < sig->offset) { + } else if (file->currentOffset() < sig->fileOffset) { /* skip over the signature */ int num_flags = read_uint(); for (int i = 0; i < num_flags; ++i) { @@ -520,41 +520,78 @@ bool Parser::parse_call_backtrace(Call *call, Mode mode) { unsigned num_frames = read_uint(); Backtrace* backtrace = new Backtrace(num_frames); for (unsigned i = 0; i < num_frames; ++i) { - parse_backtrace_frame(&(*backtrace)[i], mode); + (*backtrace)[i] = parse_backtrace_frame(mode); } call->backtrace = backtrace; return true; } -bool Parser::parse_backtrace_frame(StackFrame *frame, Mode mode) { - do { +StackFrame * Parser::parse_backtrace_frame(Mode mode) { + size_t id = read_uint(); + + StackFrameState *frame = lookup(frames, id); + + if (!frame) { + frame = new StackFrameState; int c = read_byte(); - switch (c) { - case trace::BACKTRACE_END: - return true; - case trace::BACKTRACE_MODULE: - frame->module = read_string(); - break; - case trace::BACKTRACE_FUNCTION: - frame->function = read_string(); - break; - case trace::BACKTRACE_FILENAME: - frame->filename = read_string(); - break; - case trace::BACKTRACE_LINENUMBER: - frame->linenumber = read_uint(); - break; - case trace::BACKTRACE_OFFSET: - frame->offset = read_uint(); - break; - default: - std::cerr << "error: unknown backtrace detail " - << c << "\n"; - exit(1); - case -1: - return false; + while (c != trace::BACKTRACE_END && + c != -1) { + switch (c) { + case trace::BACKTRACE_MODULE: + frame->module = read_string(); + break; + case trace::BACKTRACE_FUNCTION: + frame->function = read_string(); + break; + case trace::BACKTRACE_FILENAME: + frame->filename = read_string(); + break; + case trace::BACKTRACE_LINENUMBER: + frame->linenumber = read_uint(); + break; + case trace::BACKTRACE_OFFSET: + frame->offset = read_uint(); + break; + default: + std::cerr << "error: unknown backtrace detail " + << c << "\n"; + exit(1); + } + c = read_byte(); } - } while(true); + + frame->fileOffset = file->currentOffset(); + frames[id] = frame; + } else if (file->currentOffset() < frame->fileOffset) { + int c = read_byte(); + while (c != trace::BACKTRACE_END && + c != -1) { + switch (c) { + case trace::BACKTRACE_MODULE: + scan_string(); + break; + case trace::BACKTRACE_FUNCTION: + scan_string(); + break; + case trace::BACKTRACE_FILENAME: + scan_string(); + break; + case trace::BACKTRACE_LINENUMBER: + scan_uint(); + break; + case trace::BACKTRACE_OFFSET: + scan_uint(); + break; + default: + std::cerr << "error: unknown backtrace detail " + << c << "\n"; + exit(1); + } + c = read_byte(); + } + } + + return frame; } /** diff --git a/common/trace_parser.hpp b/common/trace_parser.hpp index e0f8434..7bf0a7d 100644 --- a/common/trace_parser.hpp +++ b/common/trace_parser.hpp @@ -71,23 +71,26 @@ protected: // Offset in the file of where signature was defined. It is used when // reparsing to determine whether the signature definition is to be // expected next or not. - File::Offset offset; + File::Offset fileOffset; }; typedef SigState FunctionSigState; typedef SigState StructSigState; typedef SigState EnumSigState; typedef SigState BitmaskSigState; + typedef SigState StackFrameState; typedef std::vector FunctionMap; typedef std::vector StructMap; typedef std::vector EnumMap; typedef std::vector BitmaskMap; + typedef std::vector StackFrameMap; FunctionMap functions; StructMap structs; EnumMap enums; BitmaskMap bitmasks; + StackFrameMap frames; FunctionSig *glGetErrorSig; @@ -148,7 +151,7 @@ protected: bool parse_call_details(Call *call, Mode mode); bool parse_call_backtrace(Call *call, Mode mode); - bool parse_backtrace_frame(StackFrame *frame, Mode mode); + StackFrame * parse_backtrace_frame(Mode mode); void adjust_call_flags(Call *call); diff --git a/common/trace_writer.cpp b/common/trace_writer.cpp index 9ecfa2c..46e6392 100644 --- a/common/trace_writer.cpp +++ b/common/trace_writer.cpp @@ -72,6 +72,7 @@ Writer::open(const char *filename) { structs.clear(); enums.clear(); bitmasks.clear(); + frames.clear(); _writeUInt(TRACE_VERSION); @@ -142,28 +143,32 @@ void Writer::beginBacktrace(unsigned num_frames) { } } -void Writer::writeStackFrame(const RawStackFrame &frame) { - if (frame.module != NULL) { - _writeByte(trace::BACKTRACE_MODULE); - _writeString(frame.module); - } - if (frame.function != NULL) { - _writeByte(trace::BACKTRACE_FUNCTION); - _writeString(frame.function); - } - if (frame.filename != NULL) { - _writeByte(trace::BACKTRACE_FILENAME); - _writeString(frame.filename); - } - if (frame.linenumber >= 0) { - _writeByte(trace::BACKTRACE_LINENUMBER); - _writeUInt(frame.linenumber); - } - if (frame.offset >= 0) { - _writeByte(trace::BACKTRACE_OFFSET); - _writeUInt(frame.offset); +void Writer::writeStackFrame(const RawStackFrame *frame) { + _writeUInt(frame->id); + if (!lookup(frames, frame->id)) { + if (frame->module != NULL) { + _writeByte(trace::BACKTRACE_MODULE); + _writeString(frame->module); + } + if (frame->function != NULL) { + _writeByte(trace::BACKTRACE_FUNCTION); + _writeString(frame->function); + } + if (frame->filename != NULL) { + _writeByte(trace::BACKTRACE_FILENAME); + _writeString(frame->filename); + } + if (frame->linenumber >= 0) { + _writeByte(trace::BACKTRACE_LINENUMBER); + _writeUInt(frame->linenumber); + } + if (frame->offset >= 0) { + _writeByte(trace::BACKTRACE_OFFSET); + _writeUInt(frame->offset); + } + _writeByte(trace::BACKTRACE_END); + frames[frame->id] = true; } - _writeByte(trace::BACKTRACE_END); } unsigned Writer::beginEnter(const FunctionSig *sig, unsigned thread_id) { diff --git a/common/trace_writer.hpp b/common/trace_writer.hpp index 35a828f..a75d5ac 100644 --- a/common/trace_writer.hpp +++ b/common/trace_writer.hpp @@ -50,6 +50,7 @@ namespace trace { std::vector structs; std::vector enums; std::vector bitmasks; + std::vector frames; public: Writer(); @@ -71,7 +72,7 @@ namespace trace { inline void endReturn(void) {} void beginBacktrace(unsigned num_frames); - void writeStackFrame(const RawStackFrame &frame); + void writeStackFrame(const RawStackFrame *frame); inline void endBacktrace(void) {} void beginArray(size_t length); diff --git a/common/trace_writer_local.cpp b/common/trace_writer_local.cpp index ef4a9bd..e323bb4 100644 --- a/common/trace_writer_local.cpp +++ b/common/trace_writer_local.cpp @@ -157,7 +157,7 @@ unsigned LocalWriter::beginEnter(const FunctionSig *sig, bool fake) { std::vector backtrace = get_backtrace(); beginBacktrace(backtrace.size()); for (unsigned i = 0; i < backtrace.size(); ++i) { - writeStackFrame(backtrace[i]); + writeStackFrame(&backtrace[i]); } endBacktrace(); } diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp index 3f0fc0b..0175bff 100644 --- a/gui/apitracecall.cpp +++ b/gui/apitracecall.cpp @@ -688,22 +688,22 @@ ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, if (call->backtrace != NULL) { QString qbacktrace; for (int i = 0; i < call->backtrace->size(); i++) { - const trace::StackFrame & frame = (*call->backtrace)[i]; - if (frame.module != NULL) { - qbacktrace += QString("%1 ").arg(frame.module); + const trace::StackFrame * frame = (*call->backtrace)[i]; + if (frame->module != NULL) { + qbacktrace += QString("%1 ").arg(frame->module); } - if (frame.function != NULL) { - qbacktrace += QString("at %1() ").arg(frame.function); + if (frame->function != NULL) { + qbacktrace += QString("at %1() ").arg(frame->function); } - if (frame.filename != NULL) { - qbacktrace += QString("at %1").arg(frame.filename); - if (frame.linenumber >= 0) { - qbacktrace += QString(":%1 ").arg(frame.linenumber); + if (frame->filename != NULL) { + qbacktrace += QString("at %1").arg(frame->filename); + if (frame->linenumber >= 0) { + qbacktrace += QString(":%1 ").arg(frame->linenumber); } } else { - if (frame.offset >= 0) { - qbacktrace += QString("[0x%1]").arg(frame.offset, 0, 16); + if (frame->offset >= 0) { + qbacktrace += QString("[0x%1]").arg(frame->offset, 0, 16); } } qbacktrace += "\n"; -- 2.43.0