asan_descriptions.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //===-- asan_descriptions.h -------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of AddressSanitizer, an address sanity checker.
  10. //
  11. // ASan-private header for asan_descriptions.cpp.
  12. // TODO(filcab): Most struct definitions should move to the interface headers.
  13. //===----------------------------------------------------------------------===//
  14. #ifndef ASAN_DESCRIPTIONS_H
  15. #define ASAN_DESCRIPTIONS_H
  16. #include "asan_allocator.h"
  17. #include "asan_thread.h"
  18. #include "sanitizer_common/sanitizer_common.h"
  19. #include "sanitizer_common/sanitizer_report_decorator.h"
  20. namespace __asan {
  21. void DescribeThread(AsanThreadContext *context);
  22. static inline void DescribeThread(AsanThread *t) {
  23. if (t) DescribeThread(t->context());
  24. }
  25. class AsanThreadIdAndName {
  26. public:
  27. explicit AsanThreadIdAndName(AsanThreadContext *t);
  28. explicit AsanThreadIdAndName(u32 tid);
  29. // Contains "T%tid (%name)" or "T%tid" if the name is empty.
  30. const char *c_str() const { return &name[0]; }
  31. private:
  32. void Init(u32 tid, const char *tname);
  33. char name[128];
  34. };
  35. class Decorator : public __sanitizer::SanitizerCommonDecorator {
  36. public:
  37. Decorator() : SanitizerCommonDecorator() {}
  38. const char *Access() { return Blue(); }
  39. const char *Location() { return Green(); }
  40. const char *Allocation() { return Magenta(); }
  41. const char *ShadowByte(u8 byte) {
  42. switch (byte) {
  43. case kAsanHeapLeftRedzoneMagic:
  44. case kAsanArrayCookieMagic:
  45. return Red();
  46. case kAsanHeapFreeMagic:
  47. return Magenta();
  48. case kAsanStackLeftRedzoneMagic:
  49. case kAsanStackMidRedzoneMagic:
  50. case kAsanStackRightRedzoneMagic:
  51. return Red();
  52. case kAsanStackAfterReturnMagic:
  53. return Magenta();
  54. case kAsanInitializationOrderMagic:
  55. return Cyan();
  56. case kAsanUserPoisonedMemoryMagic:
  57. case kAsanContiguousContainerOOBMagic:
  58. case kAsanAllocaLeftMagic:
  59. case kAsanAllocaRightMagic:
  60. return Blue();
  61. case kAsanStackUseAfterScopeMagic:
  62. return Magenta();
  63. case kAsanGlobalRedzoneMagic:
  64. return Red();
  65. case kAsanInternalHeapMagic:
  66. return Yellow();
  67. case kAsanIntraObjectRedzone:
  68. return Yellow();
  69. default:
  70. return Default();
  71. }
  72. }
  73. };
  74. enum ShadowKind : u8 {
  75. kShadowKindLow,
  76. kShadowKindGap,
  77. kShadowKindHigh,
  78. };
  79. static const char *const ShadowNames[] = {"low shadow", "shadow gap",
  80. "high shadow"};
  81. struct ShadowAddressDescription {
  82. uptr addr;
  83. ShadowKind kind;
  84. u8 shadow_byte;
  85. void Print() const;
  86. };
  87. bool GetShadowAddressInformation(uptr addr, ShadowAddressDescription *descr);
  88. bool DescribeAddressIfShadow(uptr addr);
  89. enum AccessType {
  90. kAccessTypeLeft,
  91. kAccessTypeRight,
  92. kAccessTypeInside,
  93. kAccessTypeUnknown, // This means we have an AddressSanitizer bug!
  94. };
  95. struct ChunkAccess {
  96. uptr bad_addr;
  97. sptr offset;
  98. uptr chunk_begin;
  99. uptr chunk_size;
  100. u32 user_requested_alignment : 12;
  101. u32 access_type : 2;
  102. u32 alloc_type : 2;
  103. };
  104. struct HeapAddressDescription {
  105. uptr addr;
  106. uptr alloc_tid;
  107. uptr free_tid;
  108. u32 alloc_stack_id;
  109. u32 free_stack_id;
  110. ChunkAccess chunk_access;
  111. void Print() const;
  112. };
  113. bool GetHeapAddressInformation(uptr addr, uptr access_size,
  114. HeapAddressDescription *descr);
  115. bool DescribeAddressIfHeap(uptr addr, uptr access_size = 1);
  116. struct StackAddressDescription {
  117. uptr addr;
  118. uptr tid;
  119. uptr offset;
  120. uptr frame_pc;
  121. uptr access_size;
  122. const char *frame_descr;
  123. void Print() const;
  124. };
  125. bool GetStackAddressInformation(uptr addr, uptr access_size,
  126. StackAddressDescription *descr);
  127. struct WildAddressDescription {
  128. uptr addr;
  129. uptr access_size;
  130. void Print() const;
  131. };
  132. struct GlobalAddressDescription {
  133. uptr addr;
  134. // Assume address is close to at most four globals.
  135. static const int kMaxGlobals = 4;
  136. __asan_global globals[kMaxGlobals];
  137. u32 reg_sites[kMaxGlobals];
  138. uptr access_size;
  139. u8 size;
  140. void Print(const char *bug_type = "") const;
  141. // Returns true when this descriptions points inside the same global variable
  142. // as other. Descriptions can have different address within the variable
  143. bool PointsInsideTheSameVariable(const GlobalAddressDescription &other) const;
  144. };
  145. bool GetGlobalAddressInformation(uptr addr, uptr access_size,
  146. GlobalAddressDescription *descr);
  147. bool DescribeAddressIfGlobal(uptr addr, uptr access_size, const char *bug_type);
  148. // General function to describe an address. Will try to describe the address as
  149. // a shadow, global (variable), stack, or heap address.
  150. // bug_type is optional and is used for checking if we're reporting an
  151. // initialization-order-fiasco
  152. // The proper access_size should be passed for stack, global, and heap
  153. // addresses. Defaults to 1.
  154. // Each of the *AddressDescription functions has its own Print() member, which
  155. // may take access_size and bug_type parameters if needed.
  156. void PrintAddressDescription(uptr addr, uptr access_size = 1,
  157. const char *bug_type = "");
  158. enum AddressKind {
  159. kAddressKindWild,
  160. kAddressKindShadow,
  161. kAddressKindHeap,
  162. kAddressKindStack,
  163. kAddressKindGlobal,
  164. };
  165. class AddressDescription {
  166. struct AddressDescriptionData {
  167. AddressKind kind;
  168. union {
  169. ShadowAddressDescription shadow;
  170. HeapAddressDescription heap;
  171. StackAddressDescription stack;
  172. GlobalAddressDescription global;
  173. WildAddressDescription wild;
  174. };
  175. };
  176. AddressDescriptionData data;
  177. public:
  178. AddressDescription() = default;
  179. // shouldLockThreadRegistry allows us to skip locking if we're sure we already
  180. // have done it.
  181. explicit AddressDescription(uptr addr, bool shouldLockThreadRegistry = true)
  182. : AddressDescription(addr, 1, shouldLockThreadRegistry) {}
  183. AddressDescription(uptr addr, uptr access_size,
  184. bool shouldLockThreadRegistry = true);
  185. uptr Address() const {
  186. switch (data.kind) {
  187. case kAddressKindWild:
  188. return data.wild.addr;
  189. case kAddressKindShadow:
  190. return data.shadow.addr;
  191. case kAddressKindHeap:
  192. return data.heap.addr;
  193. case kAddressKindStack:
  194. return data.stack.addr;
  195. case kAddressKindGlobal:
  196. return data.global.addr;
  197. }
  198. UNREACHABLE("AddressInformation kind is invalid");
  199. }
  200. void Print(const char *bug_descr = nullptr) const {
  201. switch (data.kind) {
  202. case kAddressKindWild:
  203. data.wild.Print();
  204. return;
  205. case kAddressKindShadow:
  206. return data.shadow.Print();
  207. case kAddressKindHeap:
  208. return data.heap.Print();
  209. case kAddressKindStack:
  210. return data.stack.Print();
  211. case kAddressKindGlobal:
  212. // initialization-order-fiasco has a special Print()
  213. return data.global.Print(bug_descr);
  214. }
  215. UNREACHABLE("AddressInformation kind is invalid");
  216. }
  217. void StoreTo(AddressDescriptionData *dst) const { *dst = data; }
  218. const ShadowAddressDescription *AsShadow() const {
  219. return data.kind == kAddressKindShadow ? &data.shadow : nullptr;
  220. }
  221. const HeapAddressDescription *AsHeap() const {
  222. return data.kind == kAddressKindHeap ? &data.heap : nullptr;
  223. }
  224. const StackAddressDescription *AsStack() const {
  225. return data.kind == kAddressKindStack ? &data.stack : nullptr;
  226. }
  227. const GlobalAddressDescription *AsGlobal() const {
  228. return data.kind == kAddressKindGlobal ? &data.global : nullptr;
  229. }
  230. };
  231. } // namespace __asan
  232. #endif // ASAN_DESCRIPTIONS_H