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