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().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 //------------------------------------------------------------------ 285 // Static Functions 286 //------------------------------------------------------------------ 287 LanguageRuntime * 288 ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language) 289 { 290 // FIXME: We have to check the process and make sure we actually know that this process supports 291 // the Itanium ABI. 292 if (language == eLanguageTypeC_plus_plus || 293 language == eLanguageTypeC_plus_plus_03 || 294 language == eLanguageTypeC_plus_plus_11) 295 return new ItaniumABILanguageRuntime (process); 296 else 297 return NULL; 298 } 299 300 void 301 ItaniumABILanguageRuntime::Initialize() 302 { 303 PluginManager::RegisterPlugin (GetPluginNameStatic(), 304 "Itanium ABI for the C++ language", 305 CreateInstance); 306 } 307 308 void 309 ItaniumABILanguageRuntime::Terminate() 310 { 311 PluginManager::UnregisterPlugin (CreateInstance); 312 } 313 314 lldb_private::ConstString 315 ItaniumABILanguageRuntime::GetPluginNameStatic() 316 { 317 static ConstString g_name("itanium"); 318 return g_name; 319 } 320 321 //------------------------------------------------------------------ 322 // PluginInterface protocol 323 //------------------------------------------------------------------ 324 lldb_private::ConstString 325 ItaniumABILanguageRuntime::GetPluginName() 326 { 327 return GetPluginNameStatic(); 328 } 329 330 uint32_t 331 ItaniumABILanguageRuntime::GetPluginVersion() 332 { 333 return 1; 334 } 335 336 BreakpointResolverSP 337 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) 338 { 339 return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false); 340 } 341 342 BreakpointResolverSP 343 ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) 344 { 345 // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do 346 // anything better with predicting unwinding the expression parser does. So we have two forms of the exception 347 // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it. 348 // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former. 349 static const char *g_catch_name = "__cxa_begin_catch"; 350 static const char *g_throw_name1 = "__cxa_throw"; 351 static const char *g_throw_name2 = "__cxa_rethrow"; 352 static const char *g_exception_throw_name = "__cxa_allocate_exception"; 353 std::vector<const char *> exception_names; 354 exception_names.reserve(4); 355 if (catch_bp) 356 exception_names.push_back(g_catch_name); 357 358 if (throw_bp) 359 { 360 exception_names.push_back(g_throw_name1); 361 exception_names.push_back(g_throw_name2); 362 } 363 364 if (for_expressions) 365 exception_names.push_back(g_exception_throw_name); 366 367 BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt, 368 exception_names.data(), 369 exception_names.size(), 370 eFunctionNameTypeBase, 371 eLazyBoolNo)); 372 373 return resolver_sp; 374 } 375 376 377 378 lldb::SearchFilterSP 379 ItaniumABILanguageRuntime::CreateExceptionSearchFilter () 380 { 381 Target &target = m_process->GetTarget(); 382 383 if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) 384 { 385 // Limit the number of modules that are searched for these breakpoints for 386 // Apple binaries. 387 FileSpecList filter_modules; 388 filter_modules.Append(FileSpec("libc++abi.dylib", false)); 389 filter_modules.Append(FileSpec("libSystem.B.dylib", false)); 390 return target.GetSearchFilterForModuleList(&filter_modules); 391 } 392 else 393 { 394 return LanguageRuntime::CreateExceptionSearchFilter(); 395 } 396 } 397 398 lldb::BreakpointSP 399 ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp, 400 bool throw_bp, 401 bool for_expressions, 402 bool is_internal) 403 { 404 Target &target = m_process->GetTarget(); 405 FileSpecList filter_modules; 406 BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions); 407 SearchFilterSP filter_sp (CreateExceptionSearchFilter ()); 408 const bool hardware = false; 409 const bool resolve_indirect_functions = false; 410 return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions); 411 } 412 413 void 414 ItaniumABILanguageRuntime::SetExceptionBreakpoints () 415 { 416 if (!m_process) 417 return; 418 419 const bool catch_bp = false; 420 const bool throw_bp = true; 421 const bool is_internal = true; 422 const bool for_expressions = true; 423 424 // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and 425 // stop at exception allocation as well. 426 427 if (m_cxx_exception_bp_sp) 428 { 429 m_cxx_exception_bp_sp->SetEnabled (true); 430 } 431 else 432 { 433 m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal); 434 if (m_cxx_exception_bp_sp) 435 m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception"); 436 } 437 438 } 439 440 void 441 ItaniumABILanguageRuntime::ClearExceptionBreakpoints () 442 { 443 if (!m_process) 444 return; 445 446 if (m_cxx_exception_bp_sp) 447 { 448 m_cxx_exception_bp_sp->SetEnabled (false); 449 } 450 } 451 452 bool 453 ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet () 454 { 455 return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled(); 456 } 457 458 bool 459 ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason) 460 { 461 if (!m_process) 462 return false; 463 464 if (!stop_reason || 465 stop_reason->GetStopReason() != eStopReasonBreakpoint) 466 return false; 467 468 uint64_t break_site_id = stop_reason->GetValue(); 469 return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id, 470 m_cxx_exception_bp_sp->GetID()); 471 472 } 473