Module.cpp revision e005f2ce03c489ebde9110678a29cbfe8488d5b4
1//===-- Module.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 "lldb/Core/Module.h" 11#include "lldb/Core/Log.h" 12#include "lldb/Core/ModuleList.h" 13#include "lldb/Core/RegularExpression.h" 14#include "lldb/Core/Timer.h" 15#include "lldb/lldb-private-log.h" 16#include "lldb/Symbol/ObjectFile.h" 17#include "lldb/Symbol/SymbolContext.h" 18#include "lldb/Symbol/SymbolVendor.h" 19 20using namespace lldb; 21using namespace lldb_private; 22 23Module::Module(const FileSpec& file_spec, const ArchSpec& arch, const ConstString *object_name, off_t object_offset) : 24 m_mutex (Mutex::eMutexTypeRecursive), 25 m_mod_time (file_spec.GetModificationTime()), 26 m_arch (arch), 27 m_uuid (), 28 m_file (file_spec), 29 m_object_name (), 30 m_objfile_ap (), 31 m_symfile_ap (), 32 m_did_load_objfile (false), 33 m_did_load_symbol_vendor (false), 34 m_did_parse_uuid (false), 35 m_is_dynamic_loader_module (false) 36{ 37 if (object_name) 38 m_object_name = *object_name; 39 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 40 if (log) 41 log->Printf ("%p Module::Module((%s) '%s/%s%s%s%s')", 42 this, 43 m_arch.AsCString(), 44 m_file.GetDirectory().AsCString(""), 45 m_file.GetFilename().AsCString(""), 46 m_object_name.IsEmpty() ? "" : "(", 47 m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), 48 m_object_name.IsEmpty() ? "" : ")"); 49} 50 51Module::~Module() 52{ 53 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 54 if (log) 55 log->Printf ("%p Module::~Module((%s) '%s/%s%s%s%s')", 56 this, 57 m_arch.AsCString(), 58 m_file.GetDirectory().AsCString(""), 59 m_file.GetFilename().AsCString(""), 60 m_object_name.IsEmpty() ? "" : "(", 61 m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), 62 m_object_name.IsEmpty() ? "" : ")"); 63} 64 65 66ModuleSP 67Module::GetSP () 68{ 69 return ModuleList::GetModuleSP (this); 70} 71 72const UUID& 73Module::GetUUID() 74{ 75 Mutex::Locker locker (m_mutex); 76 if (m_did_parse_uuid == false) 77 { 78 ObjectFile * obj_file = GetObjectFile (); 79 80 if (obj_file != NULL) 81 { 82 obj_file->GetUUID(&m_uuid); 83 m_did_parse_uuid = true; 84 } 85 } 86 return m_uuid; 87} 88 89void 90Module::ParseAllDebugSymbols() 91{ 92 Mutex::Locker locker (m_mutex); 93 uint32_t num_comp_units = GetNumCompileUnits(); 94 if (num_comp_units == 0) 95 return; 96 97 TargetSP null_target; 98 SymbolContext sc(null_target, GetSP()); 99 uint32_t cu_idx; 100 SymbolVendor *symbols = GetSymbolVendor (); 101 102 for (cu_idx = 0; cu_idx < num_comp_units; cu_idx++) 103 { 104 sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get(); 105 if (sc.comp_unit) 106 { 107 sc.function = NULL; 108 symbols->ParseVariablesForContext(sc); 109 110 symbols->ParseCompileUnitFunctions(sc); 111 112 uint32_t func_idx; 113 for (func_idx = 0; (sc.function = sc.comp_unit->GetFunctionAtIndex(func_idx).get()) != NULL; ++func_idx) 114 { 115 symbols->ParseFunctionBlocks(sc); 116 117 // Parse the variables for this function and all its blocks 118 symbols->ParseVariablesForContext(sc); 119 } 120 121 122 // Parse all types for this compile unit 123 sc.function = NULL; 124 symbols->ParseTypes(sc); 125 } 126 } 127} 128 129void 130Module::CalculateSymbolContext(SymbolContext* sc) 131{ 132 sc->module_sp = GetSP(); 133} 134 135void 136Module::DumpSymbolContext(Stream *s) 137{ 138 s->Printf(", Module{0x%8.8x}", this); 139} 140 141uint32_t 142Module::GetNumCompileUnits() 143{ 144 Mutex::Locker locker (m_mutex); 145 Timer scoped_timer(__PRETTY_FUNCTION__, "Module::GetNumCompileUnits (module = %p)", this); 146 SymbolVendor *symbols = GetSymbolVendor (); 147 if (symbols) 148 return symbols->GetNumCompileUnits(); 149 return 0; 150} 151 152CompUnitSP 153Module::GetCompileUnitAtIndex (uint32_t index) 154{ 155 Mutex::Locker locker (m_mutex); 156 uint32_t num_comp_units = GetNumCompileUnits (); 157 CompUnitSP cu_sp; 158 159 if (index < num_comp_units) 160 { 161 SymbolVendor *symbols = GetSymbolVendor (); 162 if (symbols) 163 cu_sp = symbols->GetCompileUnitAtIndex(index); 164 } 165 return cu_sp; 166} 167 168//CompUnitSP 169//Module::FindCompUnit(lldb::user_id_t uid) 170//{ 171// CompUnitSP cu_sp; 172// SymbolVendor *symbols = GetSymbolVendor (); 173// if (symbols) 174// cu_sp = symbols->FindCompUnit(uid); 175// return cu_sp; 176//} 177 178bool 179Module::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) 180{ 181 Mutex::Locker locker (m_mutex); 182 Timer scoped_timer(__PRETTY_FUNCTION__, "Module::ResolveFileAddress (vm_addr = 0x%llx)", vm_addr); 183 ObjectFile* ofile = GetObjectFile(); 184 if (ofile) 185 return so_addr.ResolveAddressUsingFileSections(vm_addr, ofile->GetSectionList()); 186 return false; 187} 188 189uint32_t 190Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) 191{ 192 Mutex::Locker locker (m_mutex); 193 uint32_t resolved_flags = 0; 194 195 // Clear the result symbol context in case we don't find anything 196 sc.Clear(); 197 198 // Get the section from the section/offset address. 199 const Section *section = so_addr.GetSection(); 200 201 // Make sure the section matches this module before we try and match anything 202 if (section && section->GetModule() == this) 203 { 204 // If the section offset based address resolved itself, then this 205 // is the right module. 206 sc.module_sp = GetSP(); 207 resolved_flags |= eSymbolContextModule; 208 209 // Resolve the compile unit, function, block, line table or line 210 // entry if requested. 211 if (resolve_scope & eSymbolContextCompUnit || 212 resolve_scope & eSymbolContextFunction || 213 resolve_scope & eSymbolContextBlock || 214 resolve_scope & eSymbolContextLineEntry ) 215 { 216 SymbolVendor *symbols = GetSymbolVendor (); 217 if (symbols) 218 resolved_flags |= symbols->ResolveSymbolContext (so_addr, resolve_scope, sc); 219 } 220 221 // Resolve the symbol if requested, but don't re-look it up if we've already found it. 222 if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol)) 223 { 224 ObjectFile* ofile = GetObjectFile(); 225 if (ofile) 226 { 227 Symtab *symtab = ofile->GetSymtab(); 228 if (symtab) 229 { 230 if (so_addr.IsSectionOffset()) 231 { 232 sc.symbol = symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); 233 if (sc.symbol) 234 resolved_flags |= eSymbolContextSymbol; 235 } 236 } 237 } 238 } 239 } 240 return resolved_flags; 241} 242 243uint32_t 244Module::ResolveSymbolContextForFilePath 245( 246 const char *file_path, 247 uint32_t line, 248 bool check_inlines, 249 uint32_t resolve_scope, 250 SymbolContextList& sc_list 251) 252{ 253 FileSpec file_spec(file_path, false); 254 return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); 255} 256 257uint32_t 258Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) 259{ 260 Mutex::Locker locker (m_mutex); 261 Timer scoped_timer(__PRETTY_FUNCTION__, 262 "Module::ResolveSymbolContextForFilePath (%s%s%s:%u, check_inlines = %s, resolve_scope = 0x%8.8x)", 263 file_spec.GetDirectory().AsCString(""), 264 file_spec.GetDirectory() ? "/" : "", 265 file_spec.GetFilename().AsCString(""), 266 line, 267 check_inlines ? "yes" : "no", 268 resolve_scope); 269 270 const uint32_t initial_count = sc_list.GetSize(); 271 272 SymbolVendor *symbols = GetSymbolVendor (); 273 if (symbols) 274 symbols->ResolveSymbolContext (file_spec, line, check_inlines, resolve_scope, sc_list); 275 276 return sc_list.GetSize() - initial_count; 277} 278 279 280uint32_t 281Module::FindGlobalVariables(const ConstString &name, bool append, uint32_t max_matches, VariableList& variables) 282{ 283 SymbolVendor *symbols = GetSymbolVendor (); 284 if (symbols) 285 return symbols->FindGlobalVariables(name, append, max_matches, variables); 286 return 0; 287} 288uint32_t 289Module::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) 290{ 291 SymbolVendor *symbols = GetSymbolVendor (); 292 if (symbols) 293 return symbols->FindGlobalVariables(regex, append, max_matches, variables); 294 return 0; 295} 296 297uint32_t 298Module::FindFunctions(const ConstString &name, uint32_t name_type_mask, bool append, SymbolContextList& sc_list) 299{ 300 SymbolVendor *symbols = GetSymbolVendor (); 301 if (symbols) 302 return symbols->FindFunctions(name, name_type_mask, append, sc_list); 303 return 0; 304} 305 306uint32_t 307Module::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list) 308{ 309 SymbolVendor *symbols = GetSymbolVendor (); 310 if (symbols) 311 return symbols->FindFunctions(regex, append, sc_list); 312 return 0; 313} 314 315uint32_t 316Module::FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) 317{ 318 Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 319 if (sc.module_sp.get() == NULL || sc.module_sp.get() == this) 320 { 321 SymbolVendor *symbols = GetSymbolVendor (); 322 if (symbols) 323 return symbols->FindTypes(sc, name, append, max_matches, types); 324 } 325 return 0; 326} 327 328//uint32_t 329//Module::FindTypes(const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, const char *udt_name, TypeList& types) 330//{ 331// Timer scoped_timer(__PRETTY_FUNCTION__); 332// SymbolVendor *symbols = GetSymbolVendor (); 333// if (symbols) 334// return symbols->FindTypes(sc, regex, append, max_matches, encoding, udt_name, types); 335// return 0; 336// 337//} 338 339SymbolVendor* 340Module::GetSymbolVendor (bool can_create) 341{ 342 Mutex::Locker locker (m_mutex); 343 if (m_did_load_symbol_vendor == false && can_create) 344 { 345 ObjectFile *obj_file = GetObjectFile (); 346 if (obj_file != NULL) 347 { 348 Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 349 m_symfile_ap.reset(SymbolVendor::FindPlugin(this)); 350 m_did_load_symbol_vendor = true; 351 } 352 } 353 return m_symfile_ap.get(); 354} 355 356const FileSpec & 357Module::GetFileSpec () const 358{ 359 return m_file; 360} 361 362void 363Module::SetFileSpecAndObjectName (const FileSpec &file, const ConstString &object_name) 364{ 365 // Container objects whose paths do not specify a file directly can call 366 // this function to correct the file and object names. 367 m_file = file; 368 m_mod_time = file.GetModificationTime(); 369 m_object_name = object_name; 370} 371 372const ArchSpec& 373Module::GetArchitecture () const 374{ 375 return m_arch; 376} 377 378void 379Module::GetDescription (Stream *s) 380{ 381 Mutex::Locker locker (m_mutex); 382 383 if (m_arch.IsValid()) 384 s->Printf("(%s) ", m_arch.AsCString()); 385 386 char path[PATH_MAX]; 387 if (m_file.GetPath(path, sizeof(path))) 388 s->PutCString(path); 389 390 const char *object_name = m_object_name.GetCString(); 391 if (object_name) 392 s->Printf("(%s)", object_name); 393} 394 395void 396Module::Dump(Stream *s) 397{ 398 Mutex::Locker locker (m_mutex); 399 //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 400 s->Indent(); 401 s->Printf("Module %s/%s%s%s%s\n", 402 m_file.GetDirectory().AsCString(), 403 m_file.GetFilename().AsCString(), 404 m_object_name ? "(" : "", 405 m_object_name ? m_object_name.GetCString() : "", 406 m_object_name ? ")" : ""); 407 408 s->IndentMore(); 409 ObjectFile *objfile = GetObjectFile (); 410 411 if (objfile) 412 objfile->Dump(s); 413 414 SymbolVendor *symbols = GetSymbolVendor (); 415 416 if (symbols) 417 symbols->Dump(s); 418 419 s->IndentLess(); 420} 421 422 423TypeList* 424Module::GetTypeList () 425{ 426 SymbolVendor *symbols = GetSymbolVendor (); 427 if (symbols) 428 return &symbols->GetTypeList(); 429 return NULL; 430} 431 432const ConstString & 433Module::GetObjectName() const 434{ 435 return m_object_name; 436} 437 438ObjectFile * 439Module::GetObjectFile() 440{ 441 Mutex::Locker locker (m_mutex); 442 if (m_did_load_objfile == false) 443 { 444 m_did_load_objfile = true; 445 Timer scoped_timer(__PRETTY_FUNCTION__, 446 "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString("")); 447 m_objfile_ap.reset(ObjectFile::FindPlugin(this, &m_file, 0, m_file.GetByteSize())); 448 } 449 return m_objfile_ap.get(); 450} 451 452 453const Symbol * 454Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type) 455{ 456 Timer scoped_timer(__PRETTY_FUNCTION__, 457 "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)", 458 name.AsCString(), 459 symbol_type); 460 ObjectFile *objfile = GetObjectFile(); 461 if (objfile) 462 { 463 Symtab *symtab = objfile->GetSymtab(); 464 if (symtab) 465 return symtab->FindFirstSymbolWithNameAndType (name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); 466 } 467 return NULL; 468} 469void 470Module::SymbolIndicesToSymbolContextList (Symtab *symtab, std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) 471{ 472 // No need to protect this call using m_mutex all other method calls are 473 // already thread safe. 474 475 size_t num_indices = symbol_indexes.size(); 476 if (num_indices > 0) 477 { 478 SymbolContext sc; 479 CalculateSymbolContext (&sc); 480 for (size_t i = 0; i < num_indices; i++) 481 { 482 sc.symbol = symtab->SymbolAtIndex (symbol_indexes[i]); 483 if (sc.symbol) 484 sc_list.Append (sc); 485 } 486 } 487} 488 489size_t 490Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list) 491{ 492 // No need to protect this call using m_mutex all other method calls are 493 // already thread safe. 494 495 496 Timer scoped_timer(__PRETTY_FUNCTION__, 497 "Module::FindSymbolsWithNameAndType (name = %s, type = %i)", 498 name.AsCString(), 499 symbol_type); 500 const size_t initial_size = sc_list.GetSize(); 501 ObjectFile *objfile = GetObjectFile (); 502 if (objfile) 503 { 504 Symtab *symtab = objfile->GetSymtab(); 505 if (symtab) 506 { 507 std::vector<uint32_t> symbol_indexes; 508 symtab->FindAllSymbolsWithNameAndType (name, symbol_type, symbol_indexes); 509 SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); 510 } 511 } 512 return sc_list.GetSize() - initial_size; 513} 514 515size_t 516Module::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, SymbolType symbol_type, SymbolContextList &sc_list) 517{ 518 // No need to protect this call using m_mutex all other method calls are 519 // already thread safe. 520 521 Timer scoped_timer(__PRETTY_FUNCTION__, 522 "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)", 523 regex.GetText(), 524 symbol_type); 525 const size_t initial_size = sc_list.GetSize(); 526 ObjectFile *objfile = GetObjectFile (); 527 if (objfile) 528 { 529 Symtab *symtab = objfile->GetSymtab(); 530 if (symtab) 531 { 532 std::vector<uint32_t> symbol_indexes; 533 symtab->FindAllSymbolsMatchingRexExAndType (regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); 534 SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); 535 } 536 } 537 return sc_list.GetSize() - initial_size; 538} 539 540const TimeValue & 541Module::GetModificationTime () const 542{ 543 return m_mod_time; 544} 545 546bool 547Module::IsExecutable () 548{ 549 if (GetObjectFile() == NULL) 550 return false; 551 else 552 return GetObjectFile()->IsExecutable(); 553} 554 555bool 556Module::SetArchitecture (const ArchSpec &new_arch) 557{ 558 if (m_arch == new_arch) 559 return true; 560 else if (!m_arch.IsValid()) 561 { 562 m_arch = new_arch; 563 return true; 564 } 565 else 566 { 567 return false; 568 } 569 570} 571 572