[llvm-commits] [compiler-rt] r170423 - in /compiler-rt/trunk/lib/ubsan: lit_tests/TypeCheck/vptr.cpp ubsan_diag.cc ubsan_diag.h ubsan_handlers_cxx.cc ubsan_type_hash.cc ubsan_type_hash.h

Alexey Samsonov samsonov at google.com
Tue Dec 18 02:31:12 PST 2012


On Tue, Dec 18, 2012 at 1:30 PM, Richard Smith
<richard-llvm at metafoo.co.uk>wrote:

> Author: rsmith
> Date: Tue Dec 18 03:30:21 2012
> New Revision: 170423
>
> URL: http://llvm.org/viewvc/llvm-project?rev=170423&view=rev
> Log:
> ubsan: Demangle class names, and be more informative when a
> reinterpret_cast
> has got us to the wrong offset within an object.
>
> Modified:
>     compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp
>     compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
>     compiler-rt/trunk/lib/ubsan/ubsan_diag.h
>     compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc
>     compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc
>     compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h
>
> Modified: compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp?rev=170423&r1=170422&r2=170423&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp (original)
> +++ compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/vptr.cpp Tue Dec 18
> 03:30:21 2012
> @@ -75,7 +75,7 @@
>
>    case 'm':
>      // 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'
> -    // CHECK-MEMBER-NEXT: [[PTR]]: note: object is of type
> [[DYN_TYPE:1S|1U]]
> +    // CHECK-MEMBER-NEXT: [[PTR]]: note: object is of type
> [[DYN_TYPE:'S'|'U']]
>      // CHECK-MEMBER-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }}
>      // CHECK-MEMBER-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)?
> *$}}
>      // CHECK-MEMBER-NEXT: {{^              vptr for}} [[DYN_TYPE]]
> @@ -89,7 +89,7 @@
>
>    case 'f':
>      // 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'
> -    // CHECK-MEMFUN-NEXT: [[PTR]]: note: object is of type
> [[DYN_TYPE:1S|1U]]
> +    // CHECK-MEMFUN-NEXT: [[PTR]]: note: object is of type
> [[DYN_TYPE:'S'|'U']]
>      // CHECK-MEMFUN-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }}
>      // CHECK-MEMFUN-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)?
> *$}}
>      // CHECK-MEMFUN-NEXT: {{^              vptr for}} [[DYN_TYPE]]
> @@ -97,10 +97,10 @@
>
>    case 'o':
>      // 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'
> -    // CHECK-OFFSET-NEXT: 0x{{[0-9a-f]*}}: note: object is base class
> subobject at offset {{8|16}} within object of type [[DYN_TYPE:1U]]
> +    // CHECK-OFFSET-NEXT: 0x{{[0-9a-f]*}}: note: object is base class
> subobject at offset {{8|16}} within object of type [[DYN_TYPE:'U']]
>      // CHECK-OFFSET-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  .. ..
> .. .. .. .. .. ..  .. .. .. .. .. .. .. ..  }}
>      // CHECK-OFFSET-NEXT: {{^              \^                        (
>                       ~~~~~~~~~~~~)~~~~~~~~~~~ *$}}
> -    // CHECK-OFFSET-NEXT: {{^                                       (
>                     )?vptr for}} [[DYN_TYPE]]
> +    // CHECK-OFFSET-NEXT: {{^                                       (
>                     )?vptr for}} 'T' base class of [[DYN_TYPE]]
>      return reinterpret_cast<U*>(p)->v() - 2;
>    }
>  }
>
> 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=170423&r1=170422&r2=170423&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (original)
> +++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Tue Dec 18 03:30:21 2012
> @@ -54,7 +54,7 @@
>    return *this;
>  }
>
> -/// Hexadecimal printing for numbers too large for fprintf to handle
> directly.
> +/// Hexadecimal printing for numbers too large for Printf to handle
> directly.
>  static void PrintHex(UIntMax Val) {
>  #if HAVE_INT128_T
>    Printf("0x%08x%08x%08x%08x",
> @@ -93,6 +93,15 @@
>    }
>  }
>
> +// C++ demangling function, as required by Itanium C++ ABI. This is weak,
> +// because we do not require a C++ ABI library to be linked to a program
> +// using UBSan; if it's not present, we'll just print the string mangled.
> +namespace __cxxabiv1 {
> +  extern "C" char *__cxa_demangle(const char *mangled, char *buffer,
> +                                  size_t *length, int *status)
> +    __attribute__((weak));
> +}
>

