File: CallStack.h

package info (click to toggle)
android-platform-system-core 1%3A10.0.0%2Br36-7
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 123,760 kB
  • sloc: cpp: 197,034; ansic: 18,211; asm: 3,606; sh: 3,180; python: 2,671; java: 693; xml: 266; makefile: 237
file content (169 lines) | stat: -rw-r--r-- 6,387 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_CALLSTACK_H
#define ANDROID_CALLSTACK_H

#include <memory>

#include <android/log.h>
#include <backtrace/backtrace_constants.h>
#include <utils/String8.h>
#include <utils/Vector.h>

#include <stdint.h>
#include <sys/types.h>

#if !defined(__APPLE__) && !defined(_WIN32)
# define WEAKS_AVAILABLE 1
#endif
#ifndef CALLSTACK_WEAK
# ifdef WEAKS_AVAILABLE
#   define CALLSTACK_WEAK __attribute__((weak))
# else // !WEAKS_AVAILABLE
#   define CALLSTACK_WEAK
# endif // !WEAKS_AVAILABLE
#endif // CALLSTACK_WEAK predefined

#define ALWAYS_INLINE __attribute__((always_inline))

namespace android {

class Printer;

// Collect/print the call stack (function, file, line) traces for a single thread.
class CallStack {
public:
    // Create an empty call stack. No-op.
    CallStack();
    // Create a callstack with the current thread's stack trace.
    // Immediately dump it to logcat using the given logtag.
    CallStack(const char* logtag, int32_t ignoreDepth = 1);
    ~CallStack();

    // Reset the stack frames (same as creating an empty call stack).
    void clear() { mFrameLines.clear(); }

    // Immediately collect the stack traces for the specified thread.
    // The default is to dump the stack of the current call.
    void update(int32_t ignoreDepth = 1, pid_t tid = BACKTRACE_CURRENT_THREAD);

    // Dump a stack trace to the log using the supplied logtag.
    void log(const char* logtag,
             android_LogPriority priority = ANDROID_LOG_DEBUG,
             const char* prefix = nullptr) const;

    // Dump a stack trace to the specified file descriptor.
    void dump(int fd, int indent = 0, const char* prefix = nullptr) const;

    // Return a string (possibly very long) containing the complete stack trace.
    String8 toString(const char* prefix = nullptr) const;

    // Dump a serialized representation of the stack trace to the specified printer.
    void print(Printer& printer) const;

    // Get the count of stack frames that are in this call stack.
    size_t size() const { return mFrameLines.size(); }

    // DO NOT USE ANYTHING BELOW HERE. The following public members are expected
    // to disappear again shortly, once a better replacement facility exists.
    // The replacement facility will be incompatible!

    // Debugging accesses to some basic functionality. These use weak symbols to
    // avoid introducing a dependency on libutilscallstack. Such a dependency from
    // libutils results in a cyclic build dependency. These routines can be called
    // from within libutils. But if the actual library is unavailable, they do
    // nothing.
    //
    // DO NOT USE THESE. They will disappear.
    struct StackDeleter {
#ifdef WEAKS_AVAILABLE
        void operator()(CallStack* stack) {
            deleteStack(stack);
        }
#else
        void operator()(CallStack*) {}
#endif
    };

    typedef std::unique_ptr<CallStack, StackDeleter> CallStackUPtr;

    // Return current call stack if possible, nullptr otherwise.
#ifdef WEAKS_AVAILABLE
    static CallStackUPtr ALWAYS_INLINE getCurrent(int32_t ignoreDepth = 1) {
        if (reinterpret_cast<uintptr_t>(getCurrentInternal) == 0) {
            ALOGW("CallStack::getCurrentInternal not linked, returning null");
            return CallStackUPtr(nullptr);
        } else {
            return getCurrentInternal(ignoreDepth);
        }
    }
#else // !WEAKS_AVAILABLE
    static CallStackUPtr ALWAYS_INLINE getCurrent(int32_t = 1) {
        return CallStackUPtr(nullptr);
    }
#endif // !WEAKS_AVAILABLE

#ifdef WEAKS_AVAILABLE
    static void ALWAYS_INLINE logStack(const char* logtag, CallStack* stack = getCurrent().get(),
                                       android_LogPriority priority = ANDROID_LOG_DEBUG) {
        if (reinterpret_cast<uintptr_t>(logStackInternal) != 0 && stack != nullptr) {
            logStackInternal(logtag, stack, priority);
        } else {
            ALOG(LOG_WARN, logtag, "CallStack::logStackInternal not linked");
        }
    }

#else
    static void ALWAYS_INLINE logStack(const char* logtag, CallStack* = getCurrent().get(),
                                       android_LogPriority = ANDROID_LOG_DEBUG) {
        ALOG(LOG_WARN, logtag, "CallStack::logStackInternal not linked");
    }
#endif // !WEAKS_AVAILABLE

#ifdef WEAKS_AVAILABLE
    static String8 ALWAYS_INLINE stackToString(const char* prefix = nullptr,
                                               const CallStack* stack = getCurrent().get()) {
        if (reinterpret_cast<uintptr_t>(stackToStringInternal) != 0 && stack != nullptr) {
            return stackToStringInternal(prefix, stack);
        } else {
            return String8::format("%s<CallStack package not linked>", (prefix ? prefix : ""));
        }
    }
#else // !WEAKS_AVAILABLE
    static String8 ALWAYS_INLINE stackToString(const char* prefix = nullptr,
                                               const CallStack* = getCurrent().get()) {
        return String8::format("%s<CallStack package not linked>", (prefix ? prefix : ""));
    }
#endif // !WEAKS_AVAILABLE

  private:
#ifdef WEAKS_AVAILABLE
    static CallStackUPtr CALLSTACK_WEAK getCurrentInternal(int32_t ignoreDepth);
    static void CALLSTACK_WEAK logStackInternal(const char* logtag, const CallStack* stack,
                                                android_LogPriority priority);
    static String8 CALLSTACK_WEAK stackToStringInternal(const char* prefix, const CallStack* stack);
    // The deleter is only invoked on non-null pointers. Hence it will never be
    // invoked if CallStack is not linked.
    static void CALLSTACK_WEAK deleteStack(CallStack* stack);
#endif // WEAKS_AVAILABLE

    Vector<String8> mFrameLines;
};

}  // namespace android

#endif // ANDROID_CALLSTACK_H