<div style="font-family: arial, helvetica, sans-serif; font-size: 10pt"><br><br><div class="gmail_quote">On Tue, Dec 18, 2012 at 1:30 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Tue Dec 18 03:30:21 2012<br>
New Revision: 170423<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=170423&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=170423&view=rev</a><br>
Log:<br>
ubsan: Demangle class names, and be more informative when a reinterpret_cast<br>
has got us to the wrong offset within an object.<br>
<br>
Modified:<br>
    compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp<br>
    compiler-rt/trunk/lib/ubsan/ubsan_diag.cc<br>
    compiler-rt/trunk/lib/ubsan/ubsan_diag.h<br>
    compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc<br>
    compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc<br>
    compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp?rev=170423&r1=170422&r2=170423&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp?rev=170423&r1=170422&r2=170423&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp (original)<br>
+++ compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp Tue Dec 18 03:30:21 2012<br>
@@ -75,7 +75,7 @@<br>
<br>
   case 'm':<br>
     // CHECK-MEMBER: vptr.cpp:[[@LINE+5]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'<br>
-    // CHECK-MEMBER-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:1S|1U]]<br>
+    // CHECK-MEMBER-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']]<br>
     // CHECK-MEMBER-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }}<br>
     // CHECK-MEMBER-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}<br>
     // CHECK-MEMBER-NEXT: {{^              vptr for}} [[DYN_TYPE]]<br>
@@ -89,7 +89,7 @@<br>
<br>
   case 'f':<br>
     // CHECK-MEMFUN: vptr.cpp:[[@LINE+5]]:12: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'<br>
-    // CHECK-MEMFUN-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:1S|1U]]<br>
+    // CHECK-MEMFUN-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']]<br>
     // CHECK-MEMFUN-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }}<br>
     // CHECK-MEMFUN-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}<br>
     // CHECK-MEMFUN-NEXT: {{^              vptr for}} [[DYN_TYPE]]<br>
@@ -97,10 +97,10 @@<br>
<br>
   case 'o':<br>
     // CHECK-OFFSET: vptr.cpp:[[@LINE+5]]:12: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'U'<br>
-    // CHECK-OFFSET-NEXT: 0x{{[0-9a-f]*}}: note: object is base class subobject at offset {{8|16}} within object of type [[DYN_TYPE:1U]]<br>
+    // CHECK-OFFSET-NEXT: 0x{{[0-9a-f]*}}: note: object is base class subobject at offset {{8|16}} within object of type [[DYN_TYPE:'U']]<br>
     // CHECK-OFFSET-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  .. .. .. .. .. .. .. ..  .. .. .. .. .. .. .. ..  }}<br>
     // CHECK-OFFSET-NEXT: {{^              \^                        (                         ~~~~~~~~~~~~)~~~~~~~~~~~ *$}}<br>
-    // CHECK-OFFSET-NEXT: {{^                                       (                         )?vptr for}} [[DYN_TYPE]]<br>
+    // CHECK-OFFSET-NEXT: {{^                                       (                         )?vptr for}} 'T' base class of [[DYN_TYPE]]<br>
     return reinterpret_cast<U*>(p)->v() - 2;<br>
   }<br>
 }<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=170423&r1=170422&r2=170423&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=170423&r1=170422&r2=170423&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (original)<br>
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Tue Dec 18 03:30:21 2012<br>
@@ -54,7 +54,7 @@<br>
   return *this;<br>
 }<br>
<br>
-/// Hexadecimal printing for numbers too large for fprintf to handle directly.<br>
+/// Hexadecimal printing for numbers too large for Printf to handle directly.<br>
 static void PrintHex(UIntMax Val) {<br>
 #if HAVE_INT128_T<br>
   Printf("0x%08x%08x%08x%08x",<br>
@@ -93,6 +93,15 @@<br>
   }<br>
 }<br>
