1 //===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "ItaniumABILanguageRuntime.h" 11 12 #include "lldb/Breakpoint/BreakpointLocation.h" 13 #include "lldb/Core/ConstString.h" 14 #include "lldb/Core/Error.h" 15 #include "lldb/Core/Log.h" 16 #include "lldb/Core/Module.h" 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Core/Scalar.h" 19 #include "lldb/Core/ValueObject.h" 20 #include "lldb/Core/ValueObjectMemory.h" 21 #include "lldb/Symbol/ClangASTContext.h" 22 #include "lldb/Symbol/Symbol.h" 23 #include "lldb/Symbol/TypeList.h" 24 #include "lldb/Target/Process.h" 25 #include "lldb/Target/RegisterContext.h" 26 #include "lldb/Target/StopInfo.h" 27 #include "lldb/Target/Target.h" 28 #include "lldb/Target/Thread.h" 29 30 #include <vector> 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 static const char *pluginName = "ItaniumABILanguageRuntime"; 36 static const char *pluginDesc = "Itanium ABI for the C++ language"; 37 static const char *pluginShort = "language.itanium"; 38 static const char *vtable_demangled_prefix = "vtable for "; 39 40 bool 41 ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) 42 { 43 return ClangASTContext::IsPossibleDynamicType(in_value.GetClangAST(), in_value.GetClangType(), NULL, 44 true, // check for C++ 45 false); // do not check for ObjC 46 } 47 48 bool 49 ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, 50 lldb::DynamicValueType use_dynamic, 51 TypeAndOrName &class_type_or_name, 52 Address &dynamic_address) 53 { 54 // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0 55 // in the object. That will point to the "address point" within the vtable (not the beginning of the 56 // vtable.) We can then look up the symbol containing this "address point" and that symbol's name 57 // demangled will contain the full class name. 58 // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the 59 // start of the value object which holds the dynamic type. 60 // 61 62 // Only a pointer or reference type can have a different dynamic and static type: 63 if (CouldHaveDynamicValue (in_value)) 64 { 65 // First job, pull out the address at 0 offset from the object. 66 AddressType address_type; 67 lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); 68 if (original_ptr == LLDB_INVALID_ADDRESS) 69 return false; 70 71 ExecutionContext exe_ctx (in_value.GetExecutionContextRef()); 72 73 Target *target = exe_ctx.GetTargetPtr(); 74 Process *process = exe_ctx.GetProcessPtr(); 75 76 char memory_buffer[16]; 77 DataExtractor data(memory_buffer, sizeof(memory_buffer), 78 process->GetByteOrder(), 79 process->GetAddressByteSize()); 80 size_t address_byte_size = process->GetAddressByteSize(); 81 Error error; 82 size_t bytes_read = process->ReadMemory (original_ptr, 83 memory_buffer, 84 address_byte_size, 85 error); 86 if (!error.Success() || (bytes_read != address_byte_size)) 87 { 88 return false; 89 } 90 91 uint32_t offset_ptr = 0; 92 lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr); 93 94 if (offset_ptr == 0) 95 return false; 96 97 // Now find the symbol that contains this address: 98 99 SymbolContext sc; 100 Address address_point_address; 101 if (target && !target->GetSectionLoadList().IsEmpty()) 102 { 103 if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address)) 104 { 105 target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc); 106 Symbol *symbol = sc.symbol; 107 if (symbol != NULL) 108 { 109 const char *name = symbol->GetMangled().GetDemangledName().AsCString(); 110 if (strstr(name, vtable_demangled_prefix) == name) 111 { 112 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 113 if (log) 114 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n", 115 original_ptr, 116 in_value.GetTypeName().GetCString(), 117 name); 118 // We are a C++ class, that's good. Get the class name and look it up: 119 const char *class_name = name + strlen(vtable_demangled_prefix); 120 class_type_or_name.SetName (class_name); 121 const bool exact_match = true; 122 TypeList class_types; 123 124 uint32_t num_matches = 0; 125 // First look in the module that the vtable symbol came from 126 // and look for a single exact match. 127 if (sc.module_sp) 128 { 129 num_matches = sc.module_sp->FindTypes (sc, 130 ConstString(class_name), 131 exact_match, 132 1, 133 class_types); 134 } 135 136 // If we didn't find a symbol, then move on to the entire 137 // module list in the target and get as many unique matches 138 // as possible 139 if (num_matches == 0) 140 { 141 num_matches = target->GetImages().FindTypes (sc, 142 ConstString(class_name), 143 exact_match, 144 UINT32_MAX, 145 class_types); 146 } 147 148 lldb::TypeSP type_sp; 149 if (num_matches == 0) 150 { 151 if (log) 152 log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr); 153 return false; 154 } 155 if (num_matches == 1) 156 { 157 type_sp = class_types.GetTypeAtIndex(0); 158 if (log) 159 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n", 160 original_ptr, 161 in_value.GetTypeName().AsCString(), 162 type_sp->GetID(), 163 type_sp->GetName().GetCString()); 164 165 class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0)); 166 } 167 else if (num_matches > 1) 168 { 169 size_t i; 170 if (log) 171 { 172 for (i = 0; i < num_matches; i++) 173 { 174 type_sp = class_types.GetTypeAtIndex(i); 175 if (type_sp) 176 { 177 if (log) 178 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n", 179 original_ptr, 180 in_value.GetTypeName().AsCString(), 181 type_sp->GetID(), 182 type_sp->GetName().GetCString()); 183 } 184 } 185 } 186 187 for (i = 0; i < num_matches; i++) 188 { 189 type_sp = class_types.GetTypeAtIndex(i); 190 if (type_sp) 191 { 192 if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType())) 193 { 194 if (log) 195 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n", 196 original_ptr, 197 in_value.GetTypeName().AsCString(), 198 type_sp->GetID(), 199 type_sp->GetName().GetCString()); 200 class_type_or_name.SetTypeSP(type_sp); 201 break; 202 } 203 } 204 } 205 206 if (i == num_matches) 207 { 208 if (log) 209 log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n", 210 original_ptr, 211 in_value.GetTypeName().AsCString()); 212 return false; 213 } 214 } 215 216 // There can only be one type with a given name, 217 // so we've just found duplicate definitions, and this 218 // one will do as well as any other. 219 // We don't consider something to have a dynamic type if 220 // it is the same as the static type. So compare against 221 // the value we were handed. 222 if (type_sp) 223 { 224 clang::ASTContext *in_ast_ctx = in_value.GetClangAST (); 225 clang::ASTContext *this_ast_ctx = type_sp->GetClangAST (); 226 if (in_ast_ctx == this_ast_ctx) 227 { 228 if (ClangASTContext::AreTypesSame (in_ast_ctx, 229 in_value.GetClangType(), 230 type_sp->GetClangFullType())) 231 { 232 // The dynamic type we found was the same type, 233 // so we don't have a dynamic type here... 234 return false; 235 } 236 } 237 238 // The offset_to_top is two pointers above the address. 239 Address offset_to_top_address = address_point_address; 240 int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize()); 241 offset_to_top_address.Slide (slide); 242 243 Error error; 244 lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target); 245 246 size_t bytes_read = process->ReadMemory (offset_to_top_location, 247 memory_buffer, 248 address_byte_size, 249 error); 250 251 if (!error.Success() || (bytes_read != address_byte_size)) 252 { 253 return false; 254 } 255 256 offset_ptr = 0; 257 int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize()); 258 259 // So the dynamic type is a value that starts at offset_to_top 260 // above the original address. 261 lldb::addr_t dynamic_addr = original_ptr + offset_to_top; 262 if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address)) 263 { 264 dynamic_address.SetRawAddress(dynamic_addr); 265 } 266 return true; 267 } 268 } 269 } 270 } 271 } 272 } 273 274 return false; 275 } 276 277 bool 278 ItaniumABILanguageRuntime::IsVTableName (const char *name) 279 { 280 if (name == NULL) 281 return false; 282 283 // Can we maybe ask Clang about this? 284 if (strstr (name, "_vptr$") == name) 285 return true; 286 else 287 return false; 288 } 289 290 //------------------------------------------------------------------ 291 // Static Functions 292 //------------------------------------------------------------------ 293 LanguageRuntime * 294 ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language) 295 { 296 // FIXME: We have to check the process and make sure we actually know that this process supports 297 // the Itanium ABI. 298 if (language == eLanguageTypeC_plus_plus) 299 return new ItaniumABILanguageRuntime (process); 300 else 301 return NULL; 302 } 303 304 void 305 ItaniumABILanguageRuntime::Initialize() 306 { 307 PluginManager::RegisterPlugin (pluginName, 308 pluginDesc, 309 CreateInstance); 310 } 311 312 void 313 ItaniumABILanguageRuntime::Terminate() 314 { 315 PluginManager::UnregisterPlugin (CreateInstance); 316 } 317 318 //------------------------------------------------------------------ 319 // PluginInterface protocol 320 //------------------------------------------------------------------ 321 const char * 322 ItaniumABILanguageRuntime::GetPluginName() 323 { 324 return pluginName; 325 } 326 327 const char * 328 ItaniumABILanguageRuntime::GetShortPluginName() 329 { 330 return pluginShort; 331 } 332 333 uint32_t 334 ItaniumABILanguageRuntime::GetPluginVersion() 335 { 336 return 1; 337 } 338 339 static const char *exception_names[] = { "__cxa_begin_catch", "__cxa_throw", "__cxa_rethrow", "__cxa_allocate_exception"}; 340 static const int num_throw_names = 3; 341 static const int num_expression_throw_names = 1; 342 343 BreakpointResolverSP 344 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) 345 { 346 return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false); 347 } 348 349 BreakpointResolverSP 350 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) 351 { 352 BreakpointResolverSP resolver_sp; 353 static const int total_expressions = sizeof (exception_names)/sizeof (char *); 354 355 // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do 356 // anything better with predicting unwinding the expression parser does. So we have two forms of the exception 357 // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it. 358 // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former. 359 360 uint32_t num_expressions; 361 if (catch_bp && throw_bp) 362 { 363 if (for_expressions) 364 num_expressions = total_expressions; 365 else 366 num_expressions = total_expressions - num_expression_throw_names; 367 368 resolver_sp.reset (new BreakpointResolverName (bkpt, 369 exception_names, 370 num_expressions, 371 eFunctionNameTypeBase, 372 eLazyBoolNo)); 373 } 374 else if (throw_bp) 375 { 376 if (for_expressions) 377 num_expressions = num_throw_names - num_expression_throw_names; 378 else 379 num_expressions = num_throw_names; 380 381 resolver_sp.reset (new BreakpointResolverName (bkpt, 382 exception_names + 1, 383 num_expressions, 384 eFunctionNameTypeBase, 385 eLazyBoolNo)); 386 } 387 else if (catch_bp) 388 resolver_sp.reset (new BreakpointResolverName (bkpt, 389 exception_names, 390 total_expressions - num_throw_names, 391 eFunctionNameTypeBase, 392 eLazyBoolNo)); 393 394 return resolver_sp; 395 } 396 397 void 398 ItaniumABILanguageRuntime::SetExceptionBreakpoints () 399 { 400 if (!m_process) 401 return; 402 403 const bool catch_bp = false; 404 const bool throw_bp = true; 405 const bool is_internal = true; 406 const bool for_expressions = true; 407 408 // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and 409 // stop at exception allocation as well. 410 411 if (!m_cxx_exception_bp_sp) 412 { 413 Target &target = m_process->GetTarget(); 414 415 BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions); 416 SearchFilterSP filter_sp = target.GetSearchFilterForModule(NULL); 417 418 m_cxx_exception_bp_sp = target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal); 419 } 420 else 421 m_cxx_exception_bp_sp->SetEnabled (true); 422 423 } 424 425 void 426 ItaniumABILanguageRuntime::ClearExceptionBreakpoints () 427 { 428 if (!m_process) 429 return; 430 431 if (m_cxx_exception_bp_sp.get()) 432 { 433 m_cxx_exception_bp_sp->SetEnabled (false); 434 } 435 } 436 437 bool 438 ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason) 439 { 440 if (!m_process) 441 return false; 442 443 if (!stop_reason || 444 stop_reason->GetStopReason() != eStopReasonBreakpoint) 445 return false; 446 447 uint64_t break_site_id = stop_reason->GetValue(); 448 return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id, 449 m_cxx_exception_bp_sp->GetID()); 450 451 } 452