1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "CallStack" 18 19 #include <string.h> 20 21 #include <utils/Log.h> 22 #include <utils/Errors.h> 23 #include <utils/CallStack.h> 24 #include <corkscrew/backtrace.h> 25 26 /*****************************************************************************/ 27 namespace android { 28 29 CallStack::CallStack() : 30 mCount(0) { 31 } 32 33 CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) { 34 this->update(ignoreDepth+1, maxDepth); 35 this->dump(logtag); 36 } 37 38 CallStack::CallStack(const CallStack& rhs) : 39 mCount(rhs.mCount) { 40 if (mCount) { 41 memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)); 42 } 43 } 44 45 CallStack::~CallStack() { 46 } 47 48 CallStack& CallStack::operator = (const CallStack& rhs) { 49 mCount = rhs.mCount; 50 if (mCount) { 51 memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)); 52 } 53 return *this; 54 } 55 56 bool CallStack::operator == (const CallStack& rhs) const { 57 if (mCount != rhs.mCount) 58 return false; 59 return !mCount || memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) == 0; 60 } 61 62 bool CallStack::operator != (const CallStack& rhs) const { 63 return !operator == (rhs); 64 } 65 66 bool CallStack::operator < (const CallStack& rhs) const { 67 if (mCount != rhs.mCount) 68 return mCount < rhs.mCount; 69 return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) < 0; 70 } 71 72 bool CallStack::operator >= (const CallStack& rhs) const { 73 return !operator < (rhs); 74 } 75 76 bool CallStack::operator > (const CallStack& rhs) const { 77 if (mCount != rhs.mCount) 78 return mCount > rhs.mCount; 79 return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) > 0; 80 } 81 82 bool CallStack::operator <= (const CallStack& rhs) const { 83 return !operator > (rhs); 84 } 85 86 const void* CallStack::operator [] (int index) const { 87 if (index >= int(mCount)) 88 return 0; 89 return reinterpret_cast<const void*>(mStack[index].absolute_pc); 90 } 91 92 void CallStack::clear() { 93 mCount = 0; 94 } 95 96 void CallStack::update(int32_t ignoreDepth, int32_t maxDepth) { 97 if (maxDepth > MAX_DEPTH) { 98 maxDepth = MAX_DEPTH; 99 } 100 ssize_t count = unwind_backtrace(mStack, ignoreDepth + 1, maxDepth); 101 mCount = count > 0 ? count : 0; 102 } 103 104 void CallStack::dump(const char* logtag, const char* prefix) const { 105 backtrace_symbol_t symbols[mCount]; 106 107 get_backtrace_symbols(mStack, mCount, symbols); 108 for (size_t i = 0; i < mCount; i++) { 109 char line[MAX_BACKTRACE_LINE_LENGTH]; 110 format_backtrace_line(i, &mStack[i], &symbols[i], 111 line, MAX_BACKTRACE_LINE_LENGTH); 112 ALOG(LOG_DEBUG, logtag, "%s%s", 113 prefix ? prefix : "", 114 line); 115 } 116 free_backtrace_symbols(symbols, mCount); 117 } 118 119 String8 CallStack::toString(const char* prefix) const { 120 String8 str; 121 backtrace_symbol_t symbols[mCount]; 122 123 get_backtrace_symbols(mStack, mCount, symbols); 124 for (size_t i = 0; i < mCount; i++) { 125 char line[MAX_BACKTRACE_LINE_LENGTH]; 126 format_backtrace_line(i, &mStack[i], &symbols[i], 127 line, MAX_BACKTRACE_LINE_LENGTH); 128 if (prefix) { 129 str.append(prefix); 130 } 131 str.append(line); 132 str.append("\n"); 133 } 134 free_backtrace_symbols(symbols, mCount); 135 return str; 136 } 137 138 }; // namespace android 139