[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