blob: 9d4d76fb55a1f153beddba189afe658fa4d95795 [file] [log] [blame]
Chris Lattner24943d22010-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"
14#include "lldb/Core/Timer.h"
15#include "lldb/Symbol/ObjectFile.h"
16#include "lldb/Symbol/Symtab.h"
17
18using namespace lldb;
19using namespace lldb_private;
20
21
22
23Symtab::Symtab(ObjectFile *objfile) :
Greg Clayton8d3802d2010-10-08 04:20:14 +000024 m_objfile (objfile),
25 m_symbols (),
26 m_addr_indexes (),
27 m_name_to_index (),
28 m_mutex (Mutex::eMutexTypeRecursive),
29 m_addr_indexes_computed (false),
30 m_name_indexes_computed (false)
Chris Lattner24943d22010-06-08 16:52:24 +000031{
32}
33
34Symtab::~Symtab()
35{
36}
37
38void
39Symtab::Reserve(uint32_t count)
40{
Greg Clayton8d3802d2010-10-08 04:20:14 +000041 // Clients should grab the mutex from this symbol table and lock it manually
42 // when calling this function to avoid performance issues.
Chris Lattner24943d22010-06-08 16:52:24 +000043 m_symbols.reserve (count);
44}
45
46Symbol *
47Symtab::Resize(uint32_t count)
48{
Greg Clayton8d3802d2010-10-08 04:20:14 +000049 // Clients should grab the mutex from this symbol table and lock it manually
50 // when calling this function to avoid performance issues.
Chris Lattner24943d22010-06-08 16:52:24 +000051 m_symbols.resize (count);
52 return &m_symbols[0];
53}
54
55uint32_t
56Symtab::AddSymbol(const Symbol& symbol)
57{
Greg Clayton8d3802d2010-10-08 04:20:14 +000058 // Clients should grab the mutex from this symbol table and lock it manually
59 // when calling this function to avoid performance issues.
Chris Lattner24943d22010-06-08 16:52:24 +000060 uint32_t symbol_idx = m_symbols.size();
61 m_name_to_index.Clear();
62 m_addr_indexes.clear();
63 m_symbols.push_back(symbol);
Greg Clayton8d3802d2010-10-08 04:20:14 +000064 m_addr_indexes_computed = false;
65 m_name_indexes_computed = false;
Chris Lattner24943d22010-06-08 16:52:24 +000066 return symbol_idx;
67}
68
69size_t
70Symtab::GetNumSymbols() const
71{
Greg Clayton8d3802d2010-10-08 04:20:14 +000072 Mutex::Locker locker (m_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +000073 return m_symbols.size();
74}
75
76void
Greg Clayton8d3802d2010-10-08 04:20:14 +000077Symtab::Dump (Stream *s, Target *target, lldb::SortOrder sort_order)
Chris Lattner24943d22010-06-08 16:52:24 +000078{
Greg Clayton8d3802d2010-10-08 04:20:14 +000079 Mutex::Locker locker (m_mutex);
80
Greg Clayton3fed8b92010-10-08 00:21:05 +000081// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
Chris Lattner24943d22010-06-08 16:52:24 +000082 s->Indent();
83 const FileSpec &file_spec = m_objfile->GetFileSpec();
84 const char * object_name = NULL;
85 if (m_objfile->GetModule())
86 object_name = m_objfile->GetModule()->GetObjectName().GetCString();
87
88 if (file_spec)
Greg Clayton8d3802d2010-10-08 04:20:14 +000089 s->Printf("Symtab, file = %s/%s%s%s%s, num_symbols = %u",
Chris Lattner24943d22010-06-08 16:52:24 +000090 file_spec.GetDirectory().AsCString(),
91 file_spec.GetFilename().AsCString(),
92 object_name ? "(" : "",
93 object_name ? object_name : "",
94 object_name ? ")" : "",
95 m_symbols.size());
96 else
Greg Clayton8d3802d2010-10-08 04:20:14 +000097 s->Printf("Symtab, num_symbols = %u", m_symbols.size());
Chris Lattner24943d22010-06-08 16:52:24 +000098
99 if (!m_symbols.empty())
100 {
Greg Clayton8d3802d2010-10-08 04:20:14 +0000101 switch (sort_order)
Chris Lattner24943d22010-06-08 16:52:24 +0000102 {
Greg Clayton8d3802d2010-10-08 04:20:14 +0000103 case eSortOrderNone:
104 {
105 s->PutCString (":\n");
106 DumpSymbolHeader (s);
107 const_iterator begin = m_symbols.begin();
108 const_iterator end = m_symbols.end();
109 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
110 {
111 s->Indent();
112 pos->Dump(s, target, std::distance(begin, pos));
113 }
114 }
115 break;
116
117 case eSortOrderByName:
118 {
119 // Although we maintain a lookup by exact name map, the table
120 // isn't sorted by name. So we must make the ordered symbol list
121 // up ourselves.
122 s->PutCString (" (sorted by name):\n");
123 DumpSymbolHeader (s);
124 typedef std::multimap<const char*, const Symbol *, CStringCompareFunctionObject> CStringToSymbol;
125 CStringToSymbol name_map;
126 for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos)
127 {
128 const char *name = pos->GetMangled().GetName(Mangled::ePreferDemangled).AsCString();
129 if (name && name[0])
130 name_map.insert (std::make_pair(name, &(*pos)));
131 }
132
133 for (CStringToSymbol::const_iterator pos = name_map.begin(), end = name_map.end(); pos != end; ++pos)
134 {
135 s->Indent();
136 pos->second->Dump (s, target, pos->second - &m_symbols[0]);
137 }
138 }
139 break;
140
141 case eSortOrderByAddress:
142 s->PutCString (" (sorted by address):\n");
143 DumpSymbolHeader (s);
144 if (!m_addr_indexes_computed)
145 InitAddressIndexes();
146 const size_t num_symbols = GetNumSymbols();
147 std::vector<uint32_t>::const_iterator pos;
148 std::vector<uint32_t>::const_iterator end = m_addr_indexes.end();
149 for (pos = m_addr_indexes.begin(); pos != end; ++pos)
150 {
151 uint32_t idx = *pos;
152 if (idx < num_symbols)
153 {
154 s->Indent();
155 m_symbols[idx].Dump(s, target, idx);
156 }
157 }
158 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000159 }
160 }
Chris Lattner24943d22010-06-08 16:52:24 +0000161}
162
163void
Greg Claytoneea26402010-09-14 23:36:40 +0000164Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const
Chris Lattner24943d22010-06-08 16:52:24 +0000165{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000166 Mutex::Locker locker (m_mutex);
167
Chris Lattner24943d22010-06-08 16:52:24 +0000168 const size_t num_symbols = GetNumSymbols();
Greg Clayton8d3802d2010-10-08 04:20:14 +0000169 //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
Chris Lattner24943d22010-06-08 16:52:24 +0000170 s->Indent();
171 s->Printf("Symtab %u symbol indexes (%u symbols total):\n", indexes.size(), m_symbols.size());
172 s->IndentMore();
173
174 if (!indexes.empty())
175 {
176 std::vector<uint32_t>::const_iterator pos;
177 std::vector<uint32_t>::const_iterator end = indexes.end();
178 DumpSymbolHeader (s);
179 for (pos = indexes.begin(); pos != end; ++pos)
180 {
181 uint32_t idx = *pos;
182 if (idx < num_symbols)
183 {
184 s->Indent();
Greg Claytoneea26402010-09-14 23:36:40 +0000185 m_symbols[idx].Dump(s, target, idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000186 }
187 }
188 }
189 s->IndentLess ();
190}
191
192void
193Symtab::DumpSymbolHeader (Stream *s)
194{
195 s->Indent(" Debug symbol\n");
196 s->Indent(" |Synthetic symbol\n");
197 s->Indent(" ||Externally Visible\n");
198 s->Indent(" |||\n");
199 s->Indent("Index UserID DSX Type File Address/Value Load Address Size Flags Name\n");
200 s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
201}
202
Greg Clayton0ad086f2010-09-07 17:36:17 +0000203
204static int
205CompareSymbolID (const void *key, const void *p)
206{
207 const user_id_t match_uid = *(user_id_t*) key;
208 const user_id_t symbol_uid = ((Symbol *)p)->GetID();
209 if (match_uid < symbol_uid)
210 return -1;
211 if (match_uid > symbol_uid)
212 return 1;
213 return 0;
214}
215
216Symbol *
217Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const
218{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000219 Mutex::Locker locker (m_mutex);
220
Greg Clayton0ad086f2010-09-07 17:36:17 +0000221 Symbol *symbol = (Symbol*)::bsearch (&symbol_uid,
222 &m_symbols[0],
223 m_symbols.size(),
Greg Clayton637029b2010-09-12 05:25:16 +0000224 (uint8_t *)&m_symbols[1] - (uint8_t *)&m_symbols[0],
Greg Clayton0ad086f2010-09-07 17:36:17 +0000225 CompareSymbolID);
226 return symbol;
227}
228
229
Chris Lattner24943d22010-06-08 16:52:24 +0000230Symbol *
231Symtab::SymbolAtIndex(uint32_t idx)
232{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000233 // Clients should grab the mutex from this symbol table and lock it manually
234 // when calling this function to avoid performance issues.
Chris Lattner24943d22010-06-08 16:52:24 +0000235 if (idx < m_symbols.size())
236 return &m_symbols[idx];
237 return NULL;
238}
239
240
241const Symbol *
242Symtab::SymbolAtIndex(uint32_t idx) const
243{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000244 // Clients should grab the mutex from this symbol table and lock it manually
245 // when calling this function to avoid performance issues.
Chris Lattner24943d22010-06-08 16:52:24 +0000246 if (idx < m_symbols.size())
247 return &m_symbols[idx];
248 return NULL;
249}
250
251//----------------------------------------------------------------------
252// InitNameIndexes
253//----------------------------------------------------------------------
254void
255Symtab::InitNameIndexes()
256{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000257 // Protected function, no need to lock mutex...
258 if (!m_name_indexes_computed)
Chris Lattner24943d22010-06-08 16:52:24 +0000259 {
Greg Clayton8d3802d2010-10-08 04:20:14 +0000260 m_name_indexes_computed = true;
261 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
262 // Create the name index vector to be able to quickly search by name
263 const size_t count = m_symbols.size();
264 assert(m_objfile != NULL);
265 assert(m_objfile->GetModule() != NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000266
Greg Clayton8d3802d2010-10-08 04:20:14 +0000267#if 1
268 m_name_to_index.Reserve (count);
269#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 Lattner24943d22010-06-08 16:52:24 +0000285
Greg Clayton8d3802d2010-10-08 04:20:14 +0000286 m_name_to_index.Reserve (actual_count);
287#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000288
Greg Clayton8d3802d2010-10-08 04:20:14 +0000289 UniqueCStringMap<uint32_t>::Entry entry;
290
291 for (entry.value = 0; entry.value < count; ++entry.value)
292 {
293 const Symbol *symbol = &m_symbols[entry.value];
294
295 // Don't let trampolines get into the lookup by name map
296 // If we ever need the trampoline symbols to be searchable by name
297 // we can remove this and then possibly add a new bool to any of the
298 // Symtab functions that lookup symbols by name to indicate if they
299 // want trampolines.
300 if (symbol->IsTrampoline())
301 continue;
302
303 const Mangled &mangled = symbol->GetMangled();
304 entry.cstring = mangled.GetMangledName().GetCString();
305 if (entry.cstring && entry.cstring[0])
306 m_name_to_index.Append (entry);
307
308 entry.cstring = mangled.GetDemangledName().GetCString();
309 if (entry.cstring && entry.cstring[0])
310 m_name_to_index.Append (entry);
311 }
312 m_name_to_index.Sort();
Chris Lattner24943d22010-06-08 16:52:24 +0000313 }
Chris Lattner24943d22010-06-08 16:52:24 +0000314}
315
316uint32_t
Greg Clayton7c36fa02010-09-11 03:13:28 +0000317Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
Chris Lattner24943d22010-06-08 16:52:24 +0000318{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000319 Mutex::Locker locker (m_mutex);
320
Chris Lattner24943d22010-06-08 16:52:24 +0000321 uint32_t prev_size = indexes.size();
322
323 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
324
325 for (uint32_t i = start_idx; i < count; ++i)
326 {
327 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
328 indexes.push_back(i);
329 }
330
331 return indexes.size() - prev_size;
332}
333
Greg Clayton7c36fa02010-09-11 03:13:28 +0000334uint32_t
335Symtab::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
336{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000337 Mutex::Locker locker (m_mutex);
338
Greg Clayton7c36fa02010-09-11 03:13:28 +0000339 uint32_t prev_size = indexes.size();
340
341 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
342
343 for (uint32_t i = start_idx; i < count; ++i)
344 {
345 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
346 {
347 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
348 indexes.push_back(i);
349 }
350 }
351
352 return indexes.size() - prev_size;
353}
354
355
356uint32_t
357Symtab::GetIndexForSymbol (const Symbol *symbol) const
358{
359 const Symbol *first_symbol = &m_symbols[0];
360 if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
361 return symbol - first_symbol;
362 return UINT32_MAX;
363}
364
Chris Lattner24943d22010-06-08 16:52:24 +0000365struct SymbolSortInfo
366{
367 const bool sort_by_load_addr;
368 const Symbol *symbols;
369};
370
Owen Andersonc3d68552010-06-16 17:34:05 +0000371namespace {
372 struct SymbolIndexComparator {
373 const std::vector<Symbol>& symbols;
374 SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { }
375 bool operator()(uint32_t index_a, uint32_t index_b) {
376 addr_t value_a;
377 addr_t value_b;
378 if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) {
379 value_a = symbols[index_a].GetValue ().GetOffset();
380 value_b = symbols[index_b].GetValue ().GetOffset();
381 } else {
382 value_a = symbols[index_a].GetValue ().GetFileAddress();
383 value_b = symbols[index_b].GetValue ().GetFileAddress();
384 }
Chris Lattner24943d22010-06-08 16:52:24 +0000385
Owen Andersonc3d68552010-06-16 17:34:05 +0000386 if (value_a == value_b) {
387 // The if the values are equal, use the original symbol user ID
388 lldb::user_id_t uid_a = symbols[index_a].GetID();
389 lldb::user_id_t uid_b = symbols[index_b].GetID();
390 if (uid_a < uid_b)
391 return true;
392 if (uid_a > uid_b)
393 return false;
394 return false;
395 } else if (value_a < value_b)
396 return true;
397
398 return false;
399 }
400 };
Eli Friedman020f3532010-06-10 23:36:31 +0000401}
402
Chris Lattner24943d22010-06-08 16:52:24 +0000403void
404Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
405{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000406 Mutex::Locker locker (m_mutex);
407
Owen Andersonc3d68552010-06-16 17:34:05 +0000408 Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
Chris Lattner24943d22010-06-08 16:52:24 +0000409 // No need to sort if we have zero or one items...
410 if (indexes.size() <= 1)
411 return;
412
Owen Andersona1e14752010-06-17 00:51:12 +0000413 // Sort the indexes in place using std::stable_sort.
414 // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
415 // not correctness. The indexes vector tends to be "close" to sorted, which the
416 // stable sort handles better.
Owen Andersonc3d68552010-06-16 17:34:05 +0000417 std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols));
Chris Lattner24943d22010-06-08 16:52:24 +0000418
419 // Remove any duplicates if requested
420 if (remove_duplicates)
421 std::unique(indexes.begin(), indexes.end());
422}
423
424uint32_t
Greg Clayton7c36fa02010-09-11 03:13:28 +0000425Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
Chris Lattner24943d22010-06-08 16:52:24 +0000426{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000427 Mutex::Locker locker (m_mutex);
428
Chris Lattner24943d22010-06-08 16:52:24 +0000429 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
430 if (symbol_name)
431 {
432 const size_t old_size = indexes.size();
Greg Clayton8d3802d2010-10-08 04:20:14 +0000433 if (!m_name_indexes_computed)
Chris Lattner24943d22010-06-08 16:52:24 +0000434 InitNameIndexes();
435
436 const char *symbol_cstr = symbol_name.GetCString();
437 const UniqueCStringMap<uint32_t>::Entry *entry_ptr;
Greg Clayton8d3802d2010-10-08 04:20:14 +0000438
Chris Lattner24943d22010-06-08 16:52:24 +0000439 for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr);
440 entry_ptr!= NULL;
441 entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr))
442 {
443 indexes.push_back (entry_ptr->value);
444 }
445 return indexes.size() - old_size;
446 }
447 return 0;
448}
449
450uint32_t
Greg Clayton7c36fa02010-09-11 03:13:28 +0000451Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
452{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000453 Mutex::Locker locker (m_mutex);
454
Greg Clayton7c36fa02010-09-11 03:13:28 +0000455 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
456 if (symbol_name)
457 {
458 const size_t old_size = indexes.size();
Greg Clayton8d3802d2010-10-08 04:20:14 +0000459 if (!m_name_indexes_computed)
Greg Clayton7c36fa02010-09-11 03:13:28 +0000460 InitNameIndexes();
461
462 const char *symbol_cstr = symbol_name.GetCString();
463 const UniqueCStringMap<uint32_t>::Entry *entry_ptr;
464 for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr);
465 entry_ptr!= NULL;
466 entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr))
467 {
468 if (CheckSymbolAtIndex(entry_ptr->value, symbol_debug_type, symbol_visibility))
469 indexes.push_back (entry_ptr->value);
470 }
471 return indexes.size() - old_size;
472 }
473 return 0;
474}
475
476uint32_t
477Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
Chris Lattner24943d22010-06-08 16:52:24 +0000478{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000479 Mutex::Locker locker (m_mutex);
480
Chris Lattner24943d22010-06-08 16:52:24 +0000481 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
482 {
483 std::vector<uint32_t>::iterator pos = indexes.begin();
484 while (pos != indexes.end())
485 {
486 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
487 ++pos;
488 else
489 indexes.erase(pos);
490 }
491 }
492 return indexes.size();
493}
494
495uint32_t
Greg Clayton7c36fa02010-09-11 03:13:28 +0000496Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
497{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000498 Mutex::Locker locker (m_mutex);
499
Greg Clayton7c36fa02010-09-11 03:13:28 +0000500 if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
501 {
502 std::vector<uint32_t>::iterator pos = indexes.begin();
503 while (pos != indexes.end())
504 {
505 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
506 ++pos;
507 else
508 indexes.erase(pos);
509 }
510 }
511 return indexes.size();
512}
513
514
515uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000516Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
517{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000518 Mutex::Locker locker (m_mutex);
519
Chris Lattner24943d22010-06-08 16:52:24 +0000520 uint32_t prev_size = indexes.size();
521 uint32_t sym_end = m_symbols.size();
522
523 for (int i = 0; i < sym_end; i++)
524 {
525 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
526 {
527 const char *name = m_symbols[i].GetMangled().GetName().AsCString();
528 if (name)
529 {
530 if (regexp.Execute (name))
531 indexes.push_back(i);
532 }
533 }
534 }
535 return indexes.size() - prev_size;
536
537}
538
Greg Clayton7c36fa02010-09-11 03:13:28 +0000539uint32_t
540Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
Chris Lattner24943d22010-06-08 16:52:24 +0000541{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000542 Mutex::Locker locker (m_mutex);
543
Greg Clayton7c36fa02010-09-11 03:13:28 +0000544 uint32_t prev_size = indexes.size();
545 uint32_t sym_end = m_symbols.size();
546
547 for (int i = 0; i < sym_end; i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000548 {
Greg Clayton7c36fa02010-09-11 03:13:28 +0000549 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
Chris Lattner24943d22010-06-08 16:52:24 +0000550 {
Greg Clayton7c36fa02010-09-11 03:13:28 +0000551 if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
552 continue;
553
554 const char *name = m_symbols[i].GetMangled().GetName().AsCString();
555 if (name)
556 {
557 if (regexp.Execute (name))
558 indexes.push_back(i);
559 }
Chris Lattner24943d22010-06-08 16:52:24 +0000560 }
561 }
Greg Clayton7c36fa02010-09-11 03:13:28 +0000562 return indexes.size() - prev_size;
563
Chris Lattner24943d22010-06-08 16:52:24 +0000564}
565
Greg Clayton7c36fa02010-09-11 03:13:28 +0000566Symbol *
567Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000568{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000569 Mutex::Locker locker (m_mutex);
570
Chris Lattner24943d22010-06-08 16:52:24 +0000571 const size_t count = m_symbols.size();
572 for (uint32_t idx = start_idx; idx < count; ++idx)
573 {
574 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
575 {
Greg Clayton7c36fa02010-09-11 03:13:28 +0000576 if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
577 {
578 start_idx = idx;
579 return &m_symbols[idx];
580 }
Chris Lattner24943d22010-06-08 16:52:24 +0000581 }
582 }
583 return NULL;
584}
585
586size_t
587Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
588{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000589 Mutex::Locker locker (m_mutex);
590
Chris Lattner24943d22010-06-08 16:52:24 +0000591 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
592 // Initialize all of the lookup by name indexes before converting NAME
593 // to a uniqued string NAME_STR below.
Greg Clayton8d3802d2010-10-08 04:20:14 +0000594 if (!m_name_indexes_computed)
Chris Lattner24943d22010-06-08 16:52:24 +0000595 InitNameIndexes();
596
597 if (name)
598 {
599 // The string table did have a string that matched, but we need
600 // to check the symbols and match the symbol_type if any was given.
Greg Clayton7c36fa02010-09-11 03:13:28 +0000601 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
Chris Lattner24943d22010-06-08 16:52:24 +0000602 }
603 return symbol_indexes.size();
604}
605
606size_t
Greg Clayton7c36fa02010-09-11 03:13:28 +0000607Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
Chris Lattner24943d22010-06-08 16:52:24 +0000608{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000609 Mutex::Locker locker (m_mutex);
610
Greg Clayton7c36fa02010-09-11 03:13:28 +0000611 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
612 // Initialize all of the lookup by name indexes before converting NAME
613 // to a uniqued string NAME_STR below.
Greg Clayton8d3802d2010-10-08 04:20:14 +0000614 if (!m_name_indexes_computed)
Greg Clayton7c36fa02010-09-11 03:13:28 +0000615 InitNameIndexes();
616
617 if (name)
618 {
619 // The string table did have a string that matched, but we need
620 // to check the symbols and match the symbol_type if any was given.
621 AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
622 }
623 return symbol_indexes.size();
624}
625
626size_t
627Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
628{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000629 Mutex::Locker locker (m_mutex);
630
Greg Clayton7c36fa02010-09-11 03:13:28 +0000631 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
Chris Lattner24943d22010-06-08 16:52:24 +0000632 return symbol_indexes.size();
633}
634
635Symbol *
Greg Clayton7c36fa02010-09-11 03:13:28 +0000636Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
Chris Lattner24943d22010-06-08 16:52:24 +0000637{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000638 Mutex::Locker locker (m_mutex);
639
Chris Lattner24943d22010-06-08 16:52:24 +0000640 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
Greg Clayton8d3802d2010-10-08 04:20:14 +0000641 if (!m_name_indexes_computed)
Chris Lattner24943d22010-06-08 16:52:24 +0000642 InitNameIndexes();
643
644 if (name)
645 {
646 std::vector<uint32_t> matching_indexes;
647 // The string table did have a string that matched, but we need
648 // to check the symbols and match the symbol_type if any was given.
Greg Clayton7c36fa02010-09-11 03:13:28 +0000649 if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
Chris Lattner24943d22010-06-08 16:52:24 +0000650 {
651 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
652 for (pos = matching_indexes.begin(); pos != end; ++pos)
653 {
654 Symbol *symbol = SymbolAtIndex(*pos);
655
656 if (symbol->Compare(name, symbol_type))
657 return symbol;
658 }
659 }
660 }
661 return NULL;
662}
663
664typedef struct
665{
666 const Symtab *symtab;
667 const addr_t file_addr;
668 Symbol *match_symbol;
669 const uint32_t *match_index_ptr;
670 addr_t match_offset;
671} SymbolSearchInfo;
672
673static int
674SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
675{
676 const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
677 if (curr_symbol == NULL)
678 return -1;
679
680 const addr_t info_file_addr = info->file_addr;
681
682 // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
683 // range if the symbol has a section!
684 const AddressRange *curr_range = curr_symbol->GetAddressRangePtr();
685 if (curr_range)
686 {
687 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
688 if (info_file_addr < curr_file_addr)
689 return -1;
690 if (info_file_addr > curr_file_addr)
691 return +1;
692 info->match_symbol = const_cast<Symbol *>(curr_symbol);
693 info->match_index_ptr = index_ptr;
694 return 0;
695 }
696
697 return -1;
698}
699
700static int
701SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
702{
703 const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
704 if (symbol == NULL)
705 return -1;
706
707 const addr_t info_file_addr = info->file_addr;
708 const AddressRange *curr_range = symbol->GetAddressRangePtr();
709 if (curr_range)
710 {
711 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
712 if (info_file_addr < curr_file_addr)
713 return -1;
714
715 // Since we are finding the closest symbol that is greater than or equal
716 // to 'info->file_addr' we set the symbol here. This will get set
717 // multiple times, but after the search is done it will contain the best
718 // symbol match
719 info->match_symbol = const_cast<Symbol *>(symbol);
720 info->match_index_ptr = index_ptr;
721 info->match_offset = info_file_addr - curr_file_addr;
722
723 if (info_file_addr > curr_file_addr)
724 return +1;
725 return 0;
726 }
727 return -1;
728}
729
730static SymbolSearchInfo
731FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
732{
733 SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
734 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
735 return info;
736}
737
738
739void
740Symtab::InitAddressIndexes()
741{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000742 // Protected function, no need to lock mutex...
743 if (!m_addr_indexes_computed && !m_symbols.empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000744 {
Greg Clayton8d3802d2010-10-08 04:20:14 +0000745 m_addr_indexes_computed = true;
746#if 0
747 // The old was to add only code, trampoline or data symbols...
Chris Lattner24943d22010-06-08 16:52:24 +0000748 AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes);
749 AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes);
750 AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes);
Greg Clayton8d3802d2010-10-08 04:20:14 +0000751#else
752 // The new way adds all symbols with valid addresses that are section
753 // offset.
754 const_iterator begin = m_symbols.begin();
755 const_iterator end = m_symbols.end();
756 for (const_iterator pos = m_symbols.begin(); pos != end; ++pos)
757 {
758 if (pos->GetAddressRangePtr())
759 m_addr_indexes.push_back (std::distance(begin, pos));
760 }
761#endif
762 SortSymbolIndexesByValue (m_addr_indexes, false);
763 m_addr_indexes.push_back (UINT32_MAX); // Terminator for bsearch since we might need to look at the next symbol
Chris Lattner24943d22010-06-08 16:52:24 +0000764 }
765}
766
767size_t
768Symtab::CalculateSymbolSize (Symbol *symbol)
769{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000770 Mutex::Locker locker (m_mutex);
771
Greg Clayton53d68e72010-07-20 22:52:08 +0000772 if (m_symbols.empty())
773 return 0;
774
Chris Lattner24943d22010-06-08 16:52:24 +0000775 // Make sure this symbol is from this symbol table...
Greg Clayton53d68e72010-07-20 22:52:08 +0000776 if (symbol < &m_symbols.front() || symbol > &m_symbols.back())
Chris Lattner24943d22010-06-08 16:52:24 +0000777 return 0;
778
779 // See if this symbol already has a byte size?
780 size_t byte_size = symbol->GetByteSize();
781
782 if (byte_size)
783 {
784 // It does, just return it
785 return byte_size;
786 }
787
788 // Else if this is an address based symbol, figure out the delta between
789 // it and the next address based symbol
790 if (symbol->GetAddressRangePtr())
791 {
Greg Clayton8d3802d2010-10-08 04:20:14 +0000792 if (!m_addr_indexes_computed)
Chris Lattner24943d22010-06-08 16:52:24 +0000793 InitAddressIndexes();
794 const size_t num_addr_indexes = m_addr_indexes.size();
Greg Clayton53d68e72010-07-20 22:52:08 +0000795 SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), &m_addr_indexes.front(), num_addr_indexes);
Chris Lattner24943d22010-06-08 16:52:24 +0000796 if (info.match_index_ptr != NULL)
797 {
798 const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
799 // We can figure out the address range of all symbols except the
800 // last one by taking the delta between the current symbol and
801 // the next symbol
802
Greg Clayton53d68e72010-07-20 22:52:08 +0000803 for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000804 addr_index < num_addr_indexes;
805 ++addr_index)
806 {
807 Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
808 if (next_symbol == NULL)
809 break;
810
811 assert (next_symbol->GetAddressRangePtr());
812 const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
813 if (next_file_addr > curr_file_addr)
814 {
815 byte_size = next_file_addr - curr_file_addr;
816 symbol->GetAddressRangePtr()->SetByteSize(byte_size);
817 symbol->SetSizeIsSynthesized(true);
818 break;
819 }
820 }
821 }
822 }
823 return byte_size;
824}
825
826Symbol *
827Symtab::FindSymbolWithFileAddress (addr_t file_addr)
828{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000829 Mutex::Locker locker (m_mutex);
830
831 if (!m_addr_indexes_computed)
Chris Lattner24943d22010-06-08 16:52:24 +0000832 InitAddressIndexes();
833
834 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
835
836 uint32_t* match = (uint32_t*)bsearch(&info, &m_addr_indexes[0], m_addr_indexes.size(), sizeof(uint32_t), (comparison_function)SymbolWithFileAddress);
837 if (match)
838 return SymbolAtIndex (*match);
839 return NULL;
840}
841
842
843Symbol *
844Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
845{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000846 Mutex::Locker locker (m_mutex);
847
Chris Lattner24943d22010-06-08 16:52:24 +0000848 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
849
850 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
851
852 if (info.match_symbol)
853 {
Greg Clayton3fed8b92010-10-08 00:21:05 +0000854 if (info.match_offset == 0)
855 {
856 // We found an exact match!
857 return info.match_symbol;
858 }
859
860 const size_t symbol_byte_size = CalculateSymbolSize(info.match_symbol);
861
862 if (symbol_byte_size == 0)
863 {
864 // We weren't able to find the size of the symbol so lets just go
865 // with that match we found in our search...
866 return info.match_symbol;
867 }
868
869 // We were able to figure out a symbol size so lets make sure our
870 // offset puts "file_addr" in the symbol's address range.
871 if (info.match_offset < symbol_byte_size)
Chris Lattner24943d22010-06-08 16:52:24 +0000872 return info.match_symbol;
873 }
874 return NULL;
875}
876
877Symbol *
878Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
879{
Greg Clayton8d3802d2010-10-08 04:20:14 +0000880 Mutex::Locker locker (m_mutex);
881
882 if (!m_addr_indexes_computed)
Chris Lattner24943d22010-06-08 16:52:24 +0000883 InitAddressIndexes();
884
885 return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
886}
887