blob: 1b65bced75d5a84626789b9e39d2066ab7766df6 [file] [log] [blame]
Peter Collingbourne0c547de2013-05-17 16:17:19 +00001//===-- sanitizer_common_libcdep.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 shared between AddressSanitizer and ThreadSanitizer
11// run-time libraries.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common.h"
Stephen Hines2d1fdb22014-05-28 23:58:16 -070015#include "sanitizer_flags.h"
Stephen Hines86277eb2015-03-23 12:06:32 -070016#include "sanitizer_stackdepot.h"
Stephen Hines6d186232014-11-26 17:56:19 -080017#include "sanitizer_stacktrace.h"
18#include "sanitizer_symbolizer.h"
Peter Collingbourne0c547de2013-05-17 16:17:19 +000019
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070020#if SANITIZER_POSIX
21#include "sanitizer_posix.h"
22#endif
23
Peter Collingbourne0c547de2013-05-17 16:17:19 +000024namespace __sanitizer {
25
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070026bool ReportFile::SupportsColors() {
Stephen Hines86277eb2015-03-23 12:06:32 -070027 SpinMutexLock l(mu);
28 ReopenIfNecessary();
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070029 return SupportsColoredOutput(fd);
Sergey Matveev650c7d42013-09-03 13:31:03 +000030}
Stephen Hines2d1fdb22014-05-28 23:58:16 -070031
32bool ColorizeReports() {
Stephen Hines86277eb2015-03-23 12:06:32 -070033 // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
34 // printing on Windows.
35 if (SANITIZER_WINDOWS)
36 return false;
37
Stephen Hines2d1fdb22014-05-28 23:58:16 -070038 const char *flag = common_flags()->color;
39 return internal_strcmp(flag, "always") == 0 ||
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070040 (internal_strcmp(flag, "auto") == 0 && report_file.SupportsColors());
Stephen Hines2d1fdb22014-05-28 23:58:16 -070041}
42
43static void (*sandboxing_callback)();
44void SetSandboxingCallback(void (*f)()) {
45 sandboxing_callback = f;
46}
47
Stephen Hines6d186232014-11-26 17:56:19 -080048void ReportErrorSummary(const char *error_type, StackTrace *stack) {
49 if (!common_flags()->print_summary)
50 return;
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070051 if (stack->size == 0) {
52 ReportErrorSummary(error_type);
53 return;
Stephen Hines6d186232014-11-26 17:56:19 -080054 }
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070055 // Currently, we include the first stack frame into the report summary.
56 // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
57 uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
58 SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
59 ReportErrorSummary(error_type, frame->info);
60 frame->ClearAll();
Stephen Hines86277eb2015-03-23 12:06:32 -070061}
62
63static void (*SoftRssLimitExceededCallback)(bool exceeded);
64void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) {
65 CHECK_EQ(SoftRssLimitExceededCallback, nullptr);
66 SoftRssLimitExceededCallback = Callback;
67}
68
69void BackgroundThread(void *arg) {
70 uptr hard_rss_limit_mb = common_flags()->hard_rss_limit_mb;
71 uptr soft_rss_limit_mb = common_flags()->soft_rss_limit_mb;
72 uptr prev_reported_rss = 0;
73 uptr prev_reported_stack_depot_size = 0;
74 bool reached_soft_rss_limit = false;
75 while (true) {
76 SleepForMillis(100);
77 uptr current_rss_mb = GetRSS() >> 20;
78 if (Verbosity()) {
79 // If RSS has grown 10% since last time, print some information.
80 if (prev_reported_rss * 11 / 10 < current_rss_mb) {
81 Printf("%s: RSS: %zdMb\n", SanitizerToolName, current_rss_mb);
82 prev_reported_rss = current_rss_mb;
83 }
84 // If stack depot has grown 10% since last time, print it too.
85 StackDepotStats *stack_depot_stats = StackDepotGetStats();
86 if (prev_reported_stack_depot_size * 11 / 10 <
87 stack_depot_stats->allocated) {
88 Printf("%s: StackDepot: %zd ids; %zdM allocated\n",
89 SanitizerToolName,
90 stack_depot_stats->n_uniq_ids,
91 stack_depot_stats->allocated >> 20);
92 prev_reported_stack_depot_size = stack_depot_stats->allocated;
93 }
94 }
95 // Check RSS against the limit.
96 if (hard_rss_limit_mb && hard_rss_limit_mb < current_rss_mb) {
97 Report("%s: hard rss limit exhausted (%zdMb vs %zdMb)\n",
98 SanitizerToolName, hard_rss_limit_mb, current_rss_mb);
99 DumpProcessMap();
100 Die();
101 }
102 if (soft_rss_limit_mb) {
103 if (soft_rss_limit_mb < current_rss_mb && !reached_soft_rss_limit) {
104 reached_soft_rss_limit = true;
105 Report("%s: soft rss limit exhausted (%zdMb vs %zdMb)\n",
106 SanitizerToolName, soft_rss_limit_mb, current_rss_mb);
107 if (SoftRssLimitExceededCallback)
108 SoftRssLimitExceededCallback(true);
109 } else if (soft_rss_limit_mb >= current_rss_mb &&
110 reached_soft_rss_limit) {
111 reached_soft_rss_limit = false;
112 if (SoftRssLimitExceededCallback)
113 SoftRssLimitExceededCallback(false);
114 }
115 }
116 }
117}
118
119void MaybeStartBackgroudThread() {
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700120#if SANITIZER_LINUX // Need to implement/test on other platforms.
Stephen Hines86277eb2015-03-23 12:06:32 -0700121 // Start the background thread if one of the rss limits is given.
122 if (!common_flags()->hard_rss_limit_mb &&
123 !common_flags()->soft_rss_limit_mb) return;
124 if (!&real_pthread_create) return; // Can't spawn the thread anyway.
125 internal_start_thread(BackgroundThread, nullptr);
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700126#endif
Stephen Hines6d186232014-11-26 17:56:19 -0800127}
128
Peter Collingbourne0c547de2013-05-17 16:17:19 +0000129} // namespace __sanitizer
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700130
131void NOINLINE
132__sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args) {
133 PrepareForSandboxing(args);
134 if (sandboxing_callback)
135 sandboxing_callback();
136}