partition_alloc_check.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright 2020 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_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_CHECK_H_
  5. #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_CHECK_H_
  6. #include <cstdint>
  7. #include "base/allocator/partition_allocator/page_allocator_constants.h"
  8. #include "base/allocator/partition_allocator/partition_alloc_base/check.h"
  9. #include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
  10. #include "base/allocator/partition_allocator/partition_alloc_base/debug/alias.h"
  11. #include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
  12. #include "base/allocator/partition_allocator/partition_alloc_base/immediate_crash.h"
  13. #include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
  14. #include "build/build_config.h"
  15. #define PA_STRINGIFY_IMPL(s) #s
  16. #define PA_STRINGIFY(s) PA_STRINGIFY_IMPL(s)
  17. // When PartitionAlloc is used as the default allocator, we cannot use the
  18. // regular (D)CHECK() macros, as they allocate internally. When an assertion is
  19. // triggered, they format strings, leading to reentrancy in the code, which none
  20. // of PartitionAlloc is designed to support (and especially not for error
  21. // paths).
  22. //
  23. // As a consequence:
  24. // - When PartitionAlloc is not malloc(), use the regular macros
  25. // - Otherwise, crash immediately. This provides worse error messages though.
  26. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  27. // For official build discard log strings to reduce binary bloat.
  28. #if defined(OFFICIAL_BUILD) && defined(NDEBUG)
  29. // See base/check.h for implementation details.
  30. #define PA_CHECK(condition) \
  31. PA_UNLIKELY(!(condition)) ? PA_IMMEDIATE_CRASH() \
  32. : PA_EAT_CHECK_STREAM_PARAMS()
  33. #else
  34. // PartitionAlloc uses async-signal-safe RawCheck() for error reporting.
  35. // Async-signal-safe functions are guaranteed to not allocate as otherwise they
  36. // could operate with inconsistent allocator state.
  37. #define PA_CHECK(condition) \
  38. PA_UNLIKELY(!(condition)) \
  39. ? ::partition_alloc::internal::logging::RawCheck( \
  40. __FILE__ "(" PA_STRINGIFY(__LINE__) ") Check failed: " #condition) \
  41. : PA_EAT_CHECK_STREAM_PARAMS()
  42. #endif // defined(OFFICIAL_BUILD) && defined(NDEBUG)
  43. #if BUILDFLAG(PA_DCHECK_IS_ON)
  44. #define PA_DCHECK(condition) PA_CHECK(condition)
  45. #else
  46. #define PA_DCHECK(condition) PA_EAT_CHECK_STREAM_PARAMS(!(condition))
  47. #endif // BUILDFLAG(PA_DCHECK_IS_ON)
  48. #define PA_PCHECK(condition) \
  49. if (!(condition)) { \
  50. int error = errno; \
  51. ::partition_alloc::internal::base::debug::Alias(&error); \
  52. PA_IMMEDIATE_CRASH(); \
  53. }
  54. #if BUILDFLAG(PA_DCHECK_IS_ON)
  55. #define PA_DPCHECK(condition) PA_PCHECK(condition)
  56. #else
  57. #define PA_DPCHECK(condition) PA_EAT_CHECK_STREAM_PARAMS(!(condition))
  58. #endif // BUILDFLAG(PA_DCHECK_IS_ON)
  59. #else
  60. #define PA_CHECK(condition) PA_BASE_CHECK(condition)
  61. #define PA_DCHECK(condition) PA_BASE_DCHECK(condition)
  62. #define PA_PCHECK(condition) PA_BASE_PCHECK(condition)
  63. #define PA_DPCHECK(condition) PA_BASE_DPCHECK(condition)
  64. #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  65. // Expensive dchecks that run within *Scan. These checks are only enabled in
  66. // debug builds with dchecks enabled.
  67. #if !defined(NDEBUG)
  68. #define PA_SCAN_DCHECK_IS_ON() BUILDFLAG(PA_DCHECK_IS_ON)
  69. #else
  70. #define PA_SCAN_DCHECK_IS_ON() 0
  71. #endif
  72. #if PA_SCAN_DCHECK_IS_ON()
  73. #define PA_SCAN_DCHECK(expr) PA_DCHECK(expr)
  74. #else
  75. #define PA_SCAN_DCHECK(expr) PA_EAT_CHECK_STREAM_PARAMS(!(expr))
  76. #endif
  77. #if defined(PAGE_ALLOCATOR_CONSTANTS_ARE_CONSTEXPR)
  78. // Use this macro to assert on things that are conditionally constexpr as
  79. // determined by PAGE_ALLOCATOR_CONSTANTS_ARE_CONSTEXPR or
  80. // PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR. Where fixed at compile time, this
  81. // is a static_assert. Where determined at run time, this is a PA_CHECK.
  82. // Therefore, this macro must only be used where both a static_assert and a
  83. // PA_CHECK would be viable, that is, within a function, and ideally a function
  84. // that executes only once, early in the program, such as during initialization.
  85. #define STATIC_ASSERT_OR_PA_CHECK(condition, message) \
  86. static_assert(condition, message)
  87. #else
  88. #define STATIC_ASSERT_OR_PA_CHECK(condition, message) \
  89. do { \
  90. PA_CHECK(condition) << (message); \
  91. } while (false)
  92. #endif
  93. // alignas(16) DebugKv causes breakpad_unittests and sandbox_linux_unittests
  94. // failures on android-marshmallow-x86-rel because of SIGSEGV.
  95. #if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_X86_FAMILY) && \
  96. defined(ARCH_CPU_32_BITS)
  97. #define PA_DEBUGKV_ALIGN alignas(8)
  98. #else
  99. #define PA_DEBUGKV_ALIGN alignas(16)
  100. #endif
  101. namespace partition_alloc::internal {
  102. // Used for PA_DEBUG_DATA_ON_STACK, below.
  103. struct PA_DEBUGKV_ALIGN DebugKv {
  104. // 16 bytes object aligned on 16 bytes, to make it easier to see in crash
  105. // reports.
  106. char k[8] = {}; // Not necessarily 0-terminated.
  107. uint64_t v = 0;
  108. DebugKv(const char* key, size_t value) {
  109. // Fill with ' ', so that the stack dump is nicer to read. Not using
  110. // memset() on purpose, this header is included from *many* places.
  111. for (int index = 0; index < 8; index++) {
  112. k[index] = ' ';
  113. }
  114. for (int index = 0; index < 8; index++) {
  115. k[index] = key[index];
  116. if (key[index] == '\0')
  117. break;
  118. }
  119. v = value;
  120. }
  121. };
  122. } // namespace partition_alloc::internal
  123. #define PA_CONCAT(x, y) x##y
  124. #define PA_CONCAT2(x, y) PA_CONCAT(x, y)
  125. #define PA_DEBUG_UNIQUE_NAME PA_CONCAT2(kv, __LINE__)
  126. // Puts a key-value pair on the stack for debugging. `base::debug::Alias()`
  127. // makes sure a local variable is saved on the stack, but the variables can be
  128. // hard to find in crash reports, particularly if the frame pointer is not
  129. // present / invalid.
  130. //
  131. // This puts a key right before the value on the stack. The key has to be a C
  132. // string, which gets truncated if it's longer than 8 characters.
  133. // Example use:
  134. // PA_DEBUG_DATA_ON_STACK("size", 0x42)
  135. //
  136. // Sample output in lldb:
  137. // (lldb) x 0x00007fffffffd0d0 0x00007fffffffd0f0
  138. // 0x7fffffffd0d0: 73 69 7a 65 00 00 00 00 42 00 00 00 00 00 00 00
  139. // size............
  140. //
  141. // With gdb, one can use:
  142. // x/8g <STACK_POINTER>
  143. // to see the data. With lldb, "x <STACK_POINTER> <FRAME_POJNTER>" can be used.
  144. #define PA_DEBUG_DATA_ON_STACK(name, value) \
  145. ::partition_alloc::internal::DebugKv PA_DEBUG_UNIQUE_NAME{name, value}; \
  146. ::partition_alloc::internal::base::debug::Alias(&PA_DEBUG_UNIQUE_NAME);
  147. #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_CHECK_H_