xref: /aosp_15_r20/external/cronet/base/debug/crash_logging.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_DEBUG_CRASH_LOGGING_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_DEBUG_CRASH_LOGGING_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <iosfwd>
11*6777b538SAndroid Build Coastguard Worker #include <memory>
12*6777b538SAndroid Build Coastguard Worker #include <string_view>
13*6777b538SAndroid Build Coastguard Worker #include <type_traits>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace base {
20*6777b538SAndroid Build Coastguard Worker namespace debug {
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker // A crash key is an annotation that is carried along with a crash report, to
23*6777b538SAndroid Build Coastguard Worker // provide additional debugging information beyond a stack trace. Crash keys
24*6777b538SAndroid Build Coastguard Worker // have a name and a string value.
25*6777b538SAndroid Build Coastguard Worker //
26*6777b538SAndroid Build Coastguard Worker // The preferred API is //components/crash/core/common:crash_key, however not
27*6777b538SAndroid Build Coastguard Worker // all clients can hold a direct dependency on that target. The API provided
28*6777b538SAndroid Build Coastguard Worker // in this file indirects the dependency and adds some convenience helpers that
29*6777b538SAndroid Build Coastguard Worker // make the API a bit less clunky.
30*6777b538SAndroid Build Coastguard Worker //
31*6777b538SAndroid Build Coastguard Worker // TODO(dcheng): Some of the nicer APIs should probably be upstreamed into
32*6777b538SAndroid Build Coastguard Worker // //components/crash.
33*6777b538SAndroid Build Coastguard Worker //
34*6777b538SAndroid Build Coastguard Worker // Preferred usage when a crash key value only needs to be set within a scope:
35*6777b538SAndroid Build Coastguard Worker //
36*6777b538SAndroid Build Coastguard Worker //   SCOPED_CRASH_KEY_STRING32("category", "name", "value");
37*6777b538SAndroid Build Coastguard Worker //   base::debug::DumpWithoutCrashing();
38*6777b538SAndroid Build Coastguard Worker //
39*6777b538SAndroid Build Coastguard Worker // If the crash key is pre-allocated elsewhere, but the value only needs to be
40*6777b538SAndroid Build Coastguard Worker // set within a scope:
41*6777b538SAndroid Build Coastguard Worker //
42*6777b538SAndroid Build Coastguard Worker //   base::debug::ScopedCrashKeyString scoper(
43*6777b538SAndroid Build Coastguard Worker //       GetCrashKeyForComponent(),
44*6777b538SAndroid Build Coastguard Worker //       "value");
45*6777b538SAndroid Build Coastguard Worker //
46*6777b538SAndroid Build Coastguard Worker // Otherwise, if the crash key needs to persist (e.g. the actual crash dump is
47*6777b538SAndroid Build Coastguard Worker // triggered some time later asynchronously):
48*6777b538SAndroid Build Coastguard Worker //
49*6777b538SAndroid Build Coastguard Worker //   static auto* const crash_key = base::debug::AllocateCrashKeyString(
50*6777b538SAndroid Build Coastguard Worker //       "name", base::debug::CrashKeySize::Size32);
51*6777b538SAndroid Build Coastguard Worker //   base::debug::SetCrashKeyString(crash_key, "value");
52*6777b538SAndroid Build Coastguard Worker //
53*6777b538SAndroid Build Coastguard Worker //   // Do other work before calling `base::debug::DumpWithoutCrashing()` later.
54*6777b538SAndroid Build Coastguard Worker //
55*6777b538SAndroid Build Coastguard Worker // ***WARNING***
56*6777b538SAndroid Build Coastguard Worker //
57*6777b538SAndroid Build Coastguard Worker // Do *not* write this:
58*6777b538SAndroid Build Coastguard Worker //
59*6777b538SAndroid Build Coastguard Worker //   base::debug::SetCrashKeyString(
60*6777b538SAndroid Build Coastguard Worker //       base::debug::AllocateCrashKeyString(
61*6777b538SAndroid Build Coastguard Worker //           "name", base::debug::CrashKeySize::Size32),
62*6777b538SAndroid Build Coastguard Worker //       "value");
63*6777b538SAndroid Build Coastguard Worker //
64*6777b538SAndroid Build Coastguard Worker // As this will leak a heap allocation every time the crash key is set!
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker // The maximum length for a crash key's value must be one of the following
67*6777b538SAndroid Build Coastguard Worker // pre-determined values.
68*6777b538SAndroid Build Coastguard Worker enum class CrashKeySize {
69*6777b538SAndroid Build Coastguard Worker   Size32 = 32,
70*6777b538SAndroid Build Coastguard Worker   Size64 = 64,
71*6777b538SAndroid Build Coastguard Worker   Size256 = 256,
72*6777b538SAndroid Build Coastguard Worker   Size1024 = 1024,
73*6777b538SAndroid Build Coastguard Worker };
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker struct CrashKeyString;
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker // Allocates a new crash key with the specified |name| with storage for a
78*6777b538SAndroid Build Coastguard Worker // value up to length |size|. This will return null if the crash key system is
79*6777b538SAndroid Build Coastguard Worker // not initialized.
80*6777b538SAndroid Build Coastguard Worker //
81*6777b538SAndroid Build Coastguard Worker // Note: this internally allocates, so the returned pointer should always
82*6777b538SAndroid Build Coastguard Worker // be cached in a variable with static storage duration, e.g.:
83*6777b538SAndroid Build Coastguard Worker //   static auto* const crash_key = base::debug::AllocateCrashKeyString(...);
84*6777b538SAndroid Build Coastguard Worker BASE_EXPORT CrashKeyString* AllocateCrashKeyString(const char name[],
85*6777b538SAndroid Build Coastguard Worker                                                    CrashKeySize size);
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker // Stores |value| into the specified |crash_key|. The |crash_key| may be null
88*6777b538SAndroid Build Coastguard Worker // if AllocateCrashKeyString() returned null. If |value| is longer than the
89*6777b538SAndroid Build Coastguard Worker // size with which the key was allocated, it will be truncated.
90*6777b538SAndroid Build Coastguard Worker BASE_EXPORT void SetCrashKeyString(CrashKeyString* crash_key,
91*6777b538SAndroid Build Coastguard Worker                                    std::string_view value);
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker // Clears any value that was stored in |crash_key|. The |crash_key| may be
94*6777b538SAndroid Build Coastguard Worker // null.
95*6777b538SAndroid Build Coastguard Worker BASE_EXPORT void ClearCrashKeyString(CrashKeyString* crash_key);
96*6777b538SAndroid Build Coastguard Worker 
97*6777b538SAndroid Build Coastguard Worker // Outputs current (i.e. allocated and non-empty) crash keys to `out`.
98*6777b538SAndroid Build Coastguard Worker BASE_EXPORT void OutputCrashKeysToStream(std::ostream& out);
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker // A scoper that sets the specified key to value for the lifetime of the
101*6777b538SAndroid Build Coastguard Worker // object, and clears it on destruction.
102*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT [[nodiscard]] ScopedCrashKeyString {
103*6777b538SAndroid Build Coastguard Worker  public:
104*6777b538SAndroid Build Coastguard Worker   ScopedCrashKeyString(CrashKeyString* crash_key, std::string_view value);
105*6777b538SAndroid Build Coastguard Worker   ScopedCrashKeyString(ScopedCrashKeyString&& other);
106*6777b538SAndroid Build Coastguard Worker   ~ScopedCrashKeyString();
107*6777b538SAndroid Build Coastguard Worker 
108*6777b538SAndroid Build Coastguard Worker   // Disallow copy and assign.
109*6777b538SAndroid Build Coastguard Worker   ScopedCrashKeyString(const ScopedCrashKeyString&) = delete;
110*6777b538SAndroid Build Coastguard Worker   ScopedCrashKeyString& operator=(const ScopedCrashKeyString&) = delete;
111*6777b538SAndroid Build Coastguard Worker 
112*6777b538SAndroid Build Coastguard Worker   // Disallow move assign to keep the time at which the crash key is cleared
113*6777b538SAndroid Build Coastguard Worker   // easy to reason about. Assigning over an existing instance would
114*6777b538SAndroid Build Coastguard Worker   // automatically clear the key instead of at the destruction of the object.
115*6777b538SAndroid Build Coastguard Worker   ScopedCrashKeyString& operator=(ScopedCrashKeyString&&) = delete;
116*6777b538SAndroid Build Coastguard Worker 
117*6777b538SAndroid Build Coastguard Worker  private:
118*6777b538SAndroid Build Coastguard Worker   raw_ptr<CrashKeyString> crash_key_;
119*6777b538SAndroid Build Coastguard Worker };
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker // Internal helpers for the SCOPED_CRASH_KEY_... helper macros defined below.
122*6777b538SAndroid Build Coastguard Worker //
123*6777b538SAndroid Build Coastguard Worker // The first static_assert that checks the length of |key_name| is a
124*6777b538SAndroid Build Coastguard Worker // compile-time equivalent of the DCHECK in
125*6777b538SAndroid Build Coastguard Worker // crash_reporter::internal::CrashKeyStringImpl::Set that restricts the name of
126*6777b538SAndroid Build Coastguard Worker // a crash key to 40 characters.
127*6777b538SAndroid Build Coastguard Worker //
128*6777b538SAndroid Build Coastguard Worker // The second static_assert that checks for reserved characters is a compile
129*6777b538SAndroid Build Coastguard Worker // time equivalent of the DCHECK in base::debug::AllocateCrashKeyString.
130*6777b538SAndroid Build Coastguard Worker #define SCOPED_CRASH_KEY_STRING_INTERNAL2(category, name, nonce, data,  \
131*6777b538SAndroid Build Coastguard Worker                                           key_size)                     \
132*6777b538SAndroid Build Coastguard Worker   static_assert(::std::size(category "-" name) < 40,                    \
133*6777b538SAndroid Build Coastguard Worker                 "Crash key names must be shorter than 40 characters."); \
134*6777b538SAndroid Build Coastguard Worker   static_assert(::std::string_view(category "-" name).find(':') ==      \
135*6777b538SAndroid Build Coastguard Worker                     ::base::StringPiece::npos,                          \
136*6777b538SAndroid Build Coastguard Worker                 "Crash key names must not contain the ':' character."); \
137*6777b538SAndroid Build Coastguard Worker   ::base::debug::ScopedCrashKeyString scoped_crash_key_helper##nonce(   \
138*6777b538SAndroid Build Coastguard Worker       [] {                                                              \
139*6777b538SAndroid Build Coastguard Worker         static auto* const key = ::base::debug::AllocateCrashKeyString( \
140*6777b538SAndroid Build Coastguard Worker             category "-" name, key_size);                               \
141*6777b538SAndroid Build Coastguard Worker         return key;                                                     \
142*6777b538SAndroid Build Coastguard Worker       }(),                                                              \
143*6777b538SAndroid Build Coastguard Worker       (data))
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker // This indirection is needed to expand __COUNTER__.
146*6777b538SAndroid Build Coastguard Worker #define SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, nonce, data, \
147*6777b538SAndroid Build Coastguard Worker                                          key_size)                    \
148*6777b538SAndroid Build Coastguard Worker   SCOPED_CRASH_KEY_STRING_INTERNAL2(category, name, nonce, data, key_size)
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker // Helper macros for putting a local variable crash key on the stack before
151*6777b538SAndroid Build Coastguard Worker // causing a crash or calling CrashWithoutDumping(). `category` and `name`
152*6777b538SAndroid Build Coastguard Worker // should be string literals.
153*6777b538SAndroid Build Coastguard Worker //
154*6777b538SAndroid Build Coastguard Worker //   SCOPED_CRASH_KEY_STRING32("MyCategory", "key_name", "value");
155*6777b538SAndroid Build Coastguard Worker //
156*6777b538SAndroid Build Coastguard Worker // will set the crash key annotation named "MyCategory-key_name" to "value"
157*6777b538SAndroid Build Coastguard Worker // while in scope.
158*6777b538SAndroid Build Coastguard Worker #define SCOPED_CRASH_KEY_STRING32(category, name, data)                 \
159*6777b538SAndroid Build Coastguard Worker   SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \
160*6777b538SAndroid Build Coastguard Worker                                    ::base::debug::CrashKeySize::Size32)
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker #define SCOPED_CRASH_KEY_STRING64(category, name, data)                 \
163*6777b538SAndroid Build Coastguard Worker   SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \
164*6777b538SAndroid Build Coastguard Worker                                    ::base::debug::CrashKeySize::Size64)
165*6777b538SAndroid Build Coastguard Worker 
166*6777b538SAndroid Build Coastguard Worker #define SCOPED_CRASH_KEY_STRING256(category, name, data)                \
167*6777b538SAndroid Build Coastguard Worker   SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \
168*6777b538SAndroid Build Coastguard Worker                                    ::base::debug::CrashKeySize::Size256)
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker #define SCOPED_CRASH_KEY_STRING1024(category, name, data)               \
171*6777b538SAndroid Build Coastguard Worker   SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \
172*6777b538SAndroid Build Coastguard Worker                                    ::base::debug::CrashKeySize::Size1024)
173*6777b538SAndroid Build Coastguard Worker 
174*6777b538SAndroid Build Coastguard Worker #define SCOPED_CRASH_KEY_BOOL(category, name, data)                       \
175*6777b538SAndroid Build Coastguard Worker   static_assert(std::is_same_v<std::decay_t<decltype(data)>, bool>,       \
176*6777b538SAndroid Build Coastguard Worker                 "SCOPED_CRASH_KEY_BOOL must be passed a boolean value."); \
177*6777b538SAndroid Build Coastguard Worker   SCOPED_CRASH_KEY_STRING32(category, name, (data) ? "true" : "false")
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker #define SCOPED_CRASH_KEY_NUMBER(category, name, data) \
180*6777b538SAndroid Build Coastguard Worker   SCOPED_CRASH_KEY_STRING32(category, name, ::base::NumberToString(data))
181*6777b538SAndroid Build Coastguard Worker 
182*6777b538SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
183*6777b538SAndroid Build Coastguard Worker // The following declarations are used to initialize the crash key system
184*6777b538SAndroid Build Coastguard Worker // in //base by providing implementations for the above functions.
185*6777b538SAndroid Build Coastguard Worker 
186*6777b538SAndroid Build Coastguard Worker // The virtual interface that provides the implementation for the crash key
187*6777b538SAndroid Build Coastguard Worker // API. This is implemented by a higher-layer component, and the instance is
188*6777b538SAndroid Build Coastguard Worker // set using the function below.
189*6777b538SAndroid Build Coastguard Worker class CrashKeyImplementation {
190*6777b538SAndroid Build Coastguard Worker  public:
191*6777b538SAndroid Build Coastguard Worker   virtual ~CrashKeyImplementation() = default;
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker   virtual CrashKeyString* Allocate(const char name[], CrashKeySize size) = 0;
194*6777b538SAndroid Build Coastguard Worker   virtual void Set(CrashKeyString* crash_key, std::string_view value) = 0;
195*6777b538SAndroid Build Coastguard Worker   virtual void Clear(CrashKeyString* crash_key) = 0;
196*6777b538SAndroid Build Coastguard Worker   virtual void OutputCrashKeysToStream(std::ostream& out) = 0;
197*6777b538SAndroid Build Coastguard Worker };
198*6777b538SAndroid Build Coastguard Worker 
199*6777b538SAndroid Build Coastguard Worker // Initializes the crash key system in base by replacing the existing
200*6777b538SAndroid Build Coastguard Worker // implementation, if it exists, with |impl|. The |impl| is copied into base.
201*6777b538SAndroid Build Coastguard Worker BASE_EXPORT void SetCrashKeyImplementation(
202*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<CrashKeyImplementation> impl);
203*6777b538SAndroid Build Coastguard Worker 
204*6777b538SAndroid Build Coastguard Worker // The base structure for a crash key, storing the allocation metadata.
205*6777b538SAndroid Build Coastguard Worker struct CrashKeyString {
CrashKeyStringCrashKeyString206*6777b538SAndroid Build Coastguard Worker   constexpr CrashKeyString(const char name[], CrashKeySize size)
207*6777b538SAndroid Build Coastguard Worker       : name(name), size(size) {}
208*6777b538SAndroid Build Coastguard Worker   const char* const name;
209*6777b538SAndroid Build Coastguard Worker   const CrashKeySize size;
210*6777b538SAndroid Build Coastguard Worker };
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker }  // namespace debug
213*6777b538SAndroid Build Coastguard Worker }  // namespace base
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker #endif  // BASE_DEBUG_CRASH_LOGGING_H_
216