2012-08-09 15:40:58 +08:00
|
|
|
//===-- asan_report.cc ----------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is a part of AddressSanitizer, an address sanity checker.
|
|
|
|
//
|
|
|
|
// This file contains error reporting code.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2015-10-01 08:22:21 +08:00
|
|
|
|
2016-08-31 01:08:55 +08:00
|
|
|
#include "asan_errors.h"
|
2012-08-10 23:13:05 +08:00
|
|
|
#include "asan_flags.h"
|
2016-08-16 03:30:21 +08:00
|
|
|
#include "asan_descriptions.h"
|
2012-08-09 15:40:58 +08:00
|
|
|
#include "asan_internal.h"
|
2012-08-09 17:06:52 +08:00
|
|
|
#include "asan_mapping.h"
|
2012-08-09 15:40:58 +08:00
|
|
|
#include "asan_report.h"
|
2016-02-09 03:21:08 +08:00
|
|
|
#include "asan_scariness_score.h"
|
2012-08-09 15:40:58 +08:00
|
|
|
#include "asan_stack.h"
|
2012-08-09 17:27:24 +08:00
|
|
|
#include "asan_thread.h"
|
2012-12-18 15:32:16 +08:00
|
|
|
#include "sanitizer_common/sanitizer_common.h"
|
2013-05-06 19:27:58 +08:00
|
|
|
#include "sanitizer_common/sanitizer_flags.h"
|
2012-12-18 15:32:16 +08:00
|
|
|
#include "sanitizer_common/sanitizer_report_decorator.h"
|
2013-10-18 22:50:44 +08:00
|
|
|
#include "sanitizer_common/sanitizer_stackdepot.h"
|
2012-12-26 22:44:46 +08:00
|
|
|
#include "sanitizer_common/sanitizer_symbolizer.h"
|
2012-08-09 15:40:58 +08:00
|
|
|
|
|
|
|
namespace __asan {
|
|
|
|
|
2012-08-13 19:23:40 +08:00
|
|
|
// -------------------- User-specified callbacks ----------------- {{{1
|
2012-08-09 18:56:57 +08:00
|
|
|
static void (*error_report_callback)(const char*);
|
2015-10-01 08:22:21 +08:00
|
|
|
static char *error_message_buffer = nullptr;
|
2012-08-09 18:56:57 +08:00
|
|
|
static uptr error_message_buffer_pos = 0;
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
static BlockingMutex error_message_buf_mutex(LINKER_INITIALIZED);
|
2015-12-10 16:08:53 +08:00
|
|
|
static const unsigned kAsanBuggyPcPoolSize = 25;
|
2015-12-10 19:07:19 +08:00
|
|
|
static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
|
2012-08-09 18:56:57 +08:00
|
|
|
|
|
|
|
void AppendToErrorMessageBuffer(const char *buffer) {
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
BlockingMutexLock l(&error_message_buf_mutex);
|
|
|
|
if (!error_message_buffer) {
|
|
|
|
error_message_buffer =
|
2015-11-21 02:42:01 +08:00
|
|
|
(char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
error_message_buffer_pos = 0;
|
2012-08-09 18:56:57 +08:00
|
|
|
}
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
uptr length = internal_strlen(buffer);
|
2015-11-21 02:42:01 +08:00
|
|
|
RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos);
|
|
|
|
uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos;
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
internal_strncpy(error_message_buffer + error_message_buffer_pos,
|
|
|
|
buffer, remaining);
|
2015-11-21 02:42:01 +08:00
|
|
|
error_message_buffer[kErrorMessageBufferSize - 1] = '\0';
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
// FIXME: reallocate the buffer instead of truncating the message.
|
|
|
|
error_message_buffer_pos += Min(remaining, length);
|
2012-08-09 18:56:57 +08:00
|
|
|
}
|
|
|
|
|
2012-08-10 23:13:05 +08:00
|
|
|
// ---------------------- Helper functions ----------------------- {{{1
|
|
|
|
|
2016-09-08 20:58:15 +08:00
|
|
|
void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
|
|
|
|
bool in_shadow, const char *after) {
|
2012-12-19 17:53:32 +08:00
|
|
|
Decorator d;
|
2014-09-22 19:58:52 +08:00
|
|
|
str->append("%s%s%x%x%s%s", before,
|
|
|
|
in_shadow ? d.ShadowByte(byte) : d.MemoryByte(),
|
|
|
|
byte >> 4, byte & 15,
|
|
|
|
in_shadow ? d.EndShadowByte() : d.EndMemoryByte(), after);
|
|
|
|
}
|
|
|
|
|
2012-08-10 23:13:05 +08:00
|
|
|
static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
|
|
|
|
const char *zone_name) {
|
|
|
|
if (zone_ptr) {
|
|
|
|
if (zone_name) {
|
2012-08-28 19:34:40 +08:00
|
|
|
Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
|
2012-08-10 23:13:05 +08:00
|
|
|
ptr, zone_ptr, zone_name);
|
|
|
|
} else {
|
2012-08-28 19:34:40 +08:00
|
|
|
Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
|
2012-08-10 23:13:05 +08:00
|
|
|
ptr, zone_ptr);
|
|
|
|
}
|
|
|
|
} else {
|
2012-08-28 19:34:40 +08:00
|
|
|
Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
|
2012-08-10 23:13:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-09 17:06:52 +08:00
|
|
|
// ---------------------- Address Descriptions ------------------- {{{1
|
|
|
|
|
2014-07-17 08:18:03 +08:00
|
|
|
bool ParseFrameDescription(const char *frame_descr,
|
|
|
|
InternalMmapVector<StackVarDescr> *vars) {
|
2014-10-02 05:13:00 +08:00
|
|
|
CHECK(frame_descr);
|
2014-07-17 08:18:03 +08:00
|
|
|
char *p;
|
2014-10-02 05:13:00 +08:00
|
|
|
// This string is created by the compiler and has the following form:
|
|
|
|
// "n alloc_1 alloc_2 ... alloc_n"
|
2017-03-30 08:41:09 +08:00
|
|
|
// where alloc_i looks like "offset size len ObjectName"
|
|
|
|
// or "offset size len ObjectName:line".
|
2014-07-17 08:18:03 +08:00
|
|
|
uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
|
2014-10-02 05:13:00 +08:00
|
|
|
if (n_objects == 0)
|
|
|
|
return false;
|
2014-07-17 08:18:03 +08:00
|
|
|
|
|
|
|
for (uptr i = 0; i < n_objects; i++) {
|
|
|
|
uptr beg = (uptr)internal_simple_strtoll(p, &p, 10);
|
|
|
|
uptr size = (uptr)internal_simple_strtoll(p, &p, 10);
|
|
|
|
uptr len = (uptr)internal_simple_strtoll(p, &p, 10);
|
|
|
|
if (beg == 0 || size == 0 || *p != ' ') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
p++;
|
2017-03-30 08:41:09 +08:00
|
|
|
char *colon_pos = internal_strchr(p, ':');
|
|
|
|
uptr line = 0;
|
|
|
|
uptr name_len = len;
|
|
|
|
if (colon_pos != nullptr && colon_pos < p + len) {
|
|
|
|
name_len = colon_pos - p;
|
|
|
|
line = (uptr)internal_simple_strtoll(colon_pos + 1, nullptr, 10);
|
|
|
|
}
|
|
|
|
StackVarDescr var = {beg, size, p, name_len, line};
|
2014-07-17 08:18:03 +08:00
|
|
|
vars->push_back(var);
|
|
|
|
p += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2013-09-03 21:58:04 +08:00
|
|
|
|
2012-08-09 17:06:52 +08:00
|
|
|
// -------------------- Different kinds of reports ----------------- {{{1
|
|
|
|
|
2012-08-10 23:13:05 +08:00
|
|
|
// Use ScopedInErrorReport to run common actions just before and
|
|
|
|
// immediately after printing error report.
|
|
|
|
class ScopedInErrorReport {
|
|
|
|
public:
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
explicit ScopedInErrorReport(bool fatal = false) {
|
2015-11-11 19:59:38 +08:00
|
|
|
halt_on_error_ = fatal || flags()->halt_on_error;
|
|
|
|
|
|
|
|
if (lock_.TryLock()) {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
StartReporting();
|
2015-11-11 19:59:38 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ASan found two bugs in different threads simultaneously.
|
|
|
|
|
|
|
|
u32 current_tid = GetCurrentTidOrInvalid();
|
2015-11-13 17:46:12 +08:00
|
|
|
if (reporting_thread_tid_ == current_tid ||
|
|
|
|
reporting_thread_tid_ == kInvalidTid) {
|
2015-11-11 19:59:38 +08:00
|
|
|
// This is either asynch signal or nested error during error reporting.
|
2015-11-13 17:46:12 +08:00
|
|
|
// Fail simple to avoid deadlocks in Report().
|
2015-11-11 19:59:38 +08:00
|
|
|
|
|
|
|
// Can't use Report() here because of potential deadlocks
|
|
|
|
// in nested signal handlers.
|
|
|
|
const char msg[] = "AddressSanitizer: nested bug in the same thread, "
|
|
|
|
"aborting.\n";
|
|
|
|
WriteToFile(kStderrFd, msg, sizeof(msg));
|
|
|
|
|
|
|
|
internal__exit(common_flags()->exitcode);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (halt_on_error_) {
|
2012-08-10 23:13:05 +08:00
|
|
|
// Do not print more than one report, otherwise they will mix up.
|
|
|
|
// Error reporting functions shouldn't return at this situation, as
|
2015-11-11 19:59:38 +08:00
|
|
|
// they are effectively no-returns.
|
|
|
|
|
2014-08-27 21:43:18 +08:00
|
|
|
Report("AddressSanitizer: while reporting a bug found another one. "
|
2015-11-11 19:59:38 +08:00
|
|
|
"Ignoring.\n");
|
|
|
|
|
|
|
|
// Sleep long enough to make sure that the thread which started
|
|
|
|
// to print an error report will finish doing it.
|
|
|
|
SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
|
|
|
|
|
2013-02-20 21:54:32 +08:00
|
|
|
// If we're still not dead for some reason, use raw _exit() instead of
|
2012-11-19 19:22:22 +08:00
|
|
|
// Die() to bypass any additional checks.
|
2015-08-22 04:49:37 +08:00
|
|
|
internal__exit(common_flags()->exitcode);
|
2015-11-11 19:59:38 +08:00
|
|
|
} else {
|
|
|
|
// The other thread will eventually finish reporting
|
|
|
|
// so it's safe to wait
|
|
|
|
lock_.Lock();
|
2012-08-10 23:13:05 +08:00
|
|
|
}
|
2015-11-11 19:59:38 +08:00
|
|
|
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
StartReporting();
|
2012-08-10 23:13:05 +08:00
|
|
|
}
|
2015-11-11 19:59:38 +08:00
|
|
|
|
|
|
|
~ScopedInErrorReport() {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
ASAN_ON_ERROR();
|
2016-08-31 01:08:55 +08:00
|
|
|
if (current_error_.IsValid()) current_error_.Print();
|
|
|
|
|
2012-08-10 23:13:05 +08:00
|
|
|
// Make sure the current thread is announced.
|
2013-09-10 16:36:21 +08:00
|
|
|
DescribeThread(GetCurrentThread());
|
2014-05-12 16:01:51 +08:00
|
|
|
// We may want to grab this lock again when printing stats.
|
|
|
|
asanThreadRegistry().Unlock();
|
2012-08-10 23:13:05 +08:00
|
|
|
// Print memory stats.
|
2013-01-28 15:34:22 +08:00
|
|
|
if (flags()->print_stats)
|
|
|
|
__asan_print_accumulated_stats();
|
2015-11-21 02:42:01 +08:00
|
|
|
|
2016-01-18 15:55:12 +08:00
|
|
|
if (common_flags()->print_cmdline)
|
|
|
|
PrintCmdline();
|
|
|
|
|
2017-01-07 04:57:47 +08:00
|
|
|
if (common_flags()->print_module_map == 2) PrintModuleMap();
|
|
|
|
|
2015-11-21 02:42:01 +08:00
|
|
|
// Copy the message buffer so that we could start logging without holding a
|
|
|
|
// lock that gets aquired during printing.
|
|
|
|
InternalScopedBuffer<char> buffer_copy(kErrorMessageBufferSize);
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
{
|
|
|
|
BlockingMutexLock l(&error_message_buf_mutex);
|
2015-11-21 02:42:01 +08:00
|
|
|
internal_memcpy(buffer_copy.data(),
|
|
|
|
error_message_buffer, kErrorMessageBufferSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
LogFullErrorReport(buffer_copy.data());
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
|
2015-11-21 02:42:01 +08:00
|
|
|
if (error_report_callback) {
|
|
|
|
error_report_callback(buffer_copy.data());
|
2012-08-10 23:13:05 +08:00
|
|
|
}
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
|
2017-06-24 07:38:20 +08:00
|
|
|
if (halt_on_error_ && common_flags()->abort_on_error) {
|
|
|
|
// On Android the message is truncated to 512 characters.
|
|
|
|
// FIXME: implement "compact" error format, possibly without, or with
|
|
|
|
// highly compressed stack traces?
|
|
|
|
// FIXME: or just use the summary line as abort message?
|
|
|
|
SetAbortMessage(buffer_copy.data());
|
|
|
|
}
|
|
|
|
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
// In halt_on_error = false mode, reset the current error object (before
|
|
|
|
// unlocking).
|
|
|
|
if (!halt_on_error_)
|
|
|
|
internal_memset(¤t_error_, 0, sizeof(current_error_));
|
|
|
|
|
2015-11-11 19:59:38 +08:00
|
|
|
CommonSanitizerReportMutex.Unlock();
|
|
|
|
reporting_thread_tid_ = kInvalidTid;
|
|
|
|
lock_.Unlock();
|
|
|
|
if (halt_on_error_) {
|
|
|
|
Report("ABORTING\n");
|
|
|
|
Die();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-31 01:08:55 +08:00
|
|
|
void ReportError(const ErrorDescription &description) {
|
|
|
|
// Can only report one error per ScopedInErrorReport.
|
|
|
|
CHECK_EQ(current_error_.kind, kErrorKindInvalid);
|
|
|
|
current_error_ = description;
|
|
|
|
}
|
|
|
|
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
static ErrorDescription &CurrentError() {
|
|
|
|
return current_error_;
|
|
|
|
}
|
|
|
|
|
2015-11-11 19:59:38 +08:00
|
|
|
private:
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
void StartReporting() {
|
2015-11-11 19:59:38 +08:00
|
|
|
// Make sure the registry and sanitizer report mutexes are locked while
|
|
|
|
// we're printing an error report.
|
|
|
|
// We can lock them only here to avoid self-deadlock in case of
|
|
|
|
// recursive reports.
|
|
|
|
asanThreadRegistry().Lock();
|
|
|
|
CommonSanitizerReportMutex.Lock();
|
|
|
|
reporting_thread_tid_ = GetCurrentTidOrInvalid();
|
|
|
|
Printf("===================================================="
|
|
|
|
"=============\n");
|
2012-08-10 23:13:05 +08:00
|
|
|
}
|
2015-11-11 19:59:38 +08:00
|
|
|
|
|
|
|
static StaticSpinMutex lock_;
|
|
|
|
static u32 reporting_thread_tid_;
|
2016-08-31 01:08:55 +08:00
|
|
|
// Error currently being reported. This enables the destructor to interact
|
|
|
|
// with the debugger and point it to an error description.
|
|
|
|
static ErrorDescription current_error_;
|
2015-11-11 19:59:38 +08:00
|
|
|
bool halt_on_error_;
|
2012-08-10 23:13:05 +08:00
|
|
|
};
|
|
|
|
|
2015-11-11 19:59:38 +08:00
|
|
|
StaticSpinMutex ScopedInErrorReport::lock_;
|
2016-05-31 16:47:18 +08:00
|
|
|
u32 ScopedInErrorReport::reporting_thread_tid_ = kInvalidTid;
|
2016-08-31 01:08:55 +08:00
|
|
|
ErrorDescription ScopedInErrorReport::current_error_;
|
2015-11-11 19:59:38 +08:00
|
|
|
|
2014-11-25 21:00:21 +08:00
|
|
|
void ReportStackOverflow(const SignalContext &sig) {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
ScopedInErrorReport in_report(/*fatal*/ true);
|
2016-09-13 01:10:44 +08:00
|
|
|
ErrorStackOverflow error(GetCurrentTidOrInvalid(), sig);
|
2016-08-31 01:08:55 +08:00
|
|
|
in_report.ReportError(error);
|
2014-02-18 19:49:52 +08:00
|
|
|
}
|
|
|
|
|
2016-09-08 20:58:15 +08:00
|
|
|
void ReportDeadlySignal(int signo, const SignalContext &sig) {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
ScopedInErrorReport in_report(/*fatal*/ true);
|
2016-09-13 01:10:44 +08:00
|
|
|
ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig, signo);
|
2016-09-08 20:58:15 +08:00
|
|
|
in_report.ReportError(error);
|
2012-08-09 15:40:58 +08:00
|
|
|
}
|
|
|
|
|
2014-10-26 11:35:14 +08:00
|
|
|
void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
|
2012-08-10 23:13:05 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-13 01:10:44 +08:00
|
|
|
ErrorDoubleFree error(GetCurrentTidOrInvalid(), free_stack, addr);
|
2016-08-31 15:38:09 +08:00
|
|
|
in_report.ReportError(error);
|
2012-08-09 16:15:46 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 22:20:54 +08:00
|
|
|
void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
|
2014-10-26 11:35:14 +08:00
|
|
|
BufferedStackTrace *free_stack) {
|
2014-07-30 17:48:23 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-13 01:10:44 +08:00
|
|
|
ErrorNewDeleteSizeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
|
|
|
|
delete_size);
|
2016-09-07 22:20:54 +08:00
|
|
|
in_report.ReportError(error);
|
2014-07-30 17:48:23 +08:00
|
|
|
}
|
|
|
|
|
2014-10-26 11:35:14 +08:00
|
|
|
void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack) {
|
2012-08-10 23:13:05 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-14 04:47:29 +08:00
|
|
|
ErrorFreeNotMalloced error(GetCurrentTidOrInvalid(), free_stack, addr);
|
|
|
|
in_report.ReportError(error);
|
2012-08-09 16:15:46 +08:00
|
|
|
}
|
|
|
|
|
2014-10-26 11:35:14 +08:00
|
|
|
void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
|
2012-12-21 16:53:59 +08:00
|
|
|
AllocType alloc_type,
|
|
|
|
AllocType dealloc_type) {
|
|
|
|
ScopedInErrorReport in_report;
|
2016-09-14 04:47:33 +08:00
|
|
|
ErrorAllocTypeMismatch error(GetCurrentTidOrInvalid(), free_stack, addr,
|
|
|
|
alloc_type, dealloc_type);
|
|
|
|
in_report.ReportError(error);
|
2012-12-21 16:53:59 +08:00
|
|
|
}
|
|
|
|
|
2014-10-26 11:35:14 +08:00
|
|
|
void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack) {
|
2012-08-10 23:13:05 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-14 04:47:37 +08:00
|
|
|
ErrorMallocUsableSizeNotOwned error(GetCurrentTidOrInvalid(), stack, addr);
|
|
|
|
in_report.ReportError(error);
|
2012-08-09 16:15:46 +08:00
|
|
|
}
|
|
|
|
|
2014-10-26 11:35:14 +08:00
|
|
|
void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
|
|
|
|
BufferedStackTrace *stack) {
|
2012-08-10 23:13:05 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-14 04:47:42 +08:00
|
|
|
ErrorSanitizerGetAllocatedSizeNotOwned error(GetCurrentTidOrInvalid(), stack,
|
|
|
|
addr);
|
|
|
|
in_report.ReportError(error);
|
2012-08-09 16:15:46 +08:00
|
|
|
}
|
|
|
|
|
2014-10-26 11:35:14 +08:00
|
|
|
void ReportStringFunctionMemoryRangesOverlap(const char *function,
|
|
|
|
const char *offset1, uptr length1,
|
|
|
|
const char *offset2, uptr length2,
|
|
|
|
BufferedStackTrace *stack) {
|
2012-08-10 23:13:05 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-14 15:37:14 +08:00
|
|
|
ErrorStringFunctionMemoryRangesOverlap error(
|
|
|
|
GetCurrentTidOrInvalid(), stack, (uptr)offset1, length1, (uptr)offset2,
|
|
|
|
length2, function);
|
|
|
|
in_report.ReportError(error);
|
2012-08-09 16:32:33 +08:00
|
|
|
}
|
2012-08-09 16:15:46 +08:00
|
|
|
|
2014-04-14 17:50:52 +08:00
|
|
|
void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
|
2014-10-26 11:35:14 +08:00
|
|
|
BufferedStackTrace *stack) {
|
2014-04-14 17:50:52 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-14 15:37:20 +08:00
|
|
|
ErrorStringFunctionSizeOverflow error(GetCurrentTidOrInvalid(), stack, offset,
|
|
|
|
size);
|
|
|
|
in_report.ReportError(error);
|
2014-04-14 17:50:52 +08:00
|
|
|
}
|
|
|
|
|
2013-12-23 15:01:43 +08:00
|
|
|
void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
|
|
|
|
uptr old_mid, uptr new_mid,
|
2014-10-26 11:35:14 +08:00
|
|
|
BufferedStackTrace *stack) {
|
2013-12-23 15:01:43 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-15 16:10:48 +08:00
|
|
|
ErrorBadParamsToAnnotateContiguousContainer error(
|
|
|
|
GetCurrentTidOrInvalid(), stack, beg, end, old_mid, new_mid);
|
|
|
|
in_report.ReportError(error);
|
2013-12-23 15:01:43 +08:00
|
|
|
}
|
|
|
|
|
2014-06-20 16:24:12 +08:00
|
|
|
void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
|
|
|
|
const __asan_global *g2, u32 stack_id2) {
|
2014-04-25 16:58:28 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-15 16:10:52 +08:00
|
|
|
ErrorODRViolation error(GetCurrentTidOrInvalid(), g1, stack_id1, g2,
|
|
|
|
stack_id2);
|
|
|
|
in_report.ReportError(error);
|
2014-04-25 16:58:28 +08:00
|
|
|
}
|
|
|
|
|
2014-02-27 20:45:36 +08:00
|
|
|
// ----------------------- CheckForInvalidPointerPair ----------- {{{1
|
2016-09-15 16:10:56 +08:00
|
|
|
static NOINLINE void ReportInvalidPointerPair(uptr pc, uptr bp, uptr sp,
|
|
|
|
uptr a1, uptr a2) {
|
2014-02-27 20:45:36 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2016-09-15 16:10:56 +08:00
|
|
|
ErrorInvalidPointerPair error(GetCurrentTidOrInvalid(), pc, bp, sp, a1, a2);
|
|
|
|
in_report.ReportError(error);
|
2014-02-27 20:45:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE void CheckForInvalidPointerPair(void *p1, void *p2) {
|
|
|
|
if (!flags()->detect_invalid_pointer_pairs) return;
|
|
|
|
uptr a1 = reinterpret_cast<uptr>(p1);
|
|
|
|
uptr a2 = reinterpret_cast<uptr>(p2);
|
|
|
|
AsanChunkView chunk1 = FindHeapChunkByAddress(a1);
|
|
|
|
AsanChunkView chunk2 = FindHeapChunkByAddress(a2);
|
[asan] Assert in __sanitizer_ptr_{sub,cmp} if one of the pointers was freed.
Summary:
This (partially) implements the check mentioned at
http://kristerw.blogspot.co.uk/2016/04/dangling-pointers-and-undefined-behavior.html
(via John Regehr)
Quoting:
"That the behavior is undefined follows from C11 6.2.4 "Storage
durations of objects"
The lifetime of an object is the portion of program execution during
which storage is guaranteed to be reserved for it. An object exists, has
a constant address, and retains its last-stored value throughout its
lifetime. If an object is referred to outside of its lifetime, the
behavior is undefined. The value of a pointer becomes indeterminate when
the object it points to (or just past) reaches the end of its lifetime.
and 7.22.3 "Memory management functions" that says that free ends the
lifetime of objects
The lifetime of an allocated object extends from the allocation until
the deallocation.
"
We can probably implement this for stack variables too, but I think this
is a good start to see if there's interest in this check.
We can also hide this behind a flag, too.
Reviewers: samsonov, kcc, rsmith, regehr
Subscribers: kubabrecka, llvm-commits
Differential Revision: http://reviews.llvm.org/D19691
llvm-svn: 268097
2016-04-30 04:37:34 +08:00
|
|
|
bool valid1 = chunk1.IsAllocated();
|
|
|
|
bool valid2 = chunk2.IsAllocated();
|
|
|
|
if (!valid1 || !valid2 || !chunk1.Eq(chunk2)) {
|
|
|
|
GET_CALLER_PC_BP_SP;
|
2014-02-27 20:45:36 +08:00
|
|
|
return ReportInvalidPointerPair(pc, bp, sp, a1, a2);
|
|
|
|
}
|
|
|
|
}
|
2012-08-09 20:15:40 +08:00
|
|
|
// ----------------------- Mac-specific reports ----------------- {{{1
|
|
|
|
|
2014-10-26 11:35:14 +08:00
|
|
|
void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr, const char *zone_name,
|
|
|
|
BufferedStackTrace *stack) {
|
2012-08-10 23:13:05 +08:00
|
|
|
ScopedInErrorReport in_report;
|
2012-08-28 19:34:40 +08:00
|
|
|
Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
|
2012-08-09 20:15:40 +08:00
|
|
|
"This is an unrecoverable problem, exiting now.\n",
|
|
|
|
addr);
|
|
|
|
PrintZoneForPointer(addr, zone_ptr, zone_name);
|
2013-12-19 19:25:05 +08:00
|
|
|
stack->Print();
|
2016-08-17 17:16:08 +08:00
|
|
|
DescribeAddressIfHeap(addr);
|
2012-08-09 20:15:40 +08:00
|
|
|
}
|
|
|
|
|
2015-12-10 16:08:53 +08:00
|
|
|
// -------------- SuppressErrorReport -------------- {{{1
|
|
|
|
// Avoid error reports duplicating for ASan recover mode.
|
|
|
|
static bool SuppressErrorReport(uptr pc) {
|
|
|
|
if (!common_flags()->suppress_equal_pcs) return false;
|
|
|
|
for (unsigned i = 0; i < kAsanBuggyPcPoolSize; i++) {
|
2015-12-10 19:07:19 +08:00
|
|
|
uptr cmp = atomic_load_relaxed(&AsanBuggyPcPool[i]);
|
2015-12-10 16:08:53 +08:00
|
|
|
if (cmp == 0 && atomic_compare_exchange_strong(&AsanBuggyPcPool[i], &cmp,
|
|
|
|
pc, memory_order_relaxed))
|
|
|
|
return false;
|
|
|
|
if (cmp == pc) return true;
|
|
|
|
}
|
|
|
|
Die();
|
|
|
|
}
|
|
|
|
|
2015-11-11 20:23:59 +08:00
|
|
|
void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
|
|
|
|
uptr access_size, u32 exp, bool fatal) {
|
2015-12-10 16:08:53 +08:00
|
|
|
if (!fatal && SuppressErrorReport(pc)) return;
|
2015-01-23 07:36:47 +08:00
|
|
|
ENABLE_FRAME_POINTER;
|
2015-01-23 08:14:22 +08:00
|
|
|
|
2015-03-18 00:59:11 +08:00
|
|
|
// Optimization experiments.
|
|
|
|
// The experiments can be used to evaluate potential optimizations that remove
|
|
|
|
// instrumentation (assess false negatives). Instead of completely removing
|
|
|
|
// some instrumentation, compiler can emit special calls into runtime
|
|
|
|
// (e.g. __asan_report_exp_load1 instead of __asan_report_load1) and pass
|
|
|
|
// mask of experiments (exp).
|
|
|
|
// The reaction to a non-zero value of exp is to be defined.
|
|
|
|
(void)exp;
|
|
|
|
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
ScopedInErrorReport in_report(fatal);
|
|
|
|
ErrorGeneric error(GetCurrentTidOrInvalid(), pc, bp, sp, addr, is_write,
|
|
|
|
access_size);
|
|
|
|
in_report.ReportError(error);
|
2012-08-09 18:56:57 +08:00
|
|
|
}
|
|
|
|
|
2015-11-11 19:59:38 +08:00
|
|
|
} // namespace __asan
|
|
|
|
|
|
|
|
// --------------------------- Interface --------------------- {{{1
|
|
|
|
using namespace __asan; // NOLINT
|
|
|
|
|
|
|
|
void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
|
|
|
|
uptr access_size, u32 exp) {
|
|
|
|
ENABLE_FRAME_POINTER;
|
|
|
|
bool fatal = flags()->halt_on_error;
|
|
|
|
ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal);
|
|
|
|
}
|
|
|
|
|
2012-08-09 18:56:57 +08:00
|
|
|
void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
BlockingMutexLock l(&error_message_buf_mutex);
|
2012-08-09 18:56:57 +08:00
|
|
|
error_report_callback = callback;
|
|
|
|
}
|
2012-08-13 19:23:40 +08:00
|
|
|
|
2012-12-29 18:18:31 +08:00
|
|
|
void __asan_describe_address(uptr addr) {
|
2014-07-22 05:33:46 +08:00
|
|
|
// Thread registry must be locked while we're describing an address.
|
|
|
|
asanThreadRegistry().Lock();
|
2016-08-19 21:07:23 +08:00
|
|
|
PrintAddressDescription(addr, 1, "");
|
2014-07-22 05:33:46 +08:00
|
|
|
asanThreadRegistry().Unlock();
|
2012-12-29 18:18:31 +08:00
|
|
|
}
|
|
|
|
|
2014-09-27 03:15:32 +08:00
|
|
|
int __asan_report_present() {
|
2016-11-29 05:18:15 +08:00
|
|
|
return ScopedInErrorReport::CurrentError().kind != kErrorKindInvalid;
|
2014-09-27 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uptr __asan_get_report_pc() {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
|
|
|
|
return ScopedInErrorReport::CurrentError().Generic.pc;
|
|
|
|
return 0;
|
2014-09-27 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uptr __asan_get_report_bp() {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
|
|
|
|
return ScopedInErrorReport::CurrentError().Generic.bp;
|
|
|
|
return 0;
|
2014-09-27 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uptr __asan_get_report_sp() {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
|
|
|
|
return ScopedInErrorReport::CurrentError().Generic.sp;
|
|
|
|
return 0;
|
2014-09-27 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uptr __asan_get_report_address() {
|
2016-11-29 05:18:15 +08:00
|
|
|
ErrorDescription &err = ScopedInErrorReport::CurrentError();
|
|
|
|
if (err.kind == kErrorKindGeneric)
|
|
|
|
return err.Generic.addr_description.Address();
|
|
|
|
else if (err.kind == kErrorKindDoubleFree)
|
|
|
|
return err.DoubleFree.addr_description.addr;
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
return 0;
|
2014-09-27 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int __asan_get_report_access_type() {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
|
|
|
|
return ScopedInErrorReport::CurrentError().Generic.is_write;
|
|
|
|
return 0;
|
2014-09-27 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uptr __asan_get_report_access_size() {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
|
|
|
|
return ScopedInErrorReport::CurrentError().Generic.access_size;
|
|
|
|
return 0;
|
2014-09-27 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *__asan_get_report_description() {
|
[asan] Reify ErrorGeneric
Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)
Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.
This has the following side-effects:
- Move ASAN_ON_ERROR(); call to the start of the destructor, instead
of in StartReporting().
- We only generate the error structure after the
ScopedInErrorReport constructor finishes, so we can't call
ASAN_ON_ERROR() during the constructor. I think this makes more
sense, since we end up never running two of the ASAN_ON_ERROR()
callback. This also works the same way as error reporting, since
we end up having a lock around it. Otherwise we could end up
with the ASAN_ON_ERROR() call for error 1, then the
ASAN_ON_ERROR() call for error 2, and then lock the mutex for
reporting error 1.
- The __asan_get_report_* functions will be able to, in the future,
provide information about other errors that aren't a "generic
error". But we might want to rethink that API, since it's too
restricted. Ideally we teach lldb about the current_error_ member of
ScopedInErrorReport.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: kubabrecka, llvm-commits
Differential Revision: https://reviews.llvm.org/D24555
llvm-svn: 282107
2016-09-22 04:18:18 +08:00
|
|
|
if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
|
|
|
|
return ScopedInErrorReport::CurrentError().Generic.bug_descr;
|
2016-11-29 05:18:15 +08:00
|
|
|
return ScopedInErrorReport::CurrentError().Base.scariness.GetDescription();
|
2014-09-27 03:15:32 +08:00
|
|
|
}
|
|
|
|
|
2014-02-27 20:45:36 +08:00
|
|
|
extern "C" {
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void __sanitizer_ptr_sub(void *a, void *b) {
|
|
|
|
CheckForInvalidPointerPair(a, b);
|
|
|
|
}
|
|
|
|
SANITIZER_INTERFACE_ATTRIBUTE
|
|
|
|
void __sanitizer_ptr_cmp(void *a, void *b) {
|
|
|
|
CheckForInvalidPointerPair(a, b);
|
|
|
|
}
|
2015-10-01 08:22:21 +08:00
|
|
|
} // extern "C"
|
2014-02-27 20:45:36 +08:00
|
|
|
|
2012-10-02 22:06:39 +08:00
|
|
|
// Provide default implementation of __asan_on_error that does nothing
|
|
|
|
// and may be overriden by user.
|
2017-01-29 13:44:59 +08:00
|
|
|
SANITIZER_INTERFACE_WEAK_DEF(void, __asan_on_error, void) {}
|