ubsan_diag.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //===-- ubsan_diag.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. // Diagnostics emission for Clang's undefined behavior sanitizer.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef UBSAN_DIAG_H
  13. #define UBSAN_DIAG_H
  14. #include "ubsan_value.h"
  15. #include "sanitizer_common/sanitizer_stacktrace.h"
  16. #include "sanitizer_common/sanitizer_symbolizer.h"
  17. namespace __ubsan {
  18. SymbolizedStack *getSymbolizedLocation(uptr PC);
  19. inline SymbolizedStack *getCallerLocation(uptr CallerPC) {
  20. CHECK(CallerPC);
  21. uptr PC = StackTrace::GetPreviousInstructionPc(CallerPC);
  22. return getSymbolizedLocation(PC);
  23. }
  24. /// A location of some data within the program's address space.
  25. typedef uptr MemoryLocation;
  26. /// \brief Location at which a diagnostic can be emitted. Either a
  27. /// SourceLocation, a MemoryLocation, or a SymbolizedStack.
  28. class Location {
  29. public:
  30. enum LocationKind { LK_Null, LK_Source, LK_Memory, LK_Symbolized };
  31. private:
  32. LocationKind Kind;
  33. // FIXME: In C++11, wrap these in an anonymous union.
  34. SourceLocation SourceLoc;
  35. MemoryLocation MemoryLoc;
  36. const SymbolizedStack *SymbolizedLoc; // Not owned.
  37. public:
  38. Location() : Kind(LK_Null) {}
  39. Location(SourceLocation Loc) :
  40. Kind(LK_Source), SourceLoc(Loc) {}
  41. Location(MemoryLocation Loc) :
  42. Kind(LK_Memory), MemoryLoc(Loc) {}
  43. // SymbolizedStackHolder must outlive Location object.
  44. Location(const SymbolizedStackHolder &Stack) :
  45. Kind(LK_Symbolized), SymbolizedLoc(Stack.get()) {}
  46. LocationKind getKind() const { return Kind; }
  47. bool isSourceLocation() const { return Kind == LK_Source; }
  48. bool isMemoryLocation() const { return Kind == LK_Memory; }
  49. bool isSymbolizedStack() const { return Kind == LK_Symbolized; }
  50. SourceLocation getSourceLocation() const {
  51. CHECK(isSourceLocation());
  52. return SourceLoc;
  53. }
  54. MemoryLocation getMemoryLocation() const {
  55. CHECK(isMemoryLocation());
  56. return MemoryLoc;
  57. }
  58. const SymbolizedStack *getSymbolizedStack() const {
  59. CHECK(isSymbolizedStack());
  60. return SymbolizedLoc;
  61. }
  62. };
  63. /// A diagnostic severity level.
  64. enum DiagLevel {
  65. DL_Error, ///< An error.
  66. DL_Note ///< A note, attached to a prior diagnostic.
  67. };
  68. /// \brief Annotation for a range of locations in a diagnostic.
  69. class Range {
  70. Location Start, End;
  71. const char *Text;
  72. public:
  73. Range() : Start(), End(), Text() {}
  74. Range(MemoryLocation Start, MemoryLocation End, const char *Text)
  75. : Start(Start), End(End), Text(Text) {}
  76. Location getStart() const { return Start; }
  77. Location getEnd() const { return End; }
  78. const char *getText() const { return Text; }
  79. };
  80. /// \brief A C++ type name. Really just a strong typedef for 'const char*'.
  81. class TypeName {
  82. const char *Name;
  83. public:
  84. TypeName(const char *Name) : Name(Name) {}
  85. const char *getName() const { return Name; }
  86. };
  87. enum class ErrorType {
  88. #define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) Name,
  89. #include "ubsan_checks.inc"
  90. #undef UBSAN_CHECK
  91. };
  92. /// \brief Representation of an in-flight diagnostic.
  93. ///
  94. /// Temporary \c Diag instances are created by the handler routines to
  95. /// accumulate arguments for a diagnostic. The destructor emits the diagnostic
  96. /// message.
  97. class Diag {
  98. /// The location at which the problem occurred.
  99. Location Loc;
  100. /// The diagnostic level.
  101. DiagLevel Level;
  102. /// The error type.
  103. ErrorType ET;
  104. /// The message which will be emitted, with %0, %1, ... placeholders for
  105. /// arguments.
  106. const char *Message;
  107. public:
  108. /// Kinds of arguments, corresponding to members of \c Arg's union.
  109. enum ArgKind {
  110. AK_String, ///< A string argument, displayed as-is.
  111. AK_TypeName,///< A C++ type name, possibly demangled before display.
  112. AK_UInt, ///< An unsigned integer argument.
  113. AK_SInt, ///< A signed integer argument.
  114. AK_Float, ///< A floating-point argument.
  115. AK_Pointer ///< A pointer argument, displayed in hexadecimal.
  116. };
  117. /// An individual diagnostic message argument.
  118. struct Arg {
  119. Arg() {}
  120. Arg(const char *String) : Kind(AK_String), String(String) {}
  121. Arg(TypeName TN) : Kind(AK_TypeName), String(TN.getName()) {}
  122. Arg(UIntMax UInt) : Kind(AK_UInt), UInt(UInt) {}
  123. Arg(SIntMax SInt) : Kind(AK_SInt), SInt(SInt) {}
  124. Arg(FloatMax Float) : Kind(AK_Float), Float(Float) {}
  125. Arg(const void *Pointer) : Kind(AK_Pointer), Pointer(Pointer) {}
  126. ArgKind Kind;
  127. union {
  128. const char *String;
  129. UIntMax UInt;
  130. SIntMax SInt;
  131. FloatMax Float;
  132. const void *Pointer;
  133. };
  134. };
  135. private:
  136. static const unsigned MaxArgs = 8;
  137. static const unsigned MaxRanges = 1;
  138. /// The arguments which have been added to this diagnostic so far.
  139. Arg Args[MaxArgs];
  140. unsigned NumArgs;
  141. /// The ranges which have been added to this diagnostic so far.
  142. Range Ranges[MaxRanges];
  143. unsigned NumRanges;
  144. Diag &AddArg(Arg A) {
  145. CHECK(NumArgs != MaxArgs);
  146. Args[NumArgs++] = A;
  147. return *this;
  148. }
  149. Diag &AddRange(Range A) {
  150. CHECK(NumRanges != MaxRanges);
  151. Ranges[NumRanges++] = A;
  152. return *this;
  153. }
  154. /// \c Diag objects are not copyable.
  155. Diag(const Diag &); // NOT IMPLEMENTED
  156. Diag &operator=(const Diag &);
  157. public:
  158. Diag(Location Loc, DiagLevel Level, ErrorType ET, const char *Message)
  159. : Loc(Loc), Level(Level), ET(ET), Message(Message), NumArgs(0),
  160. NumRanges(0) {}
  161. ~Diag();
  162. Diag &operator<<(const char *Str) { return AddArg(Str); }
  163. Diag &operator<<(TypeName TN) { return AddArg(TN); }
  164. Diag &operator<<(unsigned long long V) { return AddArg(UIntMax(V)); }
  165. Diag &operator<<(const void *V) { return AddArg(V); }
  166. Diag &operator<<(const TypeDescriptor &V);
  167. Diag &operator<<(const Value &V);
  168. Diag &operator<<(const Range &R) { return AddRange(R); }
  169. };
  170. struct ReportOptions {
  171. // If FromUnrecoverableHandler is specified, UBSan runtime handler is not
  172. // expected to return.
  173. bool FromUnrecoverableHandler;
  174. /// pc/bp are used to unwind the stack trace.
  175. uptr pc;
  176. uptr bp;
  177. };
  178. bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET);
  179. #define GET_REPORT_OPTIONS(unrecoverable_handler) \
  180. GET_CALLER_PC_BP; \
  181. ReportOptions Opts = {unrecoverable_handler, pc, bp}
  182. /// \brief Instantiate this class before printing diagnostics in the error
  183. /// report. This class ensures that reports from different threads and from
  184. /// different sanitizers won't be mixed.
  185. class ScopedReport {
  186. struct Initializer {
  187. Initializer();
  188. };
  189. Initializer initializer_;
  190. ScopedErrorReportLock report_lock_;
  191. ReportOptions Opts;
  192. Location SummaryLoc;
  193. ErrorType Type;
  194. public:
  195. ScopedReport(ReportOptions Opts, Location SummaryLoc, ErrorType Type);
  196. ~ScopedReport();
  197. static void CheckLocked() { ScopedErrorReportLock::CheckLocked(); }
  198. };
  199. void InitializeSuppressions();
  200. bool IsVptrCheckSuppressed(const char *TypeName);
  201. // Sometimes UBSan runtime can know filename from handlers arguments, even if
  202. // debug info is missing.
  203. bool IsPCSuppressed(ErrorType ET, uptr PC, const char *Filename);
  204. } // namespace __ubsan
  205. #endif // UBSAN_DIAG_H