16ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//===-- ubsan_diag.cc -----------------------------------------------------===//
26ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//
36ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//                     The LLVM Compiler Infrastructure
46ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//
56ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith// This file is distributed under the University of Illinois Open Source
66ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith// License. See LICENSE.TXT for details.
76ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//
86ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//===----------------------------------------------------------------------===//
96ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//
106ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith// Diagnostic reporting for the UBSan runtime.
116ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//
126ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith//===----------------------------------------------------------------------===//
136ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith
146ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith#include "ubsan_diag.h"
15f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith#include "sanitizer_common/sanitizer_common.h"
16f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith#include "sanitizer_common/sanitizer_libc.h"
178f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov#include "sanitizer_common/sanitizer_report_decorator.h"
185f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith#include "sanitizer_common/sanitizer_stacktrace.h"
195f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith#include "sanitizer_common/sanitizer_symbolizer.h"
206ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith#include <stdio.h>
216ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith
226ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smithusing namespace __ubsan;
236ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith
245f1164955fb28a9bcb826abc195aa2119feb0f97Richard SmithLocation __ubsan::getCallerLocation(uptr CallerLoc) {
255f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  if (!CallerLoc)
265f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    return Location();
275f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith
28d2f08ffcb97726452f4ba11c199a1e06dc2a7e54Alexey Samsonov  uptr Loc = StackTrace::GetPreviousInstructionPc(CallerLoc);
295f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith
305f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  AddressInfo Info;
31d2f08ffcb97726452f4ba11c199a1e06dc2a7e54Alexey Samsonov  if (!SymbolizeCode(Loc, &Info, 1) || !Info.module || !*Info.module)
32d2f08ffcb97726452f4ba11c199a1e06dc2a7e54Alexey Samsonov    return Location(Loc);
335f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith
347ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov  if (!Info.file)
355f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    return ModuleLocation(Info.module, Info.module_offset);
365f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith
375f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  return SourceLocation(Info.file, Info.line, Info.column);
385f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith}
395f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith
406ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard SmithDiag &Diag::operator<<(const TypeDescriptor &V) {
416ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith  return AddArg(V.getTypeName());
426ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith}
436ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith
446ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard SmithDiag &Diag::operator<<(const Value &V) {
456ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith  if (V.getType().isSignedIntegerTy())
466ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith    AddArg(V.getSIntValue());
476ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith  else if (V.getType().isUnsignedIntegerTy())
486ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith    AddArg(V.getUIntValue());
4958561700a4abad310911a24a867da49a14fae91eRichard Smith  else if (V.getType().isFloatTy())
5058561700a4abad310911a24a867da49a14fae91eRichard Smith    AddArg(V.getFloatValue());
516ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith  else
526ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith    AddArg("<unknown>");
536ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith  return *this;
546ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith}
556ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith
560ad23f7f860e27b8b9a889be665cfaea830503ceRichard Smith/// Hexadecimal printing for numbers too large for Printf to handle directly.
576ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smithstatic void PrintHex(UIntMax Val) {
58ba3fde65b900ce9d0ecdf034dfe3825eea810434Chandler Carruth#if HAVE_INT128_T
59f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith  Printf("0x%08x%08x%08x%08x",
606ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith          (unsigned int)(Val >> 96),
616ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith          (unsigned int)(Val >> 64),
626ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith          (unsigned int)(Val >> 32),
636ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith          (unsigned int)(Val));
646ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith#else
656ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith  UNREACHABLE("long long smaller than 64 bits?");
666ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith#endif
676ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith}
686ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith
695f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smithstatic void renderLocation(Location Loc) {
705f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  switch (Loc.getKind()) {
715f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  case Location::LK_Source: {
725f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    SourceLocation SLoc = Loc.getSourceLocation();
735f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    if (SLoc.isInvalid())
748f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov      Printf("<unknown>:");
755f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    else {
765f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith      Printf("%s:%d:", SLoc.getFilename(), SLoc.getLine());
775f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith      if (SLoc.getColumn())
785f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith        Printf("%d:", SLoc.getColumn());
795f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    }
805f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    break;
815f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  }
825f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  case Location::LK_Module:
835f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    Printf("%s:0x%zx:", Loc.getModuleLocation().getModuleName(),
845f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith           Loc.getModuleLocation().getOffset());
855f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    break;
865f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  case Location::LK_Memory:
87c193953bf3993760a0be8ae20cf716795d2102cdRichard Smith    Printf("%p:", Loc.getMemoryLocation());
885f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith    break;
895f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  case Location::LK_Null:
908f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov    Printf("<unknown>:");
9125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    break;
925f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith  }
935f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith}
945f1164955fb28a9bcb826abc195aa2119feb0f97Richard Smith
9525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smithstatic void renderText(const char *Message, const Diag::Arg *Args) {
966ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith  for (const char *Msg = Message; *Msg; ++Msg) {
97f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith    if (*Msg != '%') {
98f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith      char Buffer[64];
99f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith      unsigned I;
100f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith      for (I = 0; Msg[I] && Msg[I] != '%' && I != 63; ++I)
101f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith        Buffer[I] = Msg[I];
102f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith      Buffer[I] = '\0';
1038f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov      Printf(Buffer);
104f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith      Msg += I - 1;
105f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith    } else {
10625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      const Diag::Arg &A = Args[*++Msg - '0'];
1076ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith      switch (A.Kind) {
10825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      case Diag::AK_String:
109f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith        Printf("%s", A.String);
1106ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        break;
1110ad23f7f860e27b8b9a889be665cfaea830503ceRichard Smith      case Diag::AK_Mangled: {
1128f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov        Printf("'%s'", Demangle(A.String));
1130ad23f7f860e27b8b9a889be665cfaea830503ceRichard Smith        break;
1140ad23f7f860e27b8b9a889be665cfaea830503ceRichard Smith      }
11525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      case Diag::AK_SInt:
1166ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        // 'long long' is guaranteed to be at least 64 bits wide.
1176ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX)
118f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith          Printf("%lld", (long long)A.SInt);
1196ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        else
1206ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith          PrintHex(A.SInt);
1216ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        break;
12225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      case Diag::AK_UInt:
1236ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        if (A.UInt <= UINT64_MAX)
124f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith          Printf("%llu", (unsigned long long)A.UInt);
1256ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        else
1266ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith          PrintHex(A.UInt);
1276ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        break;
12825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      case Diag::AK_Float: {
129f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith        // FIXME: Support floating-point formatting in sanitizer_common's
130f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith        //        printf, and stop using snprintf here.
131f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith        char Buffer[32];
132f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith        snprintf(Buffer, sizeof(Buffer), "%Lg", (long double)A.Float);
133f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith        Printf("%s", Buffer);
13458561700a4abad310911a24a867da49a14fae91eRichard Smith        break;
135f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith      }
13625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      case Diag::AK_Pointer:
137c193953bf3993760a0be8ae20cf716795d2102cdRichard Smith        Printf("%p", A.Pointer);
1386ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith        break;
1396ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith      }
1406ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith    }
1416ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith  }
14225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith}
14325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
14425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith/// Find the earliest-starting range in Ranges which ends after Loc.
14525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smithstatic Range *upperBound(MemoryLocation Loc, Range *Ranges,
14625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith                         unsigned NumRanges) {
14725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  Range *Best = 0;
14825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  for (unsigned I = 0; I != NumRanges; ++I)
14925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    if (Ranges[I].getEnd().getMemoryLocation() > Loc &&
15025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith        (!Best ||
15125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith         Best->getStart().getMemoryLocation() >
15225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith         Ranges[I].getStart().getMemoryLocation()))
15325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      Best = &Ranges[I];
15425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  return Best;
15525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith}
15625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
15725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith/// Render a snippet of the address space near a location.
1588f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonovstatic void renderMemorySnippet(const __sanitizer::AnsiColorDecorator &Decor,
1598f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov                                MemoryLocation Loc,
16025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith                                Range *Ranges, unsigned NumRanges,
16125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith                                const Diag::Arg *Args) {
16225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  const unsigned BytesToShow = 32;
16325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  const unsigned MinBytesNearLoc = 4;
16425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
16525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  // Show at least the 8 bytes surrounding Loc.
16625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  MemoryLocation Min = Loc - MinBytesNearLoc, Max = Loc + MinBytesNearLoc;
16725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  for (unsigned I = 0; I < NumRanges; ++I) {
16825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    Min = __sanitizer::Min(Ranges[I].getStart().getMemoryLocation(), Min);
16925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    Max = __sanitizer::Max(Ranges[I].getEnd().getMemoryLocation(), Max);
17025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  }
17125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
17225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  // If we have too many interesting bytes, prefer to show bytes after Loc.
17325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  if (Max - Min > BytesToShow)
17425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    Min = __sanitizer::Min(Max - BytesToShow, Loc - MinBytesNearLoc);
17525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  Max = Min + BytesToShow;
17625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
17725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  // Emit data.
17825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  for (uptr P = Min; P != Max; ++P) {
17925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    // FIXME: Check that the address is readable before printing it.
18025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    unsigned char C = *reinterpret_cast<const unsigned char*>(P);
18125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    Printf("%s%02x", (P % 8 == 0) ? "  " : " ", C);
18225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  }
1838f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov  Printf("\n");
18425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
18525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  // Emit highlights.
1868f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov  Printf(Decor.Green());
18725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  Range *InRange = upperBound(Min, Ranges, NumRanges);
18825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  for (uptr P = Min; P != Max; ++P) {
18925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    char Pad = ' ', Byte = ' ';
19025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    if (InRange && InRange->getEnd().getMemoryLocation() == P)
19125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      InRange = upperBound(P, Ranges, NumRanges);
19225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    if (!InRange && P > Loc)
19325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      break;
19425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    if (InRange && InRange->getStart().getMemoryLocation() < P)
19525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      Pad = '~';
19625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    if (InRange && InRange->getStart().getMemoryLocation() <= P)
19725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      Byte = '~';
19825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    char Buffer[] = { Pad, Pad, P == Loc ? '^' : Byte, Byte, 0 };
1998f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov    Printf((P % 8 == 0) ? Buffer : &Buffer[1]);
20025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  }
2018f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov  Printf("%s\n", Decor.Default());
20225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
20325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  // Go over the line again, and print names for the ranges.
20425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  InRange = 0;
20525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  unsigned Spaces = 0;
20625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  for (uptr P = Min; P != Max; ++P) {
20725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    if (!InRange || InRange->getEnd().getMemoryLocation() == P)
20825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      InRange = upperBound(P, Ranges, NumRanges);
20925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    if (!InRange)
21025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      break;
21125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
21225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    Spaces += (P % 8) == 0 ? 2 : 1;
21325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
21425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    if (InRange && InRange->getStart().getMemoryLocation() == P) {
21525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      while (Spaces--)
2168f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov        Printf(" ");
21725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      renderText(InRange->getText(), Args);
2188f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov      Printf("\n");
21925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      // FIXME: We only support naming one range for now!
22025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith      break;
22125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    }
22225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
22325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    Spaces += 2;
22425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  }
22525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
22625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  // FIXME: Print names for anything we can identify within the line:
22725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  //
22825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  //  * If we can identify the memory itself as belonging to a particular
22925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  //    global, stack variable, or dynamic allocation, then do so.
23025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  //
23125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  //  * If we have a pointer-size, pointer-aligned range highlighted,
23225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  //    determine whether the value of that range is a pointer to an
23325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  //    entity which we can name, and if so, print that name.
23425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  //
23525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  // This needs an external symbolizer, or (preferably) ASan instrumentation.
23625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith}
23725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
23825ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard SmithDiag::~Diag() {
2398f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov  __sanitizer::AnsiColorDecorator Decor(PrintsToTty());
2407ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov  SpinMutexLock l(&CommonSanitizerReportMutex);
2418f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov  Printf(Decor.Bold());
24225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
24325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  renderLocation(Loc);
24425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
24525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  switch (Level) {
24625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  case DL_Error:
2478f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov    Printf("%s runtime error: %s%s",
2488f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov           Decor.Red(), Decor.Default(), Decor.Bold());
24925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    break;
25025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
25125ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  case DL_Note:
2528f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov    Printf("%s note: %s", Decor.Black(), Decor.Default());
25325ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith    break;
25425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  }
25525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
25625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  renderText(Message, Args);
25725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
2588f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov  Printf("%s\n", Decor.Default());
25925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith
26025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith  if (Loc.isMemoryLocation())
2618f72f7cae84494d9bd0676b4a499e0f895460744Alexey Samsonov    renderMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges,
262c242446f7a7c6a0c1f1bf9ad403d6dac6f215f1cRichard Smith                        NumRanges, Args);
2636ebe45146a2d93eb010b9bb5ea34cb94c6900f83Richard Smith}
264