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" 15 16 #include "sanitizer_flags.h" 17 #include "sanitizer_stackdepot.h" 18 #include "sanitizer_stacktrace.h" 19 #include "sanitizer_symbolizer.h" 20 21 #if SANITIZER_POSIX 22 #include "sanitizer_posix.h" 23 #endif 24 25 namespace __sanitizer { 26 27 bool ReportFile::SupportsColors() { 28 SpinMutexLock l(mu); 29 ReopenIfNecessary(); 30 return SupportsColoredOutput(fd); 31 } 32 33 bool ColorizeReports() { 34 // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color 35 // printing on Windows. 36 if (SANITIZER_WINDOWS) 37 return false; 38 39 const char *flag = common_flags()->color; 40 return internal_strcmp(flag, "always") == 0 || 41 (internal_strcmp(flag, "auto") == 0 && report_file.SupportsColors()); 42 } 43 44 static void (*sandboxing_callback)(); 45 void SetSandboxingCallback(void (*f)()) { 46 sandboxing_callback = f; 47 } 48 49 void ReportErrorSummary(const char *error_type, StackTrace *stack) { 50 #if !SANITIZER_GO 51 if (!common_flags()->print_summary) 52 return; 53 if (stack->size == 0) { 54 ReportErrorSummary(error_type); 55 return; 56 } 57 // Currently, we include the first stack frame into the report summary. 58 // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc). 59 uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]); 60 SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); 61 ReportErrorSummary(error_type, frame->info); 62 frame->ClearAll(); 63 #endif 64 } 65 66 static void (*SoftRssLimitExceededCallback)(bool exceeded); 67 void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) { 68 CHECK_EQ(SoftRssLimitExceededCallback, nullptr); 69 SoftRssLimitExceededCallback = Callback; 70 } 71 72 void BackgroundThread(void *arg) { 73 uptr hard_rss_limit_mb = common_flags()->hard_rss_limit_mb; 74 uptr soft_rss_limit_mb = common_flags()->soft_rss_limit_mb; 75 uptr prev_reported_rss = 0; 76 uptr prev_reported_stack_depot_size = 0; 77 bool reached_soft_rss_limit = false; 78 while (true) { 79 SleepForMillis(100); 80 uptr current_rss_mb = GetRSS() >> 20; 81 if (Verbosity()) { 82 // If RSS has grown 10% since last time, print some information. 83 if (prev_reported_rss * 11 / 10 < current_rss_mb) { 84 Printf("%s: RSS: %zdMb\n", SanitizerToolName, current_rss_mb); 85 prev_reported_rss = current_rss_mb; 86 } 87 // If stack depot has grown 10% since last time, print it too. 88 StackDepotStats *stack_depot_stats = StackDepotGetStats(); 89 if (prev_reported_stack_depot_size * 11 / 10 < 90 stack_depot_stats->allocated) { 91 Printf("%s: StackDepot: %zd ids; %zdM allocated\n", 92 SanitizerToolName, 93 stack_depot_stats->n_uniq_ids, 94 stack_depot_stats->allocated >> 20); 95 prev_reported_stack_depot_size = stack_depot_stats->allocated; 96 } 97 } 98 // Check RSS against the limit. 99 if (hard_rss_limit_mb && hard_rss_limit_mb < current_rss_mb) { 100 Report("%s: hard rss limit exhausted (%zdMb vs %zdMb)\n", 101 SanitizerToolName, hard_rss_limit_mb, current_rss_mb); 102 DumpProcessMap(); 103 Die(); 104 } 105 if (soft_rss_limit_mb) { 106 if (soft_rss_limit_mb < current_rss_mb && !reached_soft_rss_limit) { 107 reached_soft_rss_limit = true; 108 Report("%s: soft rss limit exhausted (%zdMb vs %zdMb)\n", 109 SanitizerToolName, soft_rss_limit_mb, current_rss_mb); 110 if (SoftRssLimitExceededCallback) 111 SoftRssLimitExceededCallback(true); 112 } else if (soft_rss_limit_mb >= current_rss_mb && 113 reached_soft_rss_limit) { 114 reached_soft_rss_limit = false; 115 if (SoftRssLimitExceededCallback) 116 SoftRssLimitExceededCallback(false); 117 } 118 } 119 } 120 } 121 122 void WriteToSyslog(const char *msg) { 123 InternalScopedString msg_copy(kErrorMessageBufferSize); 124 msg_copy.append("%s", msg); 125 char *p = msg_copy.data(); 126 char *q; 127 128 // Remove color sequences since syslogs cannot print them. 129 RemoveANSIEscapeSequencesFromString(p); 130 131 // Print one line at a time. 132 // syslog, at least on Android, has an implicit message length limit. 133 do { 134 q = internal_strchr(p, '\n'); 135 if (q) 136 *q = '\0'; 137 WriteOneLineToSyslog(p); 138 if (q) 139 p = q + 1; 140 } while (q); 141 } 142 143 void MaybeStartBackgroudThread() { 144 #if SANITIZER_LINUX && \ 145 !SANITIZER_GO // Need to implement/test on other platforms. 146 // Start the background thread if one of the rss limits is given. 147 if (!common_flags()->hard_rss_limit_mb && 148 !common_flags()->soft_rss_limit_mb) return; 149 if (!&real_pthread_create) return; // Can't spawn the thread anyway. 150 internal_start_thread(BackgroundThread, nullptr); 151 #endif 152 } 153 154 } // namespace __sanitizer 155 156 void NOINLINE 157 __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args) { 158 PrepareForSandboxing(args); 159 if (sandboxing_callback) 160 sandboxing_callback(); 161 } 162