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