1254721Semaste//===-- Symtab.cpp ----------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include <map> 11254721Semaste 12254721Semaste#include "lldb/Core/Module.h" 13254721Semaste#include "lldb/Core/RegularExpression.h" 14254721Semaste#include "lldb/Core/Section.h" 15254721Semaste#include "lldb/Core/Timer.h" 16254721Semaste#include "lldb/Symbol/ObjectFile.h" 17254721Semaste#include "lldb/Symbol/SymbolContext.h" 18254721Semaste#include "lldb/Symbol/Symtab.h" 19254721Semaste#include "lldb/Target/CPPLanguageRuntime.h" 20254721Semaste#include "lldb/Target/ObjCLanguageRuntime.h" 21254721Semaste 22254721Semasteusing namespace lldb; 23254721Semasteusing namespace lldb_private; 24254721Semaste 25254721Semaste 26254721Semaste 27254721SemasteSymtab::Symtab(ObjectFile *objfile) : 28254721Semaste m_objfile (objfile), 29254721Semaste m_symbols (), 30254721Semaste m_file_addr_to_index (), 31254721Semaste m_name_to_index (), 32254721Semaste m_mutex (Mutex::eMutexTypeRecursive), 33254721Semaste m_file_addr_to_index_computed (false), 34254721Semaste m_name_indexes_computed (false) 35254721Semaste{ 36254721Semaste} 37254721Semaste 38254721SemasteSymtab::~Symtab() 39254721Semaste{ 40254721Semaste} 41254721Semaste 42254721Semastevoid 43254721SemasteSymtab::Reserve(size_t count) 44254721Semaste{ 45254721Semaste // Clients should grab the mutex from this symbol table and lock it manually 46254721Semaste // when calling this function to avoid performance issues. 47254721Semaste m_symbols.reserve (count); 48254721Semaste} 49254721Semaste 50254721SemasteSymbol * 51254721SemasteSymtab::Resize(size_t count) 52254721Semaste{ 53254721Semaste // Clients should grab the mutex from this symbol table and lock it manually 54254721Semaste // when calling this function to avoid performance issues. 55254721Semaste m_symbols.resize (count); 56254721Semaste return &m_symbols[0]; 57254721Semaste} 58254721Semaste 59254721Semasteuint32_t 60254721SemasteSymtab::AddSymbol(const Symbol& symbol) 61254721Semaste{ 62254721Semaste // Clients should grab the mutex from this symbol table and lock it manually 63254721Semaste // when calling this function to avoid performance issues. 64254721Semaste uint32_t symbol_idx = m_symbols.size(); 65254721Semaste m_name_to_index.Clear(); 66254721Semaste m_file_addr_to_index.Clear(); 67254721Semaste m_symbols.push_back(symbol); 68254721Semaste m_file_addr_to_index_computed = false; 69254721Semaste m_name_indexes_computed = false; 70254721Semaste return symbol_idx; 71254721Semaste} 72254721Semaste 73254721Semastesize_t 74254721SemasteSymtab::GetNumSymbols() const 75254721Semaste{ 76254721Semaste Mutex::Locker locker (m_mutex); 77254721Semaste return m_symbols.size(); 78254721Semaste} 79254721Semaste 80254721Semastevoid 81254721SemasteSymtab::Dump (Stream *s, Target *target, SortOrder sort_order) 82254721Semaste{ 83254721Semaste Mutex::Locker locker (m_mutex); 84254721Semaste 85254721Semaste// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 86254721Semaste s->Indent(); 87254721Semaste const FileSpec &file_spec = m_objfile->GetFileSpec(); 88254721Semaste const char * object_name = NULL; 89254721Semaste if (m_objfile->GetModule()) 90254721Semaste object_name = m_objfile->GetModule()->GetObjectName().GetCString(); 91254721Semaste 92254721Semaste if (file_spec) 93263363Semaste s->Printf("Symtab, file = %s%s%s%s, num_symbols = %zu", 94254721Semaste file_spec.GetPath().c_str(), 95254721Semaste object_name ? "(" : "", 96254721Semaste object_name ? object_name : "", 97254721Semaste object_name ? ")" : "", 98254721Semaste m_symbols.size()); 99254721Semaste else 100263363Semaste s->Printf("Symtab, num_symbols = %zu", m_symbols.size()); 101254721Semaste 102254721Semaste if (!m_symbols.empty()) 103254721Semaste { 104254721Semaste switch (sort_order) 105254721Semaste { 106254721Semaste case eSortOrderNone: 107254721Semaste { 108254721Semaste s->PutCString (":\n"); 109254721Semaste DumpSymbolHeader (s); 110254721Semaste const_iterator begin = m_symbols.begin(); 111254721Semaste const_iterator end = m_symbols.end(); 112254721Semaste for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) 113254721Semaste { 114254721Semaste s->Indent(); 115254721Semaste pos->Dump(s, target, std::distance(begin, pos)); 116254721Semaste } 117254721Semaste } 118254721Semaste break; 119254721Semaste 120254721Semaste case eSortOrderByName: 121254721Semaste { 122254721Semaste // Although we maintain a lookup by exact name map, the table 123254721Semaste // isn't sorted by name. So we must make the ordered symbol list 124254721Semaste // up ourselves. 125254721Semaste s->PutCString (" (sorted by name):\n"); 126254721Semaste DumpSymbolHeader (s); 127254721Semaste typedef std::multimap<const char*, const Symbol *, CStringCompareFunctionObject> CStringToSymbol; 128254721Semaste CStringToSymbol name_map; 129254721Semaste for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos) 130254721Semaste { 131254721Semaste const char *name = pos->GetMangled().GetName(Mangled::ePreferDemangled).AsCString(); 132254721Semaste if (name && name[0]) 133254721Semaste name_map.insert (std::make_pair(name, &(*pos))); 134254721Semaste } 135254721Semaste 136254721Semaste for (CStringToSymbol::const_iterator pos = name_map.begin(), end = name_map.end(); pos != end; ++pos) 137254721Semaste { 138254721Semaste s->Indent(); 139254721Semaste pos->second->Dump (s, target, pos->second - &m_symbols[0]); 140254721Semaste } 141254721Semaste } 142254721Semaste break; 143254721Semaste 144254721Semaste case eSortOrderByAddress: 145254721Semaste s->PutCString (" (sorted by address):\n"); 146254721Semaste DumpSymbolHeader (s); 147254721Semaste if (!m_file_addr_to_index_computed) 148254721Semaste InitAddressIndexes(); 149254721Semaste const size_t num_entries = m_file_addr_to_index.GetSize(); 150254721Semaste for (size_t i=0; i<num_entries; ++i) 151254721Semaste { 152254721Semaste s->Indent(); 153254721Semaste const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data; 154254721Semaste m_symbols[symbol_idx].Dump(s, target, symbol_idx); 155254721Semaste } 156254721Semaste break; 157254721Semaste } 158254721Semaste } 159254721Semaste} 160254721Semaste 161254721Semastevoid 162254721SemasteSymtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const 163254721Semaste{ 164254721Semaste Mutex::Locker locker (m_mutex); 165254721Semaste 166254721Semaste const size_t num_symbols = GetNumSymbols(); 167254721Semaste //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 168254721Semaste s->Indent(); 169263363Semaste s->Printf("Symtab %zu symbol indexes (%zu symbols total):\n", indexes.size(), m_symbols.size()); 170254721Semaste s->IndentMore(); 171254721Semaste 172254721Semaste if (!indexes.empty()) 173254721Semaste { 174254721Semaste std::vector<uint32_t>::const_iterator pos; 175254721Semaste std::vector<uint32_t>::const_iterator end = indexes.end(); 176254721Semaste DumpSymbolHeader (s); 177254721Semaste for (pos = indexes.begin(); pos != end; ++pos) 178254721Semaste { 179254721Semaste size_t idx = *pos; 180254721Semaste if (idx < num_symbols) 181254721Semaste { 182254721Semaste s->Indent(); 183254721Semaste m_symbols[idx].Dump(s, target, idx); 184254721Semaste } 185254721Semaste } 186254721Semaste } 187254721Semaste s->IndentLess (); 188254721Semaste} 189254721Semaste 190254721Semastevoid 191254721SemasteSymtab::DumpSymbolHeader (Stream *s) 192254721Semaste{ 193254721Semaste s->Indent(" Debug symbol\n"); 194254721Semaste s->Indent(" |Synthetic symbol\n"); 195254721Semaste s->Indent(" ||Externally Visible\n"); 196254721Semaste s->Indent(" |||\n"); 197254721Semaste s->Indent("Index UserID DSX Type File Address/Value Load Address Size Flags Name\n"); 198254721Semaste s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n"); 199254721Semaste} 200254721Semaste 201254721Semaste 202254721Semastestatic int 203254721SemasteCompareSymbolID (const void *key, const void *p) 204254721Semaste{ 205254721Semaste const user_id_t match_uid = *(user_id_t*) key; 206254721Semaste const user_id_t symbol_uid = ((Symbol *)p)->GetID(); 207254721Semaste if (match_uid < symbol_uid) 208254721Semaste return -1; 209254721Semaste if (match_uid > symbol_uid) 210254721Semaste return 1; 211254721Semaste return 0; 212254721Semaste} 213254721Semaste 214254721SemasteSymbol * 215254721SemasteSymtab::FindSymbolByID (lldb::user_id_t symbol_uid) const 216254721Semaste{ 217254721Semaste Mutex::Locker locker (m_mutex); 218254721Semaste 219254721Semaste Symbol *symbol = (Symbol*)::bsearch (&symbol_uid, 220254721Semaste &m_symbols[0], 221254721Semaste m_symbols.size(), 222254721Semaste (uint8_t *)&m_symbols[1] - (uint8_t *)&m_symbols[0], 223254721Semaste CompareSymbolID); 224254721Semaste return symbol; 225254721Semaste} 226254721Semaste 227254721Semaste 228254721SemasteSymbol * 229254721SemasteSymtab::SymbolAtIndex(size_t idx) 230254721Semaste{ 231254721Semaste // Clients should grab the mutex from this symbol table and lock it manually 232254721Semaste // when calling this function to avoid performance issues. 233254721Semaste if (idx < m_symbols.size()) 234254721Semaste return &m_symbols[idx]; 235254721Semaste return NULL; 236254721Semaste} 237254721Semaste 238254721Semaste 239254721Semasteconst Symbol * 240254721SemasteSymtab::SymbolAtIndex(size_t idx) const 241254721Semaste{ 242254721Semaste // Clients should grab the mutex from this symbol table and lock it manually 243254721Semaste // when calling this function to avoid performance issues. 244254721Semaste if (idx < m_symbols.size()) 245254721Semaste return &m_symbols[idx]; 246254721Semaste return NULL; 247254721Semaste} 248254721Semaste 249254721Semaste//---------------------------------------------------------------------- 250254721Semaste// InitNameIndexes 251254721Semaste//---------------------------------------------------------------------- 252254721Semastevoid 253254721SemasteSymtab::InitNameIndexes() 254254721Semaste{ 255254721Semaste // Protected function, no need to lock mutex... 256254721Semaste if (!m_name_indexes_computed) 257254721Semaste { 258254721Semaste m_name_indexes_computed = true; 259254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 260254721Semaste // Create the name index vector to be able to quickly search by name 261254721Semaste const size_t num_symbols = m_symbols.size(); 262254721Semaste#if 1 263254721Semaste m_name_to_index.Reserve (num_symbols); 264254721Semaste#else 265254721Semaste // TODO: benchmark this to see if we save any memory. Otherwise we 266254721Semaste // will always keep the memory reserved in the vector unless we pull 267254721Semaste // some STL swap magic and then recopy... 268254721Semaste uint32_t actual_count = 0; 269254721Semaste for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); 270254721Semaste pos != end; 271254721Semaste ++pos) 272254721Semaste { 273254721Semaste const Mangled &mangled = pos->GetMangled(); 274254721Semaste if (mangled.GetMangledName()) 275254721Semaste ++actual_count; 276254721Semaste 277254721Semaste if (mangled.GetDemangledName()) 278254721Semaste ++actual_count; 279254721Semaste } 280254721Semaste 281254721Semaste m_name_to_index.Reserve (actual_count); 282254721Semaste#endif 283254721Semaste 284254721Semaste NameToIndexMap::Entry entry; 285254721Semaste 286254721Semaste // The "const char *" in "class_contexts" must come from a ConstString::GetCString() 287254721Semaste std::set<const char *> class_contexts; 288254721Semaste UniqueCStringMap<uint32_t> mangled_name_to_index; 289254721Semaste std::vector<const char *> symbol_contexts(num_symbols, NULL); 290254721Semaste 291254721Semaste for (entry.value = 0; entry.value<num_symbols; ++entry.value) 292254721Semaste { 293254721Semaste const Symbol *symbol = &m_symbols[entry.value]; 294254721Semaste 295254721Semaste // Don't let trampolines get into the lookup by name map 296254721Semaste // If we ever need the trampoline symbols to be searchable by name 297254721Semaste // we can remove this and then possibly add a new bool to any of the 298254721Semaste // Symtab functions that lookup symbols by name to indicate if they 299254721Semaste // want trampolines. 300254721Semaste if (symbol->IsTrampoline()) 301254721Semaste continue; 302254721Semaste 303254721Semaste const Mangled &mangled = symbol->GetMangled(); 304254721Semaste entry.cstring = mangled.GetMangledName().GetCString(); 305254721Semaste if (entry.cstring && entry.cstring[0]) 306254721Semaste { 307254721Semaste m_name_to_index.Append (entry); 308254721Semaste 309254721Semaste const SymbolType symbol_type = symbol->GetType(); 310254721Semaste if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver) 311254721Semaste { 312254721Semaste if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' && 313254721Semaste (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name 314254721Semaste entry.cstring[2] != 'G' && // avoid guard variables 315254721Semaste entry.cstring[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back) 316254721Semaste { 317254721Semaste CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName()); 318254721Semaste entry.cstring = ConstString(cxx_method.GetBasename()).GetCString(); 319254721Semaste if (entry.cstring && entry.cstring[0]) 320254721Semaste { 321254721Semaste // ConstString objects permanently store the string in the pool so calling 322254721Semaste // GetCString() on the value gets us a const char * that will never go away 323254721Semaste const char *const_context = ConstString(cxx_method.GetContext()).GetCString(); 324254721Semaste 325254721Semaste if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty()) 326254721Semaste { 327254721Semaste // The first character of the demangled basename is '~' which 328254721Semaste // means we have a class destructor. We can use this information 329254721Semaste // to help us know what is a class and what isn't. 330254721Semaste if (class_contexts.find(const_context) == class_contexts.end()) 331254721Semaste class_contexts.insert(const_context); 332254721Semaste m_method_to_index.Append (entry); 333254721Semaste } 334254721Semaste else 335254721Semaste { 336254721Semaste if (const_context && const_context[0]) 337254721Semaste { 338254721Semaste if (class_contexts.find(const_context) != class_contexts.end()) 339254721Semaste { 340254721Semaste // The current decl context is in our "class_contexts" which means 341254721Semaste // this is a method on a class 342254721Semaste m_method_to_index.Append (entry); 343254721Semaste } 344254721Semaste else 345254721Semaste { 346254721Semaste // We don't know if this is a function basename or a method, 347254721Semaste // so put it into a temporary collection so once we are done 348254721Semaste // we can look in class_contexts to see if each entry is a class 349254721Semaste // or just a function and will put any remaining items into 350254721Semaste // m_method_to_index or m_basename_to_index as needed 351254721Semaste mangled_name_to_index.Append (entry); 352254721Semaste symbol_contexts[entry.value] = const_context; 353254721Semaste } 354254721Semaste } 355254721Semaste else 356254721Semaste { 357254721Semaste // No context for this function so this has to be a basename 358254721Semaste m_basename_to_index.Append(entry); 359254721Semaste } 360254721Semaste } 361254721Semaste } 362254721Semaste } 363254721Semaste } 364254721Semaste } 365254721Semaste 366254721Semaste entry.cstring = mangled.GetDemangledName().GetCString(); 367254721Semaste if (entry.cstring && entry.cstring[0]) 368254721Semaste m_name_to_index.Append (entry); 369254721Semaste 370254721Semaste // If the demangled name turns out to be an ObjC name, and 371254721Semaste // is a category name, add the version without categories to the index too. 372254721Semaste ObjCLanguageRuntime::MethodName objc_method (entry.cstring, true); 373254721Semaste if (objc_method.IsValid(true)) 374254721Semaste { 375254721Semaste entry.cstring = objc_method.GetSelector().GetCString(); 376254721Semaste m_selector_to_index.Append (entry); 377254721Semaste 378254721Semaste ConstString objc_method_no_category (objc_method.GetFullNameWithoutCategory(true)); 379254721Semaste if (objc_method_no_category) 380254721Semaste { 381254721Semaste entry.cstring = objc_method_no_category.GetCString(); 382254721Semaste m_name_to_index.Append (entry); 383254721Semaste } 384254721Semaste } 385254721Semaste 386254721Semaste } 387254721Semaste 388254721Semaste size_t count; 389254721Semaste if (!mangled_name_to_index.IsEmpty()) 390254721Semaste { 391254721Semaste count = mangled_name_to_index.GetSize(); 392254721Semaste for (size_t i=0; i<count; ++i) 393254721Semaste { 394254721Semaste if (mangled_name_to_index.GetValueAtIndex(i, entry.value)) 395254721Semaste { 396254721Semaste entry.cstring = mangled_name_to_index.GetCStringAtIndex(i); 397254721Semaste if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end()) 398254721Semaste { 399254721Semaste m_method_to_index.Append (entry); 400254721Semaste } 401254721Semaste else 402254721Semaste { 403254721Semaste // If we got here, we have something that had a context (was inside a namespace or class) 404254721Semaste // yet we don't know if the entry 405254721Semaste m_method_to_index.Append (entry); 406254721Semaste m_basename_to_index.Append (entry); 407254721Semaste } 408254721Semaste } 409254721Semaste } 410254721Semaste } 411254721Semaste m_name_to_index.Sort(); 412254721Semaste m_name_to_index.SizeToFit(); 413254721Semaste m_selector_to_index.Sort(); 414254721Semaste m_selector_to_index.SizeToFit(); 415254721Semaste m_basename_to_index.Sort(); 416254721Semaste m_basename_to_index.SizeToFit(); 417254721Semaste m_method_to_index.Sort(); 418254721Semaste m_method_to_index.SizeToFit(); 419254721Semaste 420254721Semaste// static StreamFile a ("/tmp/a.txt"); 421254721Semaste// 422254721Semaste// count = m_basename_to_index.GetSize(); 423254721Semaste// if (count) 424254721Semaste// { 425254721Semaste// for (size_t i=0; i<count; ++i) 426254721Semaste// { 427254721Semaste// if (m_basename_to_index.GetValueAtIndex(i, entry.value)) 428254721Semaste// a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString()); 429254721Semaste// } 430254721Semaste// } 431254721Semaste// count = m_method_to_index.GetSize(); 432254721Semaste// if (count) 433254721Semaste// { 434254721Semaste// for (size_t i=0; i<count; ++i) 435254721Semaste// { 436254721Semaste// if (m_method_to_index.GetValueAtIndex(i, entry.value)) 437254721Semaste// a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString()); 438254721Semaste// } 439254721Semaste// } 440254721Semaste } 441254721Semaste} 442254721Semaste 443254721Semastevoid 444254721SemasteSymtab::AppendSymbolNamesToMap (const IndexCollection &indexes, 445254721Semaste bool add_demangled, 446254721Semaste bool add_mangled, 447254721Semaste NameToIndexMap &name_to_index_map) const 448254721Semaste{ 449254721Semaste if (add_demangled || add_mangled) 450254721Semaste { 451254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 452254721Semaste Mutex::Locker locker (m_mutex); 453254721Semaste 454254721Semaste // Create the name index vector to be able to quickly search by name 455254721Semaste NameToIndexMap::Entry entry; 456254721Semaste const size_t num_indexes = indexes.size(); 457254721Semaste for (size_t i=0; i<num_indexes; ++i) 458254721Semaste { 459254721Semaste entry.value = indexes[i]; 460254721Semaste assert (i < m_symbols.size()); 461254721Semaste const Symbol *symbol = &m_symbols[entry.value]; 462254721Semaste 463254721Semaste const Mangled &mangled = symbol->GetMangled(); 464254721Semaste if (add_demangled) 465254721Semaste { 466254721Semaste entry.cstring = mangled.GetDemangledName().GetCString(); 467254721Semaste if (entry.cstring && entry.cstring[0]) 468254721Semaste name_to_index_map.Append (entry); 469254721Semaste } 470254721Semaste 471254721Semaste if (add_mangled) 472254721Semaste { 473254721Semaste entry.cstring = mangled.GetMangledName().GetCString(); 474254721Semaste if (entry.cstring && entry.cstring[0]) 475254721Semaste name_to_index_map.Append (entry); 476254721Semaste } 477254721Semaste } 478254721Semaste } 479254721Semaste} 480254721Semaste 481254721Semasteuint32_t 482254721SemasteSymtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const 483254721Semaste{ 484254721Semaste Mutex::Locker locker (m_mutex); 485254721Semaste 486254721Semaste uint32_t prev_size = indexes.size(); 487254721Semaste 488254721Semaste const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); 489254721Semaste 490254721Semaste for (uint32_t i = start_idx; i < count; ++i) 491254721Semaste { 492254721Semaste if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 493254721Semaste indexes.push_back(i); 494254721Semaste } 495254721Semaste 496254721Semaste return indexes.size() - prev_size; 497254721Semaste} 498254721Semaste 499254721Semasteuint32_t 500254721SemasteSymtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const 501254721Semaste{ 502254721Semaste Mutex::Locker locker (m_mutex); 503254721Semaste 504254721Semaste uint32_t prev_size = indexes.size(); 505254721Semaste 506254721Semaste const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); 507254721Semaste 508254721Semaste for (uint32_t i = start_idx; i < count; ++i) 509254721Semaste { 510254721Semaste if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value) 511254721Semaste indexes.push_back(i); 512254721Semaste } 513254721Semaste 514254721Semaste return indexes.size() - prev_size; 515254721Semaste} 516254721Semaste 517254721Semasteuint32_t 518254721SemasteSymtab::AppendSymbolIndexesWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const 519254721Semaste{ 520254721Semaste Mutex::Locker locker (m_mutex); 521254721Semaste 522254721Semaste uint32_t prev_size = indexes.size(); 523254721Semaste 524254721Semaste const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); 525254721Semaste 526254721Semaste for (uint32_t i = start_idx; i < count; ++i) 527254721Semaste { 528254721Semaste if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 529254721Semaste { 530254721Semaste if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) 531254721Semaste indexes.push_back(i); 532254721Semaste } 533254721Semaste } 534254721Semaste 535254721Semaste return indexes.size() - prev_size; 536254721Semaste} 537254721Semaste 538254721Semaste 539254721Semasteuint32_t 540254721SemasteSymtab::GetIndexForSymbol (const Symbol *symbol) const 541254721Semaste{ 542254721Semaste const Symbol *first_symbol = &m_symbols[0]; 543254721Semaste if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) 544254721Semaste return symbol - first_symbol; 545254721Semaste return UINT32_MAX; 546254721Semaste} 547254721Semaste 548254721Semastestruct SymbolSortInfo 549254721Semaste{ 550254721Semaste const bool sort_by_load_addr; 551254721Semaste const Symbol *symbols; 552254721Semaste}; 553254721Semaste 554254721Semastenamespace { 555254721Semaste struct SymbolIndexComparator { 556254721Semaste const std::vector<Symbol>& symbols; 557254721Semaste std::vector<lldb::addr_t> &addr_cache; 558254721Semaste 559254721Semaste // Getting from the symbol to the Address to the File Address involves some work. 560254721Semaste // Since there are potentially many symbols here, and we're using this for sorting so 561254721Semaste // we're going to be computing the address many times, cache that in addr_cache. 562254721Semaste // The array passed in has to be the same size as the symbols array passed into the 563254721Semaste // member variable symbols, and should be initialized with LLDB_INVALID_ADDRESS. 564254721Semaste // NOTE: You have to make addr_cache externally and pass it in because std::stable_sort 565254721Semaste // makes copies of the comparator it is initially passed in, and you end up spending 566254721Semaste // huge amounts of time copying this array... 567254721Semaste 568254721Semaste SymbolIndexComparator(const std::vector<Symbol>& s, std::vector<lldb::addr_t> &a) : symbols(s), addr_cache(a) { 569254721Semaste assert (symbols.size() == addr_cache.size()); 570254721Semaste } 571254721Semaste bool operator()(uint32_t index_a, uint32_t index_b) { 572254721Semaste addr_t value_a = addr_cache[index_a]; 573254721Semaste if (value_a == LLDB_INVALID_ADDRESS) 574254721Semaste { 575254721Semaste value_a = symbols[index_a].GetAddress().GetFileAddress(); 576254721Semaste addr_cache[index_a] = value_a; 577254721Semaste } 578254721Semaste 579254721Semaste addr_t value_b = addr_cache[index_b]; 580254721Semaste if (value_b == LLDB_INVALID_ADDRESS) 581254721Semaste { 582254721Semaste value_b = symbols[index_b].GetAddress().GetFileAddress(); 583254721Semaste addr_cache[index_b] = value_b; 584254721Semaste } 585254721Semaste 586254721Semaste 587254721Semaste if (value_a == value_b) { 588254721Semaste // The if the values are equal, use the original symbol user ID 589254721Semaste lldb::user_id_t uid_a = symbols[index_a].GetID(); 590254721Semaste lldb::user_id_t uid_b = symbols[index_b].GetID(); 591254721Semaste if (uid_a < uid_b) 592254721Semaste return true; 593254721Semaste if (uid_a > uid_b) 594254721Semaste return false; 595254721Semaste return false; 596254721Semaste } else if (value_a < value_b) 597254721Semaste return true; 598254721Semaste 599254721Semaste return false; 600254721Semaste } 601254721Semaste }; 602254721Semaste} 603254721Semaste 604254721Semastevoid 605254721SemasteSymtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const 606254721Semaste{ 607254721Semaste Mutex::Locker locker (m_mutex); 608254721Semaste 609254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__); 610254721Semaste // No need to sort if we have zero or one items... 611254721Semaste if (indexes.size() <= 1) 612254721Semaste return; 613254721Semaste 614254721Semaste // Sort the indexes in place using std::stable_sort. 615254721Semaste // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance, 616254721Semaste // not correctness. The indexes vector tends to be "close" to sorted, which the 617254721Semaste // stable sort handles better. 618254721Semaste 619254721Semaste std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); 620254721Semaste 621254721Semaste SymbolIndexComparator comparator(m_symbols, addr_cache); 622254721Semaste std::stable_sort(indexes.begin(), indexes.end(), comparator); 623254721Semaste 624254721Semaste // Remove any duplicates if requested 625254721Semaste if (remove_duplicates) 626254721Semaste std::unique(indexes.begin(), indexes.end()); 627254721Semaste} 628254721Semaste 629254721Semasteuint32_t 630254721SemasteSymtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes) 631254721Semaste{ 632254721Semaste Mutex::Locker locker (m_mutex); 633254721Semaste 634254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 635254721Semaste if (symbol_name) 636254721Semaste { 637254721Semaste const char *symbol_cstr = symbol_name.GetCString(); 638254721Semaste if (!m_name_indexes_computed) 639254721Semaste InitNameIndexes(); 640254721Semaste 641254721Semaste return m_name_to_index.GetValues (symbol_cstr, indexes); 642254721Semaste } 643254721Semaste return 0; 644254721Semaste} 645254721Semaste 646254721Semasteuint32_t 647254721SemasteSymtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 648254721Semaste{ 649254721Semaste Mutex::Locker locker (m_mutex); 650254721Semaste 651254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 652254721Semaste if (symbol_name) 653254721Semaste { 654254721Semaste const size_t old_size = indexes.size(); 655254721Semaste if (!m_name_indexes_computed) 656254721Semaste InitNameIndexes(); 657254721Semaste 658254721Semaste const char *symbol_cstr = symbol_name.GetCString(); 659254721Semaste 660254721Semaste std::vector<uint32_t> all_name_indexes; 661254721Semaste const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes); 662254721Semaste for (size_t i=0; i<name_match_count; ++i) 663254721Semaste { 664254721Semaste if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility)) 665254721Semaste indexes.push_back (all_name_indexes[i]); 666254721Semaste } 667254721Semaste return indexes.size() - old_size; 668254721Semaste } 669254721Semaste return 0; 670254721Semaste} 671254721Semaste 672254721Semasteuint32_t 673254721SemasteSymtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes) 674254721Semaste{ 675254721Semaste Mutex::Locker locker (m_mutex); 676254721Semaste 677254721Semaste if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) 678254721Semaste { 679254721Semaste std::vector<uint32_t>::iterator pos = indexes.begin(); 680254721Semaste while (pos != indexes.end()) 681254721Semaste { 682254721Semaste if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) 683254721Semaste ++pos; 684254721Semaste else 685263363Semaste pos = indexes.erase(pos); 686254721Semaste } 687254721Semaste } 688254721Semaste return indexes.size(); 689254721Semaste} 690254721Semaste 691254721Semasteuint32_t 692254721SemasteSymtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 693254721Semaste{ 694254721Semaste Mutex::Locker locker (m_mutex); 695254721Semaste 696254721Semaste if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0) 697254721Semaste { 698254721Semaste std::vector<uint32_t>::iterator pos = indexes.begin(); 699254721Semaste while (pos != indexes.end()) 700254721Semaste { 701254721Semaste if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) 702254721Semaste ++pos; 703254721Semaste else 704263363Semaste pos = indexes.erase(pos); 705254721Semaste } 706254721Semaste } 707254721Semaste return indexes.size(); 708254721Semaste} 709254721Semaste 710254721Semaste 711254721Semasteuint32_t 712254721SemasteSymtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, std::vector<uint32_t>& indexes) 713254721Semaste{ 714254721Semaste Mutex::Locker locker (m_mutex); 715254721Semaste 716254721Semaste uint32_t prev_size = indexes.size(); 717254721Semaste uint32_t sym_end = m_symbols.size(); 718254721Semaste 719254721Semaste for (uint32_t i = 0; i < sym_end; i++) 720254721Semaste { 721254721Semaste if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 722254721Semaste { 723254721Semaste const char *name = m_symbols[i].GetMangled().GetName().AsCString(); 724254721Semaste if (name) 725254721Semaste { 726254721Semaste if (regexp.Execute (name)) 727254721Semaste indexes.push_back(i); 728254721Semaste } 729254721Semaste } 730254721Semaste } 731254721Semaste return indexes.size() - prev_size; 732254721Semaste 733254721Semaste} 734254721Semaste 735254721Semasteuint32_t 736254721SemasteSymtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) 737254721Semaste{ 738254721Semaste Mutex::Locker locker (m_mutex); 739254721Semaste 740254721Semaste uint32_t prev_size = indexes.size(); 741254721Semaste uint32_t sym_end = m_symbols.size(); 742254721Semaste 743254721Semaste for (uint32_t i = 0; i < sym_end; i++) 744254721Semaste { 745254721Semaste if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) 746254721Semaste { 747254721Semaste if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) 748254721Semaste continue; 749254721Semaste 750254721Semaste const char *name = m_symbols[i].GetMangled().GetName().AsCString(); 751254721Semaste if (name) 752254721Semaste { 753254721Semaste if (regexp.Execute (name)) 754254721Semaste indexes.push_back(i); 755254721Semaste } 756254721Semaste } 757254721Semaste } 758254721Semaste return indexes.size() - prev_size; 759254721Semaste 760254721Semaste} 761254721Semaste 762254721SemasteSymbol * 763254721SemasteSymtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx) 764254721Semaste{ 765254721Semaste Mutex::Locker locker (m_mutex); 766254721Semaste 767254721Semaste const size_t count = m_symbols.size(); 768254721Semaste for (size_t idx = start_idx; idx < count; ++idx) 769254721Semaste { 770254721Semaste if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type) 771254721Semaste { 772254721Semaste if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) 773254721Semaste { 774254721Semaste start_idx = idx; 775254721Semaste return &m_symbols[idx]; 776254721Semaste } 777254721Semaste } 778254721Semaste } 779254721Semaste return NULL; 780254721Semaste} 781254721Semaste 782254721Semastesize_t 783254721SemasteSymtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes) 784254721Semaste{ 785254721Semaste Mutex::Locker locker (m_mutex); 786254721Semaste 787254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 788254721Semaste // Initialize all of the lookup by name indexes before converting NAME 789254721Semaste // to a uniqued string NAME_STR below. 790254721Semaste if (!m_name_indexes_computed) 791254721Semaste InitNameIndexes(); 792254721Semaste 793254721Semaste if (name) 794254721Semaste { 795254721Semaste // The string table did have a string that matched, but we need 796254721Semaste // to check the symbols and match the symbol_type if any was given. 797254721Semaste AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes); 798254721Semaste } 799254721Semaste return symbol_indexes.size(); 800254721Semaste} 801254721Semaste 802254721Semastesize_t 803254721SemasteSymtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) 804254721Semaste{ 805254721Semaste Mutex::Locker locker (m_mutex); 806254721Semaste 807254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 808254721Semaste // Initialize all of the lookup by name indexes before converting NAME 809254721Semaste // to a uniqued string NAME_STR below. 810254721Semaste if (!m_name_indexes_computed) 811254721Semaste InitNameIndexes(); 812254721Semaste 813254721Semaste if (name) 814254721Semaste { 815254721Semaste // The string table did have a string that matched, but we need 816254721Semaste // to check the symbols and match the symbol_type if any was given. 817254721Semaste AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); 818254721Semaste } 819254721Semaste return symbol_indexes.size(); 820254721Semaste} 821254721Semaste 822254721Semastesize_t 823254721SemasteSymtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) 824254721Semaste{ 825254721Semaste Mutex::Locker locker (m_mutex); 826254721Semaste 827254721Semaste AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); 828254721Semaste return symbol_indexes.size(); 829254721Semaste} 830254721Semaste 831254721SemasteSymbol * 832254721SemasteSymtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility) 833254721Semaste{ 834254721Semaste Mutex::Locker locker (m_mutex); 835254721Semaste 836254721Semaste Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__); 837254721Semaste if (!m_name_indexes_computed) 838254721Semaste InitNameIndexes(); 839254721Semaste 840254721Semaste if (name) 841254721Semaste { 842254721Semaste std::vector<uint32_t> matching_indexes; 843254721Semaste // The string table did have a string that matched, but we need 844254721Semaste // to check the symbols and match the symbol_type if any was given. 845254721Semaste if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes)) 846254721Semaste { 847254721Semaste std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); 848254721Semaste for (pos = matching_indexes.begin(); pos != end; ++pos) 849254721Semaste { 850254721Semaste Symbol *symbol = SymbolAtIndex(*pos); 851254721Semaste 852254721Semaste if (symbol->Compare(name, symbol_type)) 853254721Semaste return symbol; 854254721Semaste } 855254721Semaste } 856254721Semaste } 857254721Semaste return NULL; 858254721Semaste} 859254721Semaste 860254721Semastetypedef struct 861254721Semaste{ 862254721Semaste const Symtab *symtab; 863254721Semaste const addr_t file_addr; 864254721Semaste Symbol *match_symbol; 865254721Semaste const uint32_t *match_index_ptr; 866254721Semaste addr_t match_offset; 867254721Semaste} SymbolSearchInfo; 868254721Semaste 869254721Semastestatic int 870254721SemasteSymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) 871254721Semaste{ 872254721Semaste const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]); 873254721Semaste if (curr_symbol == NULL) 874254721Semaste return -1; 875254721Semaste 876254721Semaste const addr_t info_file_addr = info->file_addr; 877254721Semaste 878254721Semaste // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address 879254721Semaste // range if the symbol has a section! 880254721Semaste if (curr_symbol->ValueIsAddress()) 881254721Semaste { 882254721Semaste const addr_t curr_file_addr = curr_symbol->GetAddress().GetFileAddress(); 883254721Semaste if (info_file_addr < curr_file_addr) 884254721Semaste return -1; 885254721Semaste if (info_file_addr > curr_file_addr) 886254721Semaste return +1; 887254721Semaste info->match_symbol = const_cast<Symbol *>(curr_symbol); 888254721Semaste info->match_index_ptr = index_ptr; 889254721Semaste return 0; 890254721Semaste } 891254721Semaste 892254721Semaste return -1; 893254721Semaste} 894254721Semaste 895254721Semastestatic int 896254721SemasteSymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr) 897254721Semaste{ 898254721Semaste const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]); 899254721Semaste if (symbol == NULL) 900254721Semaste return -1; 901254721Semaste 902254721Semaste const addr_t info_file_addr = info->file_addr; 903254721Semaste if (symbol->ValueIsAddress()) 904254721Semaste { 905254721Semaste const addr_t curr_file_addr = symbol->GetAddress().GetFileAddress(); 906254721Semaste if (info_file_addr < curr_file_addr) 907254721Semaste return -1; 908254721Semaste 909254721Semaste // Since we are finding the closest symbol that is greater than or equal 910254721Semaste // to 'info->file_addr' we set the symbol here. This will get set 911254721Semaste // multiple times, but after the search is done it will contain the best 912254721Semaste // symbol match 913254721Semaste info->match_symbol = const_cast<Symbol *>(symbol); 914254721Semaste info->match_index_ptr = index_ptr; 915254721Semaste info->match_offset = info_file_addr - curr_file_addr; 916254721Semaste 917254721Semaste if (info_file_addr > curr_file_addr) 918254721Semaste return +1; 919254721Semaste return 0; 920254721Semaste } 921254721Semaste return -1; 922254721Semaste} 923254721Semaste 924254721Semastestatic SymbolSearchInfo 925254721SemasteFindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) 926254721Semaste{ 927254721Semaste SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 }; 928254721Semaste ::bsearch (&info, 929254721Semaste indexes, 930254721Semaste num_indexes, 931254721Semaste sizeof(uint32_t), 932254721Semaste (ComparisonFunction)SymbolWithClosestFileAddress); 933254721Semaste return info; 934254721Semaste} 935254721Semaste 936254721Semaste 937254721Semastevoid 938254721SemasteSymtab::InitAddressIndexes() 939254721Semaste{ 940254721Semaste // Protected function, no need to lock mutex... 941254721Semaste if (!m_file_addr_to_index_computed && !m_symbols.empty()) 942254721Semaste { 943254721Semaste m_file_addr_to_index_computed = true; 944254721Semaste 945254721Semaste FileRangeToIndexMap::Entry entry; 946254721Semaste const_iterator begin = m_symbols.begin(); 947254721Semaste const_iterator end = m_symbols.end(); 948254721Semaste for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) 949254721Semaste { 950254721Semaste if (pos->ValueIsAddress()) 951254721Semaste { 952254721Semaste entry.SetRangeBase(pos->GetAddress().GetFileAddress()); 953254721Semaste entry.SetByteSize(pos->GetByteSize()); 954254721Semaste entry.data = std::distance(begin, pos); 955254721Semaste m_file_addr_to_index.Append(entry); 956254721Semaste } 957254721Semaste } 958254721Semaste const size_t num_entries = m_file_addr_to_index.GetSize(); 959254721Semaste if (num_entries > 0) 960254721Semaste { 961254721Semaste m_file_addr_to_index.Sort(); 962254721Semaste m_file_addr_to_index.CalculateSizesOfZeroByteSizeRanges(); 963254721Semaste 964254721Semaste // Now our last symbols might not have had sizes because there 965254721Semaste // was no subsequent symbol to calculate the size from. If this is 966254721Semaste // the case, then calculate the size by capping it at the end of the 967254721Semaste // section in which the symbol resides 968254721Semaste for (int i = num_entries - 1; i >= 0; --i) 969254721Semaste { 970254721Semaste const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i); 971254721Semaste // As we iterate backwards, as soon as we find a symbol with a valid 972254721Semaste // byte size, we are done 973254721Semaste if (entry.GetByteSize() > 0) 974254721Semaste break; 975254721Semaste 976254721Semaste // Cap the size to the end of the section in which the symbol resides 977254721Semaste SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (entry.GetRangeBase())); 978254721Semaste if (section_sp) 979254721Semaste { 980254721Semaste const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize(); 981254721Semaste const lldb::addr_t symbol_file_addr = entry.GetRangeBase(); 982254721Semaste if (end_section_file_addr > symbol_file_addr) 983254721Semaste { 984254721Semaste Symbol &symbol = m_symbols[entry.data]; 985254721Semaste 986254721Semaste symbol.SetByteSize(end_section_file_addr - symbol_file_addr); 987254721Semaste symbol.SetSizeIsSynthesized(true); 988254721Semaste } 989254721Semaste } 990254721Semaste } 991254721Semaste // Sort again in case the range size changes the ordering 992254721Semaste m_file_addr_to_index.Sort(); 993254721Semaste } 994254721Semaste } 995254721Semaste} 996254721Semaste 997254721Semastevoid 998254721SemasteSymtab::CalculateSymbolSizes () 999254721Semaste{ 1000254721Semaste Mutex::Locker locker (m_mutex); 1001254721Semaste 1002254721Semaste if (!m_symbols.empty()) 1003254721Semaste { 1004254721Semaste if (!m_file_addr_to_index_computed) 1005254721Semaste InitAddressIndexes(); 1006254721Semaste 1007254721Semaste const size_t num_entries = m_file_addr_to_index.GetSize(); 1008254721Semaste 1009254721Semaste for (size_t i = 0; i < num_entries; ++i) 1010254721Semaste { 1011254721Semaste // The entries in the m_file_addr_to_index have calculated the sizes already 1012254721Semaste // so we will use this size if we need to. 1013254721Semaste const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i); 1014254721Semaste 1015254721Semaste Symbol &symbol = m_symbols[entry.data]; 1016254721Semaste 1017254721Semaste // If the symbol size is already valid, no need to do anything 1018254721Semaste if (symbol.GetByteSizeIsValid()) 1019254721Semaste continue; 1020254721Semaste 1021254721Semaste const addr_t range_size = entry.GetByteSize(); 1022254721Semaste if (range_size > 0) 1023254721Semaste { 1024254721Semaste symbol.SetByteSize(range_size); 1025254721Semaste symbol.SetSizeIsSynthesized(true); 1026254721Semaste } 1027254721Semaste } 1028254721Semaste } 1029254721Semaste} 1030254721Semaste 1031254721SemasteSymbol * 1032254721SemasteSymtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes) 1033254721Semaste{ 1034254721Semaste Mutex::Locker locker (m_mutex); 1035254721Semaste 1036254721Semaste 1037254721Semaste SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 }; 1038254721Semaste 1039254721Semaste ::bsearch (&info, 1040254721Semaste indexes, 1041254721Semaste num_indexes, 1042254721Semaste sizeof(uint32_t), 1043254721Semaste (ComparisonFunction)SymbolWithClosestFileAddress); 1044254721Semaste 1045254721Semaste if (info.match_symbol) 1046254721Semaste { 1047254721Semaste if (info.match_offset == 0) 1048254721Semaste { 1049254721Semaste // We found an exact match! 1050254721Semaste return info.match_symbol; 1051254721Semaste } 1052254721Semaste 1053254721Semaste const size_t symbol_byte_size = info.match_symbol->GetByteSize(); 1054254721Semaste 1055254721Semaste if (symbol_byte_size == 0) 1056254721Semaste { 1057254721Semaste // We weren't able to find the size of the symbol so lets just go 1058254721Semaste // with that match we found in our search... 1059254721Semaste return info.match_symbol; 1060254721Semaste } 1061254721Semaste 1062254721Semaste // We were able to figure out a symbol size so lets make sure our 1063254721Semaste // offset puts "file_addr" in the symbol's address range. 1064254721Semaste if (info.match_offset < symbol_byte_size) 1065254721Semaste return info.match_symbol; 1066254721Semaste } 1067254721Semaste return NULL; 1068254721Semaste} 1069254721Semaste 1070254721SemasteSymbol * 1071254721SemasteSymtab::FindSymbolContainingFileAddress (addr_t file_addr) 1072254721Semaste{ 1073254721Semaste Mutex::Locker locker (m_mutex); 1074254721Semaste 1075254721Semaste if (!m_file_addr_to_index_computed) 1076254721Semaste InitAddressIndexes(); 1077254721Semaste 1078254721Semaste const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryThatContains(file_addr); 1079254721Semaste if (entry) 1080254721Semaste return SymbolAtIndex(entry->data); 1081254721Semaste return NULL; 1082254721Semaste} 1083254721Semaste 1084254721Semastevoid 1085254721SemasteSymtab::SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) 1086254721Semaste{ 1087254721Semaste // No need to protect this call using m_mutex all other method calls are 1088254721Semaste // already thread safe. 1089254721Semaste 1090254721Semaste const bool merge_symbol_into_function = true; 1091254721Semaste size_t num_indices = symbol_indexes.size(); 1092254721Semaste if (num_indices > 0) 1093254721Semaste { 1094254721Semaste SymbolContext sc; 1095254721Semaste sc.module_sp = m_objfile->GetModule(); 1096254721Semaste for (size_t i = 0; i < num_indices; i++) 1097254721Semaste { 1098254721Semaste sc.symbol = SymbolAtIndex (symbol_indexes[i]); 1099254721Semaste if (sc.symbol) 1100254721Semaste sc_list.AppendIfUnique(sc, merge_symbol_into_function); 1101254721Semaste } 1102254721Semaste } 1103254721Semaste} 1104254721Semaste 1105254721Semaste 1106254721Semastesize_t 1107254721SemasteSymtab::FindFunctionSymbols (const ConstString &name, 1108254721Semaste uint32_t name_type_mask, 1109254721Semaste SymbolContextList& sc_list) 1110254721Semaste{ 1111254721Semaste size_t count = 0; 1112254721Semaste std::vector<uint32_t> symbol_indexes; 1113254721Semaste 1114254721Semaste const char *name_cstr = name.GetCString(); 1115254721Semaste 1116254721Semaste // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup() 1117254721Semaste assert ((name_type_mask & eFunctionNameTypeAuto) == 0); 1118254721Semaste 1119254721Semaste if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) 1120254721Semaste { 1121254721Semaste std::vector<uint32_t> temp_symbol_indexes; 1122254721Semaste FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, temp_symbol_indexes); 1123254721Semaste 1124254721Semaste unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); 1125254721Semaste if (temp_symbol_indexes_size > 0) 1126254721Semaste { 1127254721Semaste Mutex::Locker locker (m_mutex); 1128254721Semaste for (unsigned i = 0; i < temp_symbol_indexes_size; i++) 1129254721Semaste { 1130254721Semaste SymbolContext sym_ctx; 1131254721Semaste sym_ctx.symbol = SymbolAtIndex (temp_symbol_indexes[i]); 1132254721Semaste if (sym_ctx.symbol) 1133254721Semaste { 1134254721Semaste switch (sym_ctx.symbol->GetType()) 1135254721Semaste { 1136254721Semaste case eSymbolTypeCode: 1137254721Semaste case eSymbolTypeResolver: 1138263363Semaste case eSymbolTypeReExported: 1139254721Semaste symbol_indexes.push_back(temp_symbol_indexes[i]); 1140254721Semaste break; 1141254721Semaste default: 1142254721Semaste break; 1143254721Semaste } 1144254721Semaste } 1145254721Semaste } 1146254721Semaste } 1147254721Semaste } 1148254721Semaste 1149254721Semaste if (name_type_mask & eFunctionNameTypeBase) 1150254721Semaste { 1151254721Semaste // From mangled names we can't tell what is a basename and what 1152254721Semaste // is a method name, so we just treat them the same 1153254721Semaste if (!m_name_indexes_computed) 1154254721Semaste InitNameIndexes(); 1155254721Semaste 1156254721Semaste if (!m_basename_to_index.IsEmpty()) 1157254721Semaste { 1158254721Semaste const UniqueCStringMap<uint32_t>::Entry *match; 1159254721Semaste for (match = m_basename_to_index.FindFirstValueForName(name_cstr); 1160254721Semaste match != NULL; 1161254721Semaste match = m_basename_to_index.FindNextValueForName(match)) 1162254721Semaste { 1163254721Semaste symbol_indexes.push_back(match->value); 1164254721Semaste } 1165254721Semaste } 1166254721Semaste } 1167254721Semaste 1168254721Semaste if (name_type_mask & eFunctionNameTypeMethod) 1169254721Semaste { 1170254721Semaste if (!m_name_indexes_computed) 1171254721Semaste InitNameIndexes(); 1172254721Semaste 1173254721Semaste if (!m_method_to_index.IsEmpty()) 1174254721Semaste { 1175254721Semaste const UniqueCStringMap<uint32_t>::Entry *match; 1176254721Semaste for (match = m_method_to_index.FindFirstValueForName(name_cstr); 1177254721Semaste match != NULL; 1178254721Semaste match = m_method_to_index.FindNextValueForName(match)) 1179254721Semaste { 1180254721Semaste symbol_indexes.push_back(match->value); 1181254721Semaste } 1182254721Semaste } 1183254721Semaste } 1184254721Semaste 1185254721Semaste if (name_type_mask & eFunctionNameTypeSelector) 1186254721Semaste { 1187254721Semaste if (!m_name_indexes_computed) 1188254721Semaste InitNameIndexes(); 1189254721Semaste 1190254721Semaste if (!m_selector_to_index.IsEmpty()) 1191254721Semaste { 1192254721Semaste const UniqueCStringMap<uint32_t>::Entry *match; 1193254721Semaste for (match = m_selector_to_index.FindFirstValueForName(name_cstr); 1194254721Semaste match != NULL; 1195254721Semaste match = m_selector_to_index.FindNextValueForName(match)) 1196254721Semaste { 1197254721Semaste symbol_indexes.push_back(match->value); 1198254721Semaste } 1199254721Semaste } 1200254721Semaste } 1201254721Semaste 1202254721Semaste if (!symbol_indexes.empty()) 1203254721Semaste { 1204254721Semaste std::sort(symbol_indexes.begin(), symbol_indexes.end()); 1205254721Semaste symbol_indexes.erase(std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end()); 1206254721Semaste count = symbol_indexes.size(); 1207254721Semaste SymbolIndicesToSymbolContextList (symbol_indexes, sc_list); 1208254721Semaste } 1209254721Semaste 1210254721Semaste return count; 1211254721Semaste} 1212254721Semaste 1213