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