Home | History | Annotate | Download | only in msan
      1 //===-- msan_report.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 // This file is a part of MemorySanitizer.
     11 //
     12 // Error reporting.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "msan.h"
     16 #include "sanitizer_common/sanitizer_common.h"
     17 #include "sanitizer_common/sanitizer_mutex.h"
     18 #include "sanitizer_common/sanitizer_report_decorator.h"
     19 #include "sanitizer_common/sanitizer_stackdepot.h"
     20 #include "sanitizer_common/sanitizer_symbolizer.h"
     21 
     22 using namespace __sanitizer;
     23 
     24 static StaticSpinMutex report_mu;
     25 
     26 namespace __msan {
     27 
     28 static bool PrintsToTtyCached() {
     29   static int cached = 0;
     30   static bool prints_to_tty;
     31   if (!cached) {  // Ok wrt threads since we are printing only from one thread.
     32     prints_to_tty = PrintsToTty();
     33     cached = 1;
     34   }
     35   return prints_to_tty;
     36 }
     37 
     38 class Decorator: private __sanitizer::AnsiColorDecorator {
     39  public:
     40   Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
     41   const char *Warning()    { return Red(); }
     42   const char *Origin()     { return Magenta(); }
     43   const char *Name()   { return Green(); }
     44   const char *End()    { return Default(); }
     45 };
     46 
     47 static void PrintStack(const uptr *trace, uptr size) {
     48   SymbolizerScope sym_scope;
     49   StackTrace::PrintStack(trace, size, true, flags()->strip_path_prefix, 0);
     50 }
     51 
     52 static void DescribeOrigin(u32 origin) {
     53   Decorator d;
     54   if (flags()->verbosity)
     55     Printf("  raw origin id: %d\n", origin);
     56   if (const char *so = __msan_get_origin_descr_if_stack(origin)) {
     57     char* s = internal_strdup(so);
     58     char* sep = internal_strchr(s, '@');
     59     CHECK(sep);
     60     *sep = '\0';
     61     Printf("%s", d.Origin());
     62     Printf("  %sUninitialized value was created by an allocation of '%s%s%s'"
     63            " in the stack frame of function '%s%s%s'%s\n",
     64            d.Origin(), d.Name(), s, d.Origin(), d.Name(), sep + 1,
     65            d.Origin(), d.End());
     66     InternalFree(s);
     67   } else {
     68     uptr size = 0;
     69     const uptr *trace = StackDepotGet(origin, &size);
     70     Printf("  %sUninitialized value was created by a heap allocation%s\n",
     71            d.Origin(), d.End());
     72     PrintStack(trace, size);
     73   }
     74 }
     75 
     76 static void ReportSummary(const char *error_type, StackTrace *stack) {
     77   if (!stack->size || !IsSymbolizerAvailable()) return;
     78   AddressInfo ai;
     79   uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
     80   {
     81     SymbolizerScope sym_scope;
     82     SymbolizeCode(pc, &ai, 1);
     83   }
     84   ReportErrorSummary(error_type,
     85                      StripPathPrefix(ai.file, flags()->strip_path_prefix),
     86                      ai.line, ai.function);
     87 }
     88 
     89 void ReportUMR(StackTrace *stack, u32 origin) {
     90   if (!__msan::flags()->report_umrs) return;
     91 
     92   GenericScopedLock<StaticSpinMutex> lock(&report_mu);
     93 
     94   Decorator d;
     95   Printf("%s", d.Warning());
     96   Report(" WARNING: Use of uninitialized value\n");
     97   Printf("%s", d.End());
     98   PrintStack(stack->trace, stack->size);
     99   if (origin) {
    100     DescribeOrigin(origin);
    101   }
    102   ReportSummary("use-of-uninitialized-value", stack);
    103 }
    104 
    105 void ReportExpectedUMRNotFound(StackTrace *stack) {
    106   GenericScopedLock<StaticSpinMutex> lock(&report_mu);
    107 
    108   Printf(" WARNING: Expected use of uninitialized value not found\n");
    109   PrintStack(stack->trace, stack->size);
    110 }
    111 
    112 void ReportAtExitStatistics() {
    113   Decorator d;
    114   Printf("%s", d.Warning());
    115   Printf("MemorySanitizer: %d warnings reported.\n", msan_report_count);
    116   Printf("%s", d.End());
    117 }
    118 
    119 
    120 }  // namespace __msan
    121