Peter Collingbourne | 0c547de | 2013-05-17 16:17:19 +0000 | [diff] [blame] | 1 | //===-- 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 Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 15 | #include "sanitizer_flags.h" |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 16 | #include "sanitizer_stackdepot.h" |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 17 | #include "sanitizer_stacktrace.h" |
| 18 | #include "sanitizer_symbolizer.h" |
Peter Collingbourne | 0c547de | 2013-05-17 16:17:19 +0000 | [diff] [blame] | 19 | |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 20 | #if SANITIZER_POSIX |
| 21 | #include "sanitizer_posix.h" |
| 22 | #endif |
| 23 | |
Peter Collingbourne | 0c547de | 2013-05-17 16:17:19 +0000 | [diff] [blame] | 24 | namespace __sanitizer { |
| 25 | |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 26 | bool ReportFile::SupportsColors() { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 27 | SpinMutexLock l(mu); |
| 28 | ReopenIfNecessary(); |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 29 | return SupportsColoredOutput(fd); |
Sergey Matveev | 650c7d4 | 2013-09-03 13:31:03 +0000 | [diff] [blame] | 30 | } |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 31 | |
| 32 | bool ColorizeReports() { |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 33 | // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color |
| 34 | // printing on Windows. |
| 35 | if (SANITIZER_WINDOWS) |
| 36 | return false; |
| 37 | |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 38 | const char *flag = common_flags()->color; |
| 39 | return internal_strcmp(flag, "always") == 0 || |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 40 | (internal_strcmp(flag, "auto") == 0 && report_file.SupportsColors()); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | static void (*sandboxing_callback)(); |
| 44 | void SetSandboxingCallback(void (*f)()) { |
| 45 | sandboxing_callback = f; |
| 46 | } |
| 47 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 48 | void ReportErrorSummary(const char *error_type, StackTrace *stack) { |
| 49 | if (!common_flags()->print_summary) |
| 50 | return; |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 51 | if (stack->size == 0) { |
| 52 | ReportErrorSummary(error_type); |
| 53 | return; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 54 | } |
Pirama Arumuga Nainar | 7c91505 | 2015-04-08 08:58:29 -0700 | [diff] [blame] | 55 | // 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 Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | static void (*SoftRssLimitExceededCallback)(bool exceeded); |
| 64 | void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) { |
| 65 | CHECK_EQ(SoftRssLimitExceededCallback, nullptr); |
| 66 | SoftRssLimitExceededCallback = Callback; |
| 67 | } |
| 68 | |
| 69 | void 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 | |
| 119 | void MaybeStartBackgroudThread() { |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 120 | #if SANITIZER_LINUX // Need to implement/test on other platforms. |
Stephen Hines | 86277eb | 2015-03-23 12:06:32 -0700 | [diff] [blame] | 121 | // 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 Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 126 | #endif |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 127 | } |
| 128 | |
Peter Collingbourne | 0c547de | 2013-05-17 16:17:19 +0000 | [diff] [blame] | 129 | } // namespace __sanitizer |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 130 | |
| 131 | void NOINLINE |
| 132 | __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args) { |
| 133 | PrepareForSandboxing(args); |
| 134 | if (sandboxing_callback) |
| 135 | sandboxing_callback(); |
| 136 | } |