mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 19:06:44 +00:00
[sanitizer] Split Symbolizer/StackTraces from core RTSanitizerCommon
Summary: Host symbolizer & stacktraces related code in their own RT: `RTSanitizerCommonSymbolizer`, which is "libcdep" by nature. Symbolizer & stacktraces specific code that used to live in common files is moved to a new file `sanitizer_symbolizer_report.cc` as is. The purpose of this is the enforce a separation between code that relies on symbolization and code that doesn't. This saves the inclusion of spurious code due to the interface functions with default visibility, and the extra data associated. The following sanitizers makefiles were modified & tested locally: - dfsan: doesn't require the new symbolizer RT - esan: requires it - hwasan: requires it - lsan: requires it - msan: requires it - safestack: doesn't require it - xray: doesn't require it - tsan: requires it - ubsan: requires it - ubsan_minimal: doesn't require it - scudo: requires it (but not for Fuchsia that has a minimal runtime) This was tested locally on Linux, Android, Fuchsia. Reviewers: alekseyshl, eugenis, dberris, kubamracek, vitalybuka, dvyukov, mcgrathr Reviewed By: alekseyshl, vitalybuka Subscribers: srhines, kubamracek, mgorny, krytarowski, delcypher, llvm-commits, #sanitizers Differential Revision: https://reviews.llvm.org/D45457 llvm-svn: 330131
This commit is contained in:
parent
1b06cc7817
commit
596b8b4a22
@ -126,6 +126,7 @@ if(APPLE)
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTLSanCommon
|
||||
RTUbsan
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
@ -140,6 +141,7 @@ else()
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTLSanCommon
|
||||
RTUbsan)
|
||||
|
||||
|
@ -252,6 +252,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID)
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonCoverage.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.osx>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.osx>
|
||||
$<TARGET_OBJECTS:RTUbsan.osx>)
|
||||
else()
|
||||
@ -262,6 +263,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID)
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>)
|
||||
@ -286,6 +288,7 @@ if(ANDROID)
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
|
||||
${COMPILER_RT_GTEST_SOURCE}
|
||||
|
@ -26,6 +26,7 @@ foreach (arch ${ESAN_SUPPORTED_ARCH})
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
|
||||
CFLAGS ${ESAN_RTL_CFLAGS})
|
||||
add_sanitizer_rt_symbols(clang_rt.esan
|
||||
ARCHS ${arch}
|
||||
|
@ -79,6 +79,7 @@ foreach(arch ${HWASAN_SUPPORTED_ARCH})
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTUbsan
|
||||
CFLAGS ${HWASAN_RTL_CFLAGS}
|
||||
PARENT_TARGET hwasan)
|
||||
@ -114,6 +115,7 @@ foreach(arch ${HWASAN_SUPPORTED_ARCH})
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTUbsan
|
||||
# The only purpose of RTHWAsan_dynamic_version_script_dummy is to
|
||||
# carry a dependency of the shared runtime on the version script.
|
||||
|
@ -44,6 +44,7 @@ if(COMPILER_RT_HAS_LSAN)
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
CFLAGS ${LSAN_CFLAGS}
|
||||
LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}
|
||||
LINK_LIBS ${LSAN_LINK_LIBS}
|
||||
@ -58,6 +59,7 @@ if(COMPILER_RT_HAS_LSAN)
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>
|
||||
CFLAGS ${LSAN_CFLAGS}
|
||||
PARENT_TARGET lsan)
|
||||
|
@ -41,6 +41,7 @@ foreach(arch ${MSAN_SUPPORTED_ARCH})
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>
|
||||
CFLAGS ${MSAN_RTL_CFLAGS}
|
||||
PARENT_TARGET msan)
|
||||
|
@ -31,16 +31,8 @@ set(SANITIZER_SOURCES_NOTERMINATION
|
||||
sanitizer_procmaps_mac.cc
|
||||
sanitizer_procmaps_solaris.cc
|
||||
sanitizer_solaris.cc
|
||||
sanitizer_stackdepot.cc
|
||||
sanitizer_stacktrace.cc
|
||||
sanitizer_stacktrace_printer.cc
|
||||
sanitizer_stoptheworld_mac.cc
|
||||
sanitizer_suppressions.cc
|
||||
sanitizer_symbolizer.cc
|
||||
sanitizer_symbolizer_fuchsia.cc
|
||||
sanitizer_symbolizer_libbacktrace.cc
|
||||
sanitizer_symbolizer_mac.cc
|
||||
sanitizer_symbolizer_win.cc
|
||||
sanitizer_tls_get_addr.cc
|
||||
sanitizer_thread_registry.cc
|
||||
sanitizer_win.cc)
|
||||
@ -67,12 +59,7 @@ set(SANITIZER_LIBCDEP_SOURCES
|
||||
sanitizer_linux_libcdep.cc
|
||||
sanitizer_mac_libcdep.cc
|
||||
sanitizer_posix_libcdep.cc
|
||||
sanitizer_stacktrace_libcdep.cc
|
||||
sanitizer_stoptheworld_linux_libcdep.cc
|
||||
sanitizer_symbolizer_libcdep.cc
|
||||
sanitizer_symbolizer_posix_libcdep.cc
|
||||
sanitizer_unwind_linux_libcdep.cc
|
||||
sanitizer_unwind_win.cc)
|
||||
sanitizer_stoptheworld_linux_libcdep.cc)
|
||||
|
||||
set(SANITIZER_COVERAGE_SOURCES
|
||||
sancov_flags.cc
|
||||
@ -80,6 +67,22 @@ set(SANITIZER_COVERAGE_SOURCES
|
||||
sanitizer_coverage_libcdep_new.cc
|
||||
sanitizer_coverage_win_sections.cc)
|
||||
|
||||
set(SANITIZER_SYMBOLIZER_SOURCES
|
||||
sanitizer_stackdepot.cc
|
||||
sanitizer_stacktrace.cc
|
||||
sanitizer_stacktrace_libcdep.cc
|
||||
sanitizer_stacktrace_printer.cc
|
||||
sanitizer_symbolizer.cc
|
||||
sanitizer_symbolizer_fuchsia.cc
|
||||
sanitizer_symbolizer_libbacktrace.cc
|
||||
sanitizer_symbolizer_libcdep.cc
|
||||
sanitizer_symbolizer_mac.cc
|
||||
sanitizer_symbolizer_posix_libcdep.cc
|
||||
sanitizer_symbolizer_report.cc
|
||||
sanitizer_symbolizer_win.cc
|
||||
sanitizer_unwind_linux_libcdep.cc
|
||||
sanitizer_unwind_win.cc)
|
||||
|
||||
# Explicitly list all sanitizer_common headers. Not all of these are
|
||||
# included in sanitizer_common source files, but we need to depend on
|
||||
# headers when building our custom unit tests.
|
||||
@ -217,6 +220,12 @@ add_compiler_rt_object_libraries(RTSanitizerCommonCoverage
|
||||
SOURCES ${SANITIZER_COVERAGE_SOURCES}
|
||||
CFLAGS ${SANITIZER_CFLAGS}
|
||||
DEFS ${SANITIZER_COMMON_DEFINITIONS})
|
||||
add_compiler_rt_object_libraries(RTSanitizerCommonSymbolizer
|
||||
${OS_OPTION}
|
||||
ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH}
|
||||
SOURCES ${SANITIZER_SYMBOLIZER_SOURCES}
|
||||
CFLAGS ${SANITIZER_CFLAGS}
|
||||
DEFS ${SANITIZER_COMMON_DEFINITIONS})
|
||||
|
||||
set(SANITIZER_NO_WEAK_HOOKS_CFLAGS ${SANITIZER_CFLAGS})
|
||||
list(APPEND SANITIZER_NO_WEAK_HOOKS_CFLAGS "-DSANITIZER_SUPPORTS_WEAK_HOOKS=0")
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include "sanitizer_flags.h"
|
||||
#include "sanitizer_libc.h"
|
||||
#include "sanitizer_placement_new.h"
|
||||
#include "sanitizer_stacktrace_printer.h"
|
||||
#include "sanitizer_symbolizer.h"
|
||||
|
||||
namespace __sanitizer {
|
||||
|
||||
@ -107,18 +105,6 @@ void ReportErrorSummary(const char *error_message, const char *alt_tool_name) {
|
||||
__sanitizer_report_error_summary(buff.data());
|
||||
}
|
||||
|
||||
#if !SANITIZER_GO
|
||||
void ReportErrorSummary(const char *error_type, const AddressInfo &info,
|
||||
const char *alt_tool_name) {
|
||||
if (!common_flags()->print_summary) return;
|
||||
InternalScopedString buff(kMaxSummaryLength);
|
||||
buff.append("%s ", error_type);
|
||||
RenderFrame(&buff, "%L %F", 0, info, common_flags()->symbolize_vs_style,
|
||||
common_flags()->strip_path_prefix);
|
||||
ReportErrorSummary(buff.data(), alt_tool_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Removes the ANSI escape sequences from the input string (in-place).
|
||||
void RemoveANSIEscapeSequencesFromString(char *str) {
|
||||
if (!str)
|
||||
|
@ -11,100 +11,14 @@
|
||||
// run-time libraries.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "sanitizer_common.h"
|
||||
|
||||
#include "sanitizer_allocator_interface.h"
|
||||
#include "sanitizer_file.h"
|
||||
#include "sanitizer_common.h"
|
||||
#include "sanitizer_flags.h"
|
||||
#include "sanitizer_procmaps.h"
|
||||
#include "sanitizer_report_decorator.h"
|
||||
#include "sanitizer_stacktrace.h"
|
||||
#include "sanitizer_symbolizer.h"
|
||||
|
||||
#if SANITIZER_POSIX
|
||||
#include "sanitizer_posix.h"
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
namespace __sanitizer {
|
||||
|
||||
#if !SANITIZER_FUCHSIA
|
||||
|
||||
bool ReportFile::SupportsColors() {
|
||||
SpinMutexLock l(mu);
|
||||
ReopenIfNecessary();
|
||||
return SupportsColoredOutput(fd);
|
||||
}
|
||||
|
||||
static INLINE bool ReportSupportsColors() {
|
||||
return report_file.SupportsColors();
|
||||
}
|
||||
|
||||
#else // SANITIZER_FUCHSIA
|
||||
|
||||
// Fuchsia's logs always go through post-processing that handles colorization.
|
||||
static INLINE bool ReportSupportsColors() { return true; }
|
||||
|
||||
#endif // !SANITIZER_FUCHSIA
|
||||
|
||||
bool ColorizeReports() {
|
||||
// FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
|
||||
// printing on Windows.
|
||||
if (SANITIZER_WINDOWS)
|
||||
return false;
|
||||
|
||||
const char *flag = common_flags()->color;
|
||||
return internal_strcmp(flag, "always") == 0 ||
|
||||
(internal_strcmp(flag, "auto") == 0 && ReportSupportsColors());
|
||||
}
|
||||
|
||||
void ReportErrorSummary(const char *error_type, const StackTrace *stack,
|
||||
const char *alt_tool_name) {
|
||||
#if !SANITIZER_GO
|
||||
if (!common_flags()->print_summary)
|
||||
return;
|
||||
if (stack->size == 0) {
|
||||
ReportErrorSummary(error_type);
|
||||
return;
|
||||
}
|
||||
// Currently, we include the first stack frame into the report summary.
|
||||
// Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
|
||||
uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
|
||||
SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
|
||||
ReportErrorSummary(error_type, frame->info, alt_tool_name);
|
||||
frame->ClearAll();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ReportMmapWriteExec(int prot) {
|
||||
#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID)
|
||||
if ((prot & (PROT_WRITE | PROT_EXEC)) != (PROT_WRITE | PROT_EXEC))
|
||||
return;
|
||||
|
||||
ScopedErrorReportLock l;
|
||||
SanitizerCommonDecorator d;
|
||||
|
||||
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
|
||||
BufferedStackTrace *stack = stack_buffer.data();
|
||||
stack->Reset();
|
||||
uptr top = 0;
|
||||
uptr bottom = 0;
|
||||
GET_CALLER_PC_BP_SP;
|
||||
(void)sp;
|
||||
bool fast = common_flags()->fast_unwind_on_fatal;
|
||||
if (fast)
|
||||
GetThreadStackTopAndBottom(false, &top, &bottom);
|
||||
stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, fast);
|
||||
|
||||
Printf("%s", d.Warning());
|
||||
Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
|
||||
Printf("%s", d.Default());
|
||||
|
||||
stack->Print();
|
||||
ReportErrorSummary("w-and-x-usage", stack);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void (*SoftRssLimitExceededCallback)(bool exceeded);
|
||||
void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) {
|
||||
CHECK_EQ(SoftRssLimitExceededCallback, nullptr);
|
||||
@ -178,127 +92,6 @@ void BackgroundThread(void *arg) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SANITIZER_FUCHSIA && !SANITIZER_GO
|
||||
void StartReportDeadlySignal() {
|
||||
// Write the first message using fd=2, just in case.
|
||||
// It may actually fail to write in case stderr is closed.
|
||||
CatastrophicErrorWrite(SanitizerToolName, internal_strlen(SanitizerToolName));
|
||||
static const char kDeadlySignal[] = ":DEADLYSIGNAL\n";
|
||||
CatastrophicErrorWrite(kDeadlySignal, sizeof(kDeadlySignal) - 1);
|
||||
}
|
||||
|
||||
static void MaybeReportNonExecRegion(uptr pc) {
|
||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
|
||||
MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
|
||||
MemoryMappedSegment segment;
|
||||
while (proc_maps.Next(&segment)) {
|
||||
if (pc >= segment.start && pc < segment.end && !segment.IsExecutable())
|
||||
Report("Hint: PC is at a non-executable region. Maybe a wild jump?\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PrintMemoryByte(InternalScopedString *str, const char *before,
|
||||
u8 byte) {
|
||||
SanitizerCommonDecorator d;
|
||||
str->append("%s%s%x%x%s ", before, d.MemoryByte(), byte >> 4, byte & 15,
|
||||
d.Default());
|
||||
}
|
||||
|
||||
static void MaybeDumpInstructionBytes(uptr pc) {
|
||||
if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
|
||||
return;
|
||||
InternalScopedString str(1024);
|
||||
str.append("First 16 instruction bytes at pc: ");
|
||||
if (IsAccessibleMemoryRange(pc, 16)) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
PrintMemoryByte(&str, "", ((u8 *)pc)[i]);
|
||||
}
|
||||
str.append("\n");
|
||||
} else {
|
||||
str.append("unaccessible\n");
|
||||
}
|
||||
Report("%s", str.data());
|
||||
}
|
||||
|
||||
static void MaybeDumpRegisters(void *context) {
|
||||
if (!common_flags()->dump_registers) return;
|
||||
SignalContext::DumpAllRegisters(context);
|
||||
}
|
||||
|
||||
static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {
|
||||
SanitizerCommonDecorator d;
|
||||
Printf("%s", d.Warning());
|
||||
static const char kDescription[] = "stack-overflow";
|
||||
Report("ERROR: %s: %s on address %p (pc %p bp %p sp %p T%d)\n",
|
||||
SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
|
||||
(void *)sig.bp, (void *)sig.sp, tid);
|
||||
Printf("%s", d.Default());
|
||||
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
|
||||
BufferedStackTrace *stack = stack_buffer.data();
|
||||
stack->Reset();
|
||||
unwind(sig, unwind_context, stack);
|
||||
stack->Print();
|
||||
ReportErrorSummary(kDescription, stack);
|
||||
}
|
||||
|
||||
static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {
|
||||
SanitizerCommonDecorator d;
|
||||
Printf("%s", d.Warning());
|
||||
const char *description = sig.Describe();
|
||||
Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
|
||||
SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
|
||||
(void *)sig.bp, (void *)sig.sp, tid);
|
||||
Printf("%s", d.Default());
|
||||
if (sig.pc < GetPageSizeCached())
|
||||
Report("Hint: pc points to the zero page.\n");
|
||||
if (sig.is_memory_access) {
|
||||
const char *access_type =
|
||||
sig.write_flag == SignalContext::WRITE
|
||||
? "WRITE"
|
||||
: (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
|
||||
Report("The signal is caused by a %s memory access.\n", access_type);
|
||||
if (sig.addr < GetPageSizeCached())
|
||||
Report("Hint: address points to the zero page.\n");
|
||||
}
|
||||
MaybeReportNonExecRegion(sig.pc);
|
||||
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
|
||||
BufferedStackTrace *stack = stack_buffer.data();
|
||||
stack->Reset();
|
||||
unwind(sig, unwind_context, stack);
|
||||
stack->Print();
|
||||
MaybeDumpInstructionBytes(sig.pc);
|
||||
MaybeDumpRegisters(sig.context);
|
||||
Printf("%s can not provide additional info.\n", SanitizerToolName);
|
||||
ReportErrorSummary(description, stack);
|
||||
}
|
||||
|
||||
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {
|
||||
if (sig.IsStackOverflow())
|
||||
ReportStackOverflowImpl(sig, tid, unwind, unwind_context);
|
||||
else
|
||||
ReportDeadlySignalImpl(sig, tid, unwind, unwind_context);
|
||||
}
|
||||
|
||||
void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {
|
||||
StartReportDeadlySignal();
|
||||
ScopedErrorReportLock rl;
|
||||
SignalContext sig(siginfo, context);
|
||||
ReportDeadlySignal(sig, tid, unwind, unwind_context);
|
||||
Report("ABORTING\n");
|
||||
Die();
|
||||
}
|
||||
|
||||
#endif // !SANITIZER_FUCHSIA && !SANITIZER_GO
|
||||
|
||||
void WriteToSyslog(const char *msg) {
|
||||
InternalScopedString msg_copy(kErrorMessageBufferSize);
|
||||
msg_copy.append("%s", msg);
|
||||
@ -329,47 +122,6 @@ void MaybeStartBackgroudThread() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static atomic_uintptr_t reporting_thread = {0};
|
||||
static StaticSpinMutex CommonSanitizerReportMutex;
|
||||
|
||||
ScopedErrorReportLock::ScopedErrorReportLock() {
|
||||
uptr current = GetThreadSelf();
|
||||
for (;;) {
|
||||
uptr expected = 0;
|
||||
if (atomic_compare_exchange_strong(&reporting_thread, &expected, current,
|
||||
memory_order_relaxed)) {
|
||||
// We've claimed reporting_thread so proceed.
|
||||
CommonSanitizerReportMutex.Lock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (expected == current) {
|
||||
// This is either asynch signal or nested error during error reporting.
|
||||
// Fail simple to avoid deadlocks in Report().
|
||||
|
||||
// Can't use Report() here because of potential deadlocks in nested
|
||||
// signal handlers.
|
||||
CatastrophicErrorWrite(SanitizerToolName,
|
||||
internal_strlen(SanitizerToolName));
|
||||
static const char msg[] = ": nested bug in the same thread, aborting.\n";
|
||||
CatastrophicErrorWrite(msg, sizeof(msg) - 1);
|
||||
|
||||
internal__exit(common_flags()->exitcode);
|
||||
}
|
||||
|
||||
internal_sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
ScopedErrorReportLock::~ScopedErrorReportLock() {
|
||||
CommonSanitizerReportMutex.Unlock();
|
||||
atomic_store_relaxed(&reporting_thread, 0);
|
||||
}
|
||||
|
||||
void ScopedErrorReportLock::CheckLocked() {
|
||||
CommonSanitizerReportMutex.CheckLocked();
|
||||
}
|
||||
|
||||
static void (*sandboxing_callback)();
|
||||
void SetSandboxingCallback(void (*f)()) {
|
||||
sandboxing_callback = f;
|
||||
|
@ -1,11 +1,11 @@
|
||||
//===-- sanitizer_coverage_fuchsia.cc ------------------------------------===//
|
||||
//===-- sanitizer_coverage_fuchsia.cc -------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Sanitizer Coverage Controller for Trace PC Guard, Fuchsia-specific version.
|
||||
//
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "sanitizer_atomic.h"
|
||||
#include "sanitizer_common.h"
|
||||
#include "sanitizer_file.h"
|
||||
#include "sanitizer_symbolizer.h"
|
||||
|
||||
using namespace __sanitizer;
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
//===-- sanitizer_fuchsia.cc ---------------------------------------------===//
|
||||
//===-- sanitizer_fuchsia.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 shared between AddressSanitizer and other sanitizer
|
||||
// run-time libraries and implements Fuchsia-specific functions from
|
||||
// sanitizer_common.h.
|
||||
//===---------------------------------------------------------------------===//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "sanitizer_fuchsia.h"
|
||||
#if SANITIZER_FUCHSIA
|
||||
@ -18,13 +18,11 @@
|
||||
#include "sanitizer_common.h"
|
||||
#include "sanitizer_libc.h"
|
||||
#include "sanitizer_mutex.h"
|
||||
#include "sanitizer_stacktrace.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <unwind.h>
|
||||
#include <zircon/errors.h>
|
||||
#include <zircon/process.h>
|
||||
#include <zircon/syscalls.h>
|
||||
@ -92,10 +90,6 @@ void MaybeReexec() {}
|
||||
void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
|
||||
void DisableCoreDumperIfNecessary() {}
|
||||
void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
|
||||
void StartReportDeadlySignal() {}
|
||||
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {}
|
||||
void SetAlternateSignalStack() {}
|
||||
void UnsetAlternateSignalStack() {}
|
||||
void InitTlsSize() {}
|
||||
@ -106,42 +100,6 @@ bool SignalContext::IsStackOverflow() const { return false; }
|
||||
void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
|
||||
const char *SignalContext::Describe() const { UNIMPLEMENTED(); }
|
||||
|
||||
struct UnwindTraceArg {
|
||||
BufferedStackTrace *stack;
|
||||
u32 max_depth;
|
||||
};
|
||||
|
||||
_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
|
||||
UnwindTraceArg *arg = static_cast<UnwindTraceArg *>(param);
|
||||
CHECK_LT(arg->stack->size, arg->max_depth);
|
||||
uptr pc = _Unwind_GetIP(ctx);
|
||||
if (pc < PAGE_SIZE) return _URC_NORMAL_STOP;
|
||||
arg->stack->trace_buffer[arg->stack->size++] = pc;
|
||||
return (arg->stack->size == arg->max_depth ? _URC_NORMAL_STOP
|
||||
: _URC_NO_REASON);
|
||||
}
|
||||
|
||||
void BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) {
|
||||
CHECK_GE(max_depth, 2);
|
||||
size = 0;
|
||||
UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
|
||||
_Unwind_Backtrace(Unwind_Trace, &arg);
|
||||
CHECK_GT(size, 0);
|
||||
// We need to pop a few frames so that pc is on top.
|
||||
uptr to_pop = LocatePcInTrace(pc);
|
||||
// trace_buffer[0] belongs to the current function so we always pop it,
|
||||
// unless there is only 1 frame in the stack trace (1 frame is always better
|
||||
// than 0!).
|
||||
PopStackFrames(Min(to_pop, static_cast<uptr>(1)));
|
||||
trace_buffer[0] = pc;
|
||||
}
|
||||
|
||||
void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
|
||||
u32 max_depth) {
|
||||
CHECK_NE(context, nullptr);
|
||||
UNREACHABLE("signal context doesn't exist");
|
||||
}
|
||||
|
||||
enum MutexState : int { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
|
||||
|
||||
BlockingMutex::BlockingMutex() {
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include "sanitizer_platform.h"
|
||||
|
||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
||||
SANITIZER_OPENBSD || SANITIZER_SOLARIS
|
||||
|
||||
#include "sanitizer_common.h"
|
||||
@ -26,8 +26,6 @@
|
||||
#include "sanitizer_mutex.h"
|
||||
#include "sanitizer_placement_new.h"
|
||||
#include "sanitizer_procmaps.h"
|
||||
#include "sanitizer_stacktrace.h"
|
||||
#include "sanitizer_symbolizer.h"
|
||||
|
||||
#if SANITIZER_LINUX
|
||||
#include <asm/param.h>
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "sanitizer_linux.h"
|
||||
#include "sanitizer_placement_new.h"
|
||||
#include "sanitizer_procmaps.h"
|
||||
#include "sanitizer_stacktrace.h"
|
||||
|
||||
#include <dlfcn.h> // for dlsym()
|
||||
#include <link.h>
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "sanitizer_libc.h"
|
||||
#include "sanitizer_posix.h"
|
||||
#include "sanitizer_procmaps.h"
|
||||
#include "sanitizer_stacktrace.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -16,8 +16,12 @@
|
||||
#if SANITIZER_FUCHSIA
|
||||
|
||||
#include "sanitizer_fuchsia.h"
|
||||
#include "sanitizer_stacktrace.h"
|
||||
#include "sanitizer_symbolizer.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <unwind.h>
|
||||
|
||||
namespace __sanitizer {
|
||||
|
||||
// For Fuchsia we don't do any actual symbolization per se.
|
||||
@ -102,6 +106,47 @@ Symbolizer *Symbolizer::PlatformInit() {
|
||||
|
||||
void Symbolizer::LateInitialize() { Symbolizer::GetOrInit(); }
|
||||
|
||||
void StartReportDeadlySignal() {}
|
||||
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {}
|
||||
|
||||
struct UnwindTraceArg {
|
||||
BufferedStackTrace *stack;
|
||||
u32 max_depth;
|
||||
};
|
||||
|
||||
_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
|
||||
UnwindTraceArg *arg = static_cast<UnwindTraceArg *>(param);
|
||||
CHECK_LT(arg->stack->size, arg->max_depth);
|
||||
uptr pc = _Unwind_GetIP(ctx);
|
||||
if (pc < PAGE_SIZE) return _URC_NORMAL_STOP;
|
||||
arg->stack->trace_buffer[arg->stack->size++] = pc;
|
||||
return (arg->stack->size == arg->max_depth ? _URC_NORMAL_STOP
|
||||
: _URC_NO_REASON);
|
||||
}
|
||||
|
||||
void BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) {
|
||||
CHECK_GE(max_depth, 2);
|
||||
size = 0;
|
||||
UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
|
||||
_Unwind_Backtrace(Unwind_Trace, &arg);
|
||||
CHECK_GT(size, 0);
|
||||
// We need to pop a few frames so that pc is on top.
|
||||
uptr to_pop = LocatePcInTrace(pc);
|
||||
// trace_buffer[0] belongs to the current function so we always pop it,
|
||||
// unless there is only 1 frame in the stack trace (1 frame is always better
|
||||
// than 0!).
|
||||
PopStackFrames(Min(to_pop, static_cast<uptr>(1)));
|
||||
trace_buffer[0] = pc;
|
||||
}
|
||||
|
||||
void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
|
||||
u32 max_depth) {
|
||||
CHECK_NE(context, nullptr);
|
||||
UNREACHABLE("signal context doesn't exist");
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif // SANITIZER_FUCHSIA
|
||||
|
282
compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cc
Normal file
282
compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cc
Normal file
@ -0,0 +1,282 @@
|
||||
//===-- sanitizer_symbolizer_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 shared between AddressSanitizer and other sanitizer run-time
|
||||
/// libraries and implements symbolized reports related functions.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "sanitizer_common.h"
|
||||
#include "sanitizer_file.h"
|
||||
#include "sanitizer_flags.h"
|
||||
#include "sanitizer_procmaps.h"
|
||||
#include "sanitizer_report_decorator.h"
|
||||
#include "sanitizer_stacktrace.h"
|
||||
#include "sanitizer_stacktrace_printer.h"
|
||||
#include "sanitizer_symbolizer.h"
|
||||
|
||||
#if SANITIZER_POSIX
|
||||
# include "sanitizer_posix.h"
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
namespace __sanitizer {
|
||||
|
||||
#if !SANITIZER_GO
|
||||
void ReportErrorSummary(const char *error_type, const AddressInfo &info,
|
||||
const char *alt_tool_name) {
|
||||
if (!common_flags()->print_summary) return;
|
||||
InternalScopedString buff(kMaxSummaryLength);
|
||||
buff.append("%s ", error_type);
|
||||
RenderFrame(&buff, "%L %F", 0, info, common_flags()->symbolize_vs_style,
|
||||
common_flags()->strip_path_prefix);
|
||||
ReportErrorSummary(buff.data(), alt_tool_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SANITIZER_FUCHSIA
|
||||
|
||||
bool ReportFile::SupportsColors() {
|
||||
SpinMutexLock l(mu);
|
||||
ReopenIfNecessary();
|
||||
return SupportsColoredOutput(fd);
|
||||
}
|
||||
|
||||
static INLINE bool ReportSupportsColors() {
|
||||
return report_file.SupportsColors();
|
||||
}
|
||||
|
||||
#else // SANITIZER_FUCHSIA
|
||||
|
||||
// Fuchsia's logs always go through post-processing that handles colorization.
|
||||
static INLINE bool ReportSupportsColors() { return true; }
|
||||
|
||||
#endif // !SANITIZER_FUCHSIA
|
||||
|
||||
bool ColorizeReports() {
|
||||
// FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
|
||||
// printing on Windows.
|
||||
if (SANITIZER_WINDOWS)
|
||||
return false;
|
||||
|
||||
const char *flag = common_flags()->color;
|
||||
return internal_strcmp(flag, "always") == 0 ||
|
||||
(internal_strcmp(flag, "auto") == 0 && ReportSupportsColors());
|
||||
}
|
||||
|
||||
void ReportErrorSummary(const char *error_type, const StackTrace *stack,
|
||||
const char *alt_tool_name) {
|
||||
#if !SANITIZER_GO
|
||||
if (!common_flags()->print_summary)
|
||||
return;
|
||||
if (stack->size == 0) {
|
||||
ReportErrorSummary(error_type);
|
||||
return;
|
||||
}
|
||||
// Currently, we include the first stack frame into the report summary.
|
||||
// Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
|
||||
uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
|
||||
SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
|
||||
ReportErrorSummary(error_type, frame->info, alt_tool_name);
|
||||
frame->ClearAll();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ReportMmapWriteExec(int prot) {
|
||||
#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID)
|
||||
if ((prot & (PROT_WRITE | PROT_EXEC)) != (PROT_WRITE | PROT_EXEC))
|
||||
return;
|
||||
|
||||
ScopedErrorReportLock l;
|
||||
SanitizerCommonDecorator d;
|
||||
|
||||
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
|
||||
BufferedStackTrace *stack = stack_buffer.data();
|
||||
stack->Reset();
|
||||
uptr top = 0;
|
||||
uptr bottom = 0;
|
||||
GET_CALLER_PC_BP_SP;
|
||||
(void)sp;
|
||||
bool fast = common_flags()->fast_unwind_on_fatal;
|
||||
if (fast)
|
||||
GetThreadStackTopAndBottom(false, &top, &bottom);
|
||||
stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, fast);
|
||||
|
||||
Printf("%s", d.Warning());
|
||||
Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
|
||||
Printf("%s", d.Default());
|
||||
|
||||
stack->Print();
|
||||
ReportErrorSummary("w-and-x-usage", stack);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !SANITIZER_FUCHSIA && !SANITIZER_GO
|
||||
void StartReportDeadlySignal() {
|
||||
// Write the first message using fd=2, just in case.
|
||||
// It may actually fail to write in case stderr is closed.
|
||||
CatastrophicErrorWrite(SanitizerToolName, internal_strlen(SanitizerToolName));
|
||||
static const char kDeadlySignal[] = ":DEADLYSIGNAL\n";
|
||||
CatastrophicErrorWrite(kDeadlySignal, sizeof(kDeadlySignal) - 1);
|
||||
}
|
||||
|
||||
static void MaybeReportNonExecRegion(uptr pc) {
|
||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
|
||||
MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
|
||||
MemoryMappedSegment segment;
|
||||
while (proc_maps.Next(&segment)) {
|
||||
if (pc >= segment.start && pc < segment.end && !segment.IsExecutable())
|
||||
Report("Hint: PC is at a non-executable region. Maybe a wild jump?\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PrintMemoryByte(InternalScopedString *str, const char *before,
|
||||
u8 byte) {
|
||||
SanitizerCommonDecorator d;
|
||||
str->append("%s%s%x%x%s ", before, d.MemoryByte(), byte >> 4, byte & 15,
|
||||
d.Default());
|
||||
}
|
||||
|
||||
static void MaybeDumpInstructionBytes(uptr pc) {
|
||||
if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
|
||||
return;
|
||||
InternalScopedString str(1024);
|
||||
str.append("First 16 instruction bytes at pc: ");
|
||||
if (IsAccessibleMemoryRange(pc, 16)) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
PrintMemoryByte(&str, "", ((u8 *)pc)[i]);
|
||||
}
|
||||
str.append("\n");
|
||||
} else {
|
||||
str.append("unaccessible\n");
|
||||
}
|
||||
Report("%s", str.data());
|
||||
}
|
||||
|
||||
static void MaybeDumpRegisters(void *context) {
|
||||
if (!common_flags()->dump_registers) return;
|
||||
SignalContext::DumpAllRegisters(context);
|
||||
}
|
||||
|
||||
static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {
|
||||
SanitizerCommonDecorator d;
|
||||
Printf("%s", d.Warning());
|
||||
static const char kDescription[] = "stack-overflow";
|
||||
Report("ERROR: %s: %s on address %p (pc %p bp %p sp %p T%d)\n",
|
||||
SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
|
||||
(void *)sig.bp, (void *)sig.sp, tid);
|
||||
Printf("%s", d.Default());
|
||||
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
|
||||
BufferedStackTrace *stack = stack_buffer.data();
|
||||
stack->Reset();
|
||||
unwind(sig, unwind_context, stack);
|
||||
stack->Print();
|
||||
ReportErrorSummary(kDescription, stack);
|
||||
}
|
||||
|
||||
static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {
|
||||
SanitizerCommonDecorator d;
|
||||
Printf("%s", d.Warning());
|
||||
const char *description = sig.Describe();
|
||||
Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
|
||||
SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
|
||||
(void *)sig.bp, (void *)sig.sp, tid);
|
||||
Printf("%s", d.Default());
|
||||
if (sig.pc < GetPageSizeCached())
|
||||
Report("Hint: pc points to the zero page.\n");
|
||||
if (sig.is_memory_access) {
|
||||
const char *access_type =
|
||||
sig.write_flag == SignalContext::WRITE
|
||||
? "WRITE"
|
||||
: (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
|
||||
Report("The signal is caused by a %s memory access.\n", access_type);
|
||||
if (sig.addr < GetPageSizeCached())
|
||||
Report("Hint: address points to the zero page.\n");
|
||||
}
|
||||
MaybeReportNonExecRegion(sig.pc);
|
||||
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
|
||||
BufferedStackTrace *stack = stack_buffer.data();
|
||||
stack->Reset();
|
||||
unwind(sig, unwind_context, stack);
|
||||
stack->Print();
|
||||
MaybeDumpInstructionBytes(sig.pc);
|
||||
MaybeDumpRegisters(sig.context);
|
||||
Printf("%s can not provide additional info.\n", SanitizerToolName);
|
||||
ReportErrorSummary(description, stack);
|
||||
}
|
||||
|
||||
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {
|
||||
if (sig.IsStackOverflow())
|
||||
ReportStackOverflowImpl(sig, tid, unwind, unwind_context);
|
||||
else
|
||||
ReportDeadlySignalImpl(sig, tid, unwind, unwind_context);
|
||||
}
|
||||
|
||||
void HandleDeadlySignal(void *siginfo, void *context, u32 tid,
|
||||
UnwindSignalStackCallbackType unwind,
|
||||
const void *unwind_context) {
|
||||
StartReportDeadlySignal();
|
||||
ScopedErrorReportLock rl;
|
||||
SignalContext sig(siginfo, context);
|
||||
ReportDeadlySignal(sig, tid, unwind, unwind_context);
|
||||
Report("ABORTING\n");
|
||||
Die();
|
||||
}
|
||||
|
||||
#endif // !SANITIZER_FUCHSIA && !SANITIZER_GO
|
||||
|
||||
static atomic_uintptr_t reporting_thread = {0};
|
||||
static StaticSpinMutex CommonSanitizerReportMutex;
|
||||
|
||||
ScopedErrorReportLock::ScopedErrorReportLock() {
|
||||
uptr current = GetThreadSelf();
|
||||
for (;;) {
|
||||
uptr expected = 0;
|
||||
if (atomic_compare_exchange_strong(&reporting_thread, &expected, current,
|
||||
memory_order_relaxed)) {
|
||||
// We've claimed reporting_thread so proceed.
|
||||
CommonSanitizerReportMutex.Lock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (expected == current) {
|
||||
// This is either asynch signal or nested error during error reporting.
|
||||
// Fail simple to avoid deadlocks in Report().
|
||||
|
||||
// Can't use Report() here because of potential deadlocks in nested
|
||||
// signal handlers.
|
||||
CatastrophicErrorWrite(SanitizerToolName,
|
||||
internal_strlen(SanitizerToolName));
|
||||
static const char msg[] = ": nested bug in the same thread, aborting.\n";
|
||||
CatastrophicErrorWrite(msg, sizeof(msg) - 1);
|
||||
|
||||
internal__exit(common_flags()->exitcode);
|
||||
}
|
||||
|
||||
internal_sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
ScopedErrorReportLock::~ScopedErrorReportLock() {
|
||||
CommonSanitizerReportMutex.Unlock();
|
||||
atomic_store_relaxed(&reporting_thread, 0);
|
||||
}
|
||||
|
||||
void ScopedErrorReportLock::CheckLocked() {
|
||||
CommonSanitizerReportMutex.CheckLocked();
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
@ -178,7 +178,8 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID)
|
||||
if(APPLE)
|
||||
add_sanitizer_common_lib("RTSanitizerCommon.test.osx"
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.osx>)
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.osx>)
|
||||
else()
|
||||
if(CAN_TARGET_x86_64)
|
||||
add_sanitizer_common_lib("RTSanitizerCommon.test.nolibc.x86_64"
|
||||
@ -188,7 +189,8 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID)
|
||||
foreach(arch ${SANITIZER_UNITTEST_SUPPORTED_ARCH})
|
||||
add_sanitizer_common_lib("RTSanitizerCommon.test.${arch}"
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>)
|
||||
endforeach()
|
||||
endif()
|
||||
foreach(arch ${SANITIZER_UNITTEST_SUPPORTED_ARCH})
|
||||
@ -202,7 +204,8 @@ if(ANDROID)
|
||||
${SANITIZER_UNITTESTS}
|
||||
${COMPILER_RT_GTEST_SOURCE}
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>)
|
||||
set_target_compile_flags(SanitizerTest
|
||||
${SANITIZER_COMMON_CFLAGS}
|
||||
${SANITIZER_TEST_CFLAGS_COMMON})
|
||||
|
@ -25,10 +25,11 @@ set(SCUDO_OBJECT_LIBS
|
||||
if (FUCHSIA)
|
||||
list(APPEND SCUDO_CFLAGS -nostdinc++)
|
||||
list(APPEND SCUDO_DYNAMIC_LINK_FLAGS -nostdlib++)
|
||||
# TODO(kostyak): remove when stacktraces are split off of RTSanitizerCommon
|
||||
list(APPEND SCUDO_DYNAMIC_LIBS unwind_shared)
|
||||
else()
|
||||
list(APPEND SCUDO_OBJECT_LIBS RTSanitizerCommonCoverage RTUbsan)
|
||||
list(APPEND SCUDO_OBJECT_LIBS
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTUbsan)
|
||||
list(APPEND SCUDO_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARY})
|
||||
endif()
|
||||
|
||||
|
@ -115,6 +115,7 @@ if(APPLE)
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTUbsan
|
||||
CFLAGS ${TSAN_RTL_CFLAGS}
|
||||
LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS}
|
||||
@ -174,6 +175,7 @@ else()
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>
|
||||
CFLAGS ${TSAN_RTL_CFLAGS}
|
||||
PARENT_TARGET tsan)
|
||||
|
@ -35,6 +35,7 @@ SRCS="
|
||||
../../sanitizer_common/sanitizer_stackdepot.cc
|
||||
../../sanitizer_common/sanitizer_stacktrace.cc
|
||||
../../sanitizer_common/sanitizer_symbolizer.cc
|
||||
../../sanitizer_common/sanitizer_symbolizer_report.cc
|
||||
../../sanitizer_common/sanitizer_termination.cc
|
||||
"
|
||||
|
||||
|
@ -23,6 +23,7 @@ if(APPLE)
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonCoverage.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.osx>
|
||||
$<TARGET_OBJECTS:RTUbsan.osx>)
|
||||
set(TSAN_TEST_RUNTIME RTTsanTest)
|
||||
add_library(${TSAN_TEST_RUNTIME} STATIC ${TSAN_TEST_RUNTIME_OBJECTS})
|
||||
|
@ -77,6 +77,7 @@ if(APPLE)
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTInterception
|
||||
LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS}
|
||||
PARENT_TARGET ubsan)
|
||||
@ -90,6 +91,7 @@ if(APPLE)
|
||||
RTSanitizerCommonNoHooks
|
||||
RTSanitizerCommonLibcNoHooks
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTInterception
|
||||
LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS}
|
||||
PARENT_TARGET ubsan)
|
||||
@ -157,6 +159,7 @@ else()
|
||||
OBJECT_LIBS RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTUbsan
|
||||
RTUbsan_standalone
|
||||
RTInterception
|
||||
@ -177,6 +180,7 @@ else()
|
||||
OBJECT_LIBS RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
RTSanitizerCommonCoverage
|
||||
RTSanitizerCommonSymbolizer
|
||||
RTUbsan
|
||||
RTUbsan_cxx
|
||||
RTUbsan_standalone
|
||||
|
Loading…
x
Reference in New Issue
Block a user