crash_logging.h 8.5 KB

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