summaryrefslogtreecommitdiff
path: root/lib/ubsan
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-08-22 21:42:04 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-08-22 21:42:04 +0000
commit4cc09bc1b2697b131b2b7a5126c92d90283e6140 (patch)
treeced65a4f49ffc7e58897efff8761a9346c468848 /lib/ubsan
parent93497aeca041c0157c8a47b48bcbf9a2195e9040 (diff)
[UBSan] Add support for printing backtraces to all UBSan handlers
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@216289 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ubsan')
-rw-r--r--lib/ubsan/ubsan_diag.cc8
-rw-r--r--lib/ubsan/ubsan_diag.h20
-rw-r--r--lib/ubsan/ubsan_handlers.cc118
-rw-r--r--lib/ubsan/ubsan_handlers.h10
-rw-r--r--lib/ubsan/ubsan_handlers_cxx.cc14
5 files changed, 102 insertions, 68 deletions
diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc
index 2fca8d1c2..26f34376f 100644
--- a/lib/ubsan/ubsan_diag.cc
+++ b/lib/ubsan/ubsan_diag.cc
@@ -21,7 +21,7 @@
using namespace __ubsan;
-void __ubsan::MaybePrintStackTrace(uptr pc, uptr bp) {
+static void MaybePrintStackTrace(uptr pc, uptr bp) {
// We assume that flags are already parsed: InitIfNecessary
// will definitely be called when we print the first diagnostics message.
if (!flags()->print_stacktrace)
@@ -301,15 +301,15 @@ Diag::~Diag() {
NumRanges, Args);
}
-ScopedReport::ScopedReport(bool DieAfterReport)
- : DieAfterReport(DieAfterReport) {
+ScopedReport::ScopedReport(ReportOptions Opts) : Opts(Opts) {
InitIfNecessary();
CommonSanitizerReportMutex.Lock();
}
ScopedReport::~ScopedReport() {
+ MaybePrintStackTrace(Opts.pc, Opts.bp);
CommonSanitizerReportMutex.Unlock();
- if (DieAfterReport)
+ if (Opts.DieAfterReport)
Die();
}
diff --git a/lib/ubsan/ubsan_diag.h b/lib/ubsan/ubsan_diag.h
index 77aaa6764..b2fe735a2 100644
--- a/lib/ubsan/ubsan_diag.h
+++ b/lib/ubsan/ubsan_diag.h
@@ -205,17 +205,27 @@ public:
Diag &operator<<(const Range &R) { return AddRange(R); }
};
-void MaybePrintStackTrace(uptr pc, uptr bp);
+struct ReportOptions {
+ /// If DieAfterReport is specified, UBSan will terminate the program after the
+ /// report is printed.
+ bool DieAfterReport;
+ /// pc/bp are used to unwind the stack trace.
+ uptr pc;
+ uptr bp;
+};
+
+#define GET_REPORT_OPTIONS(die_after_report) \
+ GET_CALLER_PC_BP; \
+ ReportOptions Opts = {die_after_report, pc, bp}
/// \brief Instantiate this class before printing diagnostics in the error
/// report. This class ensures that reports from different threads and from
-/// different sanitizers won't be mixed. If DieAfterReport is specified, it
-/// will terminate the program in the destructor.
+/// different sanitizers won't be mixed.
class ScopedReport {
- bool DieAfterReport;
+ ReportOptions Opts;
public:
- ScopedReport(bool DieAfterReport);
+ ScopedReport(ReportOptions Opts);
~ScopedReport();
};
diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc
index 14b12b6a9..154cbc893 100644
--- a/lib/ubsan/ubsan_handlers.cc
+++ b/lib/ubsan/ubsan_handlers.cc
@@ -27,13 +27,13 @@ namespace __ubsan {
}
static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
- Location FallbackLoc, bool Abort) {
+ Location FallbackLoc, ReportOptions Opts) {
Location Loc = Data->Loc.acquire();
// Use the SourceLocation from Data to track deduplication, even if 'invalid'
if (Loc.getSourceLocation().isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
if (Data->Loc.isInvalid())
Loc = FallbackLoc;
@@ -56,22 +56,25 @@ static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
ValueHandle Pointer) {
- handleTypeMismatchImpl(Data, Pointer, getCallerLocation(), false);
+ GET_REPORT_OPTIONS(false);
+ handleTypeMismatchImpl(Data, Pointer, getCallerLocation(), Opts);
}
void __ubsan::__ubsan_handle_type_mismatch_abort(TypeMismatchData *Data,
ValueHandle Pointer) {
- handleTypeMismatchImpl(Data, Pointer, getCallerLocation(), true);
+ GET_REPORT_OPTIONS(true);
+ handleTypeMismatchImpl(Data, Pointer, getCallerLocation(), Opts);
}
/// \brief Common diagnostic emission for various forms of integer overflow.
template <typename T>
static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
- const char *Operator, T RHS, bool Abort) {
+ const char *Operator, T RHS,
+ ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Diag(Loc, DL_Error, "%0 integer overflow: "
"%1 %2 %3 cannot be represented in type %4")
@@ -82,7 +85,8 @@ static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
#define UBSAN_OVERFLOW_HANDLER(handler_name, op, abort) \
void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \
ValueHandle RHS) { \
- handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), abort); \
+ GET_REPORT_OPTIONS(abort); \
+ handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \
}
UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
@@ -93,12 +97,12 @@ UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false)
UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true)
static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
- bool Abort) {
+ ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
if (Data->Type.isSignedIntegerTy())
Diag(Loc, DL_Error,
@@ -113,20 +117,22 @@ static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
ValueHandle OldVal) {
- handleNegateOverflowImpl(Data, OldVal, false);
+ GET_REPORT_OPTIONS(false);
+ handleNegateOverflowImpl(Data, OldVal, Opts);
}
void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
ValueHandle OldVal) {
- handleNegateOverflowImpl(Data, OldVal, true);
+ GET_REPORT_OPTIONS(true);
+ handleNegateOverflowImpl(Data, OldVal, Opts);
}
static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
- ValueHandle RHS, bool Abort) {
+ ValueHandle RHS, ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Value LHSVal(Data->Type, LHS);
Value RHSVal(Data->Type, RHS);
@@ -140,22 +146,24 @@ static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
ValueHandle LHS, ValueHandle RHS) {
- handleDivremOverflowImpl(Data, LHS, RHS, false);
+ GET_REPORT_OPTIONS(false);
+ handleDivremOverflowImpl(Data, LHS, RHS, Opts);
}
void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
ValueHandle LHS,
ValueHandle RHS) {
- handleDivremOverflowImpl(Data, LHS, RHS, true);
+ GET_REPORT_OPTIONS(true);
+ handleDivremOverflowImpl(Data, LHS, RHS, Opts);
}
static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
ValueHandle LHS, ValueHandle RHS,
- bool Abort) {
+ ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Value LHSVal(Data->LHSType, LHS);
Value RHSVal(Data->RHSType, RHS);
@@ -176,22 +184,24 @@ static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
ValueHandle LHS,
ValueHandle RHS) {
- handleShiftOutOfBoundsImpl(Data, LHS, RHS, false);
+ GET_REPORT_OPTIONS(false);
+ handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
}
void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
ShiftOutOfBoundsData *Data,
ValueHandle LHS,
ValueHandle RHS) {
- handleShiftOutOfBoundsImpl(Data, LHS, RHS, true);
+ GET_REPORT_OPTIONS(true);
+ handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
}
static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
- bool Abort) {
+ ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Value IndexVal(Data->IndexType, Index);
Diag(Loc, DL_Error, "index %0 out of bounds for type %1")
@@ -200,32 +210,36 @@ static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
ValueHandle Index) {
- handleOutOfBoundsImpl(Data, Index, false);
+ GET_REPORT_OPTIONS(false);
+ handleOutOfBoundsImpl(Data, Index, Opts);
}
void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
ValueHandle Index) {
- handleOutOfBoundsImpl(Data, Index, true);
+ GET_REPORT_OPTIONS(true);
+ handleOutOfBoundsImpl(Data, Index, Opts);
}
void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
- ScopedReport R(true);
+ GET_REPORT_OPTIONS(true);
+ ScopedReport R(Opts);
Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call");
}
void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
- ScopedReport R(true);
+ GET_REPORT_OPTIONS(true);
+ ScopedReport R(Opts);
Diag(Data->Loc, DL_Error,
"execution reached the end of a value-returning function "
"without returning a value");
}
static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
- bool Abort) {
+ ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Diag(Loc, DL_Error, "variable length array bound evaluates to "
"non-positive value %0")
@@ -234,18 +248,19 @@ static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
ValueHandle Bound) {
- handleVLABoundNotPositive(Data, Bound, false);
+ GET_REPORT_OPTIONS(false);
+ handleVLABoundNotPositive(Data, Bound, Opts);
}
void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
ValueHandle Bound) {
- handleVLABoundNotPositive(Data, Bound, true);
+ GET_REPORT_OPTIONS(true);
+ handleVLABoundNotPositive(Data, Bound, Opts);
}
-
-static void handleFloatCastOverflow(FloatCastOverflowData *Data, ValueHandle From,
- bool Abort) {
+static void handleFloatCastOverflow(FloatCastOverflowData *Data,
+ ValueHandle From, ReportOptions Opts) {
// TODO: Add deduplication once a SourceLocation is generated for this check.
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Diag(getCallerLocation(), DL_Error,
"value %0 is outside the range of representable values of type %2")
@@ -254,21 +269,23 @@ static void handleFloatCastOverflow(FloatCastOverflowData *Data, ValueHandle Fro
void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data,
ValueHandle From) {
- handleFloatCastOverflow(Data, From, false);
+ GET_REPORT_OPTIONS(false);
+ handleFloatCastOverflow(Data, From, Opts);
}
void
__ubsan::__ubsan_handle_float_cast_overflow_abort(FloatCastOverflowData *Data,
ValueHandle From) {
- handleFloatCastOverflow(Data, From, true);
+ GET_REPORT_OPTIONS(true);
+ handleFloatCastOverflow(Data, From, Opts);
}
static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
- bool Abort) {
+ ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Diag(Loc, DL_Error,
"load of value %0, which is not a valid value for type %1")
@@ -277,20 +294,23 @@ static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
ValueHandle Val) {
- handleLoadInvalidValue(Data, Val, false);
+ GET_REPORT_OPTIONS(false);
+ handleLoadInvalidValue(Data, Val, Opts);
}
void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
ValueHandle Val) {
- handleLoadInvalidValue(Data, Val, true);
+ GET_REPORT_OPTIONS(true);
+ handleLoadInvalidValue(Data, Val, Opts);
}
static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
- ValueHandle Function, bool Abort) {
+ ValueHandle Function,
+ ReportOptions Opts) {
const char *FName = "(unknown)";
Location Loc = getFunctionLocation(Function, &FName);
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Diag(Data->Loc, DL_Error,
"call to function %0 through pointer to incorrect function type %1")
@@ -301,29 +321,33 @@ static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
void
__ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
ValueHandle Function) {
- handleFunctionTypeMismatch(Data, Function, false);
+ GET_REPORT_OPTIONS(false);
+ handleFunctionTypeMismatch(Data, Function, Opts);
}
void __ubsan::__ubsan_handle_function_type_mismatch_abort(
FunctionTypeMismatchData *Data, ValueHandle Function) {
- handleFunctionTypeMismatch(Data, Function, true);
+ GET_REPORT_OPTIONS(true);
+ handleFunctionTypeMismatch(Data, Function, Opts);
}
-static void handleNonnullReturn(NonNullReturnData *Data, bool Abort) {
+static void handleNonnullReturn(NonNullReturnData *Data, ReportOptions Opts) {
SourceLocation Loc = Data->Loc.acquire();
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Diag(Loc, DL_Error, "null pointer returned from function declared to never "
"return null");
}
void __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) {
- handleNonnullReturn(Data, false);
+ GET_REPORT_OPTIONS(false);
+ handleNonnullReturn(Data, Opts);
}
void __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) {
- handleNonnullReturn(Data, true);
+ GET_REPORT_OPTIONS(true);
+ handleNonnullReturn(Data, Opts);
}
diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h
index 910198c51..4a4da43ee 100644
--- a/lib/ubsan/ubsan_handlers.h
+++ b/lib/ubsan/ubsan_handlers.h
@@ -24,6 +24,10 @@ struct TypeMismatchData {
unsigned char TypeCheckKind;
};
+#define UNRECOVERABLE(checkname, ...) \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE \
+ void __ubsan_handle_ ## checkname( __VA_ARGS__ );
+
#define RECOVERABLE(checkname, ...) \
extern "C" SANITIZER_INTERFACE_ATTRIBUTE \
void __ubsan_handle_ ## checkname( __VA_ARGS__ ); \
@@ -81,11 +85,9 @@ struct UnreachableData {
};
/// \brief Handle a __builtin_unreachable which is reached.
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-void __ubsan_handle_builtin_unreachable(UnreachableData *Data);
+UNRECOVERABLE(builtin_unreachable, UnreachableData *Data)
/// \brief Handle reaching the end of a value-returning function.
-extern "C" SANITIZER_INTERFACE_ATTRIBUTE
-void __ubsan_handle_missing_return(UnreachableData *Data);
+UNRECOVERABLE(missing_return, UnreachableData *Data)
struct VLABoundData {
SourceLocation Loc;
diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc
index 4002e61ef..fa244c85d 100644
--- a/lib/ubsan/ubsan_handlers_cxx.cc
+++ b/lib/ubsan/ubsan_handlers_cxx.cc
@@ -29,7 +29,7 @@ namespace __ubsan {
static void HandleDynamicTypeCacheMiss(
DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash,
- bool Abort, uptr pc, uptr bp) {
+ ReportOptions Opts) {
if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash))
// Just a cache miss. The type matches after all.
return;
@@ -44,7 +44,7 @@ static void HandleDynamicTypeCacheMiss(
if (Loc.isDisabled())
return;
- ScopedReport R(Abort);
+ ScopedReport R(Opts);
Diag(Loc, DL_Error,
"%0 address %1 which does not point to an object of type %2")
@@ -68,17 +68,15 @@ static void HandleDynamicTypeCacheMiss(
<< MangledName(DTI.getSubobjectTypeName())
<< Range(Pointer, Pointer + sizeof(uptr),
"vptr for %2 base class of %1");
-
- MaybePrintStackTrace(pc, bp);
}
void __ubsan::__ubsan_handle_dynamic_type_cache_miss(
DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
- GET_CALLER_PC_BP;
- HandleDynamicTypeCacheMiss(Data, Pointer, Hash, false, pc, bp);
+ GET_REPORT_OPTIONS(false);
+ HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
}
void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort(
DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
- GET_CALLER_PC_BP;
- HandleDynamicTypeCacheMiss(Data, Pointer, Hash, true, pc, bp);
+ GET_REPORT_OPTIONS(true);
+ HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
}