1 //===-- sanitizer_common_libcdep.cc ---------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_common.h"
13 #include "sanitizer_flags.h"
14 #include "sanitizer_stackdepot.h"
15 #include "sanitizer_stacktrace.h"
16 #include "sanitizer_symbolizer.h"
19 #include "sanitizer_posix.h"
22 namespace __sanitizer
{
24 bool ReportFile::SupportsColors() {
27 return SupportsColoredOutput(fd
);
30 bool ColorizeReports() {
31 // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
32 // printing on Windows.
33 if (SANITIZER_WINDOWS
)
36 const char *flag
= common_flags()->color
;
37 return internal_strcmp(flag
, "always") == 0 ||
38 (internal_strcmp(flag
, "auto") == 0 && report_file
.SupportsColors());
41 static void (*sandboxing_callback
)();
42 void SetSandboxingCallback(void (*f
)()) {
43 sandboxing_callback
= f
;
46 void ReportErrorSummary(const char *error_type
, StackTrace
*stack
) {
47 if (!common_flags()->print_summary
)
49 if (stack
->size
== 0) {
50 ReportErrorSummary(error_type
);
53 // Currently, we include the first stack frame into the report summary.
54 // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
55 uptr pc
= StackTrace::GetPreviousInstructionPc(stack
->trace
[0]);
56 SymbolizedStack
*frame
= Symbolizer::GetOrInit()->SymbolizePC(pc
);
57 ReportErrorSummary(error_type
, frame
->info
);
61 static void (*SoftRssLimitExceededCallback
)(bool exceeded
);
62 void SetSoftRssLimitExceededCallback(void (*Callback
)(bool exceeded
)) {
63 CHECK_EQ(SoftRssLimitExceededCallback
, nullptr);
64 SoftRssLimitExceededCallback
= Callback
;
67 void BackgroundThread(void *arg
) {
68 uptr hard_rss_limit_mb
= common_flags()->hard_rss_limit_mb
;
69 uptr soft_rss_limit_mb
= common_flags()->soft_rss_limit_mb
;
70 uptr prev_reported_rss
= 0;
71 uptr prev_reported_stack_depot_size
= 0;
72 bool reached_soft_rss_limit
= false;
75 uptr current_rss_mb
= GetRSS() >> 20;
77 // If RSS has grown 10% since last time, print some information.
78 if (prev_reported_rss
* 11 / 10 < current_rss_mb
) {
79 Printf("%s: RSS: %zdMb\n", SanitizerToolName
, current_rss_mb
);
80 prev_reported_rss
= current_rss_mb
;
82 // If stack depot has grown 10% since last time, print it too.
83 StackDepotStats
*stack_depot_stats
= StackDepotGetStats();
84 if (prev_reported_stack_depot_size
* 11 / 10 <
85 stack_depot_stats
->allocated
) {
86 Printf("%s: StackDepot: %zd ids; %zdM allocated\n",
88 stack_depot_stats
->n_uniq_ids
,
89 stack_depot_stats
->allocated
>> 20);
90 prev_reported_stack_depot_size
= stack_depot_stats
->allocated
;
93 // Check RSS against the limit.
94 if (hard_rss_limit_mb
&& hard_rss_limit_mb
< current_rss_mb
) {
95 Report("%s: hard rss limit exhausted (%zdMb vs %zdMb)\n",
96 SanitizerToolName
, hard_rss_limit_mb
, current_rss_mb
);
100 if (soft_rss_limit_mb
) {
101 if (soft_rss_limit_mb
< current_rss_mb
&& !reached_soft_rss_limit
) {
102 reached_soft_rss_limit
= true;
103 Report("%s: soft rss limit exhausted (%zdMb vs %zdMb)\n",
104 SanitizerToolName
, soft_rss_limit_mb
, current_rss_mb
);
105 if (SoftRssLimitExceededCallback
)
106 SoftRssLimitExceededCallback(true);
107 } else if (soft_rss_limit_mb
>= current_rss_mb
&&
108 reached_soft_rss_limit
) {
109 reached_soft_rss_limit
= false;
110 if (SoftRssLimitExceededCallback
)
111 SoftRssLimitExceededCallback(false);
117 void MaybeStartBackgroudThread() {
118 #if SANITIZER_LINUX // Need to implement/test on other platforms.
119 // Start the background thread if one of the rss limits is given.
120 if (!common_flags()->hard_rss_limit_mb
&&
121 !common_flags()->soft_rss_limit_mb
) return;
122 if (!&real_pthread_create
) return; // Can't spawn the thread anyway.
123 internal_start_thread(BackgroundThread
, nullptr);
127 } // namespace __sanitizer
130 __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments
*args
) {
131 PrepareForSandboxing(args
);
132 if (sandboxing_callback
)
133 sandboxing_callback();