Home | History | Annotate | Download | only in src
      1 // Copyright (C) 2011 The Android Open Source Project
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions
      6 // are met:
      7 // 1. Redistributions of source code must retain the above copyright
      8 //    notice, this list of conditions and the following disclaimer.
      9 // 2. Redistributions in binary form must reproduce the above copyright
     10 //    notice, this list of conditions and the following disclaimer in the
     11 //    documentation and/or other materials provided with the distribution.
     12 // 3. Neither the name of the project nor the names of its contributors
     13 //    may be used to endorse or promote products derived from this software
     14 //    without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19 // ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26 // SUCH DAMAGE.
     27 //
     28 // dynamic_cast.cc: RTTI support.
     29 //
     30 // References:
     31 // Itanium C++ ABI at http://www.codesourcery.com/public/cxx-abi/abi.html
     32 // IHI0041A C++ Application Binary Interface for the ARM architecture.
     33 //
     34 
     35 #include <cxxabi.h>
     36 
     37 #include <cstddef>
     38 #include <cassert>
     39 
     40 namespace
     41 {
     42   // Adjust a pointer by an offset.
     43 
     44   const void*
     45   adjust_pointer(const void* p, std::ptrdiff_t off)
     46   {
     47     // FIXME: should we align pointer after adjustment?
     48     const char *cp = reinterpret_cast<const char*>(p) + off;
     49     return reinterpret_cast<const void*>(cp);
     50   }
     51 
     52   // Return the vtable pointer of a polymorphic object pointed by p.
     53 
     54   inline const void*
     55   get_vtable(const void* p)
     56   {
     57     return *reinterpret_cast<void*const*>(p);
     58   }
     59 
     60   // Return a pointer to a __class_type_info in a vtable.
     61 
     62   inline const abi::__class_type_info*
     63   get_class_type_info(const void* vtable)
     64   {
     65     const void* type_info_ptr = adjust_pointer(vtable, -sizeof(void*));
     66     return *reinterpret_cast<abi::__class_type_info*const*>(type_info_ptr);
     67   }
     68 
     69   // Return offset to object in a vtable.
     70 
     71   inline std::ptrdiff_t
     72   get_offset_to_top(const void* vtable)
     73   {
     74     const void* type_info_ptr_address = adjust_pointer(vtable, -sizeof(void*));
     75     const void* offset_to_top_address =
     76       adjust_pointer(type_info_ptr_address, -sizeof(std::ptrdiff_t));
     77     return *reinterpret_cast<const std::ptrdiff_t*>(offset_to_top_address);
     78   }
     79 
     80   // Return the virtual pointer to the most derived object of referred by a
     81   // pointer p.
     82 
     83   const void*
     84   get_most_derived_object(const void* p)
     85   {
     86     const void* vtable = get_vtable(p);
     87     std::ptrdiff_t offset_to_top = get_offset_to_top(vtable);
     88     return adjust_pointer(p, offset_to_top);
     89   }
     90 
     91   // We assume that -1 cannot be a valid pointer to object.
     92   const void * const ambiguous_object =
     93     reinterpret_cast<const void*>(-1);
     94 
     95   // Return a pointer to the subobject described by base_info.
     96 
     97   const void*
     98   get_subobject(const void* object,
     99                 const void* vtable,
    100                 const abi::__base_class_type_info* base_info)
    101   {
    102     long offset = base_info->offset();
    103     if (base_info->is_virtual())
    104       {
    105         const std::ptrdiff_t* virtual_base_offset_address =
    106           static_cast<const std::ptrdiff_t*> (adjust_pointer(vtable, offset));
    107         offset = *virtual_base_offset_address;
    108       }
    109     return adjust_pointer(object, offset);
    110   }
    111 
    112   // Helper of __dyanmic_cast to walk the type tree of an object.
    113 
    114   const void *
    115   walk_object(const void *object,
    116               const abi::__class_type_info *type,
    117               const void *match_object,
    118               const abi::__class_type_info *match_type)
    119   {
    120     if (*type == *match_type)
    121       return (match_object == NULL || object == match_object) ? object : NULL;
    122 
    123     switch(type->code())
    124       {
    125       case abi::__class_type_info::CLASS_TYPE_INFO_CODE:
    126         // This isn't not the class you're looking for.
    127         return NULL;
    128 
    129       case abi::__class_type_info::SI_CLASS_TYPE_INFO_CODE:
    130         // derived type has a single public base at offset 0.
    131         {
    132           const abi::__si_class_type_info* ti =
    133             static_cast<const abi::__si_class_type_info*>(type);
    134           return walk_object(object, ti->__base_type, match_object,
    135                              match_type);
    136         }
    137 
    138       case abi::__class_type_info::VMI_CLASS_TYPE_INFO_CODE:
    139         {
    140           const void* vtable = get_vtable(object);
    141           const abi::__vmi_class_type_info* ti =
    142             static_cast<const abi::__vmi_class_type_info*>(type);
    143 
    144           // Look at all direct bases.
    145           const void* result = NULL;
    146           for (unsigned i = 0; i < ti->__base_count; ++i)
    147             {
    148               if (!ti->__base_info[i].is_public())
    149                 continue;
    150 
    151               const void *subobject =
    152                 get_subobject(object, vtable, &ti->__base_info[i]);
    153               const void* walk_subobject_result =
    154                 walk_object(subobject, ti->__base_info[i].__base_type,
    155                             match_object, match_type);
    156 
    157               if (walk_subobject_result == ambiguous_object)
    158                 return ambiguous_object;
    159               else if (walk_subobject_result != NULL)
    160                 {
    161                   if (result == NULL)
    162                     {
    163                       result = walk_subobject_result;
    164                     }
    165                   else if (result != walk_subobject_result)
    166                     return ambiguous_object;
    167                 }
    168             }
    169           return result;
    170         }
    171 
    172       default:
    173         assert(0);
    174       }
    175     return NULL;
    176   }
    177 
    178   // Bookkeeping structure for derived-to-base cast in the general case.
    179   struct cast_context
    180   {
    181   public:
    182     const void* object;
    183     const abi::__class_type_info *src_type;
    184     const abi::__class_type_info *dst_type;
    185     std::ptrdiff_t src2dst_offset;
    186 
    187     const void* dst_object;
    188     const void* result;
    189 
    190     cast_context(const void* obj, const abi::__class_type_info *src,
    191                  const abi::__class_type_info *dst, std::ptrdiff_t offset)
    192       : object(obj), src_type(src), dst_type(dst), src2dst_offset(offset),
    193         dst_object(NULL), result(NULL)
    194     { }
    195   };
    196 
    197   // based-to-derive cast in the general case.
    198 
    199   void
    200   base_to_derived_cast(const void *object,
    201                        const abi::__class_type_info *type,
    202                        cast_context* context)
    203   {
    204     const void* saved_dst_object = context->dst_object;
    205     bool is_dst_type = *type == *context->dst_type;
    206     if (is_dst_type)
    207       context->dst_object = object;
    208 
    209     if (object == context->object
    210         && context->dst_object != NULL
    211         && *type == *context->src_type)
    212       {
    213         if (context->result == NULL)
    214           context->result = context->dst_object;
    215         else if (context->result != context->dst_object)
    216           context->result = ambiguous_object;
    217         context->dst_object = saved_dst_object;
    218         return;
    219       }
    220 
    221     switch(type->code())
    222       {
    223       case abi::__class_type_info::CLASS_TYPE_INFO_CODE:
    224         // This isn't not the class you're looking for.
    225         break;
    226 
    227       case abi::__class_type_info::SI_CLASS_TYPE_INFO_CODE:
    228         // derived type has a single public base at offset 0.
    229         {
    230           const abi::__si_class_type_info* ti =
    231             static_cast<const abi::__si_class_type_info*>(type);
    232           base_to_derived_cast(object, ti->__base_type, context);
    233           break;
    234         }
    235 
    236       case abi::__class_type_info::VMI_CLASS_TYPE_INFO_CODE:
    237         {
    238           const void* vtable = get_vtable(object);
    239           const abi::__vmi_class_type_info* ti =
    240             static_cast<const abi::__vmi_class_type_info*>(type);
    241 
    242           // Look at all direct bases.
    243           for (unsigned i = 0; i < ti->__base_count; ++i)
    244             {
    245               if (!ti->__base_info[i].is_public())
    246                 continue;
    247 
    248               const void *subobject =
    249                 get_subobject(object, vtable, &ti->__base_info[i]);
    250               base_to_derived_cast(subobject, ti->__base_info[i].__base_type,
    251                                    context);
    252 
    253               // FIXME: Use flags in base_info to optimize search.
    254               if (context->result == ambiguous_object)
    255                 break;
    256             }
    257           break;
    258         }
    259 
    260       default:
    261         assert(0);
    262       }
    263      context->dst_object = saved_dst_object;
    264   }
    265 } // namespace
    266 
    267 namespace __cxxabiv1
    268 {
    269 #define DYNAMIC_CAST_NO_HINT -1
    270 #define DYNAMIC_CAST_NOT_PUBLIC_BASE -2
    271 #define DYNAMIC_CAST_MULTIPLE_PUBLIC_NONVIRTUAL_BASE -3
    272 
    273   /* v: source address to be adjusted; nonnull, and since the
    274    *    source object is polymorphic, *(void**)v is a virtual pointer.
    275    * src: static type of the source object.
    276    * dst: destination type (the "T" in "dynamic_cast<T>(v)").
    277    * src2dst_offset: a static hint about the location of the
    278    *    source subobject with respect to the complete object;
    279    *    special negative values are:
    280    *       -1: no hint
    281    *       -2: src is not a public base of dst
    282    *       -3: src is a multiple public base type but never a
    283    *           virtual base type
    284    *    otherwise, the src type is a unique public nonvirtual
    285    *    base type of dst at offset src2dst_offset from the
    286    *    origin of dst.
    287    */
    288   extern "C" void*
    289   __dynamic_cast (const void *v,
    290                   const abi::__class_type_info *src,
    291                   const abi::__class_type_info *dst,
    292                   std::ptrdiff_t src2dst_offset)
    293   {
    294     const void* most_derived_object = get_most_derived_object(v);
    295     const void* vtable = get_vtable(most_derived_object);
    296     const abi::__class_type_info* most_derived_class_type_info =
    297       get_class_type_info(vtable);
    298 
    299     // If T is not a public base type of the most derived class referred
    300     // by v, the cast always fails.
    301     void* t_object =
    302       const_cast<void*>(walk_object(most_derived_object,
    303                                     most_derived_class_type_info, NULL, dst));
    304     if (t_object == NULL)
    305       return NULL;
    306 
    307     // C++ ABI 2.9.7 The dynamic_cast Algorithm:
    308     //
    309     // If, in the most derived object pointed (referred) to by v, v points
    310     // (refers) to a public base class subobject of a T object [note: this can
    311     // be checked at compile time], and if only one object of type T is derived
    312     // from the subobject pointed (referred) to by v, the result is a pointer
    313     // (an lvalue referring) to that T object.
    314 
    315     // We knew that src is not a public base, so base-to-derived cast
    316     // is not possible.  This works even if there are multiple subobjects
    317     // of type T in the most derived object.
    318     if (src2dst_offset != DYNAMIC_CAST_NOT_PUBLIC_BASE)
    319       {
    320         // If it is known that v points to a public base class subobject
    321         // of a T object, simply adjust the pointer by the offset.
    322         if (t_object != ambiguous_object && src2dst_offset >= 0)
    323           return const_cast<void*>(adjust_pointer(v, -src2dst_offset));
    324 
    325         // If there is only one T type subobject, we only need to look at
    326         // there.  Otherwise, look for the subobject referred by v in the
    327         // most derived object.
    328         cast_context context(v, src, dst, src2dst_offset);
    329         if (t_object != ambiguous_object)
    330           base_to_derived_cast(t_object, dst, &context);
    331         else
    332           base_to_derived_cast(most_derived_object,
    333                                most_derived_class_type_info, &context);
    334 
    335         if (context.result != NULL && context.result != ambiguous_object)
    336           return const_cast<void*>(context.result);
    337       }
    338 
    339     // C++ ABI 2.9.7 The dynamic_cast Algorithm:
    340     //
    341     // Otherwise, if v points (refers) to a public base class subobject of the
    342     // most derived object, and the type of the most derived object has an
    343     // unambiguous public base class of type T, the result is a pointer (an
    344     // lvalue referring) to the T subobject of the most derived object.
    345     // Otherwise, the run-time check fails.
    346 
    347     // Check to see if T is a unambiguous public base class.
    348     if (t_object == ambiguous_object)
    349       return NULL;
    350 
    351     // See if v refers to a public base class subobject.
    352     const void* v_object =
    353       walk_object(most_derived_object, most_derived_class_type_info, v, src);
    354     return v_object == v ? t_object : NULL;
    355   }
    356 } // namespace __cxxabiv1
    357