Do you think we should hoist (optional) demangling to sanitizer_common
and make it more portable (e.g. declare __cxa_demangle on Linux only,
use WEAK macro instead of attribute etc.)?


> +
>  static void renderText(const char *Message, const Diag::Arg *Args) {
>    for (const char *Msg = Message; *Msg; ++Msg) {
>      if (*Msg != '%') {
> @@ -109,6 +118,20 @@
>        case Diag::AK_String:
>          Printf("%s", A.String);
>          break;
> +      case Diag::AK_Mangled: {
> +        const char *String = 0;
> +        // FIXME: __cxa_demangle aggressively insists on allocating
> memory.
> +        // There's not much we can do about that, short of providing our
> +        // own demangler (libc++abi's implementation could easily be made
> +        // to not allocate). For now, we just call it anyway, and we leak
> +        // the returned value.
> +        if (__cxxabiv1::__cxa_demangle)
> +          String = __cxxabiv1::__cxa_demangle(A.String, 0, 0, 0);
> +        RawWrite("'");
> +        RawWrite(String ? String : A.String);
> +        RawWrite("'");
> +        break;
> +      }
>        case Diag::AK_SInt:
>          // 'long long' is guaranteed to be at least 64 bits wide.
>          if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX)
>
> 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=170423&r1=170422&r2=170423&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/ubsan/ubsan_diag.h (original)
> +++ compiler-rt/trunk/lib/ubsan/ubsan_diag.h Tue Dec 18 03:30:21 2012
> @@ -100,6 +100,14 @@
>    const char *getText() const { return Text; }
>  };
>
> +/// \brief A mangled C++ name. Really just a strong typedef for 'const
> char*'.
> +class MangledName {
> +  const char *Name;
> +public:
> +  MangledName(const char *Name) : Name(Name) {}
> +  const char *getName() const { return Name; }
> +};
> +
>  /// \brief Representation of an in-flight diagnostic.
>  ///
>  /// Temporary \c Diag instances are created by the handler routines to
> @@ -120,6 +128,7 @@
>    /// Kinds of arguments, corresponding to members of \c Arg's union.
>    enum ArgKind {
>      AK_String, ///< A string argument, displayed as-is.
> +    AK_Mangled,///< A C++ mangled name, demangled before display.
>      AK_UInt,   ///< An unsigned integer argument.
>      AK_SInt,   ///< A signed integer argument.
>      AK_Float,  ///< A floating-point argument.
> @@ -130,6 +139,7 @@
>    struct Arg {
>      Arg() {}
>      Arg(const char *String) : Kind(AK_String), String(String) {}
> +    Arg(MangledName MN) : Kind(AK_Mangled), String(MN.getName()) {}
>      Arg(UIntMax UInt) : Kind(AK_UInt), UInt(UInt) {}
>      Arg(SIntMax SInt) : Kind(AK_SInt), SInt(SInt) {}
>      Arg(FloatMax Float) : Kind(AK_Float), Float(Float) {}
> @@ -179,6 +189,7 @@
>    ~Diag();
>
>    Diag &operator<<(const char *Str) { return AddArg(Str); }
> +  Diag &operator<<(MangledName MN) { return AddArg(MN); }
>    Diag &operator<<(unsigned long long V) { return AddArg(UIntMax(V)); }
>    Diag &operator<<(const void *V) { return AddArg(V); }
>    Diag &operator<<(const TypeDescriptor &V);
>
> Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc?rev=170423&r1=170422&r2=170423&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc (original)
> +++ compiler-rt/trunk/lib/ubsan/ubsan_handlers_cxx.cc Tue Dec 18 03:30:21
> 2012
> @@ -42,17 +42,20 @@
>    DynamicTypeInfo DTI = getDynamicTypeInfo((void*)Pointer);
>    if (!DTI.isValid())
>      Diag(Pointer, DL_Note, "object has invalid vptr")
> -      << DTI.getMostDerivedTypeName()
> +      << MangledName(DTI.getMostDerivedTypeName())
>        << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");
>    else if (!DTI.getOffset())
>      Diag(Pointer, DL_Note, "object is of type %0")
> -      << DTI.getMostDerivedTypeName()
> +      << MangledName(DTI.getMostDerivedTypeName())
>        << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");
>    else
> +    // FIXME: Find the type at the specified offset, and include that
> +    //        in the note.
>      Diag(Pointer - DTI.getOffset(), DL_Note,
>           "object is base class subobject at offset %0 within object of
> type %1")
> -      << DTI.getOffset() << DTI.getMostDerivedTypeName()
> -      << Range(Pointer, Pointer + sizeof(uptr), "vptr for %1");
> +      << DTI.getOffset() << MangledName(DTI.getMostDerivedTypeName())
> +      << MangledName(DTI.getSubobjectTypeName())
> +      << Range(Pointer, Pointer + sizeof(uptr), "vptr for %2 base class
> of %1");
>
>    if (Abort)
>      Die();
>
> Modified: compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc?rev=170423&r1=170422&r2=170423&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc (original)
> +++ compiler-rt/trunk/lib/ubsan/ubsan_type_hash.cc Tue Dec 18 03:30:21 2012
> @@ -129,7 +129,7 @@
>      // No base class subobjects.
>      return false;
>
> -  // Look for a zero-offset base class which is derived from \p Base.
> +  // Look for a base class which is derived from \p Base at the right
> offset.
>    for (unsigned int base = 0; base != VTI->base_count; ++base) {
>      // FIXME: Curtail the recursion if this base can't possibly contain
> the
>      //        given offset.
> @@ -149,6 +149,39 @@
>    return false;
>  }
>
> +/// \brief Find the derived-most dynamic base class of \p Derived at
> offset
> +/// \p Offset.
> +static const abi::__class_type_info *findBaseAtOffset(
> +    const abi::__class_type_info *Derived, sptr Offset) {
> +  if (!Offset)
> +    return Derived;
> +
> +  if (const abi::__si_class_type_info *SI =
> +        dynamic_cast<const abi::__si_class_type_info*>(Derived))
> +    return findBaseAtOffset(SI->__base_type, Offset);
> +
> +  const abi::__vmi_class_type_info *VTI =
> +    dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
> +  if (!VTI)
> +    // No base class subobjects.
> +    return 0;
> +
> +  for (unsigned int base = 0; base != VTI->base_count; ++base) {
> +    sptr OffsetHere = VTI->base_info[base].__offset_flags >>
> +                      abi::__base_class_type_info::__offset_shift;
> +    if (VTI->base_info[base].__offset_flags &
> +          abi::__base_class_type_info::__virtual_mask)
> +      // FIXME: Can't handle virtual bases yet.
> +      continue;
> +    if (const abi::__class_type_info *Base =
> +          findBaseAtOffset(VTI->base_info[base].__base_type,
> +                           Offset - OffsetHere))
> +      return Base;
> +  }
> +
> +  return 0;
> +}
> +
>  namespace {
>
>  struct VtablePrefix {
> @@ -206,6 +239,10 @@
>  __ubsan::DynamicTypeInfo __ubsan::getDynamicTypeInfo(void *Object) {
>    VtablePrefix *Vtable = getVtablePrefix(Object);
>    if (!Vtable)
> -    return DynamicTypeInfo(0, 0);
> -  return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset);
> +    return DynamicTypeInfo(0, 0, 0);
> +  const abi::__class_type_info *ObjectType = findBaseAtOffset(
> +    static_cast<const abi::__class_type_info*>(Vtable->TypeInfo),
> +    -Vtable->Offset);
> +  return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset,
> +                         ObjectType ? ObjectType->__type_name :
> "<unknown>");
>  }
>
> Modified: compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h?rev=170423&r1=170422&r2=170423&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h (original)
> +++ compiler-rt/trunk/lib/ubsan/ubsan_type_hash.h Tue Dec 18 03:30:21 2012
> @@ -24,10 +24,11 @@
>  class DynamicTypeInfo {
>    const char *MostDerivedTypeName;
>    sptr Offset;
> +  const char *SubobjectTypeName;
>
>  public:
> -  DynamicTypeInfo(const char *MDTN, sptr Offset)
> -    : MostDerivedTypeName(MDTN), Offset(Offset) {}
> +  DynamicTypeInfo(const char *MDTN, sptr Offset, const char *STN)
> +    : MostDerivedTypeName(MDTN), Offset(Offset), SubobjectTypeName(STN) {}
>
>    /// Determine whether the object had a valid dynamic type.
>    bool isValid() const { return MostDerivedTypeName; }
> @@ -35,6 +36,8 @@
>    const char *getMostDerivedTypeName() const { return
> MostDerivedTypeName; }
>    /// Get the offset from the most-derived type to this base class.
>    sptr getOffset() const { return Offset; }
> +  /// Get the name of the most-derived type at the specified offset.
> +  const char *getSubobjectTypeName() const { return SubobjectTypeName; }
>  };
>
>  /// \brief Get information about the dynamic type of an object.
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>



-- 
Alexey Samsonov, MSK
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121218/433d9fe9/attachment.html>


More information about the llvm-commits mailing list