<br>
+// C++ demangling function, as required by Itanium C++ ABI. This is weak,<br>
+// because we do not require a C++ ABI library to be linked to a program<br>
+// using UBSan; if it's not present, we'll just print the string mangled.<br>
+namespace __cxxabiv1 {<br>
+  extern "C" char *__cxa_demangle(const char *mangled, char *buffer,<br>
+                                  size_t *length, int *status)<br>
+    __attribute__((weak));<br>
+}<br></blockquote><div><br></div><div>Do you think we should hoist (optional) demangling to sanitizer_common</div><div>and make it more portable (e.g. declare __cxa_demangle on Linux only,</div><div>use WEAK macro instead of attribute etc.)?</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
 static void renderText(const char *Message, const Diag::Arg *Args) {<br>
   for (const char *Msg = Message; *Msg; ++Msg) {<br>
     if (*Msg != '%') {<br>
@@ -109,6 +118,20 @@<br>
       case Diag::AK_String:<br>
         Printf("%s", A.String);<br>
         break;<br>
+      case Diag::AK_Mangled: {<br>
+        const char *String = 0;<br>
+        // FIXME: __cxa_demangle aggressively insists on allocating memory.<br>
+        // There's not much we can do about that, short of providing our<br>
+        // own demangler (libc++abi's implementation could easily be made<br>
+        // to not allocate). For now, we just call it anyway, and we leak<br>
+        // the returned value.<br>
+        if (__cxxabiv1::__cxa_demangle)<br>
+          String = __cxxabiv1::__cxa_demangle(A.String, 0, 0, 0);<br>
+        RawWrite("'");<br>
+        RawWrite(String ? String : A.String);<br>
+        RawWrite("'");<br>
+        break;<br>
+      }<br>
       case Diag::AK_SInt:<br>
         // 'long long' is guaranteed to be at least 64 bits wide.<br>
         if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX)<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.h?rev=170423&r1=170422&r2=170423&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.h?rev=170423&r1=170422&r2=170423&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.h (original)<br>
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.h Tue Dec 18 03:30:21 2012<br>
@@ -100,6 +100,14 @@<br>
   const char *getText() const { return Text; }<br>
 };<br>
<br>
+/// \brief A mangled C++ name. Really just a strong typedef for 'const char*'.<br>
+class MangledName {<br>
+  const char *Name;<br>
+public:<br>
+  MangledName(const char *Name) : Name(Name) {}<br>
+  const char *getName() const { return Name; }<br>
+};<br>
+<br>
 /// \brief Representation of an in-flight diagnostic.<br>
 ///<br>
 /// Temporary \c Diag instances are created by the handler routines to<br>
@@ -120,6 +128,7 @@<br>
   /// Kinds of arguments, corresponding to members of \c Arg's union.<br>
   enum ArgKind {<br>
     AK_String, ///< A string argument, displayed as-is.<br>
+    AK_Mangled,///< A C++ mangled name, demangled before display.<br>
     AK_UInt,   ///< An unsigned integer argument.<br>
     AK_SInt,   ///< A signed integer argument.<br>
     AK_Float,  ///< A floating-point argument.<br>
@@ -130,6 +139,7 @@<br>
   struct Arg {<br>
     Arg() {}<br>
     Arg(const char *String) : Kind(AK_String), String(String) {}<br>
+    Arg(MangledName MN) : Kind(AK_Mangled), String(MN.getName()) {}<br>
     Arg(UIntMax UInt) : Kind(AK_UInt), UInt(UInt) {}<br>
     Arg(SIntMax SInt) : Kind(AK_SInt), SInt(SInt) {}<br>
     Arg(FloatMax Float) : Kind(AK_Float), Float(Float) {}<br>
@@ -179,6 +189,7 @@<br>
   ~Diag();<br>
<br>
   Diag &operator<<(const char *Str) { return AddArg(Str); }<br>
+  Diag &operator<<(MangledName MN) { return AddArg(MN); }<br>
   Diag &operator<<(unsigned long long V) { return AddArg(UIntMax(V)); }<br>
   Diag &operator<<(const void *V) { return AddArg(V); }<br>
   Diag &operator<<(const TypeDescriptor &V);<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc?rev=170423&r1=170422&r2=170423&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc?rev=170423&r1=170422&r2=170423&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc (original)<br>
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc Tue Dec 18 03:30:21 2012<br>
@@ -42,17 +42,20 @@<br>
   DynamicTypeInfo DTI = getDynamicTypeInfo((void*)Pointer);<br>
   if (!DTI.isValid())<br>
     Diag(Pointer, DL_Note, "object has invalid vptr")<br>
-      << DTI.getMostDerivedTypeName()<br>
+      << MangledName(DTI.getMostDerivedTypeName())<br>
       << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");<br>
   else if (!DTI.getOffset())<br>
     Diag(Pointer, DL_Note, "object is of type %0")<br>
-      << DTI.getMostDerivedTypeName()<br>
+      << MangledName(DTI.getMostDerivedTypeName())<br>
       << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");<br>
   else<br>
+    // FIXME: Find the type at the specified offset, and include that<br>
+    //        in the note.<br>
     Diag(Pointer - DTI.getOffset(), DL_Note,<br>
          "object is base class subobject at offset %0 within object of type %1")<br>
-      << DTI.getOffset() << DTI.getMostDerivedTypeName()<br>
-      << Range(Pointer, Pointer + sizeof(uptr), "vptr for %1");<br>
+      << DTI.getOffset() << MangledName(DTI.getMostDerivedTypeName())<br>
+      << MangledName(DTI.getSubobjectTypeName())<br>
+      << Range(Pointer, Pointer + sizeof(uptr), "vptr for %2 base class of %1");<br>
<br>
   if (Abort)<br>
     Die();<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc?rev=170423&r1=170422&r2=170423&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc?rev=170423&r1=170422&r2=170423&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc (original)<br>
+++ compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc Tue Dec 18 03:30:21 2012<br>
@@ -129,7 +129,7 @@<br>
     // No base class subobjects.<br>
     return false;<br>
<br>
-  // Look for a zero-offset base class which is derived from \p Base.<br>
+  // Look for a base class which is derived from \p Base at the right offset.<br>
   for (unsigned int base = 0; base != VTI->base_count; ++base) {<br>
     // FIXME: Curtail the recursion if this base can't possibly contain the<br>
     //        given offset.<br>
@@ -149,6 +149,39 @@<br>
   return false;<br>
 }<br>
<br>
+/// \brief Find the derived-most dynamic base class of \p Derived at offset<br>
+/// \p Offset.<br>
+static const abi::__class_type_info *findBaseAtOffset(<br>
+    const abi::__class_type_info *Derived, sptr Offset) {<br>
+  if (!Offset)<br>
+    return Derived;<br>
+<br>
+  if (const abi::__si_class_type_info *SI =<br>
+        dynamic_cast<const abi::__si_class_type_info*>(Derived))<br>
+    return findBaseAtOffset(SI->__base_type, Offset);<br>
+<br>
+  const abi::__vmi_class_type_info *VTI =<br>
+    dynamic_cast<const abi::__vmi_class_type_info*>(Derived);<br>
+  if (!VTI)<br>
+    // No base class subobjects.<br>
+    return 0;<br>
+<br>
+  for (unsigned int base = 0; base != VTI->base_count; ++base) {<br>
+    sptr OffsetHere = VTI->base_info[base].__offset_flags >><br>
+                      abi::__base_class_type_info::__offset_shift;<br>
+    if (VTI->base_info[base].__offset_flags &<br>
+          abi::__base_class_type_info::__virtual_mask)<br>
+      // FIXME: Can't handle virtual bases yet.<br>
+      continue;<br>
+    if (const abi::__class_type_info *Base =<br>
+          findBaseAtOffset(VTI->base_info[base].__base_type,<br>
+                           Offset - OffsetHere))<br>
+      return Base;<br>
+  }<br>
+<br>
+  return 0;<br>
+}<br>
+<br>
 namespace {<br>
<br>
 struct VtablePrefix {<br>
@@ -206,6 +239,10 @@<br>
 __ubsan::DynamicTypeInfo __ubsan::getDynamicTypeInfo(void *Object) {<br>
   VtablePrefix *Vtable = getVtablePrefix(Object);<br>
   if (!Vtable)<br>
-    return DynamicTypeInfo(0, 0);<br>
-  return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset);<br>
+    return DynamicTypeInfo(0, 0, 0);<br>
+  const abi::__class_type_info *ObjectType = findBaseAtOffset(<br>
+    static_cast<const abi::__class_type_info*>(Vtable->TypeInfo),<br>
+    -Vtable->Offset);<br>
+  return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset,<br>
+                         ObjectType ? ObjectType->__type_name : "<unknown>");<br>
 }<br>
<br>
Modified: compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h?rev=170423&r1=170422&r2=170423&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h?rev=170423&r1=170422&r2=170423&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h (original)<br>
+++ compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h Tue Dec 18 03:30:21 2012<br>
@@ -24,10 +24,11 @@<br>
 class DynamicTypeInfo {<br>
   const char *MostDerivedTypeName;<br>
   sptr Offset;<br>
+  const char *SubobjectTypeName;<br>
<br>
 public:<br>
-  DynamicTypeInfo(const char *MDTN, sptr Offset)<br>
-    : MostDerivedTypeName(MDTN), Offset(Offset) {}<br>
+  DynamicTypeInfo(const char *MDTN, sptr Offset, const char *STN)<br>
+    : MostDerivedTypeName(MDTN), Offset(Offset), SubobjectTypeName(STN) {}<br>
<br>
   /// Determine whether the object had a valid dynamic type.<br>
   bool isValid() const { return MostDerivedTypeName; }<br>
@@ -35,6 +36,8 @@<br>
   const char *getMostDerivedTypeName() const { return MostDerivedTypeName; }<br>
   /// Get the offset from the most-derived type to this base class.<br>
   sptr getOffset() const { return Offset; }<br>
+  /// Get the name of the most-derived type at the specified offset.<br>
+  const char *getSubobjectTypeName() const { return SubobjectTypeName; }<br>
 };<br>
<br>
 /// \brief Get information about the dynamic type of an object.<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div><br>
</div>