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/*****************************************************************************/ 27namespace android { 28 29CallStack::CallStack() : 30 mCount(0) { 31} 32 33CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) { 34 this->update(ignoreDepth+1, maxDepth); 35 this->dump(logtag); 36} 37 38CallStack::CallStack(const CallStack& rhs) : 39 mCount(rhs.mCount) { 40 if (mCount) { 41 memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)); 42 } 43} 44 45CallStack::~CallStack() { 46} 47 48CallStack& 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 56bool 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 62bool CallStack::operator != (const CallStack& rhs) const { 63 return !operator == (rhs); 64} 65 66bool 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 72bool CallStack::operator >= (const CallStack& rhs) const { 73 return !operator < (rhs); 74} 75 76bool 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 82bool CallStack::operator <= (const CallStack& rhs) const { 83 return !operator > (rhs); 84} 85 86const 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 92void CallStack::clear() { 93 mCount = 0; 94} 95 96void 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 104void 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 119String8 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