Loading include/utils/CallStack.h +8 −31 Original line number Diff line number Diff line Loading @@ -18,8 +18,9 @@ #define ANDROID_CALLSTACK_H #include <android/log.h> #include <backtrace/backtrace.h> #include <utils/String8.h> #include <corkscrew/backtrace.h> #include <utils/Vector.h> #include <stdint.h> #include <sys/types.h> Loading @@ -31,42 +32,19 @@ class Printer; // Collect/print the call stack (function, file, line) traces for a single thread. class CallStack { public: enum { // Prune the lowest-most stack frames until we have at most MAX_DEPTH. MAX_DEPTH = 31, // Placeholder for specifying the current thread when updating the stack. CURRENT_THREAD = -1, }; // Create an empty call stack. No-op. CallStack(); // Create a callstack with the current thread's stack trace. // Immediately dump it to logcat using the given logtag. CallStack(const char* logtag, int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH); // Copy the existing callstack (no other side effects). CallStack(const CallStack& rhs); CallStack(const char* logtag, int32_t ignoreDepth=1); ~CallStack(); // Copy the existing callstack (no other side effects). CallStack& operator = (const CallStack& rhs); // Compare call stacks by their backtrace frame memory. bool operator == (const CallStack& rhs) const; bool operator != (const CallStack& rhs) const; bool operator < (const CallStack& rhs) const; bool operator >= (const CallStack& rhs) const; bool operator > (const CallStack& rhs) const; bool operator <= (const CallStack& rhs) const; // Get the PC address for the stack frame specified by index. const void* operator [] (int index) const; // Reset the stack frames (same as creating an empty call stack). void clear(); void clear() { mFrameLines.clear(); } // Immediately collect the stack traces for the specified thread. void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH, pid_t tid=CURRENT_THREAD); // The default is to dump the stack of the current call. void update(int32_t ignoreDepth=1, pid_t tid=BACKTRACE_NO_TID); // Dump a stack trace to the log using the supplied logtag. void log(const char* logtag, Loading @@ -83,11 +61,10 @@ public: void print(Printer& printer) const; // Get the count of stack frames that are in this call stack. size_t size() const { return mCount; } size_t size() const { return mFrameLines.size(); } private: size_t mCount; backtrace_frame_t mStack[MAX_DEPTH]; Vector<String8> mFrameLines; }; }; // namespace android Loading include/utils/ProcessCallStack.h +1 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ public: ~ProcessCallStack(); // Immediately collect the stack traces for all threads. void update(int32_t maxDepth = CallStack::MAX_DEPTH); void update(); // Print all stack traces to the log using the supplied logtag. void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG, Loading libutils/Android.mk +7 −3 Original line number Diff line number Diff line Loading @@ -116,10 +116,12 @@ LOCAL_STATIC_LIBRARIES := \ libcutils LOCAL_SHARED_LIBRARIES := \ libcorkscrew \ libbacktrace \ liblog \ libdl include external/stlport/libstlport.mk LOCAL_MODULE:= libutils include $(BUILD_STATIC_LIBRARY) Loading @@ -129,10 +131,12 @@ include $(CLEAR_VARS) LOCAL_MODULE:= libutils LOCAL_WHOLE_STATIC_LIBRARIES := libutils LOCAL_SHARED_LIBRARIES := \ liblog \ libbacktrace \ libcutils \ libdl \ libcorkscrew liblog \ include external/stlport/libstlport.mk include $(BUILD_SHARED_LIBRARY) Loading libutils/CallStack.cpp +15 −82 Original line number Diff line number Diff line Loading @@ -20,93 +20,33 @@ #include <utils/Printer.h> #include <utils/Errors.h> #include <utils/Log.h> #include <corkscrew/backtrace.h> #include <UniquePtr.h> #include <backtrace/Backtrace.h> namespace android { CallStack::CallStack() : mCount(0) { CallStack::CallStack() { } CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) { this->update(ignoreDepth+1, maxDepth, CURRENT_THREAD); CallStack::CallStack(const char* logtag, int32_t ignoreDepth) { this->update(ignoreDepth+1); this->log(logtag); } CallStack::CallStack(const CallStack& rhs) : mCount(rhs.mCount) { if (mCount) { memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)); } } CallStack::~CallStack() { } CallStack& CallStack::operator = (const CallStack& rhs) { mCount = rhs.mCount; if (mCount) { memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)); } return *this; } bool CallStack::operator == (const CallStack& rhs) const { if (mCount != rhs.mCount) return false; return !mCount || memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) == 0; } bool CallStack::operator != (const CallStack& rhs) const { return !operator == (rhs); } void CallStack::update(int32_t ignoreDepth, pid_t tid) { mFrameLines.clear(); bool CallStack::operator < (const CallStack& rhs) const { if (mCount != rhs.mCount) return mCount < rhs.mCount; return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) < 0; UniquePtr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid)); if (!backtrace->Unwind(ignoreDepth)) { ALOGW("%s: Failed to unwind callstack.", __FUNCTION__); } bool CallStack::operator >= (const CallStack& rhs) const { return !operator < (rhs); for (size_t i = 0; i < backtrace->NumFrames(); i++) { mFrameLines.push_back(String8(backtrace->FormatFrameData(i).c_str())); } bool CallStack::operator > (const CallStack& rhs) const { if (mCount != rhs.mCount) return mCount > rhs.mCount; return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) > 0; } bool CallStack::operator <= (const CallStack& rhs) const { return !operator > (rhs); } const void* CallStack::operator [] (int index) const { if (index >= int(mCount)) return 0; return reinterpret_cast<const void*>(mStack[index].absolute_pc); } void CallStack::clear() { mCount = 0; } void CallStack::update(int32_t ignoreDepth, int32_t maxDepth, pid_t tid) { if (maxDepth > MAX_DEPTH) { maxDepth = MAX_DEPTH; } ssize_t count; if (tid >= 0) { count = unwind_backtrace_thread(tid, mStack, ignoreDepth + 1, maxDepth); } else if (tid == CURRENT_THREAD) { count = unwind_backtrace(mStack, ignoreDepth + 1, maxDepth); } else { ALOGE("%s: Invalid tid specified (%d)", __FUNCTION__, tid); count = 0; } mCount = count > 0 ? count : 0; } void CallStack::log(const char* logtag, android_LogPriority priority, const char* prefix) const { Loading @@ -129,16 +69,9 @@ String8 CallStack::toString(const char* prefix) const { } void CallStack::print(Printer& printer) const { backtrace_symbol_t symbols[mCount]; get_backtrace_symbols(mStack, mCount, symbols); for (size_t i = 0; i < mCount; i++) { char line[MAX_BACKTRACE_LINE_LENGTH]; format_backtrace_line(i, &mStack[i], &symbols[i], line, MAX_BACKTRACE_LINE_LENGTH); printer.printLine(line); for (size_t i = 0; i < mFrameLines.size(); i++) { printer.printLine(mFrameLines[i]); } free_backtrace_symbols(symbols, mCount); } }; // namespace android libutils/Printer.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,7 @@ void String8Printer::printLine(const char* string) { return; } mTarget->append(mPrefix); mTarget->append(string); mTarget->append("\n"); } Loading Loading
include/utils/CallStack.h +8 −31 Original line number Diff line number Diff line Loading @@ -18,8 +18,9 @@ #define ANDROID_CALLSTACK_H #include <android/log.h> #include <backtrace/backtrace.h> #include <utils/String8.h> #include <corkscrew/backtrace.h> #include <utils/Vector.h> #include <stdint.h> #include <sys/types.h> Loading @@ -31,42 +32,19 @@ class Printer; // Collect/print the call stack (function, file, line) traces for a single thread. class CallStack { public: enum { // Prune the lowest-most stack frames until we have at most MAX_DEPTH. MAX_DEPTH = 31, // Placeholder for specifying the current thread when updating the stack. CURRENT_THREAD = -1, }; // Create an empty call stack. No-op. CallStack(); // Create a callstack with the current thread's stack trace. // Immediately dump it to logcat using the given logtag. CallStack(const char* logtag, int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH); // Copy the existing callstack (no other side effects). CallStack(const CallStack& rhs); CallStack(const char* logtag, int32_t ignoreDepth=1); ~CallStack(); // Copy the existing callstack (no other side effects). CallStack& operator = (const CallStack& rhs); // Compare call stacks by their backtrace frame memory. bool operator == (const CallStack& rhs) const; bool operator != (const CallStack& rhs) const; bool operator < (const CallStack& rhs) const; bool operator >= (const CallStack& rhs) const; bool operator > (const CallStack& rhs) const; bool operator <= (const CallStack& rhs) const; // Get the PC address for the stack frame specified by index. const void* operator [] (int index) const; // Reset the stack frames (same as creating an empty call stack). void clear(); void clear() { mFrameLines.clear(); } // Immediately collect the stack traces for the specified thread. void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH, pid_t tid=CURRENT_THREAD); // The default is to dump the stack of the current call. void update(int32_t ignoreDepth=1, pid_t tid=BACKTRACE_NO_TID); // Dump a stack trace to the log using the supplied logtag. void log(const char* logtag, Loading @@ -83,11 +61,10 @@ public: void print(Printer& printer) const; // Get the count of stack frames that are in this call stack. size_t size() const { return mCount; } size_t size() const { return mFrameLines.size(); } private: size_t mCount; backtrace_frame_t mStack[MAX_DEPTH]; Vector<String8> mFrameLines; }; }; // namespace android Loading
include/utils/ProcessCallStack.h +1 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ public: ~ProcessCallStack(); // Immediately collect the stack traces for all threads. void update(int32_t maxDepth = CallStack::MAX_DEPTH); void update(); // Print all stack traces to the log using the supplied logtag. void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG, Loading
libutils/Android.mk +7 −3 Original line number Diff line number Diff line Loading @@ -116,10 +116,12 @@ LOCAL_STATIC_LIBRARIES := \ libcutils LOCAL_SHARED_LIBRARIES := \ libcorkscrew \ libbacktrace \ liblog \ libdl include external/stlport/libstlport.mk LOCAL_MODULE:= libutils include $(BUILD_STATIC_LIBRARY) Loading @@ -129,10 +131,12 @@ include $(CLEAR_VARS) LOCAL_MODULE:= libutils LOCAL_WHOLE_STATIC_LIBRARIES := libutils LOCAL_SHARED_LIBRARIES := \ liblog \ libbacktrace \ libcutils \ libdl \ libcorkscrew liblog \ include external/stlport/libstlport.mk include $(BUILD_SHARED_LIBRARY) Loading
libutils/CallStack.cpp +15 −82 Original line number Diff line number Diff line Loading @@ -20,93 +20,33 @@ #include <utils/Printer.h> #include <utils/Errors.h> #include <utils/Log.h> #include <corkscrew/backtrace.h> #include <UniquePtr.h> #include <backtrace/Backtrace.h> namespace android { CallStack::CallStack() : mCount(0) { CallStack::CallStack() { } CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) { this->update(ignoreDepth+1, maxDepth, CURRENT_THREAD); CallStack::CallStack(const char* logtag, int32_t ignoreDepth) { this->update(ignoreDepth+1); this->log(logtag); } CallStack::CallStack(const CallStack& rhs) : mCount(rhs.mCount) { if (mCount) { memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)); } } CallStack::~CallStack() { } CallStack& CallStack::operator = (const CallStack& rhs) { mCount = rhs.mCount; if (mCount) { memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)); } return *this; } bool CallStack::operator == (const CallStack& rhs) const { if (mCount != rhs.mCount) return false; return !mCount || memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) == 0; } bool CallStack::operator != (const CallStack& rhs) const { return !operator == (rhs); } void CallStack::update(int32_t ignoreDepth, pid_t tid) { mFrameLines.clear(); bool CallStack::operator < (const CallStack& rhs) const { if (mCount != rhs.mCount) return mCount < rhs.mCount; return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) < 0; UniquePtr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid)); if (!backtrace->Unwind(ignoreDepth)) { ALOGW("%s: Failed to unwind callstack.", __FUNCTION__); } bool CallStack::operator >= (const CallStack& rhs) const { return !operator < (rhs); for (size_t i = 0; i < backtrace->NumFrames(); i++) { mFrameLines.push_back(String8(backtrace->FormatFrameData(i).c_str())); } bool CallStack::operator > (const CallStack& rhs) const { if (mCount != rhs.mCount) return mCount > rhs.mCount; return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) > 0; } bool CallStack::operator <= (const CallStack& rhs) const { return !operator > (rhs); } const void* CallStack::operator [] (int index) const { if (index >= int(mCount)) return 0; return reinterpret_cast<const void*>(mStack[index].absolute_pc); } void CallStack::clear() { mCount = 0; } void CallStack::update(int32_t ignoreDepth, int32_t maxDepth, pid_t tid) { if (maxDepth > MAX_DEPTH) { maxDepth = MAX_DEPTH; } ssize_t count; if (tid >= 0) { count = unwind_backtrace_thread(tid, mStack, ignoreDepth + 1, maxDepth); } else if (tid == CURRENT_THREAD) { count = unwind_backtrace(mStack, ignoreDepth + 1, maxDepth); } else { ALOGE("%s: Invalid tid specified (%d)", __FUNCTION__, tid); count = 0; } mCount = count > 0 ? count : 0; } void CallStack::log(const char* logtag, android_LogPriority priority, const char* prefix) const { Loading @@ -129,16 +69,9 @@ String8 CallStack::toString(const char* prefix) const { } void CallStack::print(Printer& printer) const { backtrace_symbol_t symbols[mCount]; get_backtrace_symbols(mStack, mCount, symbols); for (size_t i = 0; i < mCount; i++) { char line[MAX_BACKTRACE_LINE_LENGTH]; format_backtrace_line(i, &mStack[i], &symbols[i], line, MAX_BACKTRACE_LINE_LENGTH); printer.printLine(line); for (size_t i = 0; i < mFrameLines.size(); i++) { printer.printLine(mFrameLines[i]); } free_backtrace_symbols(symbols, mCount); } }; // namespace android
libutils/Printer.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,7 @@ void String8Printer::printLine(const char* string) { return; } mTarget->append(mPrefix); mTarget->append(string); mTarget->append("\n"); } Loading