blob: 7cb76106c340eb68577bd4c8e39c3174eb83e007 [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) :
24 m_objfile(objfile),
25 m_symbols(),
26 m_addr_indexes(),
27 m_name_to_index()
28{
29}
30
31Symtab::~Symtab()
32{
33}
34
35void
36Symtab::Reserve(uint32_t count)
37{
38 m_symbols.reserve (count);
39}
40
41Symbol *
42Symtab::Resize(uint32_t count)
43{
44 m_symbols.resize (count);
45 return &m_symbols[0];
46}
47
48uint32_t
49Symtab::AddSymbol(const Symbol& symbol)
50{
51 uint32_t symbol_idx = m_symbols.size();
52 m_name_to_index.Clear();
53 m_addr_indexes.clear();
54 m_symbols.push_back(symbol);
55 return symbol_idx;
56}
57
58size_t
59Symtab::GetNumSymbols() const
60{
61 return m_symbols.size();
62}
63
64void
65Symtab::Dump(Stream *s, Process *process) const
66{
67 const_iterator pos;
68 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
69 s->Indent();
70 const FileSpec &file_spec = m_objfile->GetFileSpec();
71 const char * object_name = NULL;
72 if (m_objfile->GetModule())
73 object_name = m_objfile->GetModule()->GetObjectName().GetCString();
74
75 if (file_spec)
76 s->Printf("Symtab, file = %s/%s%s%s%s, num_symbols = %u:\n",
77 file_spec.GetDirectory().AsCString(),
78 file_spec.GetFilename().AsCString(),
79 object_name ? "(" : "",
80 object_name ? object_name : "",
81 object_name ? ")" : "",
82 m_symbols.size());
83 else
84 s->Printf("Symtab, num_symbols = %u:\n", m_symbols.size());
85 s->IndentMore();
86
87 if (!m_symbols.empty())
88 {
89 const_iterator begin = m_symbols.begin();
90 const_iterator end = m_symbols.end();
91 DumpSymbolHeader (s);
92 for (pos = m_symbols.begin(); pos != end; ++pos)
93 {
94 s->Indent();
95 pos->Dump(s, process, std::distance(begin, pos));
96 }
97 }
98 s->IndentLess ();
99}
100
101void
102Symtab::Dump(Stream *s, Process *process, std::vector<uint32_t>& indexes) const
103{
104 const size_t num_symbols = GetNumSymbols();
105 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
106 s->Indent();
107 s->Printf("Symtab %u symbol indexes (%u symbols total):\n", indexes.size(), m_symbols.size());
108 s->IndentMore();
109
110 if (!indexes.empty())
111 {
112 std::vector<uint32_t>::const_iterator pos;
113 std::vector<uint32_t>::const_iterator end = indexes.end();
114 DumpSymbolHeader (s);
115 for (pos = indexes.begin(); pos != end; ++pos)
116 {
117 uint32_t idx = *pos;
118 if (idx < num_symbols)
119 {
120 s->Indent();
121 m_symbols[idx].Dump(s, process, idx);
122 }
123 }
124 }
125 s->IndentLess ();
126}
127
128void
129Symtab::DumpSymbolHeader (Stream *s)
130{
131 s->Indent(" Debug symbol\n");
132 s->Indent(" |Synthetic symbol\n");
133 s->Indent(" ||Externally Visible\n");
134 s->Indent(" |||\n");
135 s->Indent("Index UserID DSX Type File Address/Value Load Address Size Flags Name\n");
136 s->Indent("------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------\n");
137}
138
139Symbol *
140Symtab::SymbolAtIndex(uint32_t idx)
141{
142 if (idx < m_symbols.size())
143 return &m_symbols[idx];
144 return NULL;
145}
146
147
148const Symbol *
149Symtab::SymbolAtIndex(uint32_t idx) const
150{
151 if (idx < m_symbols.size())
152 return &m_symbols[idx];
153 return NULL;
154}
155
156//----------------------------------------------------------------------
157// InitNameIndexes
158//----------------------------------------------------------------------
159void
160Symtab::InitNameIndexes()
161{
162 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
163 // Create the name index vector to be able to quickly search by name
164 const size_t count = m_symbols.size();
165 assert(m_objfile != NULL);
166 assert(m_objfile->GetModule() != NULL);
167 m_name_to_index.Reserve (count);
168
169 UniqueCStringMap<uint32_t>::Entry entry;
170
171 for (entry.value = 0; entry.value < count; ++entry.value)
172 {
173 const Symbol *symbol = &m_symbols[entry.value];
174
175 // Don't let trampolines get into the lookup by name map
176 // If we ever need the trampoline symbols to be searchable by name
177 // we can remove this and then possibly add a new bool to any of the
178 // Symtab functions that lookup symbols by name to indicate if they
179 // want trampolines.
180 if (symbol->IsTrampoline())
181 continue;
182
183 const Mangled &mangled = symbol->GetMangled();
184 entry.cstring = mangled.GetMangledName().GetCString();
185 if (entry.cstring && entry.cstring[0])
186 m_name_to_index.Append (entry);
187
188 entry.cstring = mangled.GetDemangledName().GetCString();
189 if (entry.cstring && entry.cstring[0])
190 m_name_to_index.Append (entry);
191 }
192 m_name_to_index.Sort();
193}
194
195uint32_t
196Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
197{
198 uint32_t prev_size = indexes.size();
199
200 const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
201
202 for (uint32_t i = start_idx; i < count; ++i)
203 {
204 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
205 indexes.push_back(i);
206 }
207
208 return indexes.size() - prev_size;
209}
210
211struct SymbolSortInfo
212{
213 const bool sort_by_load_addr;
214 const Symbol *symbols;
215};
216
Owen Andersonc3d68552010-06-16 17:34:05 +0000217namespace {
218 struct SymbolIndexComparator {
219 const std::vector<Symbol>& symbols;
220 SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { }
221 bool operator()(uint32_t index_a, uint32_t index_b) {
222 addr_t value_a;
223 addr_t value_b;
224 if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) {
225 value_a = symbols[index_a].GetValue ().GetOffset();
226 value_b = symbols[index_b].GetValue ().GetOffset();
227 } else {
228 value_a = symbols[index_a].GetValue ().GetFileAddress();
229 value_b = symbols[index_b].GetValue ().GetFileAddress();
230 }
Chris Lattner24943d22010-06-08 16:52:24 +0000231
Owen Andersonc3d68552010-06-16 17:34:05 +0000232 if (value_a == value_b) {
233 // The if the values are equal, use the original symbol user ID
234 lldb::user_id_t uid_a = symbols[index_a].GetID();
235 lldb::user_id_t uid_b = symbols[index_b].GetID();
236 if (uid_a < uid_b)
237 return true;
238 if (uid_a > uid_b)
239 return false;
240 return false;
241 } else if (value_a < value_b)
242 return true;
243
244 return false;
245 }
246 };
Eli Friedman020f3532010-06-10 23:36:31 +0000247}
248
Chris Lattner24943d22010-06-08 16:52:24 +0000249void
250Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
251{
Owen Andersonc3d68552010-06-16 17:34:05 +0000252 Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
Chris Lattner24943d22010-06-08 16:52:24 +0000253 // No need to sort if we have zero or one items...
254 if (indexes.size() <= 1)
255 return;
256
Owen Andersona1e14752010-06-17 00:51:12 +0000257 // Sort the indexes in place using std::stable_sort.
258 // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
259 // not correctness. The indexes vector tends to be "close" to sorted, which the
260 // stable sort handles better.
Owen Andersonc3d68552010-06-16 17:34:05 +0000261 std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols));
Chris Lattner24943d22010-06-08 16:52:24 +0000262
263 // Remove any duplicates if requested
264 if (remove_duplicates)
265 std::unique(indexes.begin(), indexes.end());
266}
267
268uint32_t
269Symtab::AppendSymbolIndexesWithName(const ConstString& symbol_name, std::vector<uint32_t>& indexes)
270{
271 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
272 if (symbol_name)
273 {
274 const size_t old_size = indexes.size();
275 if (m_name_to_index.IsEmpty())
276 InitNameIndexes();
277
278 const char *symbol_cstr = symbol_name.GetCString();
279 const UniqueCStringMap<uint32_t>::Entry *entry_ptr;
280 for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr);
281 entry_ptr!= NULL;
282 entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr))
283 {
284 indexes.push_back (entry_ptr->value);
285 }
286 return indexes.size() - old_size;
287 }
288 return 0;
289}
290
291uint32_t
292Symtab::AppendSymbolIndexesWithNameAndType(const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
293{
294 if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
295 {
296 std::vector<uint32_t>::iterator pos = indexes.begin();
297 while (pos != indexes.end())
298 {
299 if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
300 ++pos;
301 else
302 indexes.erase(pos);
303 }
304 }
305 return indexes.size();
306}
307
308uint32_t
309Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
310{
311 uint32_t prev_size = indexes.size();
312 uint32_t sym_end = m_symbols.size();
313
314 for (int i = 0; i < sym_end; i++)
315 {
316 if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
317 {
318 const char *name = m_symbols[i].GetMangled().GetName().AsCString();
319 if (name)
320 {
321 if (regexp.Execute (name))
322 indexes.push_back(i);
323 }
324 }
325 }
326 return indexes.size() - prev_size;
327
328}
329
330Symbol *
331Symtab::FindSymbolWithType(SymbolType symbol_type, uint32_t& start_idx)
332{
333 const size_t count = m_symbols.size();
334 for (uint32_t idx = start_idx; idx < count; ++idx)
335 {
336 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
337 {
338 start_idx = idx;
339 return &m_symbols[idx];
340 }
341 }
342 return NULL;
343}
344
345const Symbol *
346Symtab::FindSymbolWithType(SymbolType symbol_type, uint32_t& start_idx) const
347{
348 const size_t count = m_symbols.size();
349 for (uint32_t idx = start_idx; idx < count; ++idx)
350 {
351 if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
352 {
353 start_idx = idx;
354 return &m_symbols[idx];
355 }
356 }
357 return NULL;
358}
359
360size_t
361Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
362{
363 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
364 // Initialize all of the lookup by name indexes before converting NAME
365 // to a uniqued string NAME_STR below.
366 if (m_name_to_index.IsEmpty())
367 InitNameIndexes();
368
369 if (name)
370 {
371 // The string table did have a string that matched, but we need
372 // to check the symbols and match the symbol_type if any was given.
373 AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes);
374 }
375 return symbol_indexes.size();
376}
377
378size_t
379Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
380{
381 AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_indexes);
382 return symbol_indexes.size();
383}
384
385Symbol *
386Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type)
387{
388 Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
389 if (m_name_to_index.IsEmpty())
390 InitNameIndexes();
391
392 if (name)
393 {
394 std::vector<uint32_t> matching_indexes;
395 // The string table did have a string that matched, but we need
396 // to check the symbols and match the symbol_type if any was given.
397 if (AppendSymbolIndexesWithNameAndType(name, symbol_type, matching_indexes))
398 {
399 std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
400 for (pos = matching_indexes.begin(); pos != end; ++pos)
401 {
402 Symbol *symbol = SymbolAtIndex(*pos);
403
404 if (symbol->Compare(name, symbol_type))
405 return symbol;
406 }
407 }
408 }
409 return NULL;
410}
411
412typedef struct
413{
414 const Symtab *symtab;
415 const addr_t file_addr;
416 Symbol *match_symbol;
417 const uint32_t *match_index_ptr;
418 addr_t match_offset;
419} SymbolSearchInfo;
420
421static int
422SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
423{
424 const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
425 if (curr_symbol == NULL)
426 return -1;
427
428 const addr_t info_file_addr = info->file_addr;
429
430 // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
431 // range if the symbol has a section!
432 const AddressRange *curr_range = curr_symbol->GetAddressRangePtr();
433 if (curr_range)
434 {
435 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
436 if (info_file_addr < curr_file_addr)
437 return -1;
438 if (info_file_addr > curr_file_addr)
439 return +1;
440 info->match_symbol = const_cast<Symbol *>(curr_symbol);
441 info->match_index_ptr = index_ptr;
442 return 0;
443 }
444
445 return -1;
446}
447
448static int
449SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
450{
451 const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
452 if (symbol == NULL)
453 return -1;
454
455 const addr_t info_file_addr = info->file_addr;
456 const AddressRange *curr_range = symbol->GetAddressRangePtr();
457 if (curr_range)
458 {
459 const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
460 if (info_file_addr < curr_file_addr)
461 return -1;
462
463 // Since we are finding the closest symbol that is greater than or equal
464 // to 'info->file_addr' we set the symbol here. This will get set
465 // multiple times, but after the search is done it will contain the best
466 // symbol match
467 info->match_symbol = const_cast<Symbol *>(symbol);
468 info->match_index_ptr = index_ptr;
469 info->match_offset = info_file_addr - curr_file_addr;
470
471 if (info_file_addr > curr_file_addr)
472 return +1;
473 return 0;
474 }
475 return -1;
476}
477
478static SymbolSearchInfo
479FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
480{
481 SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
482 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
483 return info;
484}
485
486
487void
488Symtab::InitAddressIndexes()
489{
490 if (m_addr_indexes.empty())
491 {
492 AppendSymbolIndexesWithType (eSymbolTypeFunction, m_addr_indexes);
493 AppendSymbolIndexesWithType (eSymbolTypeGlobal, m_addr_indexes);
494 AppendSymbolIndexesWithType (eSymbolTypeStatic, m_addr_indexes);
495 AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes);
496 AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes);
497 AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes);
498 SortSymbolIndexesByValue(m_addr_indexes, true);
499 m_addr_indexes.push_back(UINT32_MAX); // Terminator for bsearch since we might need to look at the next symbol
500 }
501}
502
503size_t
504Symtab::CalculateSymbolSize (Symbol *symbol)
505{
Greg Clayton53d68e72010-07-20 22:52:08 +0000506 if (m_symbols.empty())
507 return 0;
508
Chris Lattner24943d22010-06-08 16:52:24 +0000509 // Make sure this symbol is from this symbol table...
Greg Clayton53d68e72010-07-20 22:52:08 +0000510 if (symbol < &m_symbols.front() || symbol > &m_symbols.back())
Chris Lattner24943d22010-06-08 16:52:24 +0000511 return 0;
512
513 // See if this symbol already has a byte size?
514 size_t byte_size = symbol->GetByteSize();
515
516 if (byte_size)
517 {
518 // It does, just return it
519 return byte_size;
520 }
521
522 // Else if this is an address based symbol, figure out the delta between
523 // it and the next address based symbol
524 if (symbol->GetAddressRangePtr())
525 {
526 if (m_addr_indexes.empty())
527 InitAddressIndexes();
528 const size_t num_addr_indexes = m_addr_indexes.size();
Greg Clayton53d68e72010-07-20 22:52:08 +0000529 SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), &m_addr_indexes.front(), num_addr_indexes);
Chris Lattner24943d22010-06-08 16:52:24 +0000530 if (info.match_index_ptr != NULL)
531 {
532 const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
533 // We can figure out the address range of all symbols except the
534 // last one by taking the delta between the current symbol and
535 // the next symbol
536
Greg Clayton53d68e72010-07-20 22:52:08 +0000537 for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000538 addr_index < num_addr_indexes;
539 ++addr_index)
540 {
541 Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
542 if (next_symbol == NULL)
543 break;
544
545 assert (next_symbol->GetAddressRangePtr());
546 const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
547 if (next_file_addr > curr_file_addr)
548 {
549 byte_size = next_file_addr - curr_file_addr;
550 symbol->GetAddressRangePtr()->SetByteSize(byte_size);
551 symbol->SetSizeIsSynthesized(true);
552 break;
553 }
554 }
555 }
556 }
557 return byte_size;
558}
559
560Symbol *
561Symtab::FindSymbolWithFileAddress (addr_t file_addr)
562{
563 if (m_addr_indexes.empty())
564 InitAddressIndexes();
565
566 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
567
568 uint32_t* match = (uint32_t*)bsearch(&info, &m_addr_indexes[0], m_addr_indexes.size(), sizeof(uint32_t), (comparison_function)SymbolWithFileAddress);
569 if (match)
570 return SymbolAtIndex (*match);
571 return NULL;
572}
573
574
575Symbol *
576Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
577{
578 SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
579
580 bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
581
582 if (info.match_symbol)
583 {
584 if (info.match_offset < CalculateSymbolSize(info.match_symbol))
585 return info.match_symbol;
586 }
587 return NULL;
588}
589
590Symbol *
591Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
592{
593 if (m_addr_indexes.empty())
594 InitAddressIndexes();
595
596 return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
597}
598