38#if defined( __ANDROID__ ) && !defined( RTTI_DUMP_USE_PRINTF )
39#include <android/log.h>
40#define RTTI_DUMP_LOG( fmt, ... ) \
41 __android_log_print( ANDROID_LOG_INFO, "rtti_dump", fmt, ##__VA_ARGS__ )
43#define RTTI_DUMP_LOG( fmt, ... ) printf( fmt "\n", ##__VA_ARGS__ )
47#define RTTI_DUMP_UNUSED __attribute__( ( unused ) )
58 extern "C" const std::type_info* __cxa_current_exception_type();
68 RTTI_DUMP_UNUSED const std::type_info* runtime_typeid(
const volatile T* dynptr )
70 T* dynptr_unqual =
const_cast<T*
>( dynptr );
76 (void)
sizeof(
dynamic_cast<void*
>( dynptr_unqual ) );
78 void* vptr = *
reinterpret_cast<void**
>( dynptr_unqual );
79 void* typeid_void =
reinterpret_cast<void**
>( vptr )[-1];
80 return reinterpret_cast<const std::type_info*
>( typeid_void );
88 if( !dladdr(
const_cast<void*
>( ptr ), &
info ) )
91 snprintf( buf,
sizeof( buf ),
"[error: dladdr failed - %d]", errno );
96 return std::string(
info.dli_fname );
103 void dump_type(
const std::type_info* type,
const char* label =
"dump_type",
int indent = 0 )
105 const std::string prefix = label + std::string(
": " ) + std::string( indent,
' ' );
109 RTTI_DUMP_LOG(
"%sERROR: dump_type called with type==NULL!", prefix.c_str() );
115 virtual ~type_info() {}
116 const char* type_name;
119 assert(
sizeof( type_info ) ==
sizeof( std::type_info ) );
120 const char*
const name = type->name();
121 const char*
const raw_name =
reinterpret_cast<const type_info*
>( type )->type_name;
123 if(
name == raw_name )
127 else if( raw_name + 1 ==
name )
129 RTTI_DUMP_LOG(
"%stype %s (raw name == '%s' @ %p):", prefix.c_str(),
name, raw_name,
137 RTTI_DUMP_LOG(
"%s type_info obj: %p (in %s)", prefix.c_str(), type,
138 dladdr_fname( type ).c_str() );
140 dladdr_fname(
name ).c_str() );
146 void dump_current_exception(
const char* label =
"dump_current_exception" )
148 const std::type_info* type = __cxa_current_exception_type();
152 dump_type( type, label );
156 RTTI_DUMP_LOG(
"%s: ERROR: dump_current_exception called outside a catch block!",
161 namespace hierarchy_dumper_internals
169 struct __class_type_info : std::type_info
173 struct __si_class_type_info : __class_type_info
178 struct __base_class_type_info
184 struct __vmi_class_type_info : __class_type_info
194 std::set<const std::type_info*>
seen_;
197 Dumper(
const char* label ) :
label_( label ) {}
198 void dump_type(
const std::type_info*
info,
int indent );
201 const int kIndent = 4;
203 void Dumper::dump_type(
const std::type_info*
info,
int indent )
205 ::rtti_dump::dump_type(
info,
label_, indent * kIndent );
212 const std::type_info* info_type = runtime_typeid(
info );
213 __base_class_type_info lone_base = { 0 };
214 const __base_class_type_info* base_table = NULL;
215 unsigned int base_count = 0;
221 const int sub_indent_sp = ( indent + 1 ) * kIndent;
223 if( info_type == NULL )
229 else if( !strcmp( info_type->name(),
"N10__cxxabiv120__si_class_type_infoE" ) )
231 const __si_class_type_info& infox =
232 *
reinterpret_cast<const __si_class_type_info*
>(
info );
233 lone_base.__base_type = infox.__base_type;
235 base_table = &lone_base;
237 else if( !strcmp( info_type->name(),
"N10__cxxabiv121__vmi_class_type_infoE" ) )
239 const __vmi_class_type_info& infox =
240 *
reinterpret_cast<const __vmi_class_type_info*
>(
info );
241 base_count = infox.__base_count;
242 base_table = infox.__base_info;
256 for(
unsigned int i = 0; i < base_count; ++i )
258 dump_type( base_table[i].
__base_type, indent + 2 );
268 void dump_class_hierarchy(
const std::type_info*
info,
269 const char* label =
"dump_class_hierarchy" )
271 hierarchy_dumper_internals::Dumper dumper( label );
272 dumper.dump_type(
info, 0 );
unsigned int __base_count
const __class_type_info * __base_type
#define RTTI_DUMP_LOG(fmt,...)
std::set< const std::type_info * > seen_
__base_class_type_info __base_info[1]