1 //===-- ubsan_diag.cc -----------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Diagnostic reporting for the UBSan runtime.
12 //===----------------------------------------------------------------------===//
14 #include "ubsan_diag.h"
15 #include "ubsan_flags.h"
16 #include "sanitizer_common/sanitizer_common.h"
17 #include "sanitizer_common/sanitizer_flags.h"
18 #include "sanitizer_common/sanitizer_libc.h"
19 #include "sanitizer_common/sanitizer_report_decorator.h"
20 #include "sanitizer_common/sanitizer_stacktrace.h"
21 #include "sanitizer_common/sanitizer_symbolizer.h"
24 using namespace __ubsan
;
26 static void InitializeSanitizerCommonAndFlags() {
27 static StaticSpinMutex init_mu
;
28 SpinMutexLock
l(&init_mu
);
29 static bool initialized
;
32 if (0 == internal_strcmp(SanitizerToolName
, "SanitizerTool")) {
33 // UBSan is run in a standalone mode. Initialize it now.
34 SanitizerToolName
= "UndefinedBehaviorSanitizer";
35 CommonFlags
*cf
= common_flags();
36 SetCommonFlagsDefaults(cf
);
37 cf
->print_summary
= false;
38 // Common flags may only be modified via UBSAN_OPTIONS.
39 ParseCommonFlagsFromString(cf
, GetEnv("UBSAN_OPTIONS"));
41 // Initialize UBSan-specific flags.
46 void __ubsan::MaybePrintStackTrace(uptr pc
, uptr bp
) {
47 // We assume that flags are already parsed: InitializeSanitizerCommonAndFlags
48 // will definitely be called when we print the first diagnostics message.
49 if (!flags()->print_stacktrace
)
51 // We can only use slow unwind, as we don't have any information about stack
53 // FIXME: It's better to respect "fast_unwind_on_fatal" runtime flag and
54 // fetch stack top/bottom information if we have it (e.g. if we're running
56 if (StackTrace::WillUseFastUnwind(false))
59 stack
.Unwind(kStackTraceMax
, pc
, bp
, 0, 0, 0, false);
64 class Decorator
: public SanitizerCommonDecorator
{
66 Decorator() : SanitizerCommonDecorator() {}
67 const char *Highlight() const { return Green(); }
68 const char *EndHighlight() const { return Default(); }
69 const char *Note() const { return Black(); }
70 const char *EndNote() const { return Default(); }
74 Location
__ubsan::getCallerLocation(uptr CallerLoc
) {
78 uptr Loc
= StackTrace::GetPreviousInstructionPc(CallerLoc
);
79 return getFunctionLocation(Loc
, 0);
82 Location
__ubsan::getFunctionLocation(uptr Loc
, const char **FName
) {
85 InitializeSanitizerCommonAndFlags();
88 if (!Symbolizer::GetOrInit()->SymbolizePC(Loc
, &Info
, 1) ||
89 !Info
.module
|| !*Info
.module
)
92 if (FName
&& Info
.function
)
93 *FName
= Info
.function
;
96 return ModuleLocation(Info
.module
, Info
.module_offset
);
98 return SourceLocation(Info
.file
, Info
.line
, Info
.column
);
101 Diag
&Diag::operator<<(const TypeDescriptor
&V
) {
102 return AddArg(V
.getTypeName());
105 Diag
&Diag::operator<<(const Value
&V
) {
106 if (V
.getType().isSignedIntegerTy())
107 AddArg(V
.getSIntValue());
108 else if (V
.getType().isUnsignedIntegerTy())
109 AddArg(V
.getUIntValue());
110 else if (V
.getType().isFloatTy())
111 AddArg(V
.getFloatValue());
117 /// Hexadecimal printing for numbers too large for Printf to handle directly.
118 static void PrintHex(UIntMax Val
) {
120 Printf("0x%08x%08x%08x%08x",
121 (unsigned int)(Val
>> 96),
122 (unsigned int)(Val
>> 64),
123 (unsigned int)(Val
>> 32),
124 (unsigned int)(Val
));
126 UNREACHABLE("long long smaller than 64 bits?");
130 static void renderLocation(Location Loc
) {
131 InternalScopedString
LocBuffer(1024);
132 switch (Loc
.getKind()) {
133 case Location::LK_Source
: {
134 SourceLocation SLoc
= Loc
.getSourceLocation();
135 if (SLoc
.isInvalid())
136 LocBuffer
.append("<unknown>");
138 PrintSourceLocation(&LocBuffer
, SLoc
.getFilename(), SLoc
.getLine(),
142 case Location::LK_Module
:
143 PrintModuleAndOffset(&LocBuffer
, Loc
.getModuleLocation().getModuleName(),
144 Loc
.getModuleLocation().getOffset());
146 case Location::LK_Memory
:
147 LocBuffer
.append("%p", Loc
.getMemoryLocation());
149 case Location::LK_Null
:
150 LocBuffer
.append("<unknown>");
153 Printf("%s:", LocBuffer
.data());
156 static void renderText(const char *Message
, const Diag::Arg
*Args
) {
157 for (const char *Msg
= Message
; *Msg
; ++Msg
) {
161 for (I
= 0; Msg
[I
] && Msg
[I
] != '%' && I
!= 63; ++I
)
167 const Diag::Arg
&A
= Args
[*++Msg
- '0'];
169 case Diag::AK_String
:
170 Printf("%s", A
.String
);
172 case Diag::AK_Mangled
: {
173 Printf("'%s'", Symbolizer::GetOrInit()->Demangle(A
.String
));
177 // 'long long' is guaranteed to be at least 64 bits wide.
178 if (A
.SInt
>= INT64_MIN
&& A
.SInt
<= INT64_MAX
)
179 Printf("%lld", (long long)A
.SInt
);
184 if (A
.UInt
<= UINT64_MAX
)
185 Printf("%llu", (unsigned long long)A
.UInt
);
189 case Diag::AK_Float
: {
190 // FIXME: Support floating-point formatting in sanitizer_common's
191 // printf, and stop using snprintf here.
193 snprintf(Buffer
, sizeof(Buffer
), "%Lg", (long double)A
.Float
);
194 Printf("%s", Buffer
);
197 case Diag::AK_Pointer
:
198 Printf("%p", A
.Pointer
);
205 /// Find the earliest-starting range in Ranges which ends after Loc.
206 static Range
*upperBound(MemoryLocation Loc
, Range
*Ranges
,
207 unsigned NumRanges
) {
209 for (unsigned I
= 0; I
!= NumRanges
; ++I
)
210 if (Ranges
[I
].getEnd().getMemoryLocation() > Loc
&&
212 Best
->getStart().getMemoryLocation() >
213 Ranges
[I
].getStart().getMemoryLocation()))
218 /// Render a snippet of the address space near a location.
219 static void renderMemorySnippet(const Decorator
&Decor
, MemoryLocation Loc
,
220 Range
*Ranges
, unsigned NumRanges
,
221 const Diag::Arg
*Args
) {
222 const unsigned BytesToShow
= 32;
223 const unsigned MinBytesNearLoc
= 4;
225 // Show at least the 8 bytes surrounding Loc.
226 MemoryLocation Min
= Loc
- MinBytesNearLoc
, Max
= Loc
+ MinBytesNearLoc
;
227 for (unsigned I
= 0; I
< NumRanges
; ++I
) {
228 Min
= __sanitizer::Min(Ranges
[I
].getStart().getMemoryLocation(), Min
);
229 Max
= __sanitizer::Max(Ranges
[I
].getEnd().getMemoryLocation(), Max
);
232 // If we have too many interesting bytes, prefer to show bytes after Loc.
233 if (Max
- Min
> BytesToShow
)
234 Min
= __sanitizer::Min(Max
- BytesToShow
, Loc
- MinBytesNearLoc
);
235 Max
= Min
+ BytesToShow
;
238 for (uptr P
= Min
; P
!= Max
; ++P
) {
239 // FIXME: Check that the address is readable before printing it.
240 unsigned char C
= *reinterpret_cast<const unsigned char*>(P
);
241 Printf("%s%02x", (P
% 8 == 0) ? " " : " ", C
);
246 Printf(Decor
.Highlight());
247 Range
*InRange
= upperBound(Min
, Ranges
, NumRanges
);
248 for (uptr P
= Min
; P
!= Max
; ++P
) {
249 char Pad
= ' ', Byte
= ' ';
250 if (InRange
&& InRange
->getEnd().getMemoryLocation() == P
)
251 InRange
= upperBound(P
, Ranges
, NumRanges
);
252 if (!InRange
&& P
> Loc
)
254 if (InRange
&& InRange
->getStart().getMemoryLocation() < P
)
256 if (InRange
&& InRange
->getStart().getMemoryLocation() <= P
)
258 char Buffer
[] = { Pad
, Pad
, P
== Loc
? '^' : Byte
, Byte
, 0 };
259 Printf((P
% 8 == 0) ? Buffer
: &Buffer
[1]);
261 Printf("%s\n", Decor
.EndHighlight());
263 // Go over the line again, and print names for the ranges.
266 for (uptr P
= Min
; P
!= Max
; ++P
) {
267 if (!InRange
|| InRange
->getEnd().getMemoryLocation() == P
)
268 InRange
= upperBound(P
, Ranges
, NumRanges
);
272 Spaces
+= (P
% 8) == 0 ? 2 : 1;
274 if (InRange
&& InRange
->getStart().getMemoryLocation() == P
) {
277 renderText(InRange
->getText(), Args
);
279 // FIXME: We only support naming one range for now!
286 // FIXME: Print names for anything we can identify within the line:
288 // * If we can identify the memory itself as belonging to a particular
289 // global, stack variable, or dynamic allocation, then do so.
291 // * If we have a pointer-size, pointer-aligned range highlighted,
292 // determine whether the value of that range is a pointer to an
293 // entity which we can name, and if so, print that name.
295 // This needs an external symbolizer, or (preferably) ASan instrumentation.
299 InitializeSanitizerCommonAndFlags();
301 SpinMutexLock
l(&CommonSanitizerReportMutex
);
302 Printf(Decor
.Bold());
308 Printf("%s runtime error: %s%s",
309 Decor
.Warning(), Decor
.EndWarning(), Decor
.Bold());
313 Printf("%s note: %s", Decor
.Note(), Decor
.EndNote());
317 renderText(Message
, Args
);
319 Printf("%s\n", Decor
.Default());
321 if (Loc
.isMemoryLocation())
322 renderMemorySnippet(Decor
, Loc
.getMemoryLocation(), Ranges
,