[llvm-commits] [compiler-rt] r170407 - in /compiler-rt/trunk/lib/ubsan: lit_tests/Misc/bool.cpp lit_tests/TypeCheck/misaligned.cpp ubsan_diag.cc ubsan_diag.h ubsan_handlers.cc
Richard Smith
richard-llvm at metafoo.co.uk
Mon Dec 17 20:23:19 PST 2012
Author: rsmith
Date: Mon Dec 17 22:23:18 2012
New Revision: 170407
URL: http://llvm.org/viewvc/llvm-project?rev=170407&view=rev
Log:
ubsan: if the frontend didn't provide us with a source location, try to work
one out from the return address. Currently, we can only resolve this address to
a file and line number if we have an external symbolizer.
Modified:
compiler-rt/trunk/lib/ubsan/lit_tests/Misc/bool.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp
compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
compiler-rt/trunk/lib/ubsan/ubsan_diag.h
compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
Modified: compiler-rt/trunk/lib/ubsan/lit_tests/Misc/bool.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Misc/bool.cpp?rev=170407&r1=170406&r2=170407&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Misc/bool.cpp (original)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Misc/bool.cpp Mon Dec 17 22:23:18 2012
@@ -1,10 +1,11 @@
-// RUN: %clang -fsanitize=bool %s -O3 -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clang -fsanitize=bool %s -O3 -o %T/bool.exe && %T/bool.exe 2>&1 | FileCheck %s
unsigned char NotABool = 123;
int main(int argc, char **argv) {
bool *p = (bool*)&NotABool;
- // CHECK: error: load of value 123, which is not a valid value for type 'bool'
+ // FIXME: Provide a better source location here.
+ // CHECK: bool.exe:0x{{[0-9a-f]*}}: runtime error: load of value 123, which is not a valid value for type 'bool'
return *p;
}
Modified: compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp?rev=170407&r1=170406&r2=170407&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp (original)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp Mon Dec 17 22:23:18 2012
@@ -1,12 +1,16 @@
// RUN: %clang -fsanitize=alignment %s -O3 -o %t
-// RUN: %t l0 && %t s0 && %t r0 && %t m0 && %t f0
+// RUN: %t l0 && %t s0 && %t r0 && %t m0 && %t f0 && %t n0
// RUN: %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD
// RUN: %t s1 2>&1 | FileCheck %s --check-prefix=CHECK-STORE
// RUN: %t r1 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
// RUN: %t m1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
// RUN: %t f1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
+// RUN: %t n1 2>&1 | FileCheck %s --check-prefix=CHECK-NEW
+
+#include <new>
struct S {
+ S() {}
int f() { return 0; }
int k;
};
@@ -22,21 +26,25 @@
switch (argv[1][0]) {
case 'l':
- // CHECK-LOAD: misaligned.cpp:26:12: runtime error: load of misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
+ // CHECK-LOAD: misaligned.cpp:[[@LINE+1]]:12: runtime error: load of misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
return *p;
case 's':
- // CHECK-STORE: misaligned.cpp:29:5: runtime error: store to misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
+ // CHECK-STORE: misaligned.cpp:[[@LINE+1]]:5: runtime error: store to misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
*p = 1;
break;
case 'r':
- // CHECK-REFERENCE: misaligned.cpp:33:15: runtime error: reference binding to misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
+ // CHECK-REFERENCE: misaligned.cpp:[[@LINE+1]]:15: runtime error: reference binding to misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
{int &r = *p;}
break;
case 'm':
- // CHECK-MEMBER: misaligned.cpp:37:15: runtime error: member access within misaligned address 0x{{[0-9a-f]*}} for type 'S', which requires 4 byte alignment
+ // CHECK-MEMBER: misaligned.cpp:[[@LINE+1]]:15: runtime error: member access within misaligned address 0x{{[0-9a-f]*}} for type 'S', which requires 4 byte alignment
return s->k;
case 'f':
- // CHECK-MEMFUN: misaligned.cpp:40:12: runtime error: member call on misaligned address 0x{{[0-9a-f]*}} for type 'S', which requires 4 byte alignment
+ // CHECK-MEMFUN: misaligned.cpp:[[@LINE+1]]:12: runtime error: member call on misaligned address 0x{{[0-9a-f]*}} for type 'S', which requires 4 byte alignment
return s->f();
+ case 'n':
+ // FIXME: Provide a better source location here.
+ // CHECK-NEW: misaligned{{.*}}:0x{{[0-9a-f]*}}: runtime error: constructor call on misaligned address 0x{{[0-9a-f]*}} for type 'S', which requires 4 byte alignment
+ return (new (s) S)->k;
}
}
Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=170407&r1=170406&r2=170407&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Mon Dec 17 22:23:18 2012
@@ -14,10 +14,30 @@
#include "ubsan_diag.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
#include <stdio.h>
using namespace __ubsan;
+Location __ubsan::getCallerLocation(uptr CallerLoc) {
+ if (!CallerLoc)
+ return Location();
+
+ // Adjust to find the call instruction.
+ // FIXME: This is not portable.
+ --CallerLoc;
+
+ AddressInfo Info;
+ if (!SymbolizeCode(CallerLoc, &Info, 1) || !Info.module || !*Info.module)
+ return Location(CallerLoc);
+
+ if (!Info.function)
+ return ModuleLocation(Info.module, Info.module_offset);
+
+ return SourceLocation(Info.file, Info.line, Info.column);
+}
+
Diag &Diag::operator<<(const TypeDescriptor &V) {
return AddArg(V.getTypeName());
}
@@ -47,19 +67,41 @@
#endif
}
+static void renderLocation(Location Loc) {
+ switch (Loc.getKind()) {
+ case Location::LK_Source: {
+ SourceLocation SLoc = Loc.getSourceLocation();
+ if (SLoc.isInvalid())
+ RawWrite("<unknown>:");
+ else {
+ Printf("%s:%d:", SLoc.getFilename(), SLoc.getLine());
+ if (SLoc.getColumn())
+ Printf("%d:", SLoc.getColumn());
+ }
+ break;
+ }
+ case Location::LK_Module:
+ Printf("%s:0x%zx:", Loc.getModuleLocation().getModuleName(),
+ Loc.getModuleLocation().getOffset());
+ break;
+ case Location::LK_Memory:
+ Printf("0x%zx:", Loc.getMemoryLocation());
+ break;
+ case Location::LK_Null:
+ RawWrite("<unknown>:");
+ }
+}
+
Diag::~Diag() {
bool UseAnsiColor = PrintsToTty();
if (UseAnsiColor)
RawWrite("\033[1m");
- if (Loc.isInvalid())
- RawWrite("<unknown>:");
- else {
- Printf("%s:%d:", Loc.getFilename(), Loc.getLine());
- if (Loc.getColumn())
- Printf("%d:", Loc.getColumn());
- }
+
+ renderLocation(Loc);
+
if (UseAnsiColor)
RawWrite("\033[31m");
+
RawWrite(" runtime error: ");
if (UseAnsiColor)
RawWrite("\033[0;1m");
Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.h?rev=170407&r1=170406&r2=170407&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.h (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.h Mon Dec 17 22:23:18 2012
@@ -17,14 +17,77 @@
namespace __ubsan {
+/// \brief A location within a loaded module in the program. These are used when
+/// the location can't be resolved to a SourceLocation.
+class ModuleLocation {
+ const char *ModuleName;
+ uptr Offset;
+
+public:
+ ModuleLocation() : ModuleName(0), Offset(0) {}
+ ModuleLocation(const char *ModuleName, uptr Offset)
+ : ModuleName(ModuleName), Offset(Offset) {}
+ const char *getModuleName() const { return ModuleName; }
+ uptr getOffset() const { return Offset; }
+};
+
+/// A location of some data within the program's address space.
+typedef uptr MemoryLocation;
+
+/// \brief Location at which a diagnostic can be emitted. Either a
+/// SourceLocation, a ModuleLocation, or a MemoryLocation.
+class Location {
+public:
+ enum LocationKind { LK_Null, LK_Source, LK_Module, LK_Memory };
+
+private:
+ LocationKind Kind;
+ // FIXME: In C++11, wrap these in an anonymous union.
+ SourceLocation SourceLoc;
+ ModuleLocation ModuleLoc;
+ MemoryLocation MemoryLoc;
+
+public:
+ Location() : Kind(LK_Null) {}
+ Location(SourceLocation Loc) :
+ Kind(LK_Source), SourceLoc(Loc) {}
+ Location(ModuleLocation Loc) :
+ Kind(LK_Module), ModuleLoc(Loc) {}
+ Location(MemoryLocation Loc) :
+ Kind(LK_Memory), MemoryLoc(Loc) {}
+
+ LocationKind getKind() const { return Kind; }
+
+ bool isSourceLocation() const { return Kind == LK_Source; }
+ bool isModuleLocation() const { return Kind == LK_Module; }
+ bool isMemoryLocation() const { return Kind == LK_Memory; }
+
+ SourceLocation getSourceLocation() const {
+ CHECK(isSourceLocation());
+ return SourceLoc;
+ }
+ ModuleLocation getModuleLocation() const {
+ CHECK(isModuleLocation());
+ return ModuleLoc;
+ }
+ MemoryLocation getMemoryLocation() const {
+ CHECK(isMemoryLocation());
+ return MemoryLoc;
+ }
+};
+
+/// Try to obtain a location for the caller. This might fail, and produce either
+/// an invalid location or a module location for the caller.
+Location getCallerLocation(uptr CallerLoc = GET_CALLER_PC());
+
/// \brief Representation of an in-flight diagnostic.
///
/// Temporary \c Diag instances are created by the handler routines to
/// accumulate arguments for a diagnostic. The destructor emits the diagnostic
/// message.
class Diag {
- /// The source location at which the problem occurred.
- const SourceLocation &Loc;
+ /// The location at which the problem occurred.
+ Location Loc;
/// The message which will be emitted, with %0, %1, ... placeholders for
/// arguments.
@@ -75,7 +138,7 @@
Diag &operator=(const Diag &);
public:
- Diag(const SourceLocation &Loc, const char *Message)
+ Diag(Location Loc, const char *Message)
: Loc(Loc), Message(Message), NumArgs(0) {}
~Diag();
Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc?rev=170407&r1=170406&r2=170407&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc Mon Dec 17 22:23:18 2012
@@ -26,24 +26,32 @@
};
}
-void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
- ValueHandle Pointer) {
+static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
+ Location FallbackLoc) {
+ Location Loc = Data->Loc;
+ if (Data->Loc.isInvalid())
+ Loc = FallbackLoc;
+
if (!Pointer)
- Diag(Data->Loc, "%0 null pointer of type %1")
+ Diag(Loc, "%0 null pointer of type %1")
<< TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
else if (Data->Alignment && (Pointer & (Data->Alignment - 1)))
- Diag(Data->Loc, "%0 misaligned address %1 for type %3, "
- "which requires %2 byte alignment")
+ Diag(Loc, "%0 misaligned address %1 for type %3, "
+ "which requires %2 byte alignment")
<< TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer
<< Data->Alignment << Data->Type;
else
- Diag(Data->Loc, "%0 address %1 with insufficient space "
- "for an object of type %2")
+ Diag(Loc, "%0 address %1 with insufficient space "
+ "for an object of type %2")
<< TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
}
+void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
+ ValueHandle Pointer) {
+ handleTypeMismatchImpl(Data, Pointer, getCallerLocation());
+}
void __ubsan::__ubsan_handle_type_mismatch_abort(TypeMismatchData *Data,
- ValueHandle Pointer) {
- __ubsan_handle_type_mismatch(Data, Pointer);
+ ValueHandle Pointer) {
+ handleTypeMismatchImpl(Data, Pointer, getCallerLocation());
Die();
}
@@ -167,27 +175,32 @@
Die();
}
+
void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data,
ValueHandle From) {
- Diag(SourceLocation(), "value %0 is outside the range of representable "
- "values of type %2")
+ Diag(getCallerLocation(), "value %0 is outside the range of representable "
+ "values of type %2")
<< Value(Data->FromType, From) << Data->FromType << Data->ToType;
}
void __ubsan::__ubsan_handle_float_cast_overflow_abort(
FloatCastOverflowData *Data,
ValueHandle From) {
- __ubsan_handle_float_cast_overflow(Data, From);
+ Diag(getCallerLocation(), "value %0 is outside the range of representable "
+ "values of type %2")
+ << Value(Data->FromType, From) << Data->FromType << Data->ToType;
Die();
}
void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
ValueHandle Val) {
- Diag(SourceLocation(), "load of value %0, which is not a valid value for "
- "type %1")
+ Diag(getCallerLocation(), "load of value %0, which is not a valid value for "
+ "type %1")
<< Value(Data->Type, Val) << Data->Type;
}
void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
ValueHandle Val) {
- __ubsan_handle_load_invalid_value(Data, Val);
+ Diag(getCallerLocation(), "load of value %0, which is not a valid value for "
+ "type %1")
+ << Value(Data->Type, Val) << Data->Type;
Die();
}
More information about the llvm-commits
mailing list