blob: f934c63d0bf25f8fa923e79cfdb589c944db7a9d [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>
11
12#include "lldb/Core/Module.h"
13#include "lldb/Core/RegularExpression.h"
Greg Clayton9422dd62013-03-04 21:46:16 +000014#include "lldb/Core/Section.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015#include "lldb/Core/Timer.h"
16#include "lldb/Symbol/ObjectFile.h"
Greg Claytonc1b2ccf2013-01-08 00:01:36 +000017#include "lldb/Symbol/SymbolContext.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Symbol/Symtab.h"
Greg Clayton43fe2172013-04-03 02:00:15 +000019#include "lldb/Target/CPPLanguageRuntime.h"
Jim Inghamff5f5ff2011-08-15 01:32:22 +000020#include "lldb/Target/ObjCLanguageRuntime.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021
22using namespace lldb;
23using namespace lldb_private;
24
25
26
27Symtab::Symtab(ObjectFile *objfile) :
Greg Clayton8087ca22010-10-08 04:20:14 +000028 m_objfile (objfile),
29 m_symbols (),
30 m_addr_indexes (),
31 m_name_to_index (),
32 m_mutex (Mutex::eMutexTypeRecursive),
33 m_addr_indexes_computed (false),
34 m_name_indexes_computed (false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035{
36}
37
38Symtab::~Symtab()
39{
40}
41
42void
Greg Claytonc7bece562013-01-25 18:06:21 +000043Symtab::Reserve(size_t count)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044{
Greg Clayton8087ca22010-10-08 04:20:14 +000045 // Clients should grab the mutex from this symbol table and lock it manually
46 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047 m_symbols.reserve (count);
48}
49
50Symbol *
Greg Claytonc7bece562013-01-25 18:06:21 +000051Symtab::Resize(size_t count)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052{
Greg Clayton8087ca22010-10-08 04:20:14 +000053 // Clients should grab the mutex from this symbol table and lock it manually
54 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055 m_symbols.resize (count);
56 return &m_symbols[0];
57}
58
59uint32_t
60Symtab::AddSymbol(const Symbol& symbol)
61{
Greg Clayton8087ca22010-10-08 04:20:14 +000062 // Clients should grab the mutex from this symbol table and lock it manually
63 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064 uint32_t symbol_idx = m_symbols.size();
65 m_name_to_index.Clear();
66 m_addr_indexes.clear();
67 m_symbols.push_back(symbol);
Greg Clayton8087ca22010-10-08 04:20:14 +000068 m_addr_indexes_computed = false;
69 m_name_indexes_computed = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000070 return symbol_idx;
71}
72
73size_t
74Symtab::GetNumSymbols() const
75{
Greg Clayton8087ca22010-10-08 04:20:14 +000076 Mutex::Locker locker (m_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000077 return m_symbols.size();
78}
79
80void
Greg Claytone0d378b2011-03-24 21:19:54 +000081Symtab::Dump (Stream *s, Target *target, SortOrder sort_order)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082{
Greg Clayton8087ca22010-10-08 04:20:14 +000083 Mutex::Locker locker (m_mutex);
84
Greg Clayton89411422010-10-08 00:21:05 +000085// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000086 s->Indent();
87 const FileSpec &file_spec = m_objfile->GetFileSpec();
88 const char * object_name = NULL;
89 if (m_objfile->GetModule())
90 object_name = m_objfile->GetModule()->GetObjectName().GetCString();
91
92 if (file_spec)
Greg Claytonb5ad4ec2013-04-29 17:25:54 +000093 s->Printf("Symtab, file = %s%s%s%s, num_symbols = %lu",
94 file_spec.GetPath().c_str(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000095 object_name ? "(" : "",
96 object_name ? object_name : "",
97 object_name ? ")" : "",
98 m_symbols.size());
99 else
Jason Molendafd54b362011-09-20 21:44:10 +0000100 s->Printf("Symtab, num_symbols = %lu", m_symbols.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101
102 if (!m_symbols.empty())
103 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000104 switch (sort_order)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000105 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000106 case eSortOrderNone:
107 {
108 s->PutCString (":\n");
109 DumpSymbolHeader (s);
110 const_iterator begin = m_symbols.begin();
111 const_iterator end = m_symbols.end();
112 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
113 {
114 s->Indent();
115 pos->Dump(s, target, std::distance(begin, pos));
116 }
117 }
118 break;
119
120 case eSortOrderByName:
121 {
122 // Although we maintain a lookup by exact name map, the table
123 // isn't sorted by name. So we must make the ordered symbol list
124 // up ourselves.
125 s->PutCString (" (sorted by name):\n");
126 DumpSymbolHeader (s);
127 typedef std::multimap<const char*, const Symbol *, CStringCompareFunctionObject> CStringToSymbol;
128 CStringToSymbol name_map;
129 for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos)
130 {
131 const char *name = pos->GetMangled().GetName(Mangled::ePreferDemangled).AsCString();
132 if (name && name[0])
133 name_map.insert (std::make_pair(name, &(*pos)));
134 }
135
136 for (CStringToSymbol::const_iterator pos = name_map.begin(), end = name_map.end(); pos != end; ++pos)
137 {
138 s->Indent();
139 pos->second->Dump (s, target, pos->second - &m_symbols[0]);
140 }
141 }
142 break;
143
144 case eSortOrderByAddress:
145 s->PutCString (" (sorted by address):\n");
146 DumpSymbolHeader (s);
147 if (!m_addr_indexes_computed)
148 InitAddressIndexes();
149 const size_t num_symbols = GetNumSymbols();
150 std::vector<uint32_t>::const_iterator pos;
151 std::vector<uint32_t>::const_iterator end = m_addr_indexes.end();
152 for (pos = m_addr_indexes.begin(); pos != end; ++pos)
153 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000154 size_t idx = *pos;
Greg Clayton8087ca22010-10-08 04:20:14 +0000155 if (idx < num_symbols)
156 {
157 s->Indent();
158 m_symbols[idx].Dump(s, target, idx);
159 }
160 }
161 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162 }
163 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164}
165
166void
Greg Claytonf5e56de2010-09-14 23:36:40 +0000167Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000168{
Greg Clayton8087ca22010-10-08 04:20:14 +0000169 Mutex::Locker locker (m_mutex);
170
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000171 const size_t num_symbols = GetNumSymbols();
Greg Clayton8087ca22010-10-08 04:20:14 +0000172 //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 s->Indent();
Jason Molendafd54b362011-09-20 21:44:10 +0000174 s->Printf("Symtab %lu symbol indexes (%lu symbols total):\n", indexes.size(), m_symbols.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000175 s->IndentMore();
176
177 if (!indexes.empty())
178 {
179 std::vector<uint32_t>::const_iterator pos;
180 std::vector<uint32_t>::const_iterator end = indexes.end();
181 DumpSymbolHeader (s);
182 for (pos = indexes.begin(); pos != end; ++pos)
183 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000184 size_t idx = *pos;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000185 if (idx < num_symbols)
186 {
187 s->Indent();
Greg Claytonf5e56de2010-09-14 23:36:40 +0000188 m_symbols[idx].Dump(s, target, idx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189 }
190 }
191 }
192 s->IndentLess ();
193}
194
195void
196Symtab::DumpSymbolHeader (Stream *s)
197{
198 s->Indent(" Debug symbol\n");
199 s->Indent(" |Synthetic symbol\n");
200 s->Indent(" ||Externally Visible\n");
201 s->Indent(" |||\n");
202 s->Indent("Index UserID DSX Type File Address/Value Load Address Size Flags Name\n");
203 s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
204}
205
Greg Clayton49bd1c82010-09-07 17:36:17 +0000206
207static int
208CompareSymbolID (const void *key, const void *p)
209{
210 const user_id_t match_uid = *(user_id_t*) key;
211 const user_id_t symbol_uid = ((Symbol *)p)->GetID();
212 if (match_uid < symbol_uid)
213 return -1;
214 if (match_uid > symbol_uid)
215 return 1;
216 return 0;
217}
218
219Symbol *
220Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const
221{
Greg Clayton8087ca22010-10-08 04:20:14 +0000222 Mutex::Locker locker (m_mutex);
223
Greg Clayton49bd1c82010-09-07 17:36:17 +0000224 Symbol *symbol = (Symbol*)::bsearch (&symbol_uid,
225 &m_symbols[0],
226 m_symbols.size(),
Greg Clayton0c38b0d2010-09-12 05:25:16 +0000227 (uint8_t *)&m_symbols[1] - (uint8_t *)&m_symbols[0],
Greg Clayton49bd1c82010-09-07 17:36:17 +0000228 CompareSymbolID);
229 return symbol;
230}
231
232
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233Symbol *
Greg Claytonc7bece562013-01-25 18:06:21 +0000234Symtab::SymbolAtIndex(size_t idx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235{
Greg Clayton8087ca22010-10-08 04:20:14 +0000236 // Clients should grab the mutex from this symbol table and lock it manually
237 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000238 if (idx < m_symbols.size())
239 return &m_symbols[idx];
240 return NULL;
241}
242
243
244const Symbol *
Greg Claytonc7bece562013-01-25 18:06:21 +0000245Symtab::SymbolAtIndex(size_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246{
Greg Clayton8087ca22010-10-08 04:20:14 +0000247 // Clients should grab the mutex from this symbol table and lock it manually
248 // when calling this function to avoid performance issues.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000249 if (idx < m_symbols.size())
250 return &m_symbols[idx];
251 return NULL;
252}
253
254//----------------------------------------------------------------------
255// InitNameIndexes
256//----------------------------------------------------------------------
257void
258Symtab::InitNameIndexes()
259{
Greg Clayton8087ca22010-10-08 04:20:14 +0000260 // Protected function, no need to lock mutex...
261 if (!m_name_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000262 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000263 m_name_indexes_computed = true;
264 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
265 // Create the name index vector to be able to quickly search by name
Greg Clayton43fe2172013-04-03 02:00:15 +0000266 const size_t num_symbols = m_symbols.size();
Greg Clayton8087ca22010-10-08 04:20:14 +0000267#if 1
Greg Clayton43fe2172013-04-03 02:00:15 +0000268 m_name_to_index.Reserve (num_symbols);
Greg Clayton8087ca22010-10-08 04:20:14 +0000269#else
270 // TODO: benchmark this to see if we save any memory. Otherwise we
271 // will always keep the memory reserved in the vector unless we pull
272 // some STL swap magic and then recopy...
273 uint32_t actual_count = 0;
274 for (const_iterator pos = m_symbols.begin(), end = m_symbols.end();
275 pos != end;
276 ++pos)
277 {
278 const Mangled &mangled = pos->GetMangled();
279 if (mangled.GetMangledName())
280 ++actual_count;
281
282 if (mangled.GetDemangledName())
283 ++actual_count;
284 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000285
Greg Clayton8087ca22010-10-08 04:20:14 +0000286 m_name_to_index.Reserve (actual_count);
287#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288
Greg Clayton1075aca2011-12-03 20:02:42 +0000289 NameToIndexMap::Entry entry;
Greg Clayton8087ca22010-10-08 04:20:14 +0000290
Greg Clayton43fe2172013-04-03 02:00:15 +0000291 // The "const char *" in "class_contexts" must come from a ConstString::GetCString()
292 std::set<const char *> class_contexts;
293 UniqueCStringMap<uint32_t> mangled_name_to_index;
294 std::vector<const char *> symbol_contexts(num_symbols, NULL);
295
296 for (entry.value = 0; entry.value<num_symbols; ++entry.value)
Greg Clayton8087ca22010-10-08 04:20:14 +0000297 {
298 const Symbol *symbol = &m_symbols[entry.value];
299
300 // Don't let trampolines get into the lookup by name map
301 // If we ever need the trampoline symbols to be searchable by name
302 // we can remove this and then possibly add a new bool to any of the
303 // Symtab functions that lookup symbols by name to indicate if they
304 // want trampolines.
305 if (symbol->IsTrampoline())
306 continue;
307
308 const Mangled &mangled = symbol->GetMangled();
309 entry.cstring = mangled.GetMangledName().GetCString();
310 if (entry.cstring && entry.cstring[0])
Greg Clayton43fe2172013-04-03 02:00:15 +0000311 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000312 m_name_to_index.Append (entry);
Greg Clayton43fe2172013-04-03 02:00:15 +0000313
314 const SymbolType symbol_type = symbol->GetType();
315 if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver)
316 {
317 if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' &&
318 (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name
319 entry.cstring[2] != 'G' && // avoid guard variables
320 entry.cstring[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
321 {
322 CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName());
Greg Clayton6ecb2322013-05-18 00:11:21 +0000323 entry.cstring = ConstString(cxx_method.GetBasename()).GetCString();
Greg Clayton43fe2172013-04-03 02:00:15 +0000324 if (entry.cstring && entry.cstring[0])
325 {
326 // ConstString objects permanently store the string in the pool so calling
327 // GetCString() on the value gets us a const char * that will never go away
328 const char *const_context = ConstString(cxx_method.GetContext()).GetCString();
Greg Clayton8087ca22010-10-08 04:20:14 +0000329
Greg Clayton43fe2172013-04-03 02:00:15 +0000330 if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty())
331 {
332 // The first character of the demangled basename is '~' which
333 // means we have a class destructor. We can use this information
334 // to help us know what is a class and what isn't.
335 if (class_contexts.find(const_context) == class_contexts.end())
336 class_contexts.insert(const_context);
337 m_method_to_index.Append (entry);
338 }
339 else
340 {
341 if (const_context && const_context[0])
342 {
343 if (class_contexts.find(const_context) != class_contexts.end())
344 {
345 // The current decl context is in our "class_contexts" which means
346 // this is a method on a class
347 m_method_to_index.Append (entry);
348 }
349 else
350 {
351 // We don't know if this is a function basename or a method,
352 // so put it into a temporary collection so once we are done
353 // we can look in class_contexts to see if each entry is a class
354 // or just a function and will put any remaining items into
355 // m_method_to_index or m_basename_to_index as needed
356 mangled_name_to_index.Append (entry);
357 symbol_contexts[entry.value] = const_context;
358 }
359 }
360 else
361 {
362 // No context for this function so this has to be a basename
363 m_basename_to_index.Append(entry);
364 }
365 }
366 }
367 }
368 }
369 }
370
Greg Clayton8087ca22010-10-08 04:20:14 +0000371 entry.cstring = mangled.GetDemangledName().GetCString();
372 if (entry.cstring && entry.cstring[0])
373 m_name_to_index.Append (entry);
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000374
375 // If the demangled name turns out to be an ObjC name, and
376 // is a category name, add the version without categories to the index too.
Greg Clayton1b3815c2013-01-30 00:18:29 +0000377 ObjCLanguageRuntime::MethodName objc_method (entry.cstring, true);
378 if (objc_method.IsValid(true))
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000379 {
Greg Clayton1b3815c2013-01-30 00:18:29 +0000380 entry.cstring = objc_method.GetSelector().GetCString();
Greg Claytonc1b2ccf2013-01-08 00:01:36 +0000381 m_selector_to_index.Append (entry);
Greg Clayton1b3815c2013-01-30 00:18:29 +0000382
383 ConstString objc_method_no_category (objc_method.GetFullNameWithoutCategory(true));
384 if (objc_method_no_category)
385 {
386 entry.cstring = objc_method_no_category.GetCString();
387 m_name_to_index.Append (entry);
388 }
Jim Inghamff5f5ff2011-08-15 01:32:22 +0000389 }
390
Greg Clayton8087ca22010-10-08 04:20:14 +0000391 }
Greg Clayton43fe2172013-04-03 02:00:15 +0000392
393 size_t count;
394 if (!mangled_name_to_index.IsEmpty())
395 {
396 count = mangled_name_to_index.GetSize();
397 for (size_t i=0; i<count; ++i)
398 {
399 if (mangled_name_to_index.GetValueAtIndex(i, entry.value))
400 {
401 entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
402 if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end())
403 {
404 m_method_to_index.Append (entry);
405 }
406 else
407 {
408 // If we got here, we have something that had a context (was inside a namespace or class)
409 // yet we don't know if the entry
410 m_method_to_index.Append (entry);
411 m_basename_to_index.Append (entry);
412 }
413 }
414 }
415 }
Greg Clayton8087ca22010-10-08 04:20:14 +0000416 m_name_to_index.Sort();
Greg Claytond2c46a62011-12-28 22:24:04 +0000417 m_name_to_index.SizeToFit();
Greg Claytonc1b2ccf2013-01-08 00:01:36 +0000418 m_selector_to_index.Sort();
419 m_selector_to_index.SizeToFit();
Greg Clayton43fe2172013-04-03 02:00:15 +0000420 m_basename_to_index.Sort();
421 m_basename_to_index.SizeToFit();
422 m_method_to_index.Sort();
423 m_method_to_index.SizeToFit();
424
425// static StreamFile a ("/tmp/a.txt");
426//
427// count = m_basename_to_index.GetSize();
428// if (count)
429// {
430// for (size_t i=0; i<count; ++i)
431// {
432// if (m_basename_to_index.GetValueAtIndex(i, entry.value))
433// a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
434// }
435// }
436// count = m_method_to_index.GetSize();
437// if (count)
438// {
439// for (size_t i=0; i<count; ++i)
440// {
441// if (m_method_to_index.GetValueAtIndex(i, entry.value))
442// a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
443// }
444// }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000445 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000446}
447
Greg Clayton1075aca2011-12-03 20:02:42 +0000448void
Greg Clayton43fe2172013-04-03 02:00:15 +0000449Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
Greg Clayton1075aca2011-12-03 20:02:42 +0000450 bool add_demangled,
451 bool add_mangled,
452 NameToIndexMap &name_to_index_map) const
453{
454 if (add_demangled || add_mangled)
455 {
456 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
457 Mutex::Locker locker (m_mutex);
458
459 // Create the name index vector to be able to quickly search by name
460 NameToIndexMap::Entry entry;
461 const size_t num_indexes = indexes.size();
462 for (size_t i=0; i<num_indexes; ++i)
463 {
464 entry.value = indexes[i];
465 assert (i < m_symbols.size());
466 const Symbol *symbol = &m_symbols[entry.value];
467
468 const Mangled &mangled = symbol->GetMangled();
469 if (add_demangled)
470 {
471 entry.cstring = mangled.GetDemangledName().GetCString();
472 if (entry.cstring && entry.cstring[0])
473 name_to_index_map.Append (entry);
474 }
475
476 if (add_mangled)
477 {
478 entry.cstring = mangled.GetMangledName().GetCString();
479 if (entry.cstring && entry.cstring[0])
480 name_to_index_map.Append (entry);
481 }
482 }
483 }
484}
485
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000486uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000487Symtab::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 +0000488{
Greg Clayton8087ca22010-10-08 04:20:14 +0000489 Mutex::Locker locker (m_mutex);
490
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000491 uint32_t prev_size = indexes.size();
492
493 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
494
495 for (uint32_t i = start_idx; i < count; ++i)
496 {
497 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
498 indexes.push_back(i);
499 }
500
501 return indexes.size() - prev_size;
502}
503
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000504uint32_t
Greg Clayton16b2d2b2011-01-20 06:08:59 +0000505Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
506{
507 Mutex::Locker locker (m_mutex);
508
509 uint32_t prev_size = indexes.size();
510
511 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
512
513 for (uint32_t i = start_idx; i < count; ++i)
514 {
515 if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value)
516 indexes.push_back(i);
517 }
518
519 return indexes.size() - prev_size;
520}
521
522uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000523Symtab::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
524{
Greg Clayton8087ca22010-10-08 04:20:14 +0000525 Mutex::Locker locker (m_mutex);
526
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000527 uint32_t prev_size = indexes.size();
528
529 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
530
531 for (uint32_t i = start_idx; i < count; ++i)
532 {
533 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
534 {
535 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
536 indexes.push_back(i);
537 }
538 }
539
540 return indexes.size() - prev_size;
541}
542
543
544uint32_t
545Symtab::GetIndexForSymbol (const Symbol *symbol) const
546{
547 const Symbol *first_symbol = &m_symbols[0];
548 if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
549 return symbol - first_symbol;
550 return UINT32_MAX;
551}
552
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000553struct SymbolSortInfo
554{
555 const bool sort_by_load_addr;
556 const Symbol *symbols;
557};
558
Owen Andersonc7da5f42010-06-16 17:34:05 +0000559namespace {
560 struct SymbolIndexComparator {
561 const std::vector<Symbol>& symbols;
Jim Inghame2b6ad62012-05-01 01:34:15 +0000562 std::vector<lldb::addr_t> &addr_cache;
563
564 // Getting from the symbol to the Address to the File Address involves some work.
565 // Since there are potentially many symbols here, and we're using this for sorting so
566 // we're going to be computing the address many times, cache that in addr_cache.
567 // The array passed in has to be the same size as the symbols array passed into the
568 // member variable symbols, and should be initialized with LLDB_INVALID_ADDRESS.
569 // NOTE: You have to make addr_cache externally and pass it in because std::stable_sort
570 // makes copies of the comparator it is initially passed in, and you end up spending
571 // huge amounts of time copying this array...
572
573 SymbolIndexComparator(const std::vector<Symbol>& s, std::vector<lldb::addr_t> &a) : symbols(s), addr_cache(a) {
574 assert (symbols.size() == addr_cache.size());
575 }
Owen Andersonc7da5f42010-06-16 17:34:05 +0000576 bool operator()(uint32_t index_a, uint32_t index_b) {
Jim Inghame2b6ad62012-05-01 01:34:15 +0000577 addr_t value_a = addr_cache[index_a];
578 if (value_a == LLDB_INVALID_ADDRESS)
579 {
580 value_a = symbols[index_a].GetAddress().GetFileAddress();
581 addr_cache[index_a] = value_a;
582 }
583
584 addr_t value_b = addr_cache[index_b];
585 if (value_b == LLDB_INVALID_ADDRESS)
586 {
587 value_b = symbols[index_b].GetAddress().GetFileAddress();
588 addr_cache[index_b] = value_b;
589 }
590
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000591
Owen Andersonc7da5f42010-06-16 17:34:05 +0000592 if (value_a == value_b) {
593 // The if the values are equal, use the original symbol user ID
594 lldb::user_id_t uid_a = symbols[index_a].GetID();
595 lldb::user_id_t uid_b = symbols[index_b].GetID();
596 if (uid_a < uid_b)
597 return true;
598 if (uid_a > uid_b)
599 return false;
600 return false;
601 } else if (value_a < value_b)
602 return true;
603
604 return false;
605 }
606 };
Eli Friedmana92e3322010-06-10 23:36:31 +0000607}
608
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000609void
610Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
611{
Greg Clayton8087ca22010-10-08 04:20:14 +0000612 Mutex::Locker locker (m_mutex);
613
Owen Andersonc7da5f42010-06-16 17:34:05 +0000614 Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000615 // No need to sort if we have zero or one items...
616 if (indexes.size() <= 1)
617 return;
618
Owen Anderson836af6b2010-06-17 00:51:12 +0000619 // Sort the indexes in place using std::stable_sort.
620 // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
621 // not correctness. The indexes vector tends to be "close" to sorted, which the
622 // stable sort handles better.
Jim Inghame2b6ad62012-05-01 01:34:15 +0000623
624 std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
625
626 SymbolIndexComparator comparator(m_symbols, addr_cache);
627 std::stable_sort(indexes.begin(), indexes.end(), comparator);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000628
629 // Remove any duplicates if requested
630 if (remove_duplicates)
631 std::unique(indexes.begin(), indexes.end());
632}
633
634uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000635Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000636{
Greg Clayton8087ca22010-10-08 04:20:14 +0000637 Mutex::Locker locker (m_mutex);
638
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000639 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
640 if (symbol_name)
641 {
Greg Clayton38e953d2011-09-11 00:20:09 +0000642 const char *symbol_cstr = symbol_name.GetCString();
Greg Clayton8087ca22010-10-08 04:20:14 +0000643 if (!m_name_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000644 InitNameIndexes();
645
Greg Clayton38e953d2011-09-11 00:20:09 +0000646 return m_name_to_index.GetValues (symbol_cstr, indexes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000647 }
648 return 0;
649}
650
651uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000652Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
653{
Greg Clayton8087ca22010-10-08 04:20:14 +0000654 Mutex::Locker locker (m_mutex);
655
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000656 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
657 if (symbol_name)
658 {
659 const size_t old_size = indexes.size();
Greg Clayton8087ca22010-10-08 04:20:14 +0000660 if (!m_name_indexes_computed)
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000661 InitNameIndexes();
662
663 const char *symbol_cstr = symbol_name.GetCString();
Greg Clayton38e953d2011-09-11 00:20:09 +0000664
665 std::vector<uint32_t> all_name_indexes;
666 const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes);
667 for (size_t i=0; i<name_match_count; ++i)
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000668 {
Greg Clayton38e953d2011-09-11 00:20:09 +0000669 if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility))
670 indexes.push_back (all_name_indexes[i]);
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000671 }
672 return indexes.size() - old_size;
673 }
674 return 0;
675}
676
677uint32_t
678Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000679{
Greg Clayton8087ca22010-10-08 04:20:14 +0000680 Mutex::Locker locker (m_mutex);
681
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000682 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
683 {
684 std::vector<uint32_t>::iterator pos = indexes.begin();
685 while (pos != indexes.end())
686 {
687 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
688 ++pos;
689 else
690 indexes.erase(pos);
691 }
692 }
693 return indexes.size();
694}
695
696uint32_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000697Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
698{
Greg Clayton8087ca22010-10-08 04:20:14 +0000699 Mutex::Locker locker (m_mutex);
700
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000701 if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
702 {
703 std::vector<uint32_t>::iterator pos = indexes.begin();
704 while (pos != indexes.end())
705 {
706 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
707 ++pos;
708 else
709 indexes.erase(pos);
710 }
711 }
712 return indexes.size();
713}
714
715
716uint32_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000717Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
718{
Greg Clayton8087ca22010-10-08 04:20:14 +0000719 Mutex::Locker locker (m_mutex);
720
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000721 uint32_t prev_size = indexes.size();
722 uint32_t sym_end = m_symbols.size();
723
Andy Gibbsa297a972013-06-19 19:04:53 +0000724 for (uint32_t i = 0; i < sym_end; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000725 {
726 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
727 {
728 const char *name = m_symbols[i].GetMangled().GetName().AsCString();
729 if (name)
730 {
731 if (regexp.Execute (name))
732 indexes.push_back(i);
733 }
734 }
735 }
736 return indexes.size() - prev_size;
737
738}
739
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000740uint32_t
741Symtab::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 +0000742{
Greg Clayton8087ca22010-10-08 04:20:14 +0000743 Mutex::Locker locker (m_mutex);
744
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000745 uint32_t prev_size = indexes.size();
746 uint32_t sym_end = m_symbols.size();
747
Andy Gibbsa297a972013-06-19 19:04:53 +0000748 for (uint32_t i = 0; i < sym_end; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000749 {
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000750 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000751 {
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000752 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
753 continue;
754
755 const char *name = m_symbols[i].GetMangled().GetName().AsCString();
756 if (name)
757 {
758 if (regexp.Execute (name))
759 indexes.push_back(i);
760 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000761 }
762 }
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000763 return indexes.size() - prev_size;
764
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000765}
766
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000767Symbol *
768Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000769{
Greg Clayton8087ca22010-10-08 04:20:14 +0000770 Mutex::Locker locker (m_mutex);
771
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000772 const size_t count = m_symbols.size();
Greg Claytonc7bece562013-01-25 18:06:21 +0000773 for (size_t idx = start_idx; idx < count; ++idx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000774 {
775 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
776 {
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000777 if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
778 {
779 start_idx = idx;
780 return &m_symbols[idx];
781 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000782 }
783 }
784 return NULL;
785}
786
787size_t
788Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
789{
Greg Clayton8087ca22010-10-08 04:20:14 +0000790 Mutex::Locker locker (m_mutex);
791
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000792 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
793 // Initialize all of the lookup by name indexes before converting NAME
794 // to a uniqued string NAME_STR below.
Greg Clayton8087ca22010-10-08 04:20:14 +0000795 if (!m_name_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000796 InitNameIndexes();
797
798 if (name)
799 {
800 // The string table did have a string that matched, but we need
801 // to check the symbols and match the symbol_type if any was given.
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000802 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000803 }
804 return symbol_indexes.size();
805}
806
807size_t
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000808Symtab::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 +0000809{
Greg Clayton8087ca22010-10-08 04:20:14 +0000810 Mutex::Locker locker (m_mutex);
811
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000812 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
813 // Initialize all of the lookup by name indexes before converting NAME
814 // to a uniqued string NAME_STR below.
Greg Clayton8087ca22010-10-08 04:20:14 +0000815 if (!m_name_indexes_computed)
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000816 InitNameIndexes();
817
818 if (name)
819 {
820 // The string table did have a string that matched, but we need
821 // to check the symbols and match the symbol_type if any was given.
822 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
823 }
824 return symbol_indexes.size();
825}
826
827size_t
828Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
829{
Greg Clayton8087ca22010-10-08 04:20:14 +0000830 Mutex::Locker locker (m_mutex);
831
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000832 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000833 return symbol_indexes.size();
834}
835
836Symbol *
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000837Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000838{
Greg Clayton8087ca22010-10-08 04:20:14 +0000839 Mutex::Locker locker (m_mutex);
840
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000841 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
Greg Clayton8087ca22010-10-08 04:20:14 +0000842 if (!m_name_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000843 InitNameIndexes();
844
845 if (name)
846 {
847 std::vector<uint32_t> matching_indexes;
848 // The string table did have a string that matched, but we need
849 // to check the symbols and match the symbol_type if any was given.
Greg Claytonbcf2cfb2010-09-11 03:13:28 +0000850 if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000851 {
852 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
853 for (pos = matching_indexes.begin(); pos != end; ++pos)
854 {
855 Symbol *symbol = SymbolAtIndex(*pos);
856
857 if (symbol->Compare(name, symbol_type))
858 return symbol;
859 }
860 }
861 }
862 return NULL;
863}
864
865typedef struct
866{
867 const Symtab *symtab;
868 const addr_t file_addr;
869 Symbol *match_symbol;
870 const uint32_t *match_index_ptr;
871 addr_t match_offset;
872} SymbolSearchInfo;
873
874static int
875SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
876{
877 const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
878 if (curr_symbol == NULL)
879 return -1;
880
881 const addr_t info_file_addr = info->file_addr;
882
883 // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
884 // range if the symbol has a section!
Greg Claytone7612132012-03-07 21:03:09 +0000885 if (curr_symbol->ValueIsAddress())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000886 {
Greg Claytone7612132012-03-07 21:03:09 +0000887 const addr_t curr_file_addr = curr_symbol->GetAddress().GetFileAddress();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000888 if (info_file_addr < curr_file_addr)
889 return -1;
890 if (info_file_addr > curr_file_addr)
891 return +1;
892 info->match_symbol = const_cast<Symbol *>(curr_symbol);
893 info->match_index_ptr = index_ptr;
894 return 0;
895 }
896
897 return -1;
898}
899
900static int
901SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
902{
903 const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
904 if (symbol == NULL)
905 return -1;
906
907 const addr_t info_file_addr = info->file_addr;
Greg Claytone7612132012-03-07 21:03:09 +0000908 if (symbol->ValueIsAddress())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000909 {
Greg Claytone7612132012-03-07 21:03:09 +0000910 const addr_t curr_file_addr = symbol->GetAddress().GetFileAddress();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000911 if (info_file_addr < curr_file_addr)
912 return -1;
913
914 // Since we are finding the closest symbol that is greater than or equal
915 // to 'info->file_addr' we set the symbol here. This will get set
916 // multiple times, but after the search is done it will contain the best
917 // symbol match
918 info->match_symbol = const_cast<Symbol *>(symbol);
919 info->match_index_ptr = index_ptr;
920 info->match_offset = info_file_addr - curr_file_addr;
921
922 if (info_file_addr > curr_file_addr)
923 return +1;
924 return 0;
925 }
926 return -1;
927}
928
929static SymbolSearchInfo
930FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
931{
932 SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
Greg Claytone0d378b2011-03-24 21:19:54 +0000933 ::bsearch (&info,
934 indexes,
935 num_indexes,
936 sizeof(uint32_t),
937 (ComparisonFunction)SymbolWithClosestFileAddress);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000938 return info;
939}
940
941
942void
943Symtab::InitAddressIndexes()
944{
Greg Clayton8087ca22010-10-08 04:20:14 +0000945 // Protected function, no need to lock mutex...
946 if (!m_addr_indexes_computed && !m_symbols.empty())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000947 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000948 m_addr_indexes_computed = true;
Greg Clayton9594f4c2013-04-13 23:17:23 +0000949
Greg Clayton8087ca22010-10-08 04:20:14 +0000950 const_iterator begin = m_symbols.begin();
951 const_iterator end = m_symbols.end();
952 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
953 {
Greg Claytone7612132012-03-07 21:03:09 +0000954 if (pos->ValueIsAddress())
Greg Clayton8087ca22010-10-08 04:20:14 +0000955 m_addr_indexes.push_back (std::distance(begin, pos));
956 }
Greg Clayton9594f4c2013-04-13 23:17:23 +0000957
Greg Clayton8087ca22010-10-08 04:20:14 +0000958 SortSymbolIndexesByValue (m_addr_indexes, false);
959 m_addr_indexes.push_back (UINT32_MAX); // Terminator for bsearch since we might need to look at the next symbol
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000960 }
961}
962
963size_t
964Symtab::CalculateSymbolSize (Symbol *symbol)
965{
Greg Clayton8087ca22010-10-08 04:20:14 +0000966 Mutex::Locker locker (m_mutex);
967
Greg Clayton471b31c2010-07-20 22:52:08 +0000968 if (m_symbols.empty())
969 return 0;
970
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000971 // Make sure this symbol is from this symbol table...
Greg Clayton471b31c2010-07-20 22:52:08 +0000972 if (symbol < &m_symbols.front() || symbol > &m_symbols.back())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000973 return 0;
974
975 // See if this symbol already has a byte size?
976 size_t byte_size = symbol->GetByteSize();
977
978 if (byte_size)
979 {
980 // It does, just return it
981 return byte_size;
982 }
983
984 // Else if this is an address based symbol, figure out the delta between
985 // it and the next address based symbol
Greg Claytone7612132012-03-07 21:03:09 +0000986 if (symbol->ValueIsAddress())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000987 {
Greg Clayton8087ca22010-10-08 04:20:14 +0000988 if (!m_addr_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000989 InitAddressIndexes();
990 const size_t num_addr_indexes = m_addr_indexes.size();
Greg Clayton9422dd62013-03-04 21:46:16 +0000991 const lldb::addr_t symbol_file_addr = symbol->GetAddress().GetFileAddress();
Greg Claytone7612132012-03-07 21:03:09 +0000992 SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress (this,
Greg Clayton9422dd62013-03-04 21:46:16 +0000993 symbol_file_addr,
Greg Claytone7612132012-03-07 21:03:09 +0000994 &m_addr_indexes.front(),
995 num_addr_indexes);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000996 if (info.match_index_ptr != NULL)
997 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000998 // We can figure out the address range of all symbols except the
999 // last one by taking the delta between the current symbol and
1000 // the next symbol
1001
Greg Clayton471b31c2010-07-20 22:52:08 +00001002 for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001003 addr_index < num_addr_indexes;
1004 ++addr_index)
1005 {
1006 Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
1007 if (next_symbol == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001008 {
Greg Clayton9422dd62013-03-04 21:46:16 +00001009 // No next symbol take the size to be the remaining bytes in the section
1010 // in which the symbol resides
1011 SectionSP section_sp (m_objfile->GetSectionList()->FindSectionContainingFileAddress (symbol_file_addr));
1012 if (section_sp)
1013 {
1014 const lldb::addr_t end_section_file_addr = section_sp->GetFileAddress() + section_sp->GetByteSize();
1015 if (end_section_file_addr > symbol_file_addr)
1016 {
1017 byte_size = end_section_file_addr - symbol_file_addr;
1018 symbol->SetByteSize(byte_size);
1019 symbol->SetSizeIsSynthesized(true);
1020 break;
1021 }
1022 }
1023 }
1024 else
1025 {
1026 const lldb::addr_t next_file_addr = next_symbol->GetAddress().GetFileAddress();
1027 if (next_file_addr > symbol_file_addr)
1028 {
1029 byte_size = next_file_addr - symbol_file_addr;
1030 symbol->SetByteSize(byte_size);
1031 symbol->SetSizeIsSynthesized(true);
1032 break;
1033 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001034 }
1035 }
1036 }
1037 }
1038 return byte_size;
1039}
1040
1041Symbol *
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001042Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
1043{
Greg Clayton8087ca22010-10-08 04:20:14 +00001044 Mutex::Locker locker (m_mutex);
1045
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001046 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
1047
Greg Claytone0d378b2011-03-24 21:19:54 +00001048 ::bsearch (&info,
1049 indexes,
1050 num_indexes,
1051 sizeof(uint32_t),
1052 (ComparisonFunction)SymbolWithClosestFileAddress);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001053
1054 if (info.match_symbol)
1055 {
Greg Clayton89411422010-10-08 00:21:05 +00001056 if (info.match_offset == 0)
1057 {
1058 // We found an exact match!
1059 return info.match_symbol;
1060 }
1061
Greg Claytonda171f12012-03-02 03:01:16 +00001062 const size_t symbol_byte_size = info.match_symbol->GetByteSize();
Greg Clayton89411422010-10-08 00:21:05 +00001063
1064 if (symbol_byte_size == 0)
1065 {
1066 // We weren't able to find the size of the symbol so lets just go
1067 // with that match we found in our search...
1068 return info.match_symbol;
1069 }
1070
1071 // We were able to figure out a symbol size so lets make sure our
1072 // offset puts "file_addr" in the symbol's address range.
1073 if (info.match_offset < symbol_byte_size)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001074 return info.match_symbol;
1075 }
1076 return NULL;
1077}
1078
1079Symbol *
1080Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
1081{
Greg Clayton8087ca22010-10-08 04:20:14 +00001082 Mutex::Locker locker (m_mutex);
1083
1084 if (!m_addr_indexes_computed)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001085 InitAddressIndexes();
1086
1087 return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
1088}
1089
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001090void
1091Symtab::SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list)
1092{
1093 // No need to protect this call using m_mutex all other method calls are
1094 // already thread safe.
1095
Greg Clayton43fe2172013-04-03 02:00:15 +00001096 const bool merge_symbol_into_function = true;
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001097 size_t num_indices = symbol_indexes.size();
1098 if (num_indices > 0)
1099 {
1100 SymbolContext sc;
1101 sc.module_sp = m_objfile->GetModule();
1102 for (size_t i = 0; i < num_indices; i++)
1103 {
1104 sc.symbol = SymbolAtIndex (symbol_indexes[i]);
1105 if (sc.symbol)
Greg Clayton43fe2172013-04-03 02:00:15 +00001106 sc_list.AppendIfUnique(sc, merge_symbol_into_function);
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001107 }
1108 }
1109}
1110
1111
1112size_t
1113Symtab::FindFunctionSymbols (const ConstString &name,
1114 uint32_t name_type_mask,
1115 SymbolContextList& sc_list)
1116{
1117 size_t count = 0;
1118 std::vector<uint32_t> symbol_indexes;
Greg Clayton43fe2172013-04-03 02:00:15 +00001119
1120 const char *name_cstr = name.GetCString();
1121
1122 // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
1123 assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
1124
1125 if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001126 {
Matt Kopec5e6a5d62013-04-22 17:02:04 +00001127 std::vector<uint32_t> temp_symbol_indexes;
1128 FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, temp_symbol_indexes);
1129
1130 unsigned temp_symbol_indexes_size = temp_symbol_indexes.size();
1131 if (temp_symbol_indexes_size > 0)
1132 {
1133 Mutex::Locker locker (m_mutex);
1134 for (unsigned i = 0; i < temp_symbol_indexes_size; i++)
1135 {
1136 SymbolContext sym_ctx;
1137 sym_ctx.symbol = SymbolAtIndex (temp_symbol_indexes[i]);
1138 if (sym_ctx.symbol)
1139 {
1140 switch (sym_ctx.symbol->GetType())
1141 {
1142 case eSymbolTypeCode:
1143 case eSymbolTypeResolver:
1144 symbol_indexes.push_back(temp_symbol_indexes[i]);
1145 break;
1146 default:
1147 break;
1148 }
1149 }
1150 }
1151 }
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001152 }
1153
Greg Clayton43fe2172013-04-03 02:00:15 +00001154 if (name_type_mask & eFunctionNameTypeBase)
1155 {
1156 // From mangled names we can't tell what is a basename and what
1157 // is a method name, so we just treat them the same
1158 if (!m_name_indexes_computed)
1159 InitNameIndexes();
1160
1161 if (!m_basename_to_index.IsEmpty())
1162 {
1163 const UniqueCStringMap<uint32_t>::Entry *match;
1164 for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
1165 match != NULL;
1166 match = m_basename_to_index.FindNextValueForName(match))
1167 {
1168 symbol_indexes.push_back(match->value);
1169 }
1170 }
1171 }
1172
1173 if (name_type_mask & eFunctionNameTypeMethod)
1174 {
1175 if (!m_name_indexes_computed)
1176 InitNameIndexes();
1177
1178 if (!m_method_to_index.IsEmpty())
1179 {
1180 const UniqueCStringMap<uint32_t>::Entry *match;
1181 for (match = m_method_to_index.FindFirstValueForName(name_cstr);
1182 match != NULL;
1183 match = m_method_to_index.FindNextValueForName(match))
1184 {
1185 symbol_indexes.push_back(match->value);
1186 }
1187 }
1188 }
1189
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001190 if (name_type_mask & eFunctionNameTypeSelector)
1191 {
1192 if (!m_name_indexes_computed)
1193 InitNameIndexes();
1194
1195 if (!m_selector_to_index.IsEmpty())
1196 {
1197 const UniqueCStringMap<uint32_t>::Entry *match;
Greg Clayton43fe2172013-04-03 02:00:15 +00001198 for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
Greg Claytonc1b2ccf2013-01-08 00:01:36 +00001199 match != NULL;
1200 match = m_selector_to_index.FindNextValueForName(match))
1201 {
1202 symbol_indexes.push_back(match->value);
1203 }
1204 }
1205 }
1206
1207 if (!symbol_indexes.empty())
1208 {
1209 std::sort(symbol_indexes.begin(), symbol_indexes.end());
1210 symbol_indexes.erase(std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end());
1211 count = symbol_indexes.size();
1212 SymbolIndicesToSymbolContextList (symbol_indexes, sc_list);
1213 }
1214
1215 return count;
1216}
1217