Loading include/utils/CallStack.h +8 −31 Original line number Original line Diff line number Diff line Loading @@ -18,8 +18,9 @@ #define ANDROID_CALLSTACK_H #define ANDROID_CALLSTACK_H #include <android/log.h> #include <android/log.h> #include <backtrace/backtrace.h> #include <utils/String8.h> #include <utils/String8.h> #include <corkscrew/backtrace.h> #include <utils/Vector.h> #include <stdint.h> #include <stdint.h> #include <sys/types.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. // Collect/print the call stack (function, file, line) traces for a single thread. class CallStack { class CallStack { public: 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. // Create an empty call stack. No-op. CallStack(); CallStack(); // Create a callstack with the current thread's stack trace. // Create a callstack with the current thread's stack trace. // Immediately dump it to logcat using the given logtag. // Immediately dump it to logcat using the given logtag. CallStack(const char* logtag, int32_t ignoreDepth=1, 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(); ~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). // 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. // 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. // Dump a stack trace to the log using the supplied logtag. void log(const char* logtag, void log(const char* logtag, Loading @@ -83,11 +61,10 @@ public: void print(Printer& printer) const; void print(Printer& printer) const; // Get the count of stack frames that are in this call stack. // 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: private: size_t mCount; Vector<String8> mFrameLines; backtrace_frame_t mStack[MAX_DEPTH]; }; }; }; // namespace android }; // namespace android Loading include/utils/ProcessCallStack.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,7 @@ public: ~ProcessCallStack(); ~ProcessCallStack(); // Immediately collect the stack traces for all threads. // 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. // Print all stack traces to the log using the supplied logtag. void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG, void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG, Loading libutils/Android.mk +7 −3 Original line number Original line Diff line number Diff line Loading @@ -116,10 +116,12 @@ LOCAL_STATIC_LIBRARIES := \ libcutils libcutils LOCAL_SHARED_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \ libcorkscrew \ libbacktrace \ liblog \ liblog \ libdl libdl include external/stlport/libstlport.mk LOCAL_MODULE:= libutils LOCAL_MODULE:= libutils include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY) Loading @@ -129,10 +131,12 @@ include $(CLEAR_VARS) LOCAL_MODULE:= libutils LOCAL_MODULE:= libutils LOCAL_WHOLE_STATIC_LIBRARIES := libutils LOCAL_WHOLE_STATIC_LIBRARIES := libutils LOCAL_SHARED_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \ liblog \ libbacktrace \ libcutils \ libcutils \ libdl \ libdl \ libcorkscrew liblog \ include external/stlport/libstlport.mk include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY) Loading libutils/CallStack.cpp +15 −82 Original line number Original line Diff line number Diff line Loading @@ -20,93 +20,33 @@ #include <utils/Printer.h> #include <utils/Printer.h> #include <utils/Errors.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/Log.h> #include <corkscrew/backtrace.h> #include <UniquePtr.h> #include <backtrace/Backtrace.h> namespace android { namespace android { CallStack::CallStack() : CallStack::CallStack() { mCount(0) { } } CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) { CallStack::CallStack(const char* logtag, int32_t ignoreDepth) { this->update(ignoreDepth+1, maxDepth, CURRENT_THREAD); this->update(ignoreDepth+1); this->log(logtag); 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() { } } CallStack& CallStack::operator = (const CallStack& rhs) { void CallStack::update(int32_t ignoreDepth, pid_t tid) { mCount = rhs.mCount; mFrameLines.clear(); 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); } bool CallStack::operator < (const CallStack& rhs) const { UniquePtr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid)); if (mCount != rhs.mCount) if (!backtrace->Unwind(ignoreDepth)) { return mCount < rhs.mCount; ALOGW("%s: Failed to unwind callstack.", __FUNCTION__); return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) < 0; } } for (size_t i = 0; i < backtrace->NumFrames(); i++) { bool CallStack::operator >= (const CallStack& rhs) const { mFrameLines.push_back(String8(backtrace->FormatFrameData(i).c_str())); return !operator < (rhs); } } 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 { 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 { void CallStack::print(Printer& printer) const { backtrace_symbol_t symbols[mCount]; for (size_t i = 0; i < mFrameLines.size(); i++) { printer.printLine(mFrameLines[i]); 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); } } free_backtrace_symbols(symbols, mCount); } } }; // namespace android }; // namespace android libutils/Printer.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -145,6 +145,7 @@ void String8Printer::printLine(const char* string) { return; return; } } mTarget->append(mPrefix); mTarget->append(string); mTarget->append(string); mTarget->append("\n"); mTarget->append("\n"); } } Loading Loading
include/utils/CallStack.h +8 −31 Original line number Original line Diff line number Diff line Loading @@ -18,8 +18,9 @@ #define ANDROID_CALLSTACK_H #define ANDROID_CALLSTACK_H #include <android/log.h> #include <android/log.h> #include <backtrace/backtrace.h> #include <utils/String8.h> #include <utils/String8.h> #include <corkscrew/backtrace.h> #include <utils/Vector.h> #include <stdint.h> #include <stdint.h> #include <sys/types.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. // Collect/print the call stack (function, file, line) traces for a single thread. class CallStack { class CallStack { public: 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. // Create an empty call stack. No-op. CallStack(); CallStack(); // Create a callstack with the current thread's stack trace. // Create a callstack with the current thread's stack trace. // Immediately dump it to logcat using the given logtag. // Immediately dump it to logcat using the given logtag. CallStack(const char* logtag, int32_t ignoreDepth=1, 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(); ~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). // 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. // 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. // Dump a stack trace to the log using the supplied logtag. void log(const char* logtag, void log(const char* logtag, Loading @@ -83,11 +61,10 @@ public: void print(Printer& printer) const; void print(Printer& printer) const; // Get the count of stack frames that are in this call stack. // 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: private: size_t mCount; Vector<String8> mFrameLines; backtrace_frame_t mStack[MAX_DEPTH]; }; }; }; // namespace android }; // namespace android Loading
include/utils/ProcessCallStack.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,7 @@ public: ~ProcessCallStack(); ~ProcessCallStack(); // Immediately collect the stack traces for all threads. // 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. // Print all stack traces to the log using the supplied logtag. void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG, void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG, Loading
libutils/Android.mk +7 −3 Original line number Original line Diff line number Diff line Loading @@ -116,10 +116,12 @@ LOCAL_STATIC_LIBRARIES := \ libcutils libcutils LOCAL_SHARED_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \ libcorkscrew \ libbacktrace \ liblog \ liblog \ libdl libdl include external/stlport/libstlport.mk LOCAL_MODULE:= libutils LOCAL_MODULE:= libutils include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY) Loading @@ -129,10 +131,12 @@ include $(CLEAR_VARS) LOCAL_MODULE:= libutils LOCAL_MODULE:= libutils LOCAL_WHOLE_STATIC_LIBRARIES := libutils LOCAL_WHOLE_STATIC_LIBRARIES := libutils LOCAL_SHARED_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \ liblog \ libbacktrace \ libcutils \ libcutils \ libdl \ libdl \ libcorkscrew liblog \ include external/stlport/libstlport.mk include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY) Loading
libutils/CallStack.cpp +15 −82 Original line number Original line Diff line number Diff line Loading @@ -20,93 +20,33 @@ #include <utils/Printer.h> #include <utils/Printer.h> #include <utils/Errors.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/Log.h> #include <corkscrew/backtrace.h> #include <UniquePtr.h> #include <backtrace/Backtrace.h> namespace android { namespace android { CallStack::CallStack() : CallStack::CallStack() { mCount(0) { } } CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) { CallStack::CallStack(const char* logtag, int32_t ignoreDepth) { this->update(ignoreDepth+1, maxDepth, CURRENT_THREAD); this->update(ignoreDepth+1); this->log(logtag); 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() { } } CallStack& CallStack::operator = (const CallStack& rhs) { void CallStack::update(int32_t ignoreDepth, pid_t tid) { mCount = rhs.mCount; mFrameLines.clear(); 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); } bool CallStack::operator < (const CallStack& rhs) const { UniquePtr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid)); if (mCount != rhs.mCount) if (!backtrace->Unwind(ignoreDepth)) { return mCount < rhs.mCount; ALOGW("%s: Failed to unwind callstack.", __FUNCTION__); return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) < 0; } } for (size_t i = 0; i < backtrace->NumFrames(); i++) { bool CallStack::operator >= (const CallStack& rhs) const { mFrameLines.push_back(String8(backtrace->FormatFrameData(i).c_str())); return !operator < (rhs); } } 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 { 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 { void CallStack::print(Printer& printer) const { backtrace_symbol_t symbols[mCount]; for (size_t i = 0; i < mFrameLines.size(); i++) { printer.printLine(mFrameLines[i]); 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); } } free_backtrace_symbols(symbols, mCount); } } }; // namespace android }; // namespace android
libutils/Printer.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -145,6 +145,7 @@ void String8Printer::printLine(const char* string) { return; return; } } mTarget->append(mPrefix); mTarget->append(string); mTarget->append(string); mTarget->append("\n"); mTarget->append("\n"); } } Loading