summaryrefslogtreecommitdiffstats
path: root/libutils/CallStack.cpp
diff options
context:
space:
mode:
authorAlex Ray <aray@google.com>2013-08-02 14:40:08 -0700
committerAlex Ray <aray@google.com>2013-08-02 14:40:08 -0700
commitd98e07fdf9c338589f263c47ce5c844ed43efad5 (patch)
treed4ff9849df225df1e4c46386fdabe30407ba5513 /libutils/CallStack.cpp
parentbe06210c508d5878dcc7d185e5613f4c7e38dfe8 (diff)
downloadsystem_core-d98e07fdf9c338589f263c47ce5c844ed43efad5.zip
system_core-d98e07fdf9c338589f263c47ce5c844ed43efad5.tar.gz
system_core-d98e07fdf9c338589f263c47ce5c844ed43efad5.tar.bz2
move libs/utils to libutils
Change-Id: I6cf4268599460791414882f91eeb88a992fbd29d
Diffstat (limited to 'libutils/CallStack.cpp')
-rw-r--r--libutils/CallStack.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
new file mode 100644
index 0000000..e60f5d8
--- /dev/null
+++ b/libutils/CallStack.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CallStack"
+
+#include <string.h>
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/CallStack.h>
+#include <corkscrew/backtrace.h>
+
+/*****************************************************************************/
+namespace android {
+
+CallStack::CallStack() :
+ mCount(0) {
+}
+
+CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) {
+ this->update(ignoreDepth+1, maxDepth);
+ this->dump(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);
+}
+
+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);
+}
+
+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) {
+ if (maxDepth > MAX_DEPTH) {
+ maxDepth = MAX_DEPTH;
+ }
+ ssize_t count = unwind_backtrace(mStack, ignoreDepth + 1, maxDepth);
+ mCount = count > 0 ? count : 0;
+}
+
+void CallStack::dump(const char* logtag, const char* prefix) 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);
+ ALOG(LOG_DEBUG, logtag, "%s%s",
+ prefix ? prefix : "",
+ line);
+ }
+ free_backtrace_symbols(symbols, mCount);
+}
+
+String8 CallStack::toString(const char* prefix) const {
+ String8 str;
+ 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);
+ if (prefix) {
+ str.append(prefix);
+ }
+ str.append(line);
+ str.append("\n");
+ }
+ free_backtrace_symbols(symbols, mCount);
+ return str;
+}
+
+}; // namespace android