1 //===-- sanitizer_common_libcdep.cc ---------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common.h"
15 #include "sanitizer_flags.h"
16 #include "sanitizer_stackdepot.h"
17 #include "sanitizer_stacktrace.h"
18 #include "sanitizer_symbolizer.h"
21 #include "sanitizer_posix.h"
24 namespace __sanitizer
{
26 bool ReportFile::SupportsColors() {
29 return SupportsColoredOutput(fd
);
32 bool ColorizeReports() {
33 // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
34 // printing on Windows.
35 if (SANITIZER_WINDOWS
)
38 const char *flag
= common_flags()->color
;
39 return internal_strcmp(flag
, "always") == 0 ||
40 (internal_strcmp(flag
, "auto") == 0 && report_file
.SupportsColors());
43 static void (*sandboxing_callback
)();
44 void SetSandboxingCallback(void (*f
)()) {
45 sandboxing_callback
= f
;
48 void ReportErrorSummary(const char *error_type
, StackTrace
*stack
) {
49 if (!common_flags()->print_summary
)
51 if (stack
->size
== 0) {
52 ReportErrorSummary(error_type
);
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
);
63 static void (*SoftRssLimitExceededCallback
)(bool exceeded
);
64 void SetSoftRssLimitExceededCallback(void (*Callback
)(bool exceeded
)) {
65 CHECK_EQ(SoftRssLimitExceededCallback
, nullptr);
66 SoftRssLimitExceededCallback
= Callback
;
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;
77 uptr current_rss_mb
= GetRSS() >> 20;
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
;
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",
90 stack_depot_stats
->n_uniq_ids
,
91 stack_depot_stats
->allocated
>> 20);
92 prev_reported_stack_depot_size
= stack_depot_stats
->allocated
;
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
);
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);
119 void MaybeStartBackgroudThread() {
120 #if SANITIZER_LINUX // Need to implement/test on other platforms.
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);
129 } // namespace __sanitizer
132 __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments
*args
) {
133 PrepareForSandboxing(args
);
134 if (sandboxing_callback
)
135 sandboxing_callback();