blob: b20504addec92e99cdaf27b9b78128c55dcaf5f9 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Symtab.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include <map>
Jim Inghamaa816b82015-09-02 01:59:14 +000011#include <set>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012
13#include "lldb/Core/Module.h"
14#include "lldb/Core/RegularExpression.h"
Greg Clayton9422dd62013-03-04 21:46:16 +000015#include "lldb/Core/Section.h"
Jim Inghamaa816b82015-09-02 01:59:14 +000016#include "lldb/Core/Stream.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Core/Timer.h"
18#include "lldb/Symbol/ObjectFile.h"
Greg Claytonbc63aac2015-02-25 22:41:34 +000019#include "lldb/Symbol/Symbol.h"
Greg Claytonc1b2ccf2013-01-08 00:01:36 +000020#include "lldb/Symbol/SymbolContext.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021#include "lldb/Symbol/Symtab.h"
Jim Inghamaa816b82015-09-02 01:59:14 +000022#include "Plugins/Language/ObjC/ObjCLanguage.h"
23#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024
25using namespace lldb;
26using namespace lldb_private;
27
28
29
30Symtab::Symtab(ObjectFile *objfile) :
Greg Clayton8087ca22010-10-08 04:20:14 +000031 m_objfile (objfile),
32 m_symbols (),
Greg Clayton3046e662013-07-10 01:23:25 +000033 m_file_addr_to_index (),
Greg Clayton8087ca22010-10-08 04:20:14 +000034 m_name_to_index (),
35 m_mutex (Mutex::eMutexTypeRecursive),
Greg Clayton3046e662013-07-10 01:23:25 +000036 m_file_addr_to_index_computed (false),
Greg Clayton8087ca22010-10-08 04:20:14 +000037 m_name_indexes_computed (false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038{
39}
40
41Symtab::~Symtab()
42{
43}
44
45void
Greg Claytonc7bece562013-01-25 18:06:21 +000046Symtab::Reserve(size_t count)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047{
Greg Clayton8087ca22010-10-08 04:20:14 +000048 // Clients should grab the mutex from this symbol table and lock it manually
49 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050 m_symbols.reserve (count);
51}
52
53Symbol *
Greg Claytonc7bece562013-01-25 18:06:21 +000054Symtab::Resize(size_t count)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055{
Greg Clayton8087ca22010-10-08 04:20:14 +000056 // Clients should grab the mutex from this symbol table and lock it manually
57 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058 m_symbols.resize (count);
59 return &m_symbols[0];
60}
61
62uint32_t
63Symtab::AddSymbol(const Symbol& symbol)
64{
Greg Clayton8087ca22010-10-08 04:20:14 +000065 // Clients should grab the mutex from this symbol table and lock it manually
66 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067 uint32_t symbol_idx = m_symbols.size();
68 m_name_to_index.Clear();
Greg Clayton3046e662013-07-10 01:23:25 +000069 m_file_addr_to_index.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000070 m_symbols.push_back(symbol);
Greg Clayton3046e662013-07-10 01:23:25 +000071 m_file_addr_to_index_computed = false;
Greg Clayton8087ca22010-10-08 04:20:14 +000072 m_name_indexes_computed = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073 return symbol_idx;
74}
75
76size_t
77Symtab::GetNumSymbols() const
78{
Greg Clayton8087ca22010-10-08 04:20:14 +000079 Mutex::Locker locker (m_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080 return m_symbols.size();
81}
82
83void
Jason Molenda05a09c62014-08-22 02:46:46 +000084Symtab::SectionFileAddressesChanged ()
85{
86 m_name_to_index.Clear();
87 m_file_addr_to_index_computed = false;
88}
89
90void
Greg Claytone0d378b2011-03-24 21:19:54 +000091Symtab::Dump (Stream *s, Target *target, SortOrder sort_order)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000092{
Greg Clayton8087ca22010-10-08 04:20:14 +000093 Mutex::Locker locker (m_mutex);
94
Greg Clayton89411422010-10-08 00:21:05 +000095// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096 s->Indent();
97 const FileSpec &file_spec = m_objfile->GetFileSpec();
Ed Masted4612ad2014-04-20 13:17:36 +000098 const char * object_name = nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099 if (m_objfile->GetModule())
100 object_name = m_objfile->GetModule()->GetObjectName().GetCString();
101
102 if (file_spec)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000103 s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64,
Greg Claytonb5ad4ec2013-04-29 17:25:54 +0000104 file_spec.GetPath().c_str(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000105 object_name ? "(" : "",
106 object_name ? object_name : "",
107 object_name ? ")" : "",
Greg Clayton6fea17e2014-03-03 19:15:20 +0000108 (uint64_t)m_symbols.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109 else
Greg Clayton6fea17e2014-03-03 19:15:20 +0000110 s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111
112 if (!m_symbols.empty())
113 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000114 switch (sort_order)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000116 case eSortOrderNone:
117 {
118 s->PutCString (":\n");
119 DumpSymbolHeader (s);
120 const_iterator begin = m_symbols.begin();
121 const_iterator end = m_symbols.end();
122 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
123 {
124 s->Indent();
125 pos->Dump(s, target, std::distance(begin, pos));
126 }
127 }
128 break;
129
130 case eSortOrderByName:
131 {
132 // Although we maintain a lookup by exact name map, the table
133 // isn't sorted by name. So we must make the ordered symbol list
134 // up ourselves.
135 s->PutCString (" (sorted by name):\n");
136 DumpSymbolHeader (s);
137 typedef std::multimap<const char*, const Symbol *, CStringCompareFunctionObject> CStringToSymbol;
138 CStringToSymbol name_map;
139 for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos)
140 {
Greg Claytonddaf6a72015-07-08 22:32:23 +0000141 const char *name = pos->GetName().AsCString();
Greg Clayton8087ca22010-10-08 04:20:14 +0000142 if (name && name[0])
143 name_map.insert (std::make_pair(name, &(*pos)));
144 }
145
146 for (CStringToSymbol::const_iterator pos = name_map.begin(), end = name_map.end(); pos != end; ++pos)
147 {
148 s->Indent();
149 pos->second->Dump (s, target, pos->second - &m_symbols[0]);
150 }
151 }
152 break;
153
154 case eSortOrderByAddress:
155 s->PutCString (" (sorted by address):\n");
156 DumpSymbolHeader (s);
Greg Clayton3046e662013-07-10 01:23:25 +0000157 if (!m_file_addr_to_index_computed)
Greg Clayton8087ca22010-10-08 04:20:14 +0000158 InitAddressIndexes();
Greg Clayton3046e662013-07-10 01:23:25 +0000159 const size_t num_entries = m_file_addr_to_index.GetSize();
160 for (size_t i=0; i<num_entries; ++i)
Greg Clayton8087ca22010-10-08 04:20:14 +0000161 {
Greg Clayton3046e662013-07-10 01:23:25 +0000162 s->Indent();
163 const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data;
164 m_symbols[symbol_idx].Dump(s, target, symbol_idx);
Greg Clayton8087ca22010-10-08 04:20:14 +0000165 }
166 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167 }
168 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169}
170
171void
Greg Claytonf5e56de2010-09-14 23:36:40 +0000172Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173{
Greg Clayton8087ca22010-10-08 04:20:14 +0000174 Mutex::Locker locker (m_mutex);
175
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000176 const size_t num_symbols = GetNumSymbols();
Greg Clayton8087ca22010-10-08 04:20:14 +0000177 //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178 s->Indent();
Greg Clayton6fea17e2014-03-03 19:15:20 +0000179 s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n", (uint64_t)indexes.size(), (uint64_t)m_symbols.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180 s->IndentMore();
181
182 if (!indexes.empty())
183 {
184 std::vector<uint32_t>::const_iterator pos;
185 std::vector<uint32_t>::const_iterator end = indexes.end();
186 DumpSymbolHeader (s);
187 for (pos = indexes.begin(); pos != end; ++pos)
188 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000189 size_t idx = *pos;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000190 if (idx < num_symbols)
191 {
192 s->Indent();
Greg Claytonf5e56de2010-09-14 23:36:40 +0000193 m_symbols[idx].Dump(s, target, idx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194 }
195 }
196 }
197 s->IndentLess ();
198}
199
200void
201Symtab::DumpSymbolHeader (Stream *s)
202{
203 s->Indent(" Debug symbol\n");
204 s->Indent(" |Synthetic symbol\n");
205 s->Indent(" ||Externally Visible\n");
206 s->Indent(" |||\n");
Greg Clayton2d9ce192015-02-25 17:22:05 +0000207 s->Indent("Index UserID DSX Type File Address/Value Load Address Size Flags Name\n");
208 s->Indent("------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000209}
210
Greg Clayton49bd1c82010-09-07 17:36:17 +0000211
212static int
213CompareSymbolID (const void *key, const void *p)
214{
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000215 const user_id_t match_uid = *(const user_id_t*) key;
216 const user_id_t symbol_uid = ((const Symbol *)p)->GetID();
Greg Clayton49bd1c82010-09-07 17:36:17 +0000217 if (match_uid < symbol_uid)
218 return -1;
219 if (match_uid > symbol_uid)
220 return 1;
221 return 0;
222}
223
224Symbol *
225Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const
226{
Greg Clayton8087ca22010-10-08 04:20:14 +0000227 Mutex::Locker locker (m_mutex);
228
Greg Clayton49bd1c82010-09-07 17:36:17 +0000229 Symbol *symbol = (Symbol*)::bsearch (&symbol_uid,
230 &m_symbols[0],
231 m_symbols.size(),
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000232 sizeof(m_symbols[0]),
Greg Clayton49bd1c82010-09-07 17:36:17 +0000233 CompareSymbolID);
234 return symbol;
235}
236
237
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000238Symbol *
Greg Claytonc7bece562013-01-25 18:06:21 +0000239Symtab::SymbolAtIndex(size_t idx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240{
Greg Clayton8087ca22010-10-08 04:20:14 +0000241 // Clients should grab the mutex from this symbol table and lock it manually
242 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243 if (idx < m_symbols.size())
244 return &m_symbols[idx];
Ed Masted4612ad2014-04-20 13:17:36 +0000245 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246}
247
248
249const Symbol *
Greg Claytonc7bece562013-01-25 18:06:21 +0000250Symtab::SymbolAtIndex(size_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251{
Greg Clayton8087ca22010-10-08 04:20:14 +0000252 // Clients should grab the mutex from this symbol table and lock it manually
253 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000254 if (idx < m_symbols.size())
255 return &m_symbols[idx];
Ed Masted4612ad2014-04-20 13:17:36 +0000256 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257}
258
259//----------------------------------------------------------------------
260// InitNameIndexes
261//----------------------------------------------------------------------
262void
263Symtab::InitNameIndexes()
264{
Greg Clayton8087ca22010-10-08 04:20:14 +0000265 // Protected function, no need to lock mutex...
266 if (!m_name_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000267 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000268 m_name_indexes_computed = true;
269 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
270 // Create the name index vector to be able to quickly search by name
Greg Clayton43fe2172013-04-03 02:00:15 +0000271 const size_t num_symbols = m_symbols.size();
Greg Clayton8087ca22010-10-08 04:20:14 +0000272#if 1
Greg Clayton43fe2172013-04-03 02:00:15 +0000273 m_name_to_index.Reserve (num_symbols);
Greg Clayton8087ca22010-10-08 04:20:14 +0000274#else
275 // TODO: benchmark this to see if we save any memory. Otherwise we
276 // will always keep the memory reserved in the vector unless we pull
277 // some STL swap magic and then recopy...
278 uint32_t actual_count = 0;
279 for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
280 pos != end;
281 ++pos)
282 {
283 const Mangled &mangled = pos->GetMangled();
284 if (mangled.GetMangledName())
285 ++actual_count;
286
287 if (mangled.GetDemangledName())
288 ++actual_count;
289 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000290
Greg Clayton8087ca22010-10-08 04:20:14 +0000291 m_name_to_index.Reserve (actual_count);
292#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293
Greg Clayton1075aca2011-12-03 20:02:42 +0000294 NameToIndexMap::Entry entry;
Greg Clayton8087ca22010-10-08 04:20:14 +0000295
Greg Clayton43fe2172013-04-03 02:00:15 +0000296 // The "const char *" in "class_contexts" must come from a ConstString::GetCString()
297 std::set<const char *> class_contexts;
298 UniqueCStringMap<uint32_t> mangled_name_to_index;
Ed Masted4612ad2014-04-20 13:17:36 +0000299 std::vector<const char *> symbol_contexts(num_symbols, nullptr);
Greg Clayton43fe2172013-04-03 02:00:15 +0000300
301 for (entry.value = 0; entry.value<num_symbols; ++entry.value)
Greg Clayton8087ca22010-10-08 04:20:14 +0000302 {
303 const Symbol *symbol = &m_symbols[entry.value];
304
305 // Don't let trampolines get into the lookup by name map
306 // If we ever need the trampoline symbols to be searchable by name
307 // we can remove this and then possibly add a new bool to any of the
308 // Symtab functions that lookup symbols by name to indicate if they
309 // want trampolines.
310 if (symbol->IsTrampoline())
311 continue;
312
313 const Mangled &mangled = symbol->GetMangled();
314 entry.cstring = mangled.GetMangledName().GetCString();
315 if (entry.cstring && entry.cstring[0])
Greg Clayton43fe2172013-04-03 02:00:15 +0000316 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000317 m_name_to_index.Append (entry);
Pavel Labathc6ae7ea2015-03-04 10:25:22 +0000318
319 if (symbol->ContainsLinkerAnnotations()) {
320 // If the symbol has linker annotations, also add the version without the
321 // annotations.
322 entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(entry.cstring)).GetCString();
323 m_name_to_index.Append (entry);
324 }
Greg Clayton43fe2172013-04-03 02:00:15 +0000325
326 const SymbolType symbol_type = symbol->GetType();
327 if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver)
328 {
329 if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' &&
330 (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name
331 entry.cstring[2] != 'G' && // avoid guard variables
332 entry.cstring[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
333 {
Jim Inghamaa816b82015-09-02 01:59:14 +0000334 CPlusPlusLanguage::MethodName cxx_method (mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
Greg Clayton6ecb2322013-05-18 00:11:21 +0000335 entry.cstring = ConstString(cxx_method.GetBasename()).GetCString();
Greg Clayton43fe2172013-04-03 02:00:15 +0000336 if (entry.cstring && entry.cstring[0])
337 {
338 // ConstString objects permanently store the string in the pool so calling
339 // GetCString() on the value gets us a const char * that will never go away
340 const char *const_context = ConstString(cxx_method.GetContext()).GetCString();
Greg Clayton8087ca22010-10-08 04:20:14 +0000341
Greg Clayton43fe2172013-04-03 02:00:15 +0000342 if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty())
343 {
344 // The first character of the demangled basename is '~' which
345 // means we have a class destructor. We can use this information
346 // to help us know what is a class and what isn't.
347 if (class_contexts.find(const_context) == class_contexts.end())
348 class_contexts.insert(const_context);
349 m_method_to_index.Append (entry);
350 }
351 else
352 {
353 if (const_context && const_context[0])
354 {
355 if (class_contexts.find(const_context) != class_contexts.end())
356 {
357 // The current decl context is in our "class_contexts" which means
358 // this is a method on a class
359 m_method_to_index.Append (entry);
360 }
361 else
362 {
363 // We don't know if this is a function basename or a method,
364 // so put it into a temporary collection so once we are done
365 // we can look in class_contexts to see if each entry is a class
366 // or just a function and will put any remaining items into
367 // m_method_to_index or m_basename_to_index as needed
368 mangled_name_to_index.Append (entry);
369 symbol_contexts[entry.value] = const_context;
370 }
371 }
372 else
373 {
374 // No context for this function so this has to be a basename
375 m_basename_to_index.Append(entry);
376 }
377 }
378 }
379 }
380 }
381 }
382
Greg Claytonddaf6a72015-07-08 22:32:23 +0000383 entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()).GetCString();
Pavel Labathc6ae7ea2015-03-04 10:25:22 +0000384 if (entry.cstring && entry.cstring[0]) {
Greg Clayton8087ca22010-10-08 04:20:14 +0000385 m_name_to_index.Append (entry);
Pavel Labathc6ae7ea2015-03-04 10:25:22 +0000386
387 if (symbol->ContainsLinkerAnnotations()) {
388 // If the symbol has linker annotations, also add the version without the
389 // annotations.
390 entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(entry.cstring)).GetCString();
391 m_name_to_index.Append (entry);
392 }
393 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000394
395 // If the demangled name turns out to be an ObjC name, and
396 // is a category name, add the version without categories to the index too.
Jim Inghamaa816b82015-09-02 01:59:14 +0000397 ObjCLanguage::MethodName objc_method (entry.cstring, true);
Greg Clayton1b3815c2013-01-30 00:18:29 +0000398 if (objc_method.IsValid(true))
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000399 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000400 entry.cstring = objc_method.GetSelector().GetCString();
Greg Claytonc1b2ccf2013-01-08 00:01:36 +0000401 m_selector_to_index.Append (entry);
Greg Clayton1b3815c2013-01-30 00:18:29 +0000402
403 ConstString objc_method_no_category (objc_method.GetFullNameWithoutCategory(true));
404 if (objc_method_no_category)
405 {
406 entry.cstring = objc_method_no_category.GetCString();
407 m_name_to_index.Append (entry);
408 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000409 }
410
Greg Clayton8087ca22010-10-08 04:20:14 +0000411 }
Greg Clayton43fe2172013-04-03 02:00:15 +0000412
413 size_t count;
414 if (!mangled_name_to_index.IsEmpty())
415 {
416 count = mangled_name_to_index.GetSize();
417 for (size_t i=0; i<count; ++i)
418 {
419 if (mangled_name_to_index.GetValueAtIndex(i, entry.value))
420 {
421 entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
422 if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end())
423 {
424 m_method_to_index.Append (entry);
425 }
426 else
427 {
428 // If we got here, we have something that had a context (was inside a namespace or class)
429 // yet we don't know if the entry
430 m_method_to_index.Append (entry);
431 m_basename_to_index.Append (entry);
432 }
433 }
434 }
435 }
Greg Clayton8087ca22010-10-08 04:20:14 +0000436 m_name_to_index.Sort();
Greg Claytond2c46a62011-12-28 22:24:04 +0000437 m_name_to_index.SizeToFit();
Greg Claytonc1b2ccf2013-01-08 00:01:36 +0000438 m_selector_to_index.Sort();
439 m_selector_to_index.SizeToFit();
Greg Clayton43fe2172013-04-03 02:00:15 +0000440 m_basename_to_index.Sort();
441 m_basename_to_index.SizeToFit();
442 m_method_to_index.Sort();
443 m_method_to_index.SizeToFit();
444
445// static StreamFile a ("/tmp/a.txt");
446//
447// count = m_basename_to_index.GetSize();
448// if (count)
449// {
450// for (size_t i=0; i<count; ++i)
451// {
452// if (m_basename_to_index.GetValueAtIndex(i, entry.value))
453// a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
454// }
455// }
456// count = m_method_to_index.GetSize();
457// if (count)
458// {
459// for (size_t i=0; i<count; ++i)
460// {
461// if (m_method_to_index.GetValueAtIndex(i, entry.value))
462// a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
463// }
464// }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000465 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000466}
467
Greg Clayton1075aca2011-12-03 20:02:42 +0000468void
Greg Clayton43fe2172013-04-03 02:00:15 +0000469Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
Greg Clayton1075aca2011-12-03 20:02:42 +0000470 bool add_demangled,
471 bool add_mangled,
472 NameToIndexMap &name_to_index_map) const
473{
474 if (add_demangled || add_mangled)
475 {
476 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
477 Mutex::Locker locker (m_mutex);
478
479 // Create the name index vector to be able to quickly search by name
480 NameToIndexMap::Entry entry;
481 const size_t num_indexes = indexes.size();
482 for (size_t i=0; i<num_indexes; ++i)
483 {
484 entry.value = indexes[i];
485 assert (i < m_symbols.size());
486 const Symbol *symbol = &m_symbols[entry.value];
487
488 const Mangled &mangled = symbol->GetMangled();
489 if (add_demangled)
490 {
Greg Claytonddaf6a72015-07-08 22:32:23 +0000491 entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()).GetCString();
Greg Clayton1075aca2011-12-03 20:02:42 +0000492 if (entry.cstring && entry.cstring[0])
493 name_to_index_map.Append (entry);
494 }
495
496 if (add_mangled)
497 {
498 entry.cstring = mangled.GetMangledName().GetCString();
499 if (entry.cstring && entry.cstring[0])
500 name_to_index_map.Append (entry);
501 }
502 }
503 }
504}
505
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000506uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000507Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000508{
Greg Clayton8087ca22010-10-08 04:20:14 +0000509 Mutex::Locker locker (m_mutex);
510
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000511 uint32_t prev_size = indexes.size();
512
513 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
514
515 for (uint32_t i = start_idx; i < count; ++i)
516 {
517 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
518 indexes.push_back(i);
519 }
520
521 return indexes.size() - prev_size;
522}
523
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000524uint32_t
Greg Clayton16b2d2b2011-01-20 06:08:59 +0000525Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
526{
527 Mutex::Locker locker (m_mutex);
528
529 uint32_t prev_size = indexes.size();
530
531 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
532
533 for (uint32_t i = start_idx; i < count; ++i)
534 {
535 if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value)
536 indexes.push_back(i);
537 }
538
539 return indexes.size() - prev_size;
540}
541
542uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000543Symtab::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
544{
Greg Clayton8087ca22010-10-08 04:20:14 +0000545 Mutex::Locker locker (m_mutex);
546
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000547 uint32_t prev_size = indexes.size();
548
549 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
550
551 for (uint32_t i = start_idx; i < count; ++i)
552 {
553 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
554 {
555 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
556 indexes.push_back(i);
557 }
558 }
559
560 return indexes.size() - prev_size;
561}
562
563
564uint32_t
565Symtab::GetIndexForSymbol (const Symbol *symbol) const
566{
Greg Claytonbc63aac2015-02-25 22:41:34 +0000567 if (!m_symbols.empty())
568 {
569 const Symbol *first_symbol = &m_symbols[0];
570 if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
571 return symbol - first_symbol;
572 }
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000573 return UINT32_MAX;
574}
575
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000576struct SymbolSortInfo
577{
578 const bool sort_by_load_addr;
579 const Symbol *symbols;
580};
581
Owen Andersonc7da5f42010-06-16 17:34:05 +0000582namespace {
583 struct SymbolIndexComparator {
584 const std::vector<Symbol>& symbols;
Jim Inghame2b6ad62012-05-01 01:34:15 +0000585 std::vector<lldb::addr_t> &addr_cache;
586
587 // Getting from the symbol to the Address to the File Address involves some work.
588 // Since there are potentially many symbols here, and we're using this for sorting so
589 // we're going to be computing the address many times, cache that in addr_cache.
590 // The array passed in has to be the same size as the symbols array passed into the
591 // member variable symbols, and should be initialized with LLDB_INVALID_ADDRESS.
592 // NOTE: You have to make addr_cache externally and pass it in because std::stable_sort
593 // makes copies of the comparator it is initially passed in, and you end up spending
594 // huge amounts of time copying this array...
595
596 SymbolIndexComparator(const std::vector<Symbol>& s, std::vector<lldb::addr_t> &a) : symbols(s), addr_cache(a) {
597 assert (symbols.size() == addr_cache.size());
598 }
Owen Andersonc7da5f42010-06-16 17:34:05 +0000599 bool operator()(uint32_t index_a, uint32_t index_b) {
Jim Inghame2b6ad62012-05-01 01:34:15 +0000600 addr_t value_a = addr_cache[index_a];
601 if (value_a == LLDB_INVALID_ADDRESS)
602 {
Greg Clayton358cf1e2015-06-25 21:46:34 +0000603 value_a = symbols[index_a].GetAddressRef().GetFileAddress();
Jim Inghame2b6ad62012-05-01 01:34:15 +0000604 addr_cache[index_a] = value_a;
605 }
606
607 addr_t value_b = addr_cache[index_b];
608 if (value_b == LLDB_INVALID_ADDRESS)
609 {
Greg Clayton358cf1e2015-06-25 21:46:34 +0000610 value_b = symbols[index_b].GetAddressRef().GetFileAddress();
Jim Inghame2b6ad62012-05-01 01:34:15 +0000611 addr_cache[index_b] = value_b;
612 }
613
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000614
Owen Andersonc7da5f42010-06-16 17:34:05 +0000615 if (value_a == value_b) {
616 // The if the values are equal, use the original symbol user ID
617 lldb::user_id_t uid_a = symbols[index_a].GetID();
618 lldb::user_id_t uid_b = symbols[index_b].GetID();
619 if (uid_a < uid_b)
620 return true;
621 if (uid_a > uid_b)
622 return false;
623 return false;
624 } else if (value_a < value_b)
625 return true;
626
627 return false;
628 }
629 };
Eli Friedmana92e3322010-06-10 23:36:31 +0000630}
631
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000632void
633Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
634{
Greg Clayton8087ca22010-10-08 04:20:14 +0000635 Mutex::Locker locker (m_mutex);
636
Owen Andersonc7da5f42010-06-16 17:34:05 +0000637 Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000638 // No need to sort if we have zero or one items...
639 if (indexes.size() <= 1)
640 return;
641
Owen Anderson836af6b2010-06-17 00:51:12 +0000642 // Sort the indexes in place using std::stable_sort.
643 // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
644 // not correctness. The indexes vector tends to be "close" to sorted, which the
645 // stable sort handles better.
Jim Inghame2b6ad62012-05-01 01:34:15 +0000646
647 std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
648
649 SymbolIndexComparator comparator(m_symbols, addr_cache);
650 std::stable_sort(indexes.begin(), indexes.end(), comparator);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000651
652 // Remove any duplicates if requested
653 if (remove_duplicates)
654 std::unique(indexes.begin(), indexes.end());
655}
656
657uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000658Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000659{
Greg Clayton8087ca22010-10-08 04:20:14 +0000660 Mutex::Locker locker (m_mutex);
661
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000662 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
663 if (symbol_name)
664 {
Greg Clayton38e953d2011-09-11 00:20:09 +0000665 const char *symbol_cstr = symbol_name.GetCString();
Greg Clayton8087ca22010-10-08 04:20:14 +0000666 if (!m_name_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000667 InitNameIndexes();
668
Greg Clayton38e953d2011-09-11 00:20:09 +0000669 return m_name_to_index.GetValues (symbol_cstr, indexes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000670 }
671 return 0;
672}
673
674uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000675Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
676{
Greg Clayton8087ca22010-10-08 04:20:14 +0000677 Mutex::Locker locker (m_mutex);
678
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000679 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
680 if (symbol_name)
681 {
682 const size_t old_size = indexes.size();
Greg Clayton8087ca22010-10-08 04:20:14 +0000683 if (!m_name_indexes_computed)
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000684 InitNameIndexes();
685
686 const char *symbol_cstr = symbol_name.GetCString();
Greg Clayton38e953d2011-09-11 00:20:09 +0000687
688 std::vector<uint32_t> all_name_indexes;
689 const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes);
690 for (size_t i=0; i<name_match_count; ++i)
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000691 {
Greg Clayton38e953d2011-09-11 00:20:09 +0000692 if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility))
693 indexes.push_back (all_name_indexes[i]);
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000694 }
695 return indexes.size() - old_size;
696 }
697 return 0;
698}
699
700uint32_t
701Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000702{
Greg Clayton8087ca22010-10-08 04:20:14 +0000703 Mutex::Locker locker (m_mutex);
704
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000705 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
706 {
707 std::vector<uint32_t>::iterator pos = indexes.begin();
708 while (pos != indexes.end())
709 {
710 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
711 ++pos;
712 else
Jim Ingham6dafc422013-09-27 20:58:17 +0000713 pos = indexes.erase(pos);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000714 }
715 }
716 return indexes.size();
717}
718
719uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000720Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
721{
Greg Clayton8087ca22010-10-08 04:20:14 +0000722 Mutex::Locker locker (m_mutex);
723
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000724 if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
725 {
726 std::vector<uint32_t>::iterator pos = indexes.begin();
727 while (pos != indexes.end())
728 {
729 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
730 ++pos;
731 else
Jim Ingham6dafc422013-09-27 20:58:17 +0000732 pos = indexes.erase(pos);
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000733 }
734 }
735 return indexes.size();
736}
737
738
739uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000740Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
741{
Greg Clayton8087ca22010-10-08 04:20:14 +0000742 Mutex::Locker locker (m_mutex);
743
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000744 uint32_t prev_size = indexes.size();
745 uint32_t sym_end = m_symbols.size();
746
Andy Gibbsa297a972013-06-19 19:04:53 +0000747 for (uint32_t i = 0; i < sym_end; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000748 {
749 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
750 {
Greg Claytonddaf6a72015-07-08 22:32:23 +0000751 const char *name = m_symbols[i].GetName().AsCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000752 if (name)
753 {
754 if (regexp.Execute (name))
755 indexes.push_back(i);
756 }
757 }
758 }
759 return indexes.size() - prev_size;
760
761}
762
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000763uint32_t
764Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000765{
Greg Clayton8087ca22010-10-08 04:20:14 +0000766 Mutex::Locker locker (m_mutex);
767
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000768 uint32_t prev_size = indexes.size();
769 uint32_t sym_end = m_symbols.size();
770
Andy Gibbsa297a972013-06-19 19:04:53 +0000771 for (uint32_t i = 0; i < sym_end; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000772 {
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000773 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000774 {
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000775 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
776 continue;
777
Greg Claytonddaf6a72015-07-08 22:32:23 +0000778 const char *name = m_symbols[i].GetName().AsCString();
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000779 if (name)
780 {
781 if (regexp.Execute (name))
782 indexes.push_back(i);
783 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000784 }
785 }
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000786 return indexes.size() - prev_size;
787
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000788}
789
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000790Symbol *
791Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000792{
Greg Clayton8087ca22010-10-08 04:20:14 +0000793 Mutex::Locker locker (m_mutex);
794
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000795 const size_t count = m_symbols.size();
Greg Claytonc7bece562013-01-25 18:06:21 +0000796 for (size_t idx = start_idx; idx < count; ++idx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000797 {
798 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
799 {
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000800 if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
801 {
802 start_idx = idx;
803 return &m_symbols[idx];
804 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000805 }
806 }
Ed Masted4612ad2014-04-20 13:17:36 +0000807 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000808}
809
810size_t
811Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
812{
Greg Clayton8087ca22010-10-08 04:20:14 +0000813 Mutex::Locker locker (m_mutex);
814
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000815 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
816 // Initialize all of the lookup by name indexes before converting NAME
817 // to a uniqued string NAME_STR below.
Greg Clayton8087ca22010-10-08 04:20:14 +0000818 if (!m_name_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000819 InitNameIndexes();
820
821 if (name)
822 {
823 // The string table did have a string that matched, but we need
824 // to check the symbols and match the symbol_type if any was given.
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000825 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000826 }
827 return symbol_indexes.size();
828}
829
830size_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000831Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000832{
Greg Clayton8087ca22010-10-08 04:20:14 +0000833 Mutex::Locker locker (m_mutex);
834
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000835 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
836 // Initialize all of the lookup by name indexes before converting NAME
837 // to a uniqued string NAME_STR below.
Greg Clayton8087ca22010-10-08 04:20:14 +0000838 if (!m_name_indexes_computed)
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000839 InitNameIndexes();
840
841 if (name)
842 {
843 // The string table did have a string that matched, but we need
844 // to check the symbols and match the symbol_type if any was given.
845 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
846 }
847 return symbol_indexes.size();
848}
849
850size_t
851Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
852{
Greg Clayton8087ca22010-10-08 04:20:14 +0000853 Mutex::Locker locker (m_mutex);
854
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000855 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000856 return symbol_indexes.size();
857}
858
859Symbol *
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000860Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000861{
Greg Clayton8087ca22010-10-08 04:20:14 +0000862 Mutex::Locker locker (m_mutex);
863
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000864 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
Greg Clayton8087ca22010-10-08 04:20:14 +0000865 if (!m_name_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000866 InitNameIndexes();
867
868 if (name)
869 {
870 std::vector<uint32_t> matching_indexes;
871 // The string table did have a string that matched, but we need
872 // to check the symbols and match the symbol_type if any was given.
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000873 if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000874 {
875 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
876 for (pos = matching_indexes.begin(); pos != end; ++pos)
877 {
878 Symbol *symbol = SymbolAtIndex(*pos);
879
880 if (symbol->Compare(name, symbol_type))
881 return symbol;
882 }
883 }
884 }
Ed Masted4612ad2014-04-20 13:17:36 +0000885 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000886}
887
888typedef struct
889{
890 const Symtab *symtab;
891 const addr_t file_addr;
892 Symbol *match_symbol;
893 const uint32_t *match_index_ptr;
894 addr_t match_offset;
895} SymbolSearchInfo;
896
897static int
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000898SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
899{
900 const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
Ed Masted4612ad2014-04-20 13:17:36 +0000901 if (symbol == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000902 return -1;
903
904 const addr_t info_file_addr = info->file_addr;
Greg Claytone7612132012-03-07 21:03:09 +0000905 if (symbol->ValueIsAddress())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000906 {
Greg Clayton358cf1e2015-06-25 21:46:34 +0000907 const addr_t curr_file_addr = symbol->GetAddressRef().GetFileAddress();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000908 if (info_file_addr < curr_file_addr)
909 return -1;
910
911 // Since we are finding the closest symbol that is greater than or equal
912 // to 'info->file_addr' we set the symbol here. This will get set
913 // multiple times, but after the search is done it will contain the best
914 // symbol match
915 info->match_symbol = const_cast<Symbol *>(symbol);
916 info->match_index_ptr = index_ptr;
917 info->match_offset = info_file_addr - curr_file_addr;
918
919 if (info_file_addr > curr_file_addr)
920 return +1;
921 return 0;
922 }
923 return -1;
924}
925
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000926void
927Symtab::InitAddressIndexes()
928{
Greg Clayton8087ca22010-10-08 04:20:14 +0000929 // Protected function, no need to lock mutex...
Greg Clayton3046e662013-07-10 01:23:25 +0000930 if (!m_file_addr_to_index_computed && !m_symbols.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000931 {
Greg Clayton3046e662013-07-10 01:23:25 +0000932 m_file_addr_to_index_computed = true;
Greg Clayton9594f4c2013-04-13 23:17:23 +0000933
Greg Clayton3046e662013-07-10 01:23:25 +0000934 FileRangeToIndexMap::Entry entry;
Greg Clayton8087ca22010-10-08 04:20:14 +0000935 const_iterator begin = m_symbols.begin();
936 const_iterator end = m_symbols.end();
937 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
938 {
Greg Claytone7612132012-03-07 21:03:09 +0000939 if (pos->ValueIsAddress())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000940 {
Greg Clayton358cf1e2015-06-25 21:46:34 +0000941 entry.SetRangeBase(pos->GetAddressRef().GetFileAddress());
Greg Clayton3046e662013-07-10 01:23:25 +0000942 entry.SetByteSize(pos->GetByteSize());
943 entry.data = std::distance(begin, pos);
944 m_file_addr_to_index.Append(entry);
945 }
946 }
947 const size_t num_entries = m_file_addr_to_index.GetSize();
948 if (num_entries > 0)
949 {
950 m_file_addr_to_index.Sort();
951 m_file_addr_to_index.CalculateSizesOfZeroByteSizeRanges();
952
953 // Now our last symbols might not have had sizes because there
954 // was no subsequent symbol to calculate the size from. If this is
955 // the case, then calculate the size by capping it at the end of the
956 // section in which the symbol resides
957 for (int i = num_entries - 1; i >= 0; --i)
958 {
959 const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i);
960 // As we iterate backwards, as soon as we find a symbol with a valid
961 // byte size, we are done
962 if (entry.GetByteSize() > 0)
963 break;
964
965 // Cap the size to the end of the section in which the symbol resides
966 SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (entry.GetRangeBase()));
967 if (section_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000968 {
Greg Clayton3046e662013-07-10 01:23:25 +0000969 const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize();
970 const lldb::addr_t symbol_file_addr = entry.GetRangeBase();
971 if (end_section_file_addr > symbol_file_addr)
Greg Clayton9422dd62013-03-04 21:46:16 +0000972 {
Greg Clayton3046e662013-07-10 01:23:25 +0000973 Symbol &symbol = m_symbols[entry.data];
974
975 symbol.SetByteSize(end_section_file_addr - symbol_file_addr);
976 symbol.SetSizeIsSynthesized(true);
Greg Clayton9422dd62013-03-04 21:46:16 +0000977 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000978 }
979 }
Greg Clayton3046e662013-07-10 01:23:25 +0000980 // Sort again in case the range size changes the ordering
981 m_file_addr_to_index.Sort();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000982 }
983 }
Greg Clayton3046e662013-07-10 01:23:25 +0000984}
985
986void
987Symtab::CalculateSymbolSizes ()
988{
989 Mutex::Locker locker (m_mutex);
990
991 if (!m_symbols.empty())
992 {
993 if (!m_file_addr_to_index_computed)
994 InitAddressIndexes();
995
996 const size_t num_entries = m_file_addr_to_index.GetSize();
997
998 for (size_t i = 0; i < num_entries; ++i)
999 {
1000 // The entries in the m_file_addr_to_index have calculated the sizes already
1001 // so we will use this size if we need to.
1002 const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i);
1003
1004 Symbol &symbol = m_symbols[entry.data];
1005
1006 // If the symbol size is already valid, no need to do anything
1007 if (symbol.GetByteSizeIsValid())
1008 continue;
1009
1010 const addr_t range_size = entry.GetByteSize();
1011 if (range_size > 0)
1012 {
1013 symbol.SetByteSize(range_size);
1014 symbol.SetSizeIsSynthesized(true);
1015 }
1016 }
1017 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001018}
1019
1020Symbol *
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001021Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
1022{
Greg Clayton8087ca22010-10-08 04:20:14 +00001023 Mutex::Locker locker (m_mutex);
1024
Greg Clayton3046e662013-07-10 01:23:25 +00001025
Ed Masted4612ad2014-04-20 13:17:36 +00001026 SymbolSearchInfo info = { this, file_addr, nullptr, nullptr, 0 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001027
Greg Claytone0d378b2011-03-24 21:19:54 +00001028 ::bsearch (&info,
1029 indexes,
1030 num_indexes,
1031 sizeof(uint32_t),
1032 (ComparisonFunction)SymbolWithClosestFileAddress);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001033
1034 if (info.match_symbol)
1035 {
Greg Clayton89411422010-10-08 00:21:05 +00001036 if (info.match_offset == 0)
1037 {
1038 // We found an exact match!
1039 return info.match_symbol;
1040 }
1041
Greg Claytonda171f12012-03-02 03:01:16 +00001042 const size_t symbol_byte_size = info.match_symbol->GetByteSize();
Greg Clayton89411422010-10-08 00:21:05 +00001043
1044 if (symbol_byte_size == 0)
1045 {
1046 // We weren't able to find the size of the symbol so lets just go
1047 // with that match we found in our search...
1048 return info.match_symbol;
1049 }
1050
1051 // We were able to figure out a symbol size so lets make sure our
1052 // offset puts "file_addr" in the symbol's address range.
1053 if (info.match_offset < symbol_byte_size)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001054 return info.match_symbol;
1055 }
Ed Masted4612ad2014-04-20 13:17:36 +00001056 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001057}
1058
1059Symbol *
1060Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
1061{
Greg Clayton8087ca22010-10-08 04:20:14 +00001062 Mutex::Locker locker (m_mutex);
1063
Greg Clayton3046e662013-07-10 01:23:25 +00001064 if (!m_file_addr_to_index_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001065 InitAddressIndexes();
1066
Greg Clayton3046e662013-07-10 01:23:25 +00001067 const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryThatContains(file_addr);
1068 if (entry)
1069 return SymbolAtIndex(entry->data);
Ed Masted4612ad2014-04-20 13:17:36 +00001070 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001071}
1072
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001073void
1074Symtab::SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list)
1075{
1076 // No need to protect this call using m_mutex all other method calls are
1077 // already thread safe.
1078
Greg Clayton43fe2172013-04-03 02:00:15 +00001079 const bool merge_symbol_into_function = true;
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001080 size_t num_indices = symbol_indexes.size();
1081 if (num_indices > 0)
1082 {
1083 SymbolContext sc;
1084 sc.module_sp = m_objfile->GetModule();
1085 for (size_t i = 0; i < num_indices; i++)
1086 {
1087 sc.symbol = SymbolAtIndex (symbol_indexes[i]);
1088 if (sc.symbol)
Greg Clayton43fe2172013-04-03 02:00:15 +00001089 sc_list.AppendIfUnique(sc, merge_symbol_into_function);
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001090 }
1091 }
1092}
1093
1094
1095size_t
1096Symtab::FindFunctionSymbols (const ConstString &name,
1097 uint32_t name_type_mask,
1098 SymbolContextList& sc_list)
1099{
1100 size_t count = 0;
1101 std::vector<uint32_t> symbol_indexes;
Greg Clayton43fe2172013-04-03 02:00:15 +00001102
1103 const char *name_cstr = name.GetCString();
1104
1105 // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
1106 assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
1107
1108 if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001109 {
Matt Kopec5e6a5d62013-04-22 17:02:04 +00001110 std::vector<uint32_t> temp_symbol_indexes;
1111 FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, temp_symbol_indexes);
1112
1113 unsigned temp_symbol_indexes_size = temp_symbol_indexes.size();
1114 if (temp_symbol_indexes_size > 0)
1115 {
1116 Mutex::Locker locker (m_mutex);
1117 for (unsigned i = 0; i < temp_symbol_indexes_size; i++)
1118 {
1119 SymbolContext sym_ctx;
1120 sym_ctx.symbol = SymbolAtIndex (temp_symbol_indexes[i]);
1121 if (sym_ctx.symbol)
1122 {
1123 switch (sym_ctx.symbol->GetType())
1124 {
1125 case eSymbolTypeCode:
1126 case eSymbolTypeResolver:
Greg Clayton9191db42013-10-21 18:40:51 +00001127 case eSymbolTypeReExported:
Matt Kopec5e6a5d62013-04-22 17:02:04 +00001128 symbol_indexes.push_back(temp_symbol_indexes[i]);
1129 break;
1130 default:
1131 break;
1132 }
1133 }
1134 }
1135 }
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001136 }
1137
Greg Clayton43fe2172013-04-03 02:00:15 +00001138 if (name_type_mask & eFunctionNameTypeBase)
1139 {
1140 // From mangled names we can't tell what is a basename and what
1141 // is a method name, so we just treat them the same
1142 if (!m_name_indexes_computed)
1143 InitNameIndexes();
1144
1145 if (!m_basename_to_index.IsEmpty())
1146 {
1147 const UniqueCStringMap<uint32_t>::Entry *match;
1148 for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
Ed Masted4612ad2014-04-20 13:17:36 +00001149 match != nullptr;
Greg Clayton43fe2172013-04-03 02:00:15 +00001150 match = m_basename_to_index.FindNextValueForName(match))
1151 {
1152 symbol_indexes.push_back(match->value);
1153 }
1154 }
1155 }
1156
1157 if (name_type_mask & eFunctionNameTypeMethod)
1158 {
1159 if (!m_name_indexes_computed)
1160 InitNameIndexes();
1161
1162 if (!m_method_to_index.IsEmpty())
1163 {
1164 const UniqueCStringMap<uint32_t>::Entry *match;
1165 for (match = m_method_to_index.FindFirstValueForName(name_cstr);
Ed Masted4612ad2014-04-20 13:17:36 +00001166 match != nullptr;
Greg Clayton43fe2172013-04-03 02:00:15 +00001167 match = m_method_to_index.FindNextValueForName(match))
1168 {
1169 symbol_indexes.push_back(match->value);
1170 }
1171 }
1172 }
1173
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001174 if (name_type_mask & eFunctionNameTypeSelector)
1175 {
1176 if (!m_name_indexes_computed)
1177 InitNameIndexes();
1178
1179 if (!m_selector_to_index.IsEmpty())
1180 {
1181 const UniqueCStringMap<uint32_t>::Entry *match;
Greg Clayton43fe2172013-04-03 02:00:15 +00001182 for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
Ed Masted4612ad2014-04-20 13:17:36 +00001183 match != nullptr;
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001184 match = m_selector_to_index.FindNextValueForName(match))
1185 {
1186 symbol_indexes.push_back(match->value);
1187 }
1188 }
1189 }
1190
1191 if (!symbol_indexes.empty())
1192 {
1193 std::sort(symbol_indexes.begin(), symbol_indexes.end());
1194 symbol_indexes.erase(std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end());
1195 count = symbol_indexes.size();
1196 SymbolIndicesToSymbolContextList (symbol_indexes, sc_list);
1197 }
1198
1199 return count;
1200}
1201
Greg Claytonbc63aac2015-02-25 22:41:34 +00001202
1203const Symbol *
1204Symtab::GetParent (Symbol *child_symbol) const
1205{
1206 uint32_t child_idx = GetIndexForSymbol(child_symbol);
1207 if (child_idx != UINT32_MAX && child_idx > 0)
1208 {
1209 for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx)
1210 {
1211 const Symbol *symbol = SymbolAtIndex (idx);
1212 const uint32_t sibling_idx = symbol->GetSiblingIndex();
1213 if (sibling_idx != UINT32_MAX && sibling_idx > child_idx)
1214 return symbol;
1215 }
1216 }
1217 return NULL;
1218}