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