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/SectionLoadList.h" 27 #include "lldb/Target/StopInfo.h" 28 #include "lldb/Target/Target.h" 29 #include "lldb/Target/Thread.h" 30 31 #include <vector> 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 static const char *vtable_demangled_prefix = "vtable for "; 37 38 bool 39 ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) 40 { 41 const bool check_cxx = true; 42 const bool check_objc = false; 43 return in_value.GetClangType().IsPossibleDynamicType (NULL, check_cxx, check_objc); 44 } 45 46 bool 47 ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, 48 lldb::DynamicValueType use_dynamic, 49 TypeAndOrName &class_type_or_name, 50 Address &dynamic_address) 51 { 52 // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0 53 // in the object. That will point to the "address point" within the vtable (not the beginning of the 54 // vtable.) We can then look up the symbol containing this "address point" and that symbol's name 55 // demangled will contain the full class name. 56 // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the 57 // start of the value object which holds the dynamic type. 58 // 59 60 class_type_or_name.Clear(); 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 lldb::offset_t offset = 0; 92 lldb::addr_t vtable_address_point = data.GetAddress (&offset); 93 94 if (offset == 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(lldb::eLanguageTypeC_plus_plus).AsCString(); 110 if (name && strstr(name, vtable_demangled_prefix) == name) 111 { 112 Log *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 (type_sp->GetClangFullType().IsCXXClassType()) 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 if (ClangASTContext::AreTypesSame (in_value.GetClangType(), 225 type_sp->GetClangFullType())) 226 { 227 // The dynamic type we found was the same type, 228 // so we don't have a dynamic type here... 229 return false; 230 } 231 232 // The offset_to_top is two pointers above the address. 233 Address offset_to_top_address = address_point_address; 234 int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize()); 235 offset_to_top_address.Slide (slide); 236 237 Error error; 238 lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target); 239 240 size_t bytes_read = process->ReadMemory (offset_to_top_location, 241 memory_buffer, 242 address_byte_size, 243 error); 244 245 if (!error.Success() || (bytes_read != address_byte_size)) 246 { 247 return false; 248 } 249 250 offset = 0; 251 int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize()); 252 253 // So the dynamic type is a value that starts at offset_to_top 254 // above the original address. 255 lldb::addr_t dynamic_addr = original_ptr + offset_to_top; 256 if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address)) 257 { 258 dynamic_address.SetRawAddress(dynamic_addr); 259 } 260 return true; 261 } 262 } 263 } 264 } 265 } 266 } 267 268 return class_type_or_name.IsEmpty() == false; 269 } 270 271 bool 272 ItaniumABILanguageRuntime::IsVTableName (const char *name) 273 { 274 if (name == NULL) 275 return false; 276 277 // Can we maybe ask Clang about this? 278 if (strstr (name, "_vptr$") == name) 279 return true; 280 else 281 return false; 282 } 283 284 static std::map<ConstString, std::vector<ConstString> >& 285 GetAlternateManglingPrefixes() 286 { 287 static std::map<ConstString, std::vector<ConstString> > g_alternate_mangling_prefixes; 288 return g_alternate_mangling_prefixes; 289 } 290 291 292 size_t 293 ItaniumABILanguageRuntime::GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) 294 { 295 if (!mangled) 296 return static_cast<size_t>(0); 297 298 alternates.clear(); 299 const char *mangled_cstr = mangled.AsCString(); 300 std::map<ConstString, std::vector<ConstString> >& alternate_mangling_prefixes = GetAlternateManglingPrefixes(); 301 for (std::map<ConstString, std::vector<ConstString> >::iterator it = alternate_mangling_prefixes.begin(); 302 it != alternate_mangling_prefixes.end(); 303 ++it) 304 { 305 const char *prefix_cstr = it->first.AsCString(); 306 if (strncmp(mangled_cstr, prefix_cstr, strlen(prefix_cstr)) == 0) 307 { 308 const std::vector<ConstString> &alternate_prefixes = it->second; 309 for (size_t i = 0; i < alternate_prefixes.size(); ++i) 310 { 311 std::string alternate_mangling(alternate_prefixes[i].AsCString()); 312 alternate_mangling.append(mangled_cstr + strlen(prefix_cstr)); 313 314 alternates.push_back(ConstString(alternate_mangling.c_str())); 315 } 316 317 return alternates.size(); 318 } 319 } 320 321 return static_cast<size_t>(0); 322 } 323 324 //------------------------------------------------------------------ 325 // Static Functions 326 //------------------------------------------------------------------ 327 LanguageRuntime * 328 ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language) 329 { 330 // FIXME: We have to check the process and make sure we actually know that this process supports 331 // the Itanium ABI. 332 if (language == eLanguageTypeC_plus_plus || 333 language == eLanguageTypeC_plus_plus_03 || 334 language == eLanguageTypeC_plus_plus_11 || 335 language == eLanguageTypeC_plus_plus_14) 336 return new ItaniumABILanguageRuntime (process); 337 else 338 return NULL; 339 } 340 341 void 342 ItaniumABILanguageRuntime::Initialize() 343 { 344 PluginManager::RegisterPlugin (GetPluginNameStatic(), 345 "Itanium ABI for the C++ language", 346 CreateInstance); 347 348 // Alternate manglings for std::basic_string<...> 349 std::vector<ConstString> basic_string_alternates; 350 basic_string_alternates.push_back(ConstString("_ZNSs")); 351 basic_string_alternates.push_back(ConstString("_ZNKSs")); 352 std::map<ConstString, std::vector<ConstString> >& alternate_mangling_prefixes = GetAlternateManglingPrefixes(); 353 354 alternate_mangling_prefixes[ConstString("_ZNSbIcSt17char_traits<char>St15allocator<char>E")] = 355 basic_string_alternates; 356 alternate_mangling_prefixes[ConstString("_ZNKSbIcSt17char_traits<char>St15allocator<char>E")] = 357 basic_string_alternates; 358 } 359 360 void 361 ItaniumABILanguageRuntime::Terminate() 362 { 363 PluginManager::UnregisterPlugin (CreateInstance); 364 } 365 366 lldb_private::ConstString 367 ItaniumABILanguageRuntime::GetPluginNameStatic() 368 { 369 static ConstString g_name("itanium"); 370 return g_name; 371 } 372 373 //------------------------------------------------------------------ 374 // PluginInterface protocol 375 //------------------------------------------------------------------ 376 lldb_private::ConstString 377 ItaniumABILanguageRuntime::GetPluginName() 378 { 379 return GetPluginNameStatic(); 380 } 381 382 uint32_t 383 ItaniumABILanguageRuntime::GetPluginVersion() 384 { 385 return 1; 386 } 387 388 BreakpointResolverSP 389 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) 390 { 391 return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false); 392 } 393 394 BreakpointResolverSP 395 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) 396 { 397 // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do 398 // anything better with predicting unwinding the expression parser does. So we have two forms of the exception 399 // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it. 400 // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former. 401 static const char *g_catch_name = "__cxa_begin_catch"; 402 static const char *g_throw_name1 = "__cxa_throw"; 403 static const char *g_throw_name2 = "__cxa_rethrow"; 404 static const char *g_exception_throw_name = "__cxa_allocate_exception"; 405 std::vector<const char *> exception_names; 406 exception_names.reserve(4); 407 if (catch_bp) 408 exception_names.push_back(g_catch_name); 409 410 if (throw_bp) 411 { 412 exception_names.push_back(g_throw_name1); 413 exception_names.push_back(g_throw_name2); 414 } 415 416 if (for_expressions) 417 exception_names.push_back(g_exception_throw_name); 418 419 BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt, 420 exception_names.data(), 421 exception_names.size(), 422 eFunctionNameTypeBase, 423 eLazyBoolNo)); 424 425 return resolver_sp; 426 } 427 428 429 430 lldb::SearchFilterSP 431 ItaniumABILanguageRuntime::CreateExceptionSearchFilter () 432 { 433 Target &target = m_process->GetTarget(); 434 435 if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) 436 { 437 // Limit the number of modules that are searched for these breakpoints for 438 // Apple binaries. 439 FileSpecList filter_modules; 440 filter_modules.Append(FileSpec("libc++abi.dylib", false)); 441 filter_modules.Append(FileSpec("libSystem.B.dylib", false)); 442 return target.GetSearchFilterForModuleList(&filter_modules); 443 } 444 else 445 { 446 return LanguageRuntime::CreateExceptionSearchFilter(); 447 } 448 } 449 450 lldb::BreakpointSP 451 ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp, 452 bool throw_bp, 453 bool for_expressions, 454 bool is_internal) 455 { 456 Target &target = m_process->GetTarget(); 457 FileSpecList filter_modules; 458 BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions); 459 SearchFilterSP filter_sp (CreateExceptionSearchFilter ()); 460 const bool hardware = false; 461 const bool resolve_indirect_functions = false; 462 return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions); 463 } 464 465 void 466 ItaniumABILanguageRuntime::SetExceptionBreakpoints () 467 { 468 if (!m_process) 469 return; 470 471 const bool catch_bp = false; 472 const bool throw_bp = true; 473 const bool is_internal = true; 474 const bool for_expressions = true; 475 476 // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and 477 // stop at exception allocation as well. 478 479 if (m_cxx_exception_bp_sp) 480 { 481 m_cxx_exception_bp_sp->SetEnabled (true); 482 } 483 else 484 { 485 m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal); 486 if (m_cxx_exception_bp_sp) 487 m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception"); 488 } 489 490 } 491 492 void 493 ItaniumABILanguageRuntime::ClearExceptionBreakpoints () 494 { 495 if (!m_process) 496 return; 497 498 if (m_cxx_exception_bp_sp) 499 { 500 m_cxx_exception_bp_sp->SetEnabled (false); 501 } 502 } 503 504 bool 505 ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet () 506 { 507 return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled(); 508 } 509 510 bool 511 ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason) 512 { 513 if (!m_process) 514 return false; 515 516 if (!stop_reason || 517 stop_reason->GetStopReason() != eStopReasonBreakpoint) 518 return false; 519 520 uint64_t break_site_id = stop_reason->GetValue(); 521 return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id, 522 m_cxx_exception_bp_sp->GetID()); 523 524 } 525