10c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne//===-- sanitizer_common_libcdep.cc ---------------------------------------===// 20c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// 30c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// The LLVM Compiler Infrastructure 40c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// 50c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// This file is distributed under the University of Illinois Open Source 60c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// License. See LICENSE.TXT for details. 70c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// 80c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne//===----------------------------------------------------------------------===// 90c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// 100c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// This file is shared between AddressSanitizer and ThreadSanitizer 110c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne// run-time libraries. 120c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne//===----------------------------------------------------------------------===// 130c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne 140c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne#include "sanitizer_common.h" 15799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_flags.h" 1786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_stackdepot.h" 186d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_stacktrace.h" 196d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_symbolizer.h" 200c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne 21259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar#if SANITIZER_POSIX 22259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar#include "sanitizer_posix.h" 23259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar#endif 24259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar 250c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbournenamespace __sanitizer { 260c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne 27259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainarbool ReportFile::SupportsColors() { 2886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SpinMutexLock l(mu); 2986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines ReopenIfNecessary(); 30259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar return SupportsColoredOutput(fd); 310c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne} 320c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne 3386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesbool ColorizeReports() { 34650c7d44b659ddfb4af471dc2ad79a727b7de939Sergey Matveev // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color 35650c7d44b659ddfb4af471dc2ad79a727b7de939Sergey Matveev // printing on Windows. 36650c7d44b659ddfb4af471dc2ad79a727b7de939Sergey Matveev if (SANITIZER_WINDOWS) 3786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines return false; 382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines const char *flag = common_flags()->color; 402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return internal_strcmp(flag, "always") == 0 || 41259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar (internal_strcmp(flag, "auto") == 0 && report_file.SupportsColors()); 422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void (*sandboxing_callback)(); 452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid SetSandboxingCallback(void (*f)()) { 462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sandboxing_callback = f; 472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 496d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesvoid ReportErrorSummary(const char *error_type, StackTrace *stack) { 50799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if !SANITIZER_GO 516d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (!common_flags()->print_summary) 526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return; 537c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar if (stack->size == 0) { 547c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ReportErrorSummary(error_type); 557c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar return; 566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 577c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // Currently, we include the first stack frame into the report summary. 587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar // Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc). 597c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]); 607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc); 617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar ReportErrorSummary(error_type, frame->info); 627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar frame->ClearAll(); 63799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void (*SoftRssLimitExceededCallback)(bool exceeded); 6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) { 6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines CHECK_EQ(SoftRssLimitExceededCallback, nullptr); 6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SoftRssLimitExceededCallback = Callback; 7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 7186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 7286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid BackgroundThread(void *arg) { 7386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr hard_rss_limit_mb = common_flags()->hard_rss_limit_mb; 7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr soft_rss_limit_mb = common_flags()->soft_rss_limit_mb; 7586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr prev_reported_rss = 0; 7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr prev_reported_stack_depot_size = 0; 7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines bool reached_soft_rss_limit = false; 7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines while (true) { 7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SleepForMillis(100); 8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines uptr current_rss_mb = GetRSS() >> 20; 8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (Verbosity()) { 8286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // If RSS has grown 10% since last time, print some information. 8386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (prev_reported_rss * 11 / 10 < current_rss_mb) { 8486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Printf("%s: RSS: %zdMb\n", SanitizerToolName, current_rss_mb); 8586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines prev_reported_rss = current_rss_mb; 8686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 8786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // If stack depot has grown 10% since last time, print it too. 8886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines StackDepotStats *stack_depot_stats = StackDepotGetStats(); 8986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (prev_reported_stack_depot_size * 11 / 10 < 9086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines stack_depot_stats->allocated) { 9186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Printf("%s: StackDepot: %zd ids; %zdM allocated\n", 9286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SanitizerToolName, 9386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines stack_depot_stats->n_uniq_ids, 9486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines stack_depot_stats->allocated >> 20); 9586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines prev_reported_stack_depot_size = stack_depot_stats->allocated; 9686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 9786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 9886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Check RSS against the limit. 9986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (hard_rss_limit_mb && hard_rss_limit_mb < current_rss_mb) { 10086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Report("%s: hard rss limit exhausted (%zdMb vs %zdMb)\n", 10186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SanitizerToolName, hard_rss_limit_mb, current_rss_mb); 10286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines DumpProcessMap(); 10386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Die(); 10486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 10586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (soft_rss_limit_mb) { 10686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (soft_rss_limit_mb < current_rss_mb && !reached_soft_rss_limit) { 10786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines reached_soft_rss_limit = true; 10886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines Report("%s: soft rss limit exhausted (%zdMb vs %zdMb)\n", 10986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SanitizerToolName, soft_rss_limit_mb, current_rss_mb); 11086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (SoftRssLimitExceededCallback) 11186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SoftRssLimitExceededCallback(true); 11286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } else if (soft_rss_limit_mb >= current_rss_mb && 11386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines reached_soft_rss_limit) { 11486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines reached_soft_rss_limit = false; 11586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (SoftRssLimitExceededCallback) 11686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines SoftRssLimitExceededCallback(false); 11786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 11886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 11986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines } 12086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 12186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 122799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid WriteToSyslog(const char *msg) { 123799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar InternalScopedString msg_copy(kErrorMessageBufferSize); 124799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar msg_copy.append("%s", msg); 125799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *p = msg_copy.data(); 126799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar char *q; 127799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 128799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Print one line at a time. 129799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // syslog, at least on Android, has an implicit message length limit. 130799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar do { 131799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar q = internal_strchr(p, '\n'); 132799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (q) 133799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar *q = '\0'; 134799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar WriteOneLineToSyslog(p); 135799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (q) 136799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar p = q + 1; 137799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } while (q); 138799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 139799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 14086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid MaybeStartBackgroudThread() { 141799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_LINUX && \ 142799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar !SANITIZER_GO // Need to implement/test on other platforms. 14386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines // Start the background thread if one of the rss limits is given. 14486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!common_flags()->hard_rss_limit_mb && 14586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines !common_flags()->soft_rss_limit_mb) return; 14686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (!&real_pthread_create) return; // Can't spawn the thread anyway. 14786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines internal_start_thread(BackgroundThread, nullptr); 148259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar#endif 1496d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 1506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 1510c547de62dc0852a03fae2d868fa571e7f5512b3Peter Collingbourne} // namespace __sanitizer 1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid NOINLINE 1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines__sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args) { 1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines PrepareForSandboxing(args); 1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (sandboxing_callback) 1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines sandboxing_callback(); 1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 159