LLDB  mainline
Symtab.cpp
Go to the documentation of this file.
1 //===-- Symtab.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <map>
10 #include <set>
11 
13 
14 #include "lldb/Core/Module.h"
16 #include "lldb/Core/STLUtils.h"
17 #include "lldb/Core/Section.h"
18 #include "lldb/Symbol/ObjectFile.h"
19 #include "lldb/Symbol/Symbol.h"
21 #include "lldb/Symbol/Symtab.h"
23 #include "lldb/Utility/Stream.h"
24 #include "lldb/Utility/Timer.h"
25 
26 #include "llvm/ADT/StringRef.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 Symtab::Symtab(ObjectFile *objfile)
32  : m_objfile(objfile), m_symbols(), m_file_addr_to_index(),
33  m_name_to_index(), m_mutex(), m_file_addr_to_index_computed(false),
34  m_name_indexes_computed(false) {}
35 
37 
38 void Symtab::Reserve(size_t count) {
39  // Clients should grab the mutex from this symbol table and lock it manually
40  // when calling this function to avoid performance issues.
41  m_symbols.reserve(count);
42 }
43 
44 Symbol *Symtab::Resize(size_t count) {
45  // Clients should grab the mutex from this symbol table and lock it manually
46  // when calling this function to avoid performance issues.
47  m_symbols.resize(count);
48  return m_symbols.empty() ? nullptr : &m_symbols[0];
49 }
50 
52  // Clients should grab the mutex from this symbol table and lock it manually
53  // when calling this function to avoid performance issues.
54  uint32_t symbol_idx = m_symbols.size();
57  m_symbols.push_back(symbol);
60  return symbol_idx;
61 }
62 
63 size_t Symtab::GetNumSymbols() const {
64  std::lock_guard<std::recursive_mutex> guard(m_mutex);
65  return m_symbols.size();
66 }
67 
71 }
72 
73 void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
74  std::lock_guard<std::recursive_mutex> guard(m_mutex);
75 
76  // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
77  s->Indent();
78  const FileSpec &file_spec = m_objfile->GetFileSpec();
79  const char *object_name = nullptr;
80  if (m_objfile->GetModule())
81  object_name = m_objfile->GetModule()->GetObjectName().GetCString();
82 
83  if (file_spec)
84  s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64,
85  file_spec.GetPath().c_str(), object_name ? "(" : "",
86  object_name ? object_name : "", object_name ? ")" : "",
87  (uint64_t)m_symbols.size());
88  else
89  s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size());
90 
91  if (!m_symbols.empty()) {
92  switch (sort_order) {
93  case eSortOrderNone: {
94  s->PutCString(":\n");
96  const_iterator begin = m_symbols.begin();
97  const_iterator end = m_symbols.end();
98  for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) {
99  s->Indent();
100  pos->Dump(s, target, std::distance(begin, pos));
101  }
102  } break;
103 
104  case eSortOrderByName: {
105  // Although we maintain a lookup by exact name map, the table isn't
106  // sorted by name. So we must make the ordered symbol list up ourselves.
107  s->PutCString(" (sorted by name):\n");
108  DumpSymbolHeader(s);
109  typedef std::multimap<const char *, const Symbol *,
111  CStringToSymbol;
112  CStringToSymbol name_map;
113  for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
114  pos != end; ++pos) {
115  const char *name = pos->GetName().AsCString();
116  if (name && name[0])
117  name_map.insert(std::make_pair(name, &(*pos)));
118  }
119 
120  for (CStringToSymbol::const_iterator pos = name_map.begin(),
121  end = name_map.end();
122  pos != end; ++pos) {
123  s->Indent();
124  pos->second->Dump(s, target, pos->second - &m_symbols[0]);
125  }
126  } break;
127 
128  case eSortOrderByAddress:
129  s->PutCString(" (sorted by address):\n");
130  DumpSymbolHeader(s);
133  const size_t num_entries = m_file_addr_to_index.GetSize();
134  for (size_t i = 0; i < num_entries; ++i) {
135  s->Indent();
136  const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data;
137  m_symbols[symbol_idx].Dump(s, target, symbol_idx);
138  }
139  break;
140  }
141  } else {
142  s->PutCString("\n");
143  }
144 }
145 
146 void Symtab::Dump(Stream *s, Target *target,
147  std::vector<uint32_t> &indexes) const {
148  std::lock_guard<std::recursive_mutex> guard(m_mutex);
149 
150  const size_t num_symbols = GetNumSymbols();
151  // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
152  s->Indent();
153  s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n",
154  (uint64_t)indexes.size(), (uint64_t)m_symbols.size());
155  s->IndentMore();
156 
157  if (!indexes.empty()) {
158  std::vector<uint32_t>::const_iterator pos;
159  std::vector<uint32_t>::const_iterator end = indexes.end();
160  DumpSymbolHeader(s);
161  for (pos = indexes.begin(); pos != end; ++pos) {
162  size_t idx = *pos;
163  if (idx < num_symbols) {
164  s->Indent();
165  m_symbols[idx].Dump(s, target, idx);
166  }
167  }
168  }
169  s->IndentLess();
170 }
171 
173  s->Indent(" Debug symbol\n");
174  s->Indent(" |Synthetic symbol\n");
175  s->Indent(" ||Externally Visible\n");
176  s->Indent(" |||\n");
177  s->Indent("Index UserID DSX Type File Address/Value Load "
178  "Address Size Flags Name\n");
179  s->Indent("------- ------ --- --------------- ------------------ "
180  "------------------ ------------------ ---------- "
181  "----------------------------------\n");
182 }
183 
184 static int CompareSymbolID(const void *key, const void *p) {
185  const user_id_t match_uid = *(const user_id_t *)key;
186  const user_id_t symbol_uid = ((const Symbol *)p)->GetID();
187  if (match_uid < symbol_uid)
188  return -1;
189  if (match_uid > symbol_uid)
190  return 1;
191  return 0;
192 }
193 
195  std::lock_guard<std::recursive_mutex> guard(m_mutex);
196 
197  Symbol *symbol =
198  (Symbol *)::bsearch(&symbol_uid, &m_symbols[0], m_symbols.size(),
199  sizeof(m_symbols[0]), CompareSymbolID);
200  return symbol;
201 }
202 
204  // Clients should grab the mutex from this symbol table and lock it manually
205  // when calling this function to avoid performance issues.
206  if (idx < m_symbols.size())
207  return &m_symbols[idx];
208  return nullptr;
209 }
210 
211 const Symbol *Symtab::SymbolAtIndex(size_t idx) const {
212  // Clients should grab the mutex from this symbol table and lock it manually
213  // when calling this function to avoid performance issues.
214  if (idx < m_symbols.size())
215  return &m_symbols[idx];
216  return nullptr;
217 }
218 
219 // InitNameIndexes
220 static bool lldb_skip_name(llvm::StringRef mangled,
221  Mangled::ManglingScheme scheme) {
222  switch (scheme) {
223  case Mangled::eManglingSchemeItanium: {
224  if (mangled.size() < 3 || !mangled.startswith("_Z"))
225  return true;
226 
227  // Avoid the following types of symbols in the index.
228  switch (mangled[2]) {
229  case 'G': // guard variables
230  case 'T': // virtual tables, VTT structures, typeinfo structures + names
231  case 'Z': // named local entities (if we eventually handle
232  // eSymbolTypeData, we will want this back)
233  return true;
234 
235  default:
236  break;
237  }
238 
239  // Include this name in the index.
240  return false;
241  }
242 
243  // No filters for this scheme yet. Include all names in indexing.
244  case Mangled::eManglingSchemeMSVC:
245  return false;
246 
247  // Don't try and demangle things we can't categorize.
248  case Mangled::eManglingSchemeNone:
249  return true;
250  }
251  llvm_unreachable("unknown scheme!");
252 }
253 
255  // Protected function, no need to lock mutex...
258  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
259  Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
260  // Create the name index vector to be able to quickly search by name
261  const size_t num_symbols = m_symbols.size();
262 #if 1
263  m_name_to_index.Reserve(num_symbols);
264 #else
265  // TODO: benchmark this to see if we save any memory. Otherwise we
266  // will always keep the memory reserved in the vector unless we pull some
267  // STL swap magic and then recopy...
268  uint32_t actual_count = 0;
269  for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
270  pos != end; ++pos) {
271  const Mangled &mangled = pos->GetMangled();
272  if (mangled.GetMangledName())
273  ++actual_count;
274 
275  if (mangled.GetDemangledName())
276  ++actual_count;
277  }
278 
279  m_name_to_index.Reserve(actual_count);
280 #endif
281 
282  // The "const char *" in "class_contexts" and backlog::value_type::second
283  // must come from a ConstString::GetCString()
284  std::set<const char *> class_contexts;
285  std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog;
286  backlog.reserve(num_symbols / 2);
287 
288  // Instantiation of the demangler is expensive, so better use a single one
289  // for all entries during batch processing.
291  NameToIndexMap::Entry entry;
292 
293  for (entry.value = 0; entry.value < num_symbols; ++entry.value) {
294  Symbol *symbol = &m_symbols[entry.value];
295 
296  // Don't let trampolines get into the lookup by name map If we ever need
297  // the trampoline symbols to be searchable by name we can remove this and
298  // then possibly add a new bool to any of the Symtab functions that
299  // lookup symbols by name to indicate if they want trampolines.
300  if (symbol->IsTrampoline())
301  continue;
302 
303  // If the symbol's name string matched a Mangled::ManglingScheme, it is
304  // stored in the mangled field.
305  Mangled &mangled = symbol->GetMangled();
306  entry.cstring = mangled.GetMangledName();
307  if (entry.cstring) {
308  m_name_to_index.Append(entry);
309 
310  if (symbol->ContainsLinkerAnnotations()) {
311  // If the symbol has linker annotations, also add the version without
312  // the annotations.
314  entry.cstring.GetStringRef()));
315  m_name_to_index.Append(entry);
316  }
317 
318  const SymbolType type = symbol->GetType();
319  if (type == eSymbolTypeCode || type == eSymbolTypeResolver) {
320  if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name))
321  RegisterMangledNameEntry(entry, class_contexts, backlog, rmc);
322  }
323  }
324 
325  // Symbol name strings that didn't match a Mangled::ManglingScheme, are
326  // stored in the demangled field.
327  entry.cstring = mangled.GetDemangledName(symbol->GetLanguage());
328  if (entry.cstring) {
329  m_name_to_index.Append(entry);
330 
331  if (symbol->ContainsLinkerAnnotations()) {
332  // If the symbol has linker annotations, also add the version without
333  // the annotations.
335  entry.cstring.GetStringRef()));
336  m_name_to_index.Append(entry);
337  }
338  }
339 
340  // If the demangled name turns out to be an ObjC name, and is a category
341  // name, add the version without categories to the index too.
342  ObjCLanguage::MethodName objc_method(entry.cstring.GetStringRef(), true);
343  if (objc_method.IsValid(true)) {
344  entry.cstring = objc_method.GetSelector();
346 
347  ConstString objc_method_no_category(
348  objc_method.GetFullNameWithoutCategory(true));
349  if (objc_method_no_category) {
350  entry.cstring = objc_method_no_category;
351  m_name_to_index.Append(entry);
352  }
353  }
354  }
355 
356  for (const auto &record : backlog) {
357  RegisterBacklogEntry(record.first, record.second, class_contexts);
358  }
359 
368  }
369 }
370 
371 void Symtab::RegisterMangledNameEntry(
372  NameToIndexMap::Entry &entry, std::set<const char *> &class_contexts,
373  std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
374  RichManglingContext &rmc) {
375  // Only register functions that have a base name.
376  rmc.ParseFunctionBaseName();
377  llvm::StringRef base_name = rmc.GetBufferRef();
378  if (base_name.empty())
379  return;
380 
381  // The base name will be our entry's name.
382  entry.cstring = ConstString(base_name);
383 
385  llvm::StringRef decl_context = rmc.GetBufferRef();
386 
387  // Register functions with no context.
388  if (decl_context.empty()) {
389  // This has to be a basename
391  // If there is no context (no namespaces or class scopes that come before
392  // the function name) then this also could be a fullname.
393  m_name_to_index.Append(entry);
394  return;
395  }
396 
397  // Make sure we have a pool-string pointer and see if we already know the
398  // context name.
399  const char *decl_context_ccstr = ConstString(decl_context).GetCString();
400  auto it = class_contexts.find(decl_context_ccstr);
401 
402  // Register constructors and destructors. They are methods and create
403  // declaration contexts.
404  if (rmc.IsCtorOrDtor()) {
405  m_method_to_index.Append(entry);
406  if (it == class_contexts.end())
407  class_contexts.insert(it, decl_context_ccstr);
408  return;
409  }
410 
411  // Register regular methods with a known declaration context.
412  if (it != class_contexts.end()) {
413  m_method_to_index.Append(entry);
414  return;
415  }
416 
417  // Regular methods in unknown declaration contexts are put to the backlog. We
418  // will revisit them once we processed all remaining symbols.
419  backlog.push_back(std::make_pair(entry, decl_context_ccstr));
420 }
421 
422 void Symtab::RegisterBacklogEntry(
423  const NameToIndexMap::Entry &entry, const char *decl_context,
424  const std::set<const char *> &class_contexts) {
425  auto it = class_contexts.find(decl_context);
426  if (it != class_contexts.end()) {
427  m_method_to_index.Append(entry);
428  } else {
429  // If we got here, we have something that had a context (was inside
430  // a namespace or class) yet we don't know the entry
431  m_method_to_index.Append(entry);
433  }
434 }
435 
437  std::lock_guard<std::recursive_mutex> guard(m_mutex);
438  InitNameIndexes();
439 }
440 
442  bool add_demangled, bool add_mangled,
443  NameToIndexMap &name_to_index_map) const {
444  if (add_demangled || add_mangled) {
445  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
446  Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
447  std::lock_guard<std::recursive_mutex> guard(m_mutex);
448 
449  // Create the name index vector to be able to quickly search by name
450  NameToIndexMap::Entry entry;
451  const size_t num_indexes = indexes.size();
452  for (size_t i = 0; i < num_indexes; ++i) {
453  entry.value = indexes[i];
454  assert(i < m_symbols.size());
455  const Symbol *symbol = &m_symbols[entry.value];
456 
457  const Mangled &mangled = symbol->GetMangled();
458  if (add_demangled) {
459  entry.cstring = mangled.GetDemangledName(symbol->GetLanguage());
460  if (entry.cstring)
461  name_to_index_map.Append(entry);
462  }
463 
464  if (add_mangled) {
465  entry.cstring = mangled.GetMangledName();
466  if (entry.cstring)
467  name_to_index_map.Append(entry);
468  }
469  }
470  }
471 }
472 
474  std::vector<uint32_t> &indexes,
475  uint32_t start_idx,
476  uint32_t end_index) const {
477  std::lock_guard<std::recursive_mutex> guard(m_mutex);
478 
479  uint32_t prev_size = indexes.size();
480 
481  const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
482 
483  for (uint32_t i = start_idx; i < count; ++i) {
484  if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
485  indexes.push_back(i);
486  }
487 
488  return indexes.size() - prev_size;
489 }
490 
492  SymbolType symbol_type, uint32_t flags_value,
493  std::vector<uint32_t> &indexes, uint32_t start_idx,
494  uint32_t end_index) const {
495  std::lock_guard<std::recursive_mutex> guard(m_mutex);
496 
497  uint32_t prev_size = indexes.size();
498 
499  const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
500 
501  for (uint32_t i = start_idx; i < count; ++i) {
502  if ((symbol_type == eSymbolTypeAny ||
503  m_symbols[i].GetType() == symbol_type) &&
504  m_symbols[i].GetFlags() == flags_value)
505  indexes.push_back(i);
506  }
507 
508  return indexes.size() - prev_size;
509 }
510 
512  Debug symbol_debug_type,
513  Visibility symbol_visibility,
514  std::vector<uint32_t> &indexes,
515  uint32_t start_idx,
516  uint32_t end_index) const {
517  std::lock_guard<std::recursive_mutex> guard(m_mutex);
518 
519  uint32_t prev_size = indexes.size();
520 
521  const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index);
522 
523  for (uint32_t i = start_idx; i < count; ++i) {
524  if (symbol_type == eSymbolTypeAny ||
525  m_symbols[i].GetType() == symbol_type) {
526  if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
527  indexes.push_back(i);
528  }
529  }
530 
531  return indexes.size() - prev_size;
532 }
533 
535  if (!m_symbols.empty()) {
536  const Symbol *first_symbol = &m_symbols[0];
537  if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
538  return symbol - first_symbol;
539  }
540  return UINT32_MAX;
541 }
542 
544  const bool sort_by_load_addr;
545  const Symbol *symbols;
546 };
547 
548 namespace {
549 struct SymbolIndexComparator {
550  const std::vector<Symbol> &symbols;
551  std::vector<lldb::addr_t> &addr_cache;
552 
553  // Getting from the symbol to the Address to the File Address involves some
554  // work. Since there are potentially many symbols here, and we're using this
555  // for sorting so we're going to be computing the address many times, cache
556  // that in addr_cache. The array passed in has to be the same size as the
557  // symbols array passed into the member variable symbols, and should be
558  // initialized with LLDB_INVALID_ADDRESS.
559  // NOTE: You have to make addr_cache externally and pass it in because
560  // std::stable_sort
561  // makes copies of the comparator it is initially passed in, and you end up
562  // spending huge amounts of time copying this array...
563 
564  SymbolIndexComparator(const std::vector<Symbol> &s,
565  std::vector<lldb::addr_t> &a)
566  : symbols(s), addr_cache(a) {
567  assert(symbols.size() == addr_cache.size());
568  }
569  bool operator()(uint32_t index_a, uint32_t index_b) {
570  addr_t value_a = addr_cache[index_a];
571  if (value_a == LLDB_INVALID_ADDRESS) {
572  value_a = symbols[index_a].GetAddressRef().GetFileAddress();
573  addr_cache[index_a] = value_a;
574  }
575 
576  addr_t value_b = addr_cache[index_b];
577  if (value_b == LLDB_INVALID_ADDRESS) {
578  value_b = symbols[index_b].GetAddressRef().GetFileAddress();
579  addr_cache[index_b] = value_b;
580  }
581 
582  if (value_a == value_b) {
583  // The if the values are equal, use the original symbol user ID
584  lldb::user_id_t uid_a = symbols[index_a].GetID();
585  lldb::user_id_t uid_b = symbols[index_b].GetID();
586  if (uid_a < uid_b)
587  return true;
588  if (uid_a > uid_b)
589  return false;
590  return false;
591  } else if (value_a < value_b)
592  return true;
593 
594  return false;
595  }
596 };
597 }
598 
599 void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
600  bool remove_duplicates) const {
601  std::lock_guard<std::recursive_mutex> guard(m_mutex);
602 
603  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
604  Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
605  // No need to sort if we have zero or one items...
606  if (indexes.size() <= 1)
607  return;
608 
609  // Sort the indexes in place using std::stable_sort.
610  // NOTE: The use of std::stable_sort instead of llvm::sort here is strictly
611  // for performance, not correctness. The indexes vector tends to be "close"
612  // to sorted, which the stable sort handles better.
613 
614  std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
615 
616  SymbolIndexComparator comparator(m_symbols, addr_cache);
617  std::stable_sort(indexes.begin(), indexes.end(), comparator);
618 
619  // Remove any duplicates if requested
620  if (remove_duplicates) {
621  auto last = std::unique(indexes.begin(), indexes.end());
622  indexes.erase(last, indexes.end());
623  }
624 }
625 
627  std::vector<uint32_t> &indexes) {
628  std::lock_guard<std::recursive_mutex> guard(m_mutex);
629 
630  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
631  Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
632  if (symbol_name) {
634  InitNameIndexes();
635 
636  return m_name_to_index.GetValues(symbol_name, indexes);
637  }
638  return 0;
639 }
640 
642  Debug symbol_debug_type,
643  Visibility symbol_visibility,
644  std::vector<uint32_t> &indexes) {
645  std::lock_guard<std::recursive_mutex> guard(m_mutex);
646 
647  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
648  Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
649  if (symbol_name) {
650  const size_t old_size = indexes.size();
652  InitNameIndexes();
653 
654  std::vector<uint32_t> all_name_indexes;
655  const size_t name_match_count =
656  m_name_to_index.GetValues(symbol_name, all_name_indexes);
657  for (size_t i = 0; i < name_match_count; ++i) {
658  if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type,
659  symbol_visibility))
660  indexes.push_back(all_name_indexes[i]);
661  }
662  return indexes.size() - old_size;
663  }
664  return 0;
665 }
666 
667 uint32_t
669  SymbolType symbol_type,
670  std::vector<uint32_t> &indexes) {
671  std::lock_guard<std::recursive_mutex> guard(m_mutex);
672 
673  if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) {
674  std::vector<uint32_t>::iterator pos = indexes.begin();
675  while (pos != indexes.end()) {
676  if (symbol_type == eSymbolTypeAny ||
677  m_symbols[*pos].GetType() == symbol_type)
678  ++pos;
679  else
680  pos = indexes.erase(pos);
681  }
682  }
683  return indexes.size();
684 }
685 
687  ConstString symbol_name, SymbolType symbol_type,
688  Debug symbol_debug_type, Visibility symbol_visibility,
689  std::vector<uint32_t> &indexes) {
690  std::lock_guard<std::recursive_mutex> guard(m_mutex);
691 
692  if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type,
693  symbol_visibility, indexes) > 0) {
694  std::vector<uint32_t>::iterator pos = indexes.begin();
695  while (pos != indexes.end()) {
696  if (symbol_type == eSymbolTypeAny ||
697  m_symbols[*pos].GetType() == symbol_type)
698  ++pos;
699  else
700  pos = indexes.erase(pos);
701  }
702  }
703  return indexes.size();
704 }
705 
707  const RegularExpression &regexp, SymbolType symbol_type,
708  std::vector<uint32_t> &indexes) {
709  std::lock_guard<std::recursive_mutex> guard(m_mutex);
710 
711  uint32_t prev_size = indexes.size();
712  uint32_t sym_end = m_symbols.size();
713 
714  for (uint32_t i = 0; i < sym_end; i++) {
715  if (symbol_type == eSymbolTypeAny ||
716  m_symbols[i].GetType() == symbol_type) {
717  const char *name = m_symbols[i].GetName().AsCString();
718  if (name) {
719  if (regexp.Execute(name))
720  indexes.push_back(i);
721  }
722  }
723  }
724  return indexes.size() - prev_size;
725 }
726 
728  const RegularExpression &regexp, SymbolType symbol_type,
729  Debug symbol_debug_type, Visibility symbol_visibility,
730  std::vector<uint32_t> &indexes) {
731  std::lock_guard<std::recursive_mutex> guard(m_mutex);
732 
733  uint32_t prev_size = indexes.size();
734  uint32_t sym_end = m_symbols.size();
735 
736  for (uint32_t i = 0; i < sym_end; i++) {
737  if (symbol_type == eSymbolTypeAny ||
738  m_symbols[i].GetType() == symbol_type) {
739  if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
740  continue;
741 
742  const char *name = m_symbols[i].GetName().AsCString();
743  if (name) {
744  if (regexp.Execute(name))
745  indexes.push_back(i);
746  }
747  }
748  }
749  return indexes.size() - prev_size;
750 }
751 
753  Debug symbol_debug_type,
754  Visibility symbol_visibility,
755  uint32_t &start_idx) {
756  std::lock_guard<std::recursive_mutex> guard(m_mutex);
757 
758  const size_t count = m_symbols.size();
759  for (size_t idx = start_idx; idx < count; ++idx) {
760  if (symbol_type == eSymbolTypeAny ||
761  m_symbols[idx].GetType() == symbol_type) {
762  if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) {
763  start_idx = idx;
764  return &m_symbols[idx];
765  }
766  }
767  }
768  return nullptr;
769 }
770 
771 size_t
773  SymbolType symbol_type,
774  std::vector<uint32_t> &symbol_indexes) {
775  std::lock_guard<std::recursive_mutex> guard(m_mutex);
776 
777  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
778  Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
779  // Initialize all of the lookup by name indexes before converting NAME to a
780  // uniqued string NAME_STR below.
782  InitNameIndexes();
783 
784  if (name) {
785  // The string table did have a string that matched, but we need to check
786  // the symbols and match the symbol_type if any was given.
787  AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes);
788  }
789  return symbol_indexes.size();
790 }
791 
793  ConstString name, SymbolType symbol_type, Debug symbol_debug_type,
794  Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) {
795  std::lock_guard<std::recursive_mutex> guard(m_mutex);
796 
797  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
798  Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
799  // Initialize all of the lookup by name indexes before converting NAME to a
800  // uniqued string NAME_STR below.
802  InitNameIndexes();
803 
804  if (name) {
805  // The string table did have a string that matched, but we need to check
806  // the symbols and match the symbol_type if any was given.
807  AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type,
808  symbol_visibility, symbol_indexes);
809  }
810  return symbol_indexes.size();
811 }
812 
814  const RegularExpression &regex, SymbolType symbol_type,
815  Debug symbol_debug_type, Visibility symbol_visibility,
816  std::vector<uint32_t> &symbol_indexes) {
817  std::lock_guard<std::recursive_mutex> guard(m_mutex);
818 
819  AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type,
820  symbol_visibility, symbol_indexes);
821  return symbol_indexes.size();
822 }
823 
825  SymbolType symbol_type,
826  Debug symbol_debug_type,
827  Visibility symbol_visibility) {
828  std::lock_guard<std::recursive_mutex> guard(m_mutex);
829 
830  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
831  Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
833  InitNameIndexes();
834 
835  if (name) {
836  std::vector<uint32_t> matching_indexes;
837  // The string table did have a string that matched, but we need to check
838  // the symbols and match the symbol_type if any was given.
839  if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type,
840  symbol_visibility,
841  matching_indexes)) {
842  std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
843  for (pos = matching_indexes.begin(); pos != end; ++pos) {
844  Symbol *symbol = SymbolAtIndex(*pos);
845 
846  if (symbol->Compare(name, symbol_type))
847  return symbol;
848  }
849  }
850  }
851  return nullptr;
852 }
853 
854 typedef struct {
855  const Symtab *symtab;
861 
862 // Add all the section file start address & size to the RangeVector, recusively
863 // adding any children sections.
864 static void AddSectionsToRangeMap(SectionList *sectlist,
865  RangeVector<addr_t, addr_t> &section_ranges) {
866  const int num_sections = sectlist->GetNumSections(0);
867  for (int i = 0; i < num_sections; i++) {
868  SectionSP sect_sp = sectlist->GetSectionAtIndex(i);
869  if (sect_sp) {
870  SectionList &child_sectlist = sect_sp->GetChildren();
871 
872  // If this section has children, add the children to the RangeVector.
873  // Else add this section to the RangeVector.
874  if (child_sectlist.GetNumSections(0) > 0) {
875  AddSectionsToRangeMap(&child_sectlist, section_ranges);
876  } else {
877  size_t size = sect_sp->GetByteSize();
878  if (size > 0) {
879  addr_t base_addr = sect_sp->GetFileAddress();
881  entry.SetRangeBase(base_addr);
882  entry.SetByteSize(size);
883  section_ranges.Append(entry);
884  }
885  }
886  }
887  }
888 }
889 
891  // Protected function, no need to lock mutex...
892  if (!m_file_addr_to_index_computed && !m_symbols.empty()) {
894 
896  const_iterator begin = m_symbols.begin();
897  const_iterator end = m_symbols.end();
898  for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) {
899  if (pos->ValueIsAddress()) {
900  entry.SetRangeBase(pos->GetAddressRef().GetFileAddress());
901  entry.SetByteSize(pos->GetByteSize());
902  entry.data = std::distance(begin, pos);
904  }
905  }
906  const size_t num_entries = m_file_addr_to_index.GetSize();
907  if (num_entries > 0) {
909 
910  // Create a RangeVector with the start & size of all the sections for
911  // this objfile. We'll need to check this for any FileRangeToIndexMap
912  // entries with an uninitialized size, which could potentially be a large
913  // number so reconstituting the weak pointer is busywork when it is
914  // invariant information.
915  SectionList *sectlist = m_objfile->GetSectionList();
916  RangeVector<addr_t, addr_t> section_ranges;
917  if (sectlist) {
918  AddSectionsToRangeMap(sectlist, section_ranges);
919  section_ranges.Sort();
920  }
921 
922  // Iterate through the FileRangeToIndexMap and fill in the size for any
923  // entries that didn't already have a size from the Symbol (e.g. if we
924  // have a plain linker symbol with an address only, instead of debug info
925  // where we get an address and a size and a type, etc.)
926  for (size_t i = 0; i < num_entries; i++) {
929  if (entry->GetByteSize() == 0) {
930  addr_t curr_base_addr = entry->GetRangeBase();
931  const RangeVector<addr_t, addr_t>::Entry *containing_section =
932  section_ranges.FindEntryThatContains(curr_base_addr);
933 
934  // Use the end of the section as the default max size of the symbol
935  addr_t sym_size = 0;
936  if (containing_section) {
937  sym_size =
938  containing_section->GetByteSize() -
939  (entry->GetRangeBase() - containing_section->GetRangeBase());
940  }
941 
942  for (size_t j = i; j < num_entries; j++) {
943  FileRangeToIndexMap::Entry *next_entry =
945  addr_t next_base_addr = next_entry->GetRangeBase();
946  if (next_base_addr > curr_base_addr) {
947  addr_t size_to_next_symbol = next_base_addr - curr_base_addr;
948 
949  // Take the difference between this symbol and the next one as
950  // its size, if it is less than the size of the section.
951  if (sym_size == 0 || size_to_next_symbol < sym_size) {
952  sym_size = size_to_next_symbol;
953  }
954  break;
955  }
956  }
957 
958  if (sym_size > 0) {
959  entry->SetByteSize(sym_size);
960  Symbol &symbol = m_symbols[entry->data];
961  symbol.SetByteSize(sym_size);
962  symbol.SetSizeIsSynthesized(true);
963  }
964  }
965  }
966 
967  // Sort again in case the range size changes the ordering
969  }
970  }
971 }
972 
974  std::lock_guard<std::recursive_mutex> guard(m_mutex);
975  // Size computation happens inside InitAddressIndexes.
977 }
978 
980  std::lock_guard<std::recursive_mutex> guard(m_mutex);
983 
984  const FileRangeToIndexMap::Entry *entry =
986  if (entry) {
987  Symbol *symbol = SymbolAtIndex(entry->data);
988  if (symbol->GetFileAddress() == file_addr)
989  return symbol;
990  }
991  return nullptr;
992 }
993 
995  std::lock_guard<std::recursive_mutex> guard(m_mutex);
996 
999 
1000  const FileRangeToIndexMap::Entry *entry =
1002  if (entry) {
1003  Symbol *symbol = SymbolAtIndex(entry->data);
1004  if (symbol->ContainsFileAddress(file_addr))
1005  return symbol;
1006  }
1007  return nullptr;
1008 }
1009 
1011  addr_t file_addr, std::function<bool(Symbol *)> const &callback) {
1012  std::lock_guard<std::recursive_mutex> guard(m_mutex);
1013 
1016 
1017  std::vector<uint32_t> all_addr_indexes;
1018 
1019  // Get all symbols with file_addr
1020  const size_t addr_match_count =
1022  all_addr_indexes);
1023 
1024  for (size_t i = 0; i < addr_match_count; ++i) {
1025  Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]);
1026  if (symbol->ContainsFileAddress(file_addr)) {
1027  if (!callback(symbol))
1028  break;
1029  }
1030  }
1031 }
1032 
1033 void Symtab::SymbolIndicesToSymbolContextList(
1034  std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) {
1035  // No need to protect this call using m_mutex all other method calls are
1036  // already thread safe.
1037 
1038  const bool merge_symbol_into_function = true;
1039  size_t num_indices = symbol_indexes.size();
1040  if (num_indices > 0) {
1041  SymbolContext sc;
1042  sc.module_sp = m_objfile->GetModule();
1043  for (size_t i = 0; i < num_indices; i++) {
1044  sc.symbol = SymbolAtIndex(symbol_indexes[i]);
1045  if (sc.symbol)
1046  sc_list.AppendIfUnique(sc, merge_symbol_into_function);
1047  }
1048  }
1049 }
1050 
1052  uint32_t name_type_mask,
1053  SymbolContextList &sc_list) {
1054  size_t count = 0;
1055  std::vector<uint32_t> symbol_indexes;
1056 
1057  // eFunctionNameTypeAuto should be pre-resolved by a call to
1058  // Module::LookupInfo::LookupInfo()
1059  assert((name_type_mask & eFunctionNameTypeAuto) == 0);
1060 
1061  if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) {
1062  std::vector<uint32_t> temp_symbol_indexes;
1063  FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes);
1064 
1065  unsigned temp_symbol_indexes_size = temp_symbol_indexes.size();
1066  if (temp_symbol_indexes_size > 0) {
1067  std::lock_guard<std::recursive_mutex> guard(m_mutex);
1068  for (unsigned i = 0; i < temp_symbol_indexes_size; i++) {
1069  SymbolContext sym_ctx;
1070  sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]);
1071  if (sym_ctx.symbol) {
1072  switch (sym_ctx.symbol->GetType()) {
1073  case eSymbolTypeCode:
1074  case eSymbolTypeResolver:
1075  case eSymbolTypeReExported:
1076  symbol_indexes.push_back(temp_symbol_indexes[i]);
1077  break;
1078  default:
1079  break;
1080  }
1081  }
1082  }
1083  }
1084  }
1085 
1086  if (name_type_mask & eFunctionNameTypeBase) {
1087  // From mangled names we can't tell what is a basename and what is a method
1088  // name, so we just treat them the same
1090  InitNameIndexes();
1091 
1092  if (!m_basename_to_index.IsEmpty()) {
1093  const UniqueCStringMap<uint32_t>::Entry *match;
1094  for (match = m_basename_to_index.FindFirstValueForName(name);
1095  match != nullptr;
1096  match = m_basename_to_index.FindNextValueForName(match)) {
1097  symbol_indexes.push_back(match->value);
1098  }
1099  }
1100  }
1101 
1102  if (name_type_mask & eFunctionNameTypeMethod) {
1104  InitNameIndexes();
1105 
1106  if (!m_method_to_index.IsEmpty()) {
1107  const UniqueCStringMap<uint32_t>::Entry *match;
1108  for (match = m_method_to_index.FindFirstValueForName(name);
1109  match != nullptr;
1110  match = m_method_to_index.FindNextValueForName(match)) {
1111  symbol_indexes.push_back(match->value);
1112  }
1113  }
1114  }
1115 
1116  if (name_type_mask & eFunctionNameTypeSelector) {
1118  InitNameIndexes();
1119 
1120  if (!m_selector_to_index.IsEmpty()) {
1121  const UniqueCStringMap<uint32_t>::Entry *match;
1122  for (match = m_selector_to_index.FindFirstValueForName(name);
1123  match != nullptr;
1124  match = m_selector_to_index.FindNextValueForName(match)) {
1125  symbol_indexes.push_back(match->value);
1126  }
1127  }
1128  }
1129 
1130  if (!symbol_indexes.empty()) {
1131  llvm::sort(symbol_indexes.begin(), symbol_indexes.end());
1132  symbol_indexes.erase(
1133  std::unique(symbol_indexes.begin(), symbol_indexes.end()),
1134  symbol_indexes.end());
1135  count = symbol_indexes.size();
1136  SymbolIndicesToSymbolContextList(symbol_indexes, sc_list);
1137  }
1138 
1139  return count;
1140 }
1141 
1142 const Symbol *Symtab::GetParent(Symbol *child_symbol) const {
1143  uint32_t child_idx = GetIndexForSymbol(child_symbol);
1144  if (child_idx != UINT32_MAX && child_idx > 0) {
1145  for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) {
1146  const Symbol *symbol = SymbolAtIndex(idx);
1147  const uint32_t sibling_idx = symbol->GetSiblingIndex();
1148  if (sibling_idx != UINT32_MAX && sibling_idx > child_idx)
1149  return symbol;
1150  }
1151  }
1152  return NULL;
1153 }
Entry & GetEntryRef(size_t i)
Definition: RangeMap.h:708
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
Uniform wrapper for access to rich mangling information from different providers. ...
UniqueCStringMap< uint32_t > m_method_to_index
Definition: Symtab.h:156
UniqueCStringMap< uint32_t > m_name_to_index
Definition: Symtab.h:154
Defines a list of symbol context objects.
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
lldb::LanguageType GetLanguage() const
Definition: Symbol.h:112
Symbol * match_symbol
Definition: Symtab.cpp:857
bool AppendIfUnique(const SymbolContext &sc, bool merge_symbol_into_function)
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
void CalculateSymbolSizes()
Definition: Symtab.cpp:973
void SetByteSize(lldb::addr_t size)
Definition: Symbol.h:173
lldb::addr_t GetFileAddress() const
Definition: Symbol.cpp:480
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
virtual FileSpec & GetFileSpec()
Get accessor to the object file specification.
Definition: ObjectFile.h:269
uint32_t AppendSymbolIndexesWithNameAndType(ConstString symbol_name, lldb::SymbolType symbol_type, std::vector< uint32_t > &matches)
Definition: Symtab.cpp:668
bool IsTrampoline() const
Definition: Symbol.cpp:170
std::recursive_mutex m_mutex
Definition: Symtab.h:159
static int CompareSymbolID(const void *key, const void *p)
Definition: Symtab.cpp:184
const Symbol * GetParent(Symbol *symbol) const
Get the parent symbol for the given symbol.
Definition: Symtab.cpp:1142
const Entry * FindFirstValueForName(ConstString unique_cstr) const
A file utility class.
Definition: FileSpec.h:55
const uint32_t * match_index_ptr
Definition: Symtab.cpp:858
"lldb/Utility/RegularExpression.h" A C++ wrapper class for regex.
bool Compare(ConstString name, lldb::SymbolType type) const
Definition: Symbol.cpp:328
Symbol * FindSymbolWithType(lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t &start_idx)
Definition: Symtab.cpp:752
static bool lldb_skip_name(llvm::StringRef mangled, Mangled::ManglingScheme scheme)
Definition: Symtab.cpp:220
llvm::StringRef GetBufferRef() const
Obtain a StringRef to the internal buffer that holds the result of the most recent ParseXy() operatio...
A timer class that simplifies common timing metrics.
Definition: Timer.h:23
size_t GetNumSymbols() const
Definition: Symtab.cpp:63
A plug-in interface definition class for object file parsers.
Definition: ObjectFile.h:58
void AppendSymbolNamesToMap(const IndexCollection &indexes, bool add_demangled, bool add_mangled, NameToIndexMap &name_to_index_map) const
Definition: Symtab.cpp:441
void ParseFunctionBaseName()
Get the base name of a function.
uint32_t GetSiblingIndex() const
Definition: Symbol.cpp:166
addr_t match_offset
Definition: Symtab.cpp:859
void ParseFunctionDeclContextName()
Get the context name for a function.
void InitNameIndexes()
Definition: Symtab.cpp:254
const Symbol * symbols
Definition: Symtab.cpp:545
Symbol * symbol
The Symbol for a given query.
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
Definition: ModuleChild.cpp:27
Symbol * FindSymbolAtFileAddress(lldb::addr_t file_addr)
Definition: Symtab.cpp:979
const Entry * FindEntryThatContains(B addr) const
Definition: RangeMap.h:518
UniqueCStringMap< uint32_t > m_basename_to_index
Definition: Symtab.h:155
lldb::SymbolType GetType() const
Definition: Symbol.h:136
void SectionFileAddressesChanged()
Definition: Symtab.cpp:68
void SortSymbolIndexesByValue(std::vector< uint32_t > &indexes, bool remove_duplicates) const
Definition: Symtab.cpp:599
#define UINT32_MAX
Definition: lldb-defines.h:31
size_t FindAllSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, std::vector< uint32_t > &symbol_indexes)
Definition: Symtab.cpp:772
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
uint64_t user_id_t
Definition: lldb-types.h:84
static void AddSectionsToRangeMap(SectionList *sectlist, RangeVector< addr_t, addr_t > &section_ranges)
Definition: Symtab.cpp:864
Entry * FindEntryThatContains(B addr)
Definition: RangeMap.h:737
uint32_t AppendSymbolIndexesWithTypeAndFlagsValue(lldb::SymbolType symbol_type, uint32_t flags_value, std::vector< uint32_t > &indexes, uint32_t start_idx=0, uint32_t end_index=UINT32_MAX) const
Definition: Symtab.cpp:491
uint32_t AppendSymbolIndexesWithName(ConstString symbol_name, std::vector< uint32_t > &matches)
Definition: Symtab.cpp:626
uint32_t AddSymbol(const Symbol &symbol)
Definition: Symtab.cpp:51
size_t GetValues(ConstString unique_cstr, std::vector< T > &values) const
FileRangeToIndexMap m_file_addr_to_index
Definition: Symtab.h:153
uint32_t FindEntryIndexesThatContain(B addr, std::vector< uint32_t > &indexes) const
Definition: RangeMap.h:722
collection m_symbols
Definition: Symtab.h:152
const Symtab * symtab
Definition: Symtab.cpp:855
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
Definition: ObjectFile.cpp:605
void Append(ConstString unique_cstr, const T &value)
void SetSizeIsSynthesized(bool b)
Definition: Symbol.h:155
static void DumpSymbolHeader(Stream *s)
Definition: Symtab.cpp:172
void InitAddressIndexes()
Definition: Symtab.cpp:890
lldb::SectionSP GetSectionAtIndex(size_t idx) const
Definition: Section.cpp:497
void IndentLess(int amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:221
std::vector< uint32_t > IndexCollection
Definition: Symtab.h:23
bool m_name_indexes_computed
Definition: Symtab.h:160
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
Symbol * FindSymbolContainingFileAddress(lldb::addr_t file_addr)
Definition: Symtab.cpp:994
ObjectFile * m_objfile
Definition: Symtab.h:151
uint32_t AppendSymbolIndexesWithType(lldb::SymbolType symbol_type, std::vector< uint32_t > &indexes, uint32_t start_idx=0, uint32_t end_index=UINT32_MAX) const
Definition: Symtab.cpp:473
void Dump(Stream *s, Target *target, SortOrder sort_type)
Definition: Symtab.cpp:73
collection::const_iterator const_iterator
Definition: Symtab.h:145
const Entry * FindEntryStartsAt(B addr) const
Definition: RangeMap.h:766
Symbol * FindFirstSymbolWithNameAndType(ConstString name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
Definition: Symtab.cpp:824
Symbol * SymbolAtIndex(size_t idx)
Definition: Symtab.cpp:203
size_t FindAllSymbolsMatchingRexExAndType(const RegularExpression &regex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector< uint32_t > &symbol_indexes)
Definition: Symtab.cpp:813
void SetByteSize(SizeType s)
Definition: RangeMap.h:73
bool IsCtorOrDtor() const
If this symbol describes a constructor or destructor.
bool ContainsLinkerAnnotations() const
Definition: Symbol.h:192
uint64_t addr_t
Definition: lldb-types.h:83
virtual llvm::StringRef StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const
Definition: ObjectFile.h:644
uint32_t GetIndexForSymbol(const Symbol *symbol) const
Definition: Symtab.cpp:534
UniqueCStringMap< uint32_t > m_selector_to_index
Definition: Symtab.h:157
const addr_t file_addr
Definition: Symtab.cpp:856
size_t GetNumSections(uint32_t depth) const
Definition: Section.cpp:486
A uniqued constant string class.
Definition: ConstString.h:38
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
bool Execute(llvm::StringRef string, Match *match=nullptr) const
Executes a regular expression.
lldb::ModuleSP module_sp
The Module for a given query.
Definition: SBAddress.h:15
Entry * GetMutableEntryAtIndex(size_t i)
Definition: RangeMap.h:702
size_t Indent(const char *s=nullptr)
Indent the current line in the stream.
Definition: Stream.cpp:131
void SetRangeBase(BaseType b)
Definition: RangeMap.h:48
bool m_file_addr_to_index_computed
Definition: Symtab.h:160
Symbol * Resize(size_t count)
Definition: Symtab.cpp:44
void ForEachSymbolContainingFileAddress(lldb::addr_t file_addr, std::function< bool(Symbol *)> const &callback)
Definition: Symtab.cpp:1010
void Append(const Entry &entry)
Definition: RangeMap.h:343
void IndentMore(int amount=2)
Increment the current indentation level.
Definition: Stream.cpp:218
Symbol * FindSymbolByID(lldb::user_id_t uid) const
Definition: Symtab.cpp:194
SizeType GetByteSize() const
Definition: RangeMap.h:71
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
bool ContainsFileAddress(lldb::addr_t file_addr) const
Definition: Symbol.cpp:563
size_t FindFunctionSymbols(ConstString name, uint32_t name_type_mask, SymbolContextList &sc_list)
Definition: Symtab.cpp:1051
const bool sort_by_load_addr
Definition: Symtab.cpp:544
void Reserve(size_t count)
Definition: Symtab.cpp:38
const Entry * FindNextValueForName(const Entry *entry_ptr) const
uint32_t AppendSymbolIndexesMatchingRegExAndType(const RegularExpression &regex, lldb::SymbolType symbol_type, std::vector< uint32_t > &indexes)
Definition: Symtab.cpp:706
BaseType GetRangeBase() const
Definition: RangeMap.h:46
Mangled & GetMangled()
Definition: Symbol.h:120
void Append(const Entry &entry)
Definition: RangeMap.h:635