ubsan_diag.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. //===-- ubsan_diag.h --------------------------------------------*- C++ -*-===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // Diagnostics emission for Clang's undefined behavior sanitizer.
  9. //
  10. //===----------------------------------------------------------------------===//
  11. #ifndef UBSAN_DIAG_H
  12. #define UBSAN_DIAG_H
  13. #include "ubsan_value.h"
  14. #include "sanitizer_common/sanitizer_stacktrace.h"
  15. #include "sanitizer_common/sanitizer_suppressions.h"
  16. namespace __ubsan {
  17. /// \brief A location within a loaded module in the program. These are used when
  18. /// the location can't be resolved to a SourceLocation.
  19. class ModuleLocation {
  20. const char *ModuleName;
  21. uptr Offset;
  22. public:
  23. ModuleLocation() : ModuleName(0), Offset(0) {}
  24. ModuleLocation(const char *ModuleName, uptr Offset)
  25. : ModuleName(ModuleName), Offset(Offset) {}
  26. const char *getModuleName() const { return ModuleName; }
  27. uptr getOffset() const { return Offset; }
  28. };
  29. /// A location of some data within the program's address space.
  30. typedef uptr MemoryLocation;
  31. /// \brief Location at which a diagnostic can be emitted. Either a
  32. /// SourceLocation, a ModuleLocation, or a MemoryLocation.
  33. class Location {
  34. public:
  35. enum LocationKind { LK_Null, LK_Source, LK_Module, LK_Memory };
  36. private:
  37. LocationKind Kind;
  38. // FIXME: In C++11, wrap these in an anonymous union.
  39. SourceLocation SourceLoc;
  40. ModuleLocation ModuleLoc;
  41. MemoryLocation MemoryLoc;
  42. public:
  43. Location() : Kind(LK_Null) {}
  44. Location(SourceLocation Loc) :
  45. Kind(LK_Source), SourceLoc(Loc) {}
  46. Location(ModuleLocation Loc) :
  47. Kind(LK_Module), ModuleLoc(Loc) {}
  48. Location(MemoryLocation Loc) :
  49. Kind(LK_Memory), MemoryLoc(Loc) {}
  50. LocationKind getKind() const { return Kind; }
  51. bool isSourceLocation() const { return Kind == LK_Source; }
  52. bool isModuleLocation() const { return Kind == LK_Module; }
  53. bool isMemoryLocation() const { return Kind == LK_Memory; }
  54. SourceLocation getSourceLocation() const {
  55. CHECK(isSourceLocation());
  56. return SourceLoc;
  57. }
  58. ModuleLocation getModuleLocation() const {
  59. CHECK(isModuleLocation());
  60. return ModuleLoc;
  61. }
  62. MemoryLocation getMemoryLocation() const {
  63. CHECK(isMemoryLocation());
  64. return MemoryLoc;
  65. }
  66. };
  67. /// Try to obtain a location for the caller. This might fail, and produce either
  68. /// an invalid location or a module location for the caller.
  69. Location getCallerLocation(uptr CallerLoc = GET_CALLER_PC());
  70. /// Try to obtain a location for the given function pointer. This might fail,
  71. /// and produce either an invalid location or a module location for the caller.
  72. /// If FName is non-null and the name of the function is known, set *FName to
  73. /// the function name, otherwise *FName is unchanged.
  74. Location getFunctionLocation(uptr Loc, const char **FName);
  75. /// A diagnostic severity level.
  76. enum DiagLevel {
  77. DL_Error, ///< An error.
  78. DL_Note ///< A note, attached to a prior diagnostic.
  79. };
  80. /// \brief Annotation for a range of locations in a diagnostic.
  81. class Range {
  82. Location Start, End;
  83. const char *Text;
  84. public:
  85. Range() : Start(), End(), Text() {}
  86. Range(MemoryLocation Start, MemoryLocation End, const char *Text)
  87. : Start(Start), End(End), Text(Text) {}
  88. Location getStart() const { return Start; }
  89. Location getEnd() const { return End; }
  90. const char *getText() const { return Text; }
  91. };
  92. /// \brief A mangled C++ name. Really just a strong typedef for 'const char*'.
  93. class MangledName {
  94. const char *Name;
  95. public:
  96. MangledName(const char *Name) : Name(Name) {}
  97. const char *getName() const { return Name; }
  98. };
  99. /// \brief Representation of an in-flight diagnostic.
  100. ///
  101. /// Temporary \c Diag instances are created by the handler routines to
  102. /// accumulate arguments for a diagnostic. The destructor emits the diagnostic
  103. /// message.
  104. class Diag {
  105. /// The location at which the problem occurred.
  106. Location Loc;
  107. /// The diagnostic level.
  108. DiagLevel Level;
  109. /// The message which will be emitted, with %0, %1, ... placeholders for
  110. /// arguments.
  111. const char *Message;
  112. public:
  113. /// Kinds of arguments, corresponding to members of \c Arg's union.
  114. enum ArgKind {
  115. AK_String, ///< A string argument, displayed as-is.
  116. AK_Mangled,///< A C++ mangled name, demangled before display.
  117. AK_UInt, ///< An unsigned integer argument.
  118. AK_SInt, ///< A signed integer argument.
  119. AK_Float, ///< A floating-point argument.
  120. AK_Pointer ///< A pointer argument, displayed in hexadecimal.
  121. };
  122. /// An individual diagnostic message argument.
  123. struct Arg {
  124. Arg() {}
  125. Arg(const char *String) : Kind(AK_String), String(String) {}
  126. Arg(MangledName MN) : Kind(AK_Mangled), String(MN.getName()) {}
  127. Arg(UIntMax UInt) : Kind(AK_UInt), UInt(UInt) {}
  128. Arg(SIntMax SInt) : Kind(AK_SInt), SInt(SInt) {}
  129. Arg(FloatMax Float) : Kind(AK_Float), Float(Float) {}
  130. Arg(const void *Pointer) : Kind(AK_Pointer), Pointer(Pointer) {}
  131. ArgKind Kind;
  132. union {
  133. const char *String;
  134. UIntMax UInt;
  135. SIntMax SInt;
  136. FloatMax Float;
  137. const void *Pointer;
  138. };
  139. };
  140. private:
  141. static const unsigned MaxArgs = 5;
  142. static const unsigned MaxRanges = 1;
  143. /// The arguments which have been added to this diagnostic so far.
  144. Arg Args[MaxArgs];
  145. unsigned NumArgs;
  146. /// The ranges which have been added to this diagnostic so far.
  147. Range Ranges[MaxRanges];
  148. unsigned NumRanges;
  149. Diag &AddArg(Arg A) {
  150. CHECK(NumArgs != MaxArgs);
  151. Args[NumArgs++] = A;
  152. return *this;
  153. }
  154. Diag &AddRange(Range A) {
  155. CHECK(NumRanges != MaxRanges);
  156. Ranges[NumRanges++] = A;
  157. return *this;
  158. }
  159. /// \c Diag objects are not copyable.
  160. Diag(const Diag &); // NOT IMPLEMENTED
  161. Diag &operator=(const Diag &);
  162. public:
  163. Diag(Location Loc, DiagLevel Level, const char *Message)
  164. : Loc(Loc), Level(Level), Message(Message), NumArgs(0), NumRanges(0) {}
  165. ~Diag();
  166. Diag &operator<<(const char *Str) { return AddArg(Str); }
  167. Diag &operator<<(MangledName MN) { return AddArg(MN); }
  168. Diag &operator<<(unsigned long long V) { return AddArg(UIntMax(V)); }
  169. Diag &operator<<(const void *V) { return AddArg(V); }
  170. Diag &operator<<(const TypeDescriptor &V);
  171. Diag &operator<<(const Value &V);
  172. Diag &operator<<(const Range &R) { return AddRange(R); }
  173. };
  174. struct ReportOptions {
  175. /// If DieAfterReport is specified, UBSan will terminate the program after the
  176. /// report is printed.
  177. bool DieAfterReport;
  178. /// pc/bp are used to unwind the stack trace.
  179. uptr pc;
  180. uptr bp;
  181. };
  182. #define GET_REPORT_OPTIONS(die_after_report) \
  183. GET_CALLER_PC_BP; \
  184. ReportOptions Opts = {die_after_report, pc, bp}
  185. /// \brief Instantiate this class before printing diagnostics in the error
  186. /// report. This class ensures that reports from different threads and from
  187. /// different sanitizers won't be mixed.
  188. class ScopedReport {
  189. ReportOptions Opts;
  190. Location SummaryLoc;
  191. public:
  192. ScopedReport(ReportOptions Opts, Location SummaryLoc);
  193. ~ScopedReport();
  194. };
  195. bool MatchSuppression(const char *Str, SuppressionType Type);
  196. } // namespace __ubsan
  197. #endif // UBSAN_DIAG_H