1 //===-- ubsan_diag.h --------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Diagnostics emission for Clang's undefined behavior sanitizer.
11 //===----------------------------------------------------------------------===//
15 #include "ubsan_value.h"
16 #include "sanitizer_common/sanitizer_stacktrace.h"
17 #include "sanitizer_common/sanitizer_symbolizer.h"
21 SymbolizedStack
*getSymbolizedLocation(uptr PC
);
23 inline SymbolizedStack
*getCallerLocation(uptr CallerPC
) {
25 uptr PC
= StackTrace::GetPreviousInstructionPc(CallerPC
);
26 return getSymbolizedLocation(PC
);
29 /// A location of some data within the program's address space.
30 typedef uptr MemoryLocation
;
32 /// \brief Location at which a diagnostic can be emitted. Either a
33 /// SourceLocation, a MemoryLocation, or a SymbolizedStack.
36 enum LocationKind
{ LK_Null
, LK_Source
, LK_Memory
, LK_Symbolized
};
40 // FIXME: In C++11, wrap these in an anonymous union.
41 SourceLocation SourceLoc
;
42 MemoryLocation MemoryLoc
;
43 const SymbolizedStack
*SymbolizedLoc
; // Not owned.
46 Location() : Kind(LK_Null
) {}
47 Location(SourceLocation Loc
) :
48 Kind(LK_Source
), SourceLoc(Loc
) {}
49 Location(MemoryLocation Loc
) :
50 Kind(LK_Memory
), MemoryLoc(Loc
) {}
51 // SymbolizedStackHolder must outlive Location object.
52 Location(const SymbolizedStackHolder
&Stack
) :
53 Kind(LK_Symbolized
), SymbolizedLoc(Stack
.get()) {}
55 LocationKind
getKind() const { return Kind
; }
57 bool isSourceLocation() const { return Kind
== LK_Source
; }
58 bool isMemoryLocation() const { return Kind
== LK_Memory
; }
59 bool isSymbolizedStack() const { return Kind
== LK_Symbolized
; }
61 SourceLocation
getSourceLocation() const {
62 CHECK(isSourceLocation());
65 MemoryLocation
getMemoryLocation() const {
66 CHECK(isMemoryLocation());
69 const SymbolizedStack
*getSymbolizedStack() const {
70 CHECK(isSymbolizedStack());
75 /// A diagnostic severity level.
77 DL_Error
, ///< An error.
78 DL_Note
///< A note, attached to a prior diagnostic.
81 /// \brief Annotation for a range of locations in a diagnostic.
87 Range() : Start(), End(), Text() {}
88 Range(MemoryLocation Start
, MemoryLocation End
, const char *Text
)
89 : Start(Start
), End(End
), Text(Text
) {}
90 Location
getStart() const { return Start
; }
91 Location
getEnd() const { return End
; }
92 const char *getText() const { return Text
; }
95 /// \brief A C++ type name. Really just a strong typedef for 'const char*'.
99 TypeName(const char *Name
) : Name(Name
) {}
100 const char *getName() const { return Name
; }
103 enum class ErrorType
{
104 #define UBSAN_CHECK(Name, SummaryKind, FSanitizeFlagName) Name,
105 #include "ubsan_checks.inc"
109 /// \brief Representation of an in-flight diagnostic.
111 /// Temporary \c Diag instances are created by the handler routines to
112 /// accumulate arguments for a diagnostic. The destructor emits the diagnostic
115 /// The location at which the problem occurred.
118 /// The diagnostic level.
124 /// The message which will be emitted, with %0, %1, ... placeholders for
129 /// Kinds of arguments, corresponding to members of \c Arg's union.
131 AK_String
, ///< A string argument, displayed as-is.
132 AK_TypeName
,///< A C++ type name, possibly demangled before display.
133 AK_UInt
, ///< An unsigned integer argument.
134 AK_SInt
, ///< A signed integer argument.
135 AK_Float
, ///< A floating-point argument.
136 AK_Pointer
///< A pointer argument, displayed in hexadecimal.
139 /// An individual diagnostic message argument.
142 Arg(const char *String
) : Kind(AK_String
), String(String
) {}
143 Arg(TypeName TN
) : Kind(AK_TypeName
), String(TN
.getName()) {}
144 Arg(UIntMax UInt
) : Kind(AK_UInt
), UInt(UInt
) {}
145 Arg(SIntMax SInt
) : Kind(AK_SInt
), SInt(SInt
) {}
146 Arg(FloatMax Float
) : Kind(AK_Float
), Float(Float
) {}
147 Arg(const void *Pointer
) : Kind(AK_Pointer
), Pointer(Pointer
) {}
160 static const unsigned MaxArgs
= 8;
161 static const unsigned MaxRanges
= 1;
163 /// The arguments which have been added to this diagnostic so far.
167 /// The ranges which have been added to this diagnostic so far.
168 Range Ranges
[MaxRanges
];
171 Diag
&AddArg(Arg A
) {
172 CHECK(NumArgs
!= MaxArgs
);
177 Diag
&AddRange(Range A
) {
178 CHECK(NumRanges
!= MaxRanges
);
179 Ranges
[NumRanges
++] = A
;
183 /// \c Diag objects are not copyable.
184 Diag(const Diag
&); // NOT IMPLEMENTED
185 Diag
&operator=(const Diag
&);
188 Diag(Location Loc
, DiagLevel Level
, ErrorType ET
, const char *Message
)
189 : Loc(Loc
), Level(Level
), ET(ET
), Message(Message
), NumArgs(0),
193 Diag
&operator<<(const char *Str
) { return AddArg(Str
); }
194 Diag
&operator<<(TypeName TN
) { return AddArg(TN
); }
195 Diag
&operator<<(unsigned long long V
) { return AddArg(UIntMax(V
)); }
196 Diag
&operator<<(const void *V
) { return AddArg(V
); }
197 Diag
&operator<<(const TypeDescriptor
&V
);
198 Diag
&operator<<(const Value
&V
);
199 Diag
&operator<<(const Range
&R
) { return AddRange(R
); }
202 struct ReportOptions
{
203 // If FromUnrecoverableHandler is specified, UBSan runtime handler is not
204 // expected to return.
205 bool FromUnrecoverableHandler
;
206 /// pc/bp are used to unwind the stack trace.
211 bool ignoreReport(SourceLocation SLoc
, ReportOptions Opts
, ErrorType ET
);
213 #define GET_REPORT_OPTIONS(unrecoverable_handler) \
215 ReportOptions Opts = {unrecoverable_handler, pc, bp}
217 /// \brief Instantiate this class before printing diagnostics in the error
218 /// report. This class ensures that reports from different threads and from
219 /// different sanitizers won't be mixed.
224 Initializer initializer_
;
225 ScopedErrorReportLock report_lock_
;
232 ScopedReport(ReportOptions Opts
, Location SummaryLoc
, ErrorType Type
);
235 static void CheckLocked() { ScopedErrorReportLock::CheckLocked(); }
238 void InitializeSuppressions();
239 bool IsVptrCheckSuppressed(const char *TypeName
);
240 // Sometimes UBSan runtime can know filename from handlers arguments, even if
241 // debug info is missing.
242 bool IsPCSuppressed(ErrorType ET
, uptr PC
, const char *Filename
);
244 } // namespace __ubsan
246 #endif // UBSAN_DIAG_H