ubsan_diag.cc revision 5f1164955fb28a9bcb826abc195aa2119feb0f97
1//===-- 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" 15#include "sanitizer_common/sanitizer_common.h" 16#include "sanitizer_common/sanitizer_libc.h" 17#include "sanitizer_common/sanitizer_stacktrace.h" 18#include "sanitizer_common/sanitizer_symbolizer.h" 19#include <stdio.h> 20 21using namespace __ubsan; 22 23Location __ubsan::getCallerLocation(uptr CallerLoc) { 24 if (!CallerLoc) 25 return Location(); 26 27 // Adjust to find the call instruction. 28 // FIXME: This is not portable. 29 --CallerLoc; 30 31 AddressInfo Info; 32 if (!SymbolizeCode(CallerLoc, &Info, 1) || !Info.module || !*Info.module) 33 return Location(CallerLoc); 34 35 if (!Info.function) 36 return ModuleLocation(Info.module, Info.module_offset); 37 38 return SourceLocation(Info.file, Info.line, Info.column); 39} 40 41Diag &Diag::operator<<(const TypeDescriptor &V) { 42 return AddArg(V.getTypeName()); 43} 44 45Diag &Diag::operator<<(const Value &V) { 46 if (V.getType().isSignedIntegerTy()) 47 AddArg(V.getSIntValue()); 48 else if (V.getType().isUnsignedIntegerTy()) 49 AddArg(V.getUIntValue()); 50 else if (V.getType().isFloatTy()) 51 AddArg(V.getFloatValue()); 52 else 53 AddArg("<unknown>"); 54 return *this; 55} 56 57/// Hexadecimal printing for numbers too large for fprintf to handle directly. 58static void PrintHex(UIntMax Val) { 59#if HAVE_INT128_T 60 Printf("0x%08x%08x%08x%08x", 61 (unsigned int)(Val >> 96), 62 (unsigned int)(Val >> 64), 63 (unsigned int)(Val >> 32), 64 (unsigned int)(Val)); 65#else 66 UNREACHABLE("long long smaller than 64 bits?"); 67#endif 68} 69 70static void renderLocation(Location Loc) { 71 switch (Loc.getKind()) { 72 case Location::LK_Source: { 73 SourceLocation SLoc = Loc.getSourceLocation(); 74 if (SLoc.isInvalid()) 75 RawWrite("<unknown>:"); 76 else { 77 Printf("%s:%d:", SLoc.getFilename(), SLoc.getLine()); 78 if (SLoc.getColumn()) 79 Printf("%d:", SLoc.getColumn()); 80 } 81 break; 82 } 83 case Location::LK_Module: 84 Printf("%s:0x%zx:", Loc.getModuleLocation().getModuleName(), 85 Loc.getModuleLocation().getOffset()); 86 break; 87 case Location::LK_Memory: 88 Printf("0x%zx:", Loc.getMemoryLocation()); 89 break; 90 case Location::LK_Null: 91 RawWrite("<unknown>:"); 92 } 93} 94 95Diag::~Diag() { 96 bool UseAnsiColor = PrintsToTty(); 97 if (UseAnsiColor) 98 RawWrite("\033[1m"); 99 100 renderLocation(Loc); 101 102 if (UseAnsiColor) 103 RawWrite("\033[31m"); 104 105 RawWrite(" runtime error: "); 106 if (UseAnsiColor) 107 RawWrite("\033[0;1m"); 108 for (const char *Msg = Message; *Msg; ++Msg) { 109 if (*Msg != '%') { 110 char Buffer[64]; 111 unsigned I; 112 for (I = 0; Msg[I] && Msg[I] != '%' && I != 63; ++I) 113 Buffer[I] = Msg[I]; 114 Buffer[I] = '\0'; 115 RawWrite(Buffer); 116 Msg += I - 1; 117 } else { 118 const Arg &A = Args[*++Msg - '0']; 119 switch (A.Kind) { 120 case AK_String: 121 Printf("%s", A.String); 122 break; 123 case AK_SInt: 124 // 'long long' is guaranteed to be at least 64 bits wide. 125 if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX) 126 Printf("%lld", (long long)A.SInt); 127 else 128 PrintHex(A.SInt); 129 break; 130 case AK_UInt: 131 if (A.UInt <= UINT64_MAX) 132 Printf("%llu", (unsigned long long)A.UInt); 133 else 134 PrintHex(A.UInt); 135 break; 136 case AK_Float: { 137 // FIXME: Support floating-point formatting in sanitizer_common's 138 // printf, and stop using snprintf here. 139 char Buffer[32]; 140 snprintf(Buffer, sizeof(Buffer), "%Lg", (long double)A.Float); 141 Printf("%s", Buffer); 142 break; 143 } 144 case AK_Pointer: 145 Printf("0x%zx", (uptr)A.Pointer); 146 break; 147 } 148 } 149 } 150 RawWrite("\n"); 151 if (UseAnsiColor) 152 Printf("\033[0m"); 153} 154