]> git.cworth.org Git - apitrace/commitdiff
Use ids for frames.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Mon, 6 May 2013 06:25:40 +0000 (07:25 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Mon, 6 May 2013 06:25:40 +0000 (07:25 +0100)
So that we don't need to send the same frames over and over again.

common/trace_backtrace.cpp
common/trace_dump.cpp
common/trace_format.hpp
common/trace_model.hpp
common/trace_parser.cpp
common/trace_parser.hpp
common/trace_writer.cpp
common/trace_writer.hpp
common/trace_writer_local.cpp
gui/apitracecall.cpp

index 6807d3db56c8de05195dfd2a2abb8454eeb19d3c..ef19aa97c7a14ab192b3936cdfda5a488050d6dd 100644 (file)
@@ -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<RawStackFrame> getParsedBacktrace() {
         std::vector<RawStackFrame> parsedBacktrace;
         void *array[numOfNestedFunctions + BT_DEPTH];
index c757cb8d6508a5c1502a926fbaaa42b700dcf3e6..655b023d55c97b7bbcf5c236be9b4949a4b3844d 100644 (file)
@@ -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";
         }
     }
index 21dbd55f954825e5912a3c607981f8a9ac66e8b7..4952ee3310a08af827d3f7ffa69506db5eccbe58 100644 (file)
@@ -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
index 531a79a64607a9abc2788176b5c2a6b9fdb3c5d8..d04fe5eb4086ae3d4166426d6d030cc678a1e166 100644 (file)
@@ -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<StackFrame> Backtrace;
+typedef std::vector<StackFrame *> Backtrace;
 
 class Visitor
 {
index 51616634cde123a2f12c86a0a3c6ef2a6acfb473..f7a1f78e54b1e0f511a78bc8ee49a17ef51b153b 100644 (file)
@@ -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;
 }
 
 /**
index e0f84343c38995b13f4bc5ae5e5dd95216615dfb..7bf0a7dce1058f2fd111ab45b2aa5ba5f1d34ca7 100644 (file)
@@ -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<FunctionSigFlags> FunctionSigState;
     typedef SigState<StructSig> StructSigState;
     typedef SigState<EnumSig> EnumSigState;
     typedef SigState<BitmaskSig> BitmaskSigState;
+    typedef SigState<StackFrame> StackFrameState;
 
     typedef std::vector<FunctionSigState *> FunctionMap;
     typedef std::vector<StructSigState *> StructMap;
     typedef std::vector<EnumSigState *> EnumMap;
     typedef std::vector<BitmaskSigState *> BitmaskMap;
+    typedef std::vector<StackFrameState *> 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);
 
index 9ecfa2ca27d3500fee3083fb753c0b6c7d991948..46e6392c6d97920215d60db45cc44ea2dd995e25 100644 (file)
@@ -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) {
index 35a828f61bd72304d9c80ba228ff2c566ffd1057..a75d5ac69ef188e49e408f71eb6c2336fcd54649 100644 (file)
@@ -50,6 +50,7 @@ namespace trace {
         std::vector<bool> structs;
         std::vector<bool> enums;
         std::vector<bool> bitmasks;
+        std::vector<bool> 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);
index ef4a9bdce9e5018f5080807fa87e7c6a884f0d7c..e323bb471effa6b2916af3545fdf6f2bcd90d7f9 100644 (file)
@@ -157,7 +157,7 @@ unsigned LocalWriter::beginEnter(const FunctionSig *sig, bool fake) {
         std::vector<RawStackFrame> backtrace = get_backtrace();
         beginBacktrace(backtrace.size());
         for (unsigned i = 0; i < backtrace.size(); ++i) {
-            writeStackFrame(backtrace[i]);
+            writeStackFrame(&backtrace[i]);
         }
         endBacktrace();
     }
index 3f0fc0b833cd49a2ace36bf91ec2bdf22167ca65..0175bff81755e9e005f101e41a0ec6fc6f324432 100644 (file)
@@ -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";