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 <utils/CallStack.h>
20#include <utils/Printer.h>
21#include <utils/Errors.h>
22#include <utils/Log.h>
23#include <corkscrew/backtrace.h>
24
25namespace android {
26
27CallStack::CallStack() :
28        mCount(0) {
29}
30
31CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) {
32    this->update(ignoreDepth+1, maxDepth, CURRENT_THREAD);
33    this->log(logtag);
34}
35
36CallStack::CallStack(const CallStack& rhs) :
37        mCount(rhs.mCount) {
38    if (mCount) {
39        memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t));
40    }
41}
42
43CallStack::~CallStack() {
44}
45
46CallStack& CallStack::operator = (const CallStack& rhs) {
47    mCount = rhs.mCount;
48    if (mCount) {
49        memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t));
50    }
51    return *this;
52}
53
54bool CallStack::operator == (const CallStack& rhs) const {
55    if (mCount != rhs.mCount)
56        return false;
57    return !mCount || memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) == 0;
58}
59
60bool CallStack::operator != (const CallStack& rhs) const {
61    return !operator == (rhs);
62}
63
64bool CallStack::operator < (const CallStack& rhs) const {
65    if (mCount != rhs.mCount)
66        return mCount < rhs.mCount;
67    return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) < 0;
68}
69
70bool CallStack::operator >= (const CallStack& rhs) const {
71    return !operator < (rhs);
72}
73
74bool CallStack::operator > (const CallStack& rhs) const {
75    if (mCount != rhs.mCount)
76        return mCount > rhs.mCount;
77    return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) > 0;
78}
79
80bool CallStack::operator <= (const CallStack& rhs) const {
81    return !operator > (rhs);
82}
83
84const void* CallStack::operator [] (int index) const {
85    if (index >= int(mCount))
86        return 0;
87    return reinterpret_cast<const void*>(mStack[index].absolute_pc);
88}
89
90void CallStack::clear() {
91    mCount = 0;
92}
93
94void CallStack::update(int32_t ignoreDepth, int32_t maxDepth, pid_t tid) {
95    if (maxDepth > MAX_DEPTH) {
96        maxDepth = MAX_DEPTH;
97    }
98    ssize_t count;
99
100    if (tid >= 0) {
101        count = unwind_backtrace_thread(tid, mStack, ignoreDepth + 1, maxDepth);
102    } else if (tid == CURRENT_THREAD) {
103        count = unwind_backtrace(mStack, ignoreDepth + 1, maxDepth);
104    } else {
105        ALOGE("%s: Invalid tid specified (%d)", __FUNCTION__, tid);
106        count = 0;
107    }
108
109    mCount = count > 0 ? count : 0;
110}
111
112void CallStack::log(const char* logtag, android_LogPriority priority, const char* prefix) const {
113    LogPrinter printer(logtag, priority, prefix, /*ignoreBlankLines*/false);
114    print(printer);
115}
116
117void CallStack::dump(int fd, int indent, const char* prefix) const {
118    FdPrinter printer(fd, indent, prefix);
119    print(printer);
120}
121
122String8 CallStack::toString(const char* prefix) const {
123    String8 str;
124
125    String8Printer printer(&str, prefix);
126    print(printer);
127
128    return str;
129}
130
131void CallStack::print(Printer& printer) const {
132    backtrace_symbol_t symbols[mCount];
133
134    get_backtrace_symbols(mStack, mCount, symbols);
135    for (size_t i = 0; i < mCount; i++) {
136        char line[MAX_BACKTRACE_LINE_LENGTH];
137        format_backtrace_line(i, &mStack[i], &symbols[i],
138                line, MAX_BACKTRACE_LINE_LENGTH);
139        printer.printLine(line);
140    }
141    free_backtrace_symbols(symbols, mCount);
142}
143
144}; // namespace android
145