Home | History | Annotate | Download | only in utils
      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