blob: 0239b682e94c0b286205ce49f6b0d01a46e32042 [file] [log] [blame]
The Android Open Source Projectcbb10112009-03-03 19:31:44 -08001/*
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
Elliott Hughesfdc64262024-02-23 00:46:16 +000017#pragma once
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080018
Hans Boehm2a019ec2018-08-07 23:45:25 +000019#include <memory>
20
Igor Murashkinec79ef22013-10-24 17:09:15 -070021#include <android/log.h>
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080022#include <utils/String8.h>
Christopher Ferris038ac692013-10-31 16:25:04 -070023#include <utils/Vector.h>
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080024
Igor Murashkinec79ef22013-10-24 17:09:15 -070025#include <stdint.h>
26#include <sys/types.h>
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080027
Hans Boehm2a019ec2018-08-07 23:45:25 +000028#if !defined(__APPLE__) && !defined(_WIN32)
Elliott Hughesfdc64262024-02-23 00:46:16 +000029# define CALLSTACK_WEAKS_AVAILABLE 1
Hans Boehm2a019ec2018-08-07 23:45:25 +000030#endif
31#ifndef CALLSTACK_WEAK
Elliott Hughesfdc64262024-02-23 00:46:16 +000032# ifdef CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +000033# define CALLSTACK_WEAK __attribute__((weak))
Elliott Hughesfdc64262024-02-23 00:46:16 +000034# else // !CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +000035# define CALLSTACK_WEAK
Elliott Hughesfdc64262024-02-23 00:46:16 +000036# endif // !CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +000037#endif // CALLSTACK_WEAK predefined
38
Serdar Kocdemir593b19b2024-02-14 13:53:13 +000039#ifndef CALLSTACK_ALWAYS_INLINE
40#define CALLSTACK_ALWAYS_INLINE __attribute__((always_inline))
41#endif // CALLSTACK_ALWAYS_INLINE predefined
Hans Boehm2a019ec2018-08-07 23:45:25 +000042
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080043namespace android {
44
Igor Murashkinec79ef22013-10-24 17:09:15 -070045class Printer;
46
47// Collect/print the call stack (function, file, line) traces for a single thread.
48class CallStack {
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080049public:
Igor Murashkinec79ef22013-10-24 17:09:15 -070050 // Create an empty call stack. No-op.
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080051 CallStack();
Igor Murashkinec79ef22013-10-24 17:09:15 -070052 // Create a callstack with the current thread's stack trace.
53 // Immediately dump it to logcat using the given logtag.
Hans Boehm2a019ec2018-08-07 23:45:25 +000054 CallStack(const char* logtag, int32_t ignoreDepth = 1);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080055 ~CallStack();
56
Igor Murashkinec79ef22013-10-24 17:09:15 -070057 // Reset the stack frames (same as creating an empty call stack).
Christopher Ferris038ac692013-10-31 16:25:04 -070058 void clear() { mFrameLines.clear(); }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080059
Igor Murashkinec79ef22013-10-24 17:09:15 -070060 // Immediately collect the stack traces for the specified thread.
Christopher Ferris038ac692013-10-31 16:25:04 -070061 // The default is to dump the stack of the current call.
Christopher Ferrisab631242022-05-10 16:13:02 -070062 void update(int32_t ignoreDepth = 1, pid_t tid = -1);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080063
Igor Murashkinec79ef22013-10-24 17:09:15 -070064 // Dump a stack trace to the log using the supplied logtag.
65 void log(const char* logtag,
66 android_LogPriority priority = ANDROID_LOG_DEBUG,
Yi Kongc1a15622018-07-11 17:37:34 -070067 const char* prefix = nullptr) const;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080068
Igor Murashkinec79ef22013-10-24 17:09:15 -070069 // Dump a stack trace to the specified file descriptor.
Yi Kongc1a15622018-07-11 17:37:34 -070070 void dump(int fd, int indent = 0, const char* prefix = nullptr) const;
Igor Murashkinec79ef22013-10-24 17:09:15 -070071
72 // Return a string (possibly very long) containing the complete stack trace.
Yi Kongc1a15622018-07-11 17:37:34 -070073 String8 toString(const char* prefix = nullptr) const;
Igor Murashkinec79ef22013-10-24 17:09:15 -070074
75 // Dump a serialized representation of the stack trace to the specified printer.
76 void print(Printer& printer) const;
77
78 // Get the count of stack frames that are in this call stack.
Christopher Ferris038ac692013-10-31 16:25:04 -070079 size_t size() const { return mFrameLines.size(); }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080080
Hans Boehm2a019ec2018-08-07 23:45:25 +000081 // DO NOT USE ANYTHING BELOW HERE. The following public members are expected
82 // to disappear again shortly, once a better replacement facility exists.
83 // The replacement facility will be incompatible!
84
85 // Debugging accesses to some basic functionality. These use weak symbols to
86 // avoid introducing a dependency on libutilscallstack. Such a dependency from
87 // libutils results in a cyclic build dependency. These routines can be called
88 // from within libutils. But if the actual library is unavailable, they do
89 // nothing.
90 //
91 // DO NOT USE THESE. They will disappear.
92 struct StackDeleter {
Elliott Hughesfdc64262024-02-23 00:46:16 +000093#ifdef CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +000094 void operator()(CallStack* stack) {
95 deleteStack(stack);
96 }
97#else
98 void operator()(CallStack*) {}
99#endif
100 };
101
102 typedef std::unique_ptr<CallStack, StackDeleter> CallStackUPtr;
103
104 // Return current call stack if possible, nullptr otherwise.
Elliott Hughesfdc64262024-02-23 00:46:16 +0000105#ifdef CALLSTACK_WEAKS_AVAILABLE
Serdar Kocdemir593b19b2024-02-14 13:53:13 +0000106 static CallStackUPtr CALLSTACK_ALWAYS_INLINE getCurrent(int32_t ignoreDepth = 1) {
Hans Boehm2a019ec2018-08-07 23:45:25 +0000107 if (reinterpret_cast<uintptr_t>(getCurrentInternal) == 0) {
108 ALOGW("CallStack::getCurrentInternal not linked, returning null");
109 return CallStackUPtr(nullptr);
110 } else {
111 return getCurrentInternal(ignoreDepth);
112 }
113 }
Elliott Hughesfdc64262024-02-23 00:46:16 +0000114#else // !CALLSTACK_WEAKS_AVAILABLE
Serdar Kocdemir593b19b2024-02-14 13:53:13 +0000115 static CallStackUPtr CALLSTACK_ALWAYS_INLINE getCurrent(int32_t = 1) {
Hans Boehm2a019ec2018-08-07 23:45:25 +0000116 return CallStackUPtr(nullptr);
117 }
Elliott Hughesfdc64262024-02-23 00:46:16 +0000118#endif // !CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +0000119
Elliott Hughesfdc64262024-02-23 00:46:16 +0000120#ifdef CALLSTACK_WEAKS_AVAILABLE
Serdar Kocdemir593b19b2024-02-14 13:53:13 +0000121 static void CALLSTACK_ALWAYS_INLINE logStack(const char* logtag,
122 CallStack* stack = getCurrent().get(),
123 android_LogPriority priority = ANDROID_LOG_DEBUG) {
Hans Boehm2a019ec2018-08-07 23:45:25 +0000124 if (reinterpret_cast<uintptr_t>(logStackInternal) != 0 && stack != nullptr) {
125 logStackInternal(logtag, stack, priority);
126 } else {
Steven Moreland83380722019-01-02 18:29:28 -0800127 ALOG(LOG_WARN, logtag, "CallStack::logStackInternal not linked");
Hans Boehm2a019ec2018-08-07 23:45:25 +0000128 }
129 }
130
131#else
Serdar Kocdemir593b19b2024-02-14 13:53:13 +0000132 static void CALLSTACK_ALWAYS_INLINE logStack(const char* logtag,
133 CallStack* = getCurrent().get(),
134 android_LogPriority = ANDROID_LOG_DEBUG) {
Steven Moreland83380722019-01-02 18:29:28 -0800135 ALOG(LOG_WARN, logtag, "CallStack::logStackInternal not linked");
Hans Boehm2a019ec2018-08-07 23:45:25 +0000136 }
Elliott Hughesfdc64262024-02-23 00:46:16 +0000137#endif // !CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +0000138
Elliott Hughesfdc64262024-02-23 00:46:16 +0000139#ifdef CALLSTACK_WEAKS_AVAILABLE
Serdar Kocdemir593b19b2024-02-14 13:53:13 +0000140 static String8 CALLSTACK_ALWAYS_INLINE
141 stackToString(const char* prefix = nullptr, const CallStack* stack = getCurrent().get()) {
Hans Boehm2a019ec2018-08-07 23:45:25 +0000142 if (reinterpret_cast<uintptr_t>(stackToStringInternal) != 0 && stack != nullptr) {
143 return stackToStringInternal(prefix, stack);
144 } else {
Steven Moreland83380722019-01-02 18:29:28 -0800145 return String8::format("%s<CallStack package not linked>", (prefix ? prefix : ""));
Hans Boehm2a019ec2018-08-07 23:45:25 +0000146 }
147 }
Elliott Hughesfdc64262024-02-23 00:46:16 +0000148#else // !CALLSTACK_WEAKS_AVAILABLE
Serdar Kocdemir593b19b2024-02-14 13:53:13 +0000149 static String8 CALLSTACK_ALWAYS_INLINE stackToString(const char* prefix = nullptr,
150 const CallStack* = getCurrent().get()) {
Steven Moreland83380722019-01-02 18:29:28 -0800151 return String8::format("%s<CallStack package not linked>", (prefix ? prefix : ""));
Hans Boehm2a019ec2018-08-07 23:45:25 +0000152 }
Elliott Hughesfdc64262024-02-23 00:46:16 +0000153#endif // !CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +0000154
155 private:
Elliott Hughesfdc64262024-02-23 00:46:16 +0000156#ifdef CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +0000157 static CallStackUPtr CALLSTACK_WEAK getCurrentInternal(int32_t ignoreDepth);
158 static void CALLSTACK_WEAK logStackInternal(const char* logtag, const CallStack* stack,
159 android_LogPriority priority);
160 static String8 CALLSTACK_WEAK stackToStringInternal(const char* prefix, const CallStack* stack);
161 // The deleter is only invoked on non-null pointers. Hence it will never be
162 // invoked if CallStack is not linked.
163 static void CALLSTACK_WEAK deleteStack(CallStack* stack);
Elliott Hughesfdc64262024-02-23 00:46:16 +0000164#endif // CALLSTACK_WEAKS_AVAILABLE
Hans Boehm2a019ec2018-08-07 23:45:25 +0000165
Christopher Ferris038ac692013-10-31 16:25:04 -0700166 Vector<String8> mFrameLines;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800167};
168
Pirama Arumuga Nainar90affce2018-04-11 23:10:28 -0700169} // namespace android
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800170
Elliott Hughesfdc64262024-02-23 00:46:16 +0000171#undef CALLSTACK_WEAKS_AVAILABLE
172#undef CALLSTACK_WEAK
Serdar Kocdemir593b19b2024-02-14 13:53:13 +0000173#undef CALLSTACK_ALWAYS_INLINE