1 //===-- ubsan_diag.h --------------------------------------------*- C++ -*-===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // Diagnostics emission for Clang's undefined behavior sanitizer.
10 //===----------------------------------------------------------------------===//
14 #include "ubsan_value.h"
15 #include "sanitizer_common/sanitizer_stacktrace.h"
16 #include "sanitizer_common/sanitizer_suppressions.h"
20 /// \brief A location within a loaded module in the program. These are used when
21 /// the location can't be resolved to a SourceLocation.
22 class ModuleLocation
{
23 const char *ModuleName
;
27 ModuleLocation() : ModuleName(0), Offset(0) {}
28 ModuleLocation(const char *ModuleName
, uptr Offset
)
29 : ModuleName(ModuleName
), Offset(Offset
) {}
30 const char *getModuleName() const { return ModuleName
; }
31 uptr
getOffset() const { return Offset
; }
34 /// A location of some data within the program's address space.
35 typedef uptr MemoryLocation
;
37 /// \brief Location at which a diagnostic can be emitted. Either a
38 /// SourceLocation, a ModuleLocation, or a MemoryLocation.
41 enum LocationKind
{ LK_Null
, LK_Source
, LK_Module
, LK_Memory
};
45 // FIXME: In C++11, wrap these in an anonymous union.
46 SourceLocation SourceLoc
;
47 ModuleLocation ModuleLoc
;
48 MemoryLocation MemoryLoc
;
51 Location() : Kind(LK_Null
) {}
52 Location(SourceLocation Loc
) :
53 Kind(LK_Source
), SourceLoc(Loc
) {}
54 Location(ModuleLocation Loc
) :
55 Kind(LK_Module
), ModuleLoc(Loc
) {}
56 Location(MemoryLocation Loc
) :
57 Kind(LK_Memory
), MemoryLoc(Loc
) {}
59 LocationKind
getKind() const { return Kind
; }
61 bool isSourceLocation() const { return Kind
== LK_Source
; }
62 bool isModuleLocation() const { return Kind
== LK_Module
; }
63 bool isMemoryLocation() const { return Kind
== LK_Memory
; }
65 SourceLocation
getSourceLocation() const {
66 CHECK(isSourceLocation());
69 ModuleLocation
getModuleLocation() const {
70 CHECK(isModuleLocation());
73 MemoryLocation
getMemoryLocation() const {
74 CHECK(isMemoryLocation());
79 /// Try to obtain a location for the caller. This might fail, and produce either
80 /// an invalid location or a module location for the caller.
81 Location
getCallerLocation(uptr CallerLoc
= GET_CALLER_PC());
83 /// Try to obtain a location for the given function pointer. This might fail,
84 /// and produce either an invalid location or a module location for the caller.
85 /// If FName is non-null and the name of the function is known, set *FName to
86 /// the function name, otherwise *FName is unchanged.
87 Location
getFunctionLocation(uptr Loc
, const char **FName
);
89 /// A diagnostic severity level.
91 DL_Error
, ///< An error.
92 DL_Note
///< A note, attached to a prior diagnostic.
95 /// \brief Annotation for a range of locations in a diagnostic.
101 Range() : Start(), End(), Text() {}
102 Range(MemoryLocation Start
, MemoryLocation End
, const char *Text
)
103 : Start(Start
), End(End
), Text(Text
) {}
104 Location
getStart() const { return Start
; }
105 Location
getEnd() const { return End
; }
106 const char *getText() const { return Text
; }
109 /// \brief A mangled C++ name. Really just a strong typedef for 'const char*'.
113 MangledName(const char *Name
) : Name(Name
) {}
114 const char *getName() const { return Name
; }
117 /// \brief Representation of an in-flight diagnostic.
119 /// Temporary \c Diag instances are created by the handler routines to
120 /// accumulate arguments for a diagnostic. The destructor emits the diagnostic
123 /// The location at which the problem occurred.
126 /// The diagnostic level.
129 /// The message which will be emitted, with %0, %1, ... placeholders for
134 /// Kinds of arguments, corresponding to members of \c Arg's union.
136 AK_String
, ///< A string argument, displayed as-is.
137 AK_Mangled
,///< A C++ mangled name, demangled before display.
138 AK_UInt
, ///< An unsigned integer argument.
139 AK_SInt
, ///< A signed integer argument.
140 AK_Float
, ///< A floating-point argument.
141 AK_Pointer
///< A pointer argument, displayed in hexadecimal.
144 /// An individual diagnostic message argument.
147 Arg(const char *String
) : Kind(AK_String
), String(String
) {}
148 Arg(MangledName MN
) : Kind(AK_Mangled
), String(MN
.getName()) {}
149 Arg(UIntMax UInt
) : Kind(AK_UInt
), UInt(UInt
) {}
150 Arg(SIntMax SInt
) : Kind(AK_SInt
), SInt(SInt
) {}
151 Arg(FloatMax Float
) : Kind(AK_Float
), Float(Float
) {}
152 Arg(const void *Pointer
) : Kind(AK_Pointer
), Pointer(Pointer
) {}
165 static const unsigned MaxArgs
= 5;
166 static const unsigned MaxRanges
= 1;
168 /// The arguments which have been added to this diagnostic so far.
172 /// The ranges which have been added to this diagnostic so far.
173 Range Ranges
[MaxRanges
];
176 Diag
&AddArg(Arg A
) {
177 CHECK(NumArgs
!= MaxArgs
);
182 Diag
&AddRange(Range A
) {
183 CHECK(NumRanges
!= MaxRanges
);
184 Ranges
[NumRanges
++] = A
;
188 /// \c Diag objects are not copyable.
189 Diag(const Diag
&); // NOT IMPLEMENTED
190 Diag
&operator=(const Diag
&);
193 Diag(Location Loc
, DiagLevel Level
, const char *Message
)
194 : Loc(Loc
), Level(Level
), Message(Message
), NumArgs(0), NumRanges(0) {}
197 Diag
&operator<<(const char *Str
) { return AddArg(Str
); }
198 Diag
&operator<<(MangledName MN
) { return AddArg(MN
); }
199 Diag
&operator<<(unsigned long long V
) { return AddArg(UIntMax(V
)); }
200 Diag
&operator<<(const void *V
) { return AddArg(V
); }
201 Diag
&operator<<(const TypeDescriptor
&V
);
202 Diag
&operator<<(const Value
&V
);
203 Diag
&operator<<(const Range
&R
) { return AddRange(R
); }
206 struct ReportOptions
{
207 /// If DieAfterReport is specified, UBSan will terminate the program after the
208 /// report is printed.
210 /// pc/bp are used to unwind the stack trace.
215 #define GET_REPORT_OPTIONS(die_after_report) \
217 ReportOptions Opts = {die_after_report, pc, bp}
219 /// \brief Instantiate this class before printing diagnostics in the error
220 /// report. This class ensures that reports from different threads and from
221 /// different sanitizers won't be mixed.
227 ScopedReport(ReportOptions Opts
, Location SummaryLoc
);
231 bool MatchSuppression(const char *Str
, SuppressionType Type
);
233 } // namespace __ubsan
235 #endif // UBSAN_DIAG_H