blob: f56250849063fae122dc15fb01f40c7a22a260da [file] [log] [blame]
Richard Smith6ebe4512012-10-09 19:34:32 +00001//===-- ubsan_diag.cc -----------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Diagnostic reporting for the UBSan runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ubsan_diag.h"
Stephen Hines6d186232014-11-26 17:56:19 -080015#include "ubsan_init.h"
16#include "ubsan_flags.h"
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +000017#include "sanitizer_common/sanitizer_report_decorator.h"
Richard Smith5f116492012-12-18 04:23:18 +000018#include "sanitizer_common/sanitizer_stacktrace.h"
Stephen Hines6d186232014-11-26 17:56:19 -080019#include "sanitizer_common/sanitizer_stacktrace_printer.h"
Richard Smith5f116492012-12-18 04:23:18 +000020#include "sanitizer_common/sanitizer_symbolizer.h"
Richard Smith6ebe4512012-10-09 19:34:32 +000021#include <stdio.h>
Richard Smith6ebe4512012-10-09 19:34:32 +000022
23using namespace __ubsan;
24
Stephen Hines6d186232014-11-26 17:56:19 -080025static void MaybePrintStackTrace(uptr pc, uptr bp) {
26 // We assume that flags are already parsed: InitIfNecessary
27 // will definitely be called when we print the first diagnostics message.
28 if (!flags()->print_stacktrace)
29 return;
30 // We can only use slow unwind, as we don't have any information about stack
31 // top/bottom.
32 // FIXME: It's better to respect "fast_unwind_on_fatal" runtime flag and
33 // fetch stack top/bottom information if we have it (e.g. if we're running
34 // under ASan).
35 if (StackTrace::WillUseFastUnwind(false))
36 return;
37 BufferedStackTrace stack;
38 stack.Unwind(kStackTraceMax, pc, bp, 0, 0, 0, false);
39 stack.Print();
40}
41
42static void MaybeReportErrorSummary(Location Loc) {
43 if (!common_flags()->print_summary)
44 return;
45 // Don't try to unwind the stack trace in UBSan summaries: just use the
46 // provided location.
47 if (Loc.isSourceLocation()) {
48 SourceLocation SLoc = Loc.getSourceLocation();
49 if (!SLoc.isInvalid()) {
50 ReportErrorSummary("undefined-behavior", SLoc.getFilename(),
51 SLoc.getLine(), "");
52 return;
53 }
Stephen Hines2d1fdb22014-05-28 23:58:16 -070054 }
Stephen Hines6d186232014-11-26 17:56:19 -080055 ReportErrorSummary("undefined-behavior");
Stephen Hines2d1fdb22014-05-28 23:58:16 -070056}
57
Stephen Hines6a211c52014-07-21 00:49:56 -070058namespace {
59class Decorator : public SanitizerCommonDecorator {
60 public:
61 Decorator() : SanitizerCommonDecorator() {}
62 const char *Highlight() const { return Green(); }
63 const char *EndHighlight() const { return Default(); }
64 const char *Note() const { return Black(); }
65 const char *EndNote() const { return Default(); }
66};
67}
68
Richard Smith5f116492012-12-18 04:23:18 +000069Location __ubsan::getCallerLocation(uptr CallerLoc) {
70 if (!CallerLoc)
71 return Location();
72
Alexey Samsonovd2f08ff2012-12-18 09:57:34 +000073 uptr Loc = StackTrace::GetPreviousInstructionPc(CallerLoc);
Peter Collingbourne9b5f95f2013-10-20 21:29:46 +000074 return getFunctionLocation(Loc, 0);
75}
76
77Location __ubsan::getFunctionLocation(uptr Loc, const char **FName) {
78 if (!Loc)
79 return Location();
Stephen Hines6d186232014-11-26 17:56:19 -080080 InitIfNecessary();
Richard Smith5f116492012-12-18 04:23:18 +000081
82 AddressInfo Info;
Stephen Hines6d186232014-11-26 17:56:19 -080083 if (!Symbolizer::GetOrInit()->SymbolizePC(Loc, &Info, 1) || !Info.module ||
84 !*Info.module)
Alexey Samsonovd2f08ff2012-12-18 09:57:34 +000085 return Location(Loc);
Richard Smith5f116492012-12-18 04:23:18 +000086
Peter Collingbourne9b5f95f2013-10-20 21:29:46 +000087 if (FName && Info.function)
88 *FName = Info.function;
89
Alexey Samsonov7ed46ff2013-04-05 07:30:29 +000090 if (!Info.file)
Richard Smith5f116492012-12-18 04:23:18 +000091 return ModuleLocation(Info.module, Info.module_offset);
92
93 return SourceLocation(Info.file, Info.line, Info.column);
94}
95
Richard Smith6ebe4512012-10-09 19:34:32 +000096Diag &Diag::operator<<(const TypeDescriptor &V) {
97 return AddArg(V.getTypeName());
98}
99
100Diag &Diag::operator<<(const Value &V) {
101 if (V.getType().isSignedIntegerTy())
102 AddArg(V.getSIntValue());
103 else if (V.getType().isUnsignedIntegerTy())
104 AddArg(V.getUIntValue());
Richard Smith58561702012-10-12 22:57:15 +0000105 else if (V.getType().isFloatTy())
106 AddArg(V.getFloatValue());
Richard Smith6ebe4512012-10-09 19:34:32 +0000107 else
108 AddArg("<unknown>");
109 return *this;
110}
111
Richard Smith0ad23f72012-12-18 09:30:21 +0000112/// Hexadecimal printing for numbers too large for Printf to handle directly.
Richard Smith6ebe4512012-10-09 19:34:32 +0000113static void PrintHex(UIntMax Val) {
Chandler Carruthba3fde62012-10-13 02:30:10 +0000114#if HAVE_INT128_T
Richard Smithf4932202012-11-13 23:42:05 +0000115 Printf("0x%08x%08x%08x%08x",
Richard Smith6ebe4512012-10-09 19:34:32 +0000116 (unsigned int)(Val >> 96),
117 (unsigned int)(Val >> 64),
118 (unsigned int)(Val >> 32),
119 (unsigned int)(Val));
120#else
121 UNREACHABLE("long long smaller than 64 bits?");
122#endif
123}
124
Richard Smith5f116492012-12-18 04:23:18 +0000125static void renderLocation(Location Loc) {
Alexey Samsonovaed85842013-11-14 09:54:10 +0000126 InternalScopedString LocBuffer(1024);
Richard Smith5f116492012-12-18 04:23:18 +0000127 switch (Loc.getKind()) {
128 case Location::LK_Source: {
129 SourceLocation SLoc = Loc.getSourceLocation();
130 if (SLoc.isInvalid())
Alexey Samsonovaed85842013-11-14 09:54:10 +0000131 LocBuffer.append("<unknown>");
Alexey Samsonov90b0f1e2013-10-04 08:55:03 +0000132 else
Stephen Hines6d186232014-11-26 17:56:19 -0800133 RenderSourceLocation(&LocBuffer, SLoc.getFilename(), SLoc.getLine(),
134 SLoc.getColumn(), common_flags()->strip_path_prefix);
Richard Smith5f116492012-12-18 04:23:18 +0000135 break;
136 }
Stephen Hines6d186232014-11-26 17:56:19 -0800137 case Location::LK_Module: {
138 ModuleLocation MLoc = Loc.getModuleLocation();
139 RenderModuleLocation(&LocBuffer, MLoc.getModuleName(), MLoc.getOffset(),
140 common_flags()->strip_path_prefix);
Richard Smith5f116492012-12-18 04:23:18 +0000141 break;
Stephen Hines6d186232014-11-26 17:56:19 -0800142 }
Richard Smith5f116492012-12-18 04:23:18 +0000143 case Location::LK_Memory:
Alexey Samsonovaed85842013-11-14 09:54:10 +0000144 LocBuffer.append("%p", Loc.getMemoryLocation());
Richard Smith5f116492012-12-18 04:23:18 +0000145 break;
146 case Location::LK_Null:
Alexey Samsonovaed85842013-11-14 09:54:10 +0000147 LocBuffer.append("<unknown>");
Richard Smith25ee97f2012-12-18 06:30:32 +0000148 break;
Richard Smith5f116492012-12-18 04:23:18 +0000149 }
Alexey Samsonovaed85842013-11-14 09:54:10 +0000150 Printf("%s:", LocBuffer.data());
Richard Smith5f116492012-12-18 04:23:18 +0000151}
152
Richard Smith25ee97f2012-12-18 06:30:32 +0000153static void renderText(const char *Message, const Diag::Arg *Args) {
Richard Smith6ebe4512012-10-09 19:34:32 +0000154 for (const char *Msg = Message; *Msg; ++Msg) {
Richard Smithf4932202012-11-13 23:42:05 +0000155 if (*Msg != '%') {
156 char Buffer[64];
157 unsigned I;
158 for (I = 0; Msg[I] && Msg[I] != '%' && I != 63; ++I)
159 Buffer[I] = Msg[I];
160 Buffer[I] = '\0';
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000161 Printf(Buffer);
Richard Smithf4932202012-11-13 23:42:05 +0000162 Msg += I - 1;
163 } else {
Richard Smith25ee97f2012-12-18 06:30:32 +0000164 const Diag::Arg &A = Args[*++Msg - '0'];
Richard Smith6ebe4512012-10-09 19:34:32 +0000165 switch (A.Kind) {
Richard Smith25ee97f2012-12-18 06:30:32 +0000166 case Diag::AK_String:
Richard Smithf4932202012-11-13 23:42:05 +0000167 Printf("%s", A.String);
Richard Smith6ebe4512012-10-09 19:34:32 +0000168 break;
Richard Smith0ad23f72012-12-18 09:30:21 +0000169 case Diag::AK_Mangled: {
Peter Collingbournec1a1ed62013-10-25 23:03:29 +0000170 Printf("'%s'", Symbolizer::GetOrInit()->Demangle(A.String));
Richard Smith0ad23f72012-12-18 09:30:21 +0000171 break;
172 }
Richard Smith25ee97f2012-12-18 06:30:32 +0000173 case Diag::AK_SInt:
Richard Smith6ebe4512012-10-09 19:34:32 +0000174 // 'long long' is guaranteed to be at least 64 bits wide.
175 if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX)
Richard Smithf4932202012-11-13 23:42:05 +0000176 Printf("%lld", (long long)A.SInt);
Richard Smith6ebe4512012-10-09 19:34:32 +0000177 else
178 PrintHex(A.SInt);
179 break;
Richard Smith25ee97f2012-12-18 06:30:32 +0000180 case Diag::AK_UInt:
Richard Smith6ebe4512012-10-09 19:34:32 +0000181 if (A.UInt <= UINT64_MAX)
Richard Smithf4932202012-11-13 23:42:05 +0000182 Printf("%llu", (unsigned long long)A.UInt);
Richard Smith6ebe4512012-10-09 19:34:32 +0000183 else
184 PrintHex(A.UInt);
185 break;
Richard Smith25ee97f2012-12-18 06:30:32 +0000186 case Diag::AK_Float: {
Richard Smithf4932202012-11-13 23:42:05 +0000187 // FIXME: Support floating-point formatting in sanitizer_common's
188 // printf, and stop using snprintf here.
189 char Buffer[32];
190 snprintf(Buffer, sizeof(Buffer), "%Lg", (long double)A.Float);
191 Printf("%s", Buffer);
Richard Smith58561702012-10-12 22:57:15 +0000192 break;
Richard Smithf4932202012-11-13 23:42:05 +0000193 }
Richard Smith25ee97f2012-12-18 06:30:32 +0000194 case Diag::AK_Pointer:
Richard Smithc1939532013-01-10 22:39:40 +0000195 Printf("%p", A.Pointer);
Richard Smith6ebe4512012-10-09 19:34:32 +0000196 break;
197 }
198 }
199 }
Richard Smith25ee97f2012-12-18 06:30:32 +0000200}
201
202/// Find the earliest-starting range in Ranges which ends after Loc.
203static Range *upperBound(MemoryLocation Loc, Range *Ranges,
204 unsigned NumRanges) {
205 Range *Best = 0;
206 for (unsigned I = 0; I != NumRanges; ++I)
207 if (Ranges[I].getEnd().getMemoryLocation() > Loc &&
208 (!Best ||
209 Best->getStart().getMemoryLocation() >
210 Ranges[I].getStart().getMemoryLocation()))
211 Best = &Ranges[I];
212 return Best;
213}
214
Stephen Hines6d186232014-11-26 17:56:19 -0800215static inline uptr subtractNoOverflow(uptr LHS, uptr RHS) {
216 return (LHS < RHS) ? 0 : LHS - RHS;
217}
218
219static inline uptr addNoOverflow(uptr LHS, uptr RHS) {
220 const uptr Limit = (uptr)-1;
221 return (LHS > Limit - RHS) ? Limit : LHS + RHS;
222}
223
Richard Smith25ee97f2012-12-18 06:30:32 +0000224/// Render a snippet of the address space near a location.
Stephen Hines6a211c52014-07-21 00:49:56 -0700225static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc,
Richard Smith25ee97f2012-12-18 06:30:32 +0000226 Range *Ranges, unsigned NumRanges,
227 const Diag::Arg *Args) {
Richard Smith25ee97f2012-12-18 06:30:32 +0000228 // Show at least the 8 bytes surrounding Loc.
Stephen Hines6d186232014-11-26 17:56:19 -0800229 const unsigned MinBytesNearLoc = 4;
230 MemoryLocation Min = subtractNoOverflow(Loc, MinBytesNearLoc);
231 MemoryLocation Max = addNoOverflow(Loc, MinBytesNearLoc);
232 MemoryLocation OrigMin = Min;
Richard Smith25ee97f2012-12-18 06:30:32 +0000233 for (unsigned I = 0; I < NumRanges; ++I) {
234 Min = __sanitizer::Min(Ranges[I].getStart().getMemoryLocation(), Min);
235 Max = __sanitizer::Max(Ranges[I].getEnd().getMemoryLocation(), Max);
236 }
237
238 // If we have too many interesting bytes, prefer to show bytes after Loc.
Stephen Hines6d186232014-11-26 17:56:19 -0800239 const unsigned BytesToShow = 32;
Richard Smith25ee97f2012-12-18 06:30:32 +0000240 if (Max - Min > BytesToShow)
Stephen Hines6d186232014-11-26 17:56:19 -0800241 Min = __sanitizer::Min(Max - BytesToShow, OrigMin);
242 Max = addNoOverflow(Min, BytesToShow);
243
244 if (!IsAccessibleMemoryRange(Min, Max - Min)) {
245 Printf("<memory cannot be printed>\n");
246 return;
247 }
Richard Smith25ee97f2012-12-18 06:30:32 +0000248
249 // Emit data.
250 for (uptr P = Min; P != Max; ++P) {
Richard Smith25ee97f2012-12-18 06:30:32 +0000251 unsigned char C = *reinterpret_cast<const unsigned char*>(P);
252 Printf("%s%02x", (P % 8 == 0) ? " " : " ", C);
253 }
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000254 Printf("\n");
Richard Smith25ee97f2012-12-18 06:30:32 +0000255
256 // Emit highlights.
Stephen Hines6a211c52014-07-21 00:49:56 -0700257 Printf(Decor.Highlight());
Richard Smith25ee97f2012-12-18 06:30:32 +0000258 Range *InRange = upperBound(Min, Ranges, NumRanges);
259 for (uptr P = Min; P != Max; ++P) {
260 char Pad = ' ', Byte = ' ';
261 if (InRange && InRange->getEnd().getMemoryLocation() == P)
262 InRange = upperBound(P, Ranges, NumRanges);
263 if (!InRange && P > Loc)
264 break;
265 if (InRange && InRange->getStart().getMemoryLocation() < P)
266 Pad = '~';
267 if (InRange && InRange->getStart().getMemoryLocation() <= P)
268 Byte = '~';
269 char Buffer[] = { Pad, Pad, P == Loc ? '^' : Byte, Byte, 0 };
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000270 Printf((P % 8 == 0) ? Buffer : &Buffer[1]);
Richard Smith25ee97f2012-12-18 06:30:32 +0000271 }
Stephen Hines6a211c52014-07-21 00:49:56 -0700272 Printf("%s\n", Decor.EndHighlight());
Richard Smith25ee97f2012-12-18 06:30:32 +0000273
274 // Go over the line again, and print names for the ranges.
275 InRange = 0;
276 unsigned Spaces = 0;
277 for (uptr P = Min; P != Max; ++P) {
278 if (!InRange || InRange->getEnd().getMemoryLocation() == P)
279 InRange = upperBound(P, Ranges, NumRanges);
280 if (!InRange)
281 break;
282
283 Spaces += (P % 8) == 0 ? 2 : 1;
284
285 if (InRange && InRange->getStart().getMemoryLocation() == P) {
286 while (Spaces--)
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000287 Printf(" ");
Richard Smith25ee97f2012-12-18 06:30:32 +0000288 renderText(InRange->getText(), Args);
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000289 Printf("\n");
Richard Smith25ee97f2012-12-18 06:30:32 +0000290 // FIXME: We only support naming one range for now!
291 break;
292 }
293
294 Spaces += 2;
295 }
296
297 // FIXME: Print names for anything we can identify within the line:
298 //
299 // * If we can identify the memory itself as belonging to a particular
300 // global, stack variable, or dynamic allocation, then do so.
301 //
302 // * If we have a pointer-size, pointer-aligned range highlighted,
303 // determine whether the value of that range is a pointer to an
304 // entity which we can name, and if so, print that name.
305 //
306 // This needs an external symbolizer, or (preferably) ASan instrumentation.
307}
308
309Diag::~Diag() {
Stephen Hines6d186232014-11-26 17:56:19 -0800310 // All diagnostics should be printed under report mutex.
311 CommonSanitizerReportMutex.CheckLocked();
Stephen Hines6a211c52014-07-21 00:49:56 -0700312 Decorator Decor;
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000313 Printf(Decor.Bold());
Richard Smith25ee97f2012-12-18 06:30:32 +0000314
315 renderLocation(Loc);
316
317 switch (Level) {
318 case DL_Error:
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000319 Printf("%s runtime error: %s%s",
Stephen Hines6a211c52014-07-21 00:49:56 -0700320 Decor.Warning(), Decor.EndWarning(), Decor.Bold());
Richard Smith25ee97f2012-12-18 06:30:32 +0000321 break;
322
323 case DL_Note:
Stephen Hines6a211c52014-07-21 00:49:56 -0700324 Printf("%s note: %s", Decor.Note(), Decor.EndNote());
Richard Smith25ee97f2012-12-18 06:30:32 +0000325 break;
326 }
327
328 renderText(Message, Args);
329
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000330 Printf("%s\n", Decor.Default());
Richard Smith25ee97f2012-12-18 06:30:32 +0000331
332 if (Loc.isMemoryLocation())
Alexey Samsonov8f72f7c2013-02-27 12:58:24 +0000333 renderMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges,
Richard Smithc2424462013-02-12 22:12:10 +0000334 NumRanges, Args);
Richard Smith6ebe4512012-10-09 19:34:32 +0000335}
Stephen Hines6d186232014-11-26 17:56:19 -0800336
337ScopedReport::ScopedReport(ReportOptions Opts, Location SummaryLoc)
338 : Opts(Opts), SummaryLoc(SummaryLoc) {
339 InitIfNecessary();
340 CommonSanitizerReportMutex.Lock();
341}
342
343ScopedReport::~ScopedReport() {
344 MaybePrintStackTrace(Opts.pc, Opts.bp);
345 MaybeReportErrorSummary(SummaryLoc);
346 CommonSanitizerReportMutex.Unlock();
347 if (Opts.DieAfterReport || flags()->halt_on_error)
348 Die();
349}
350
351bool __ubsan::MatchSuppression(const char *Str, SuppressionType Type) {
352 Suppression *s;
353 // If .preinit_array is not used, it is possible that the UBSan runtime is not
354 // initialized.
355 if (!SANITIZER_CAN_USE_PREINIT_ARRAY)
356 InitIfNecessary();
357 return SuppressionContext::Get()->Match(Str, Type, &s);
358}