Symtab.cpp revision 3fed8b9b2696fc2ea78005c8f9b1c621d5748042
1//===-- 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, Target *target) 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, target, std::distance(begin, pos));
96        }
97    }
98    s->IndentLess ();
99}
100
101void
102Symtab::Dump(Stream *s, Target *target, 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, target, 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
139
140static int
141CompareSymbolID (const void *key, const void *p)
142{
143    const user_id_t match_uid = *(user_id_t*) key;
144    const user_id_t symbol_uid = ((Symbol *)p)->GetID();
145    if (match_uid < symbol_uid)
146        return -1;
147    if (match_uid > symbol_uid)
148        return 1;
149    return 0;
150}
151
152Symbol *
153Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const
154{
155    Symbol *symbol = (Symbol*)::bsearch (&symbol_uid,
156                                         &m_symbols[0],
157                                         m_symbols.size(),
158                                         (uint8_t *)&m_symbols[1] - (uint8_t *)&m_symbols[0],
159                                         CompareSymbolID);
160    return symbol;
161}
162
163
164Symbol *
165Symtab::SymbolAtIndex(uint32_t idx)
166{
167    if (idx < m_symbols.size())
168        return &m_symbols[idx];
169    return NULL;
170}
171
172
173const Symbol *
174Symtab::SymbolAtIndex(uint32_t idx) const
175{
176    if (idx < m_symbols.size())
177        return &m_symbols[idx];
178    return NULL;
179}
180
181//----------------------------------------------------------------------
182// InitNameIndexes
183//----------------------------------------------------------------------
184void
185Symtab::InitNameIndexes()
186{
187    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
188    // Create the name index vector to be able to quickly search by name
189    const size_t count = m_symbols.size();
190    assert(m_objfile != NULL);
191    assert(m_objfile->GetModule() != NULL);
192    m_name_to_index.Reserve (count);
193
194    UniqueCStringMap<uint32_t>::Entry entry;
195
196    for (entry.value = 0; entry.value < count; ++entry.value)
197    {
198        const Symbol *symbol = &m_symbols[entry.value];
199
200        // Don't let trampolines get into the lookup by name map
201        // If we ever need the trampoline symbols to be searchable by name
202        // we can remove this and then possibly add a new bool to any of the
203        // Symtab functions that lookup symbols by name to indicate if they
204        // want trampolines.
205        if (symbol->IsTrampoline())
206            continue;
207
208        const Mangled &mangled = symbol->GetMangled();
209        entry.cstring = mangled.GetMangledName().GetCString();
210        if (entry.cstring && entry.cstring[0])
211            m_name_to_index.Append (entry);
212
213        entry.cstring = mangled.GetDemangledName().GetCString();
214        if (entry.cstring && entry.cstring[0])
215            m_name_to_index.Append (entry);
216    }
217    m_name_to_index.Sort();
218}
219
220uint32_t
221Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const
222{
223    uint32_t prev_size = indexes.size();
224
225    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
226
227    for (uint32_t i = start_idx; i < count; ++i)
228    {
229        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
230            indexes.push_back(i);
231    }
232
233    return indexes.size() - prev_size;
234}
235
236uint32_t
237Symtab::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
238{
239    uint32_t prev_size = indexes.size();
240
241    const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index);
242
243    for (uint32_t i = start_idx; i < count; ++i)
244    {
245        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
246        {
247            if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
248                indexes.push_back(i);
249        }
250    }
251
252    return indexes.size() - prev_size;
253}
254
255
256uint32_t
257Symtab::GetIndexForSymbol (const Symbol *symbol) const
258{
259    const Symbol *first_symbol = &m_symbols[0];
260    if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size())
261        return symbol - first_symbol;
262    return UINT32_MAX;
263}
264
265struct SymbolSortInfo
266{
267    const bool sort_by_load_addr;
268    const Symbol *symbols;
269};
270
271namespace {
272    struct SymbolIndexComparator {
273        const std::vector<Symbol>& symbols;
274        SymbolIndexComparator(const std::vector<Symbol>& s) : symbols(s) { }
275        bool operator()(uint32_t index_a, uint32_t index_b) {
276            addr_t value_a;
277            addr_t value_b;
278            if (symbols[index_a].GetValue().GetSection() == symbols[index_b].GetValue().GetSection()) {
279                value_a = symbols[index_a].GetValue ().GetOffset();
280                value_b = symbols[index_b].GetValue ().GetOffset();
281            } else {
282                value_a = symbols[index_a].GetValue ().GetFileAddress();
283                value_b = symbols[index_b].GetValue ().GetFileAddress();
284            }
285
286            if (value_a == value_b) {
287                // The if the values are equal, use the original symbol user ID
288                lldb::user_id_t uid_a = symbols[index_a].GetID();
289                lldb::user_id_t uid_b = symbols[index_b].GetID();
290                if (uid_a < uid_b)
291                    return true;
292                if (uid_a > uid_b)
293                    return false;
294                return false;
295            } else if (value_a < value_b)
296                return true;
297
298            return false;
299        }
300    };
301}
302
303void
304Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const
305{
306    Timer scoped_timer (__PRETTY_FUNCTION__,__PRETTY_FUNCTION__);
307    // No need to sort if we have zero or one items...
308    if (indexes.size() <= 1)
309        return;
310
311    // Sort the indexes in place using std::stable_sort.
312    // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance,
313    // not correctness.  The indexes vector tends to be "close" to sorted, which the
314    // stable sort handles better.
315    std::stable_sort(indexes.begin(), indexes.end(), SymbolIndexComparator(m_symbols));
316
317    // Remove any duplicates if requested
318    if (remove_duplicates)
319        std::unique(indexes.begin(), indexes.end());
320}
321
322uint32_t
323Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes)
324{
325    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
326    if (symbol_name)
327    {
328        const size_t old_size = indexes.size();
329        if (m_name_to_index.IsEmpty())
330            InitNameIndexes();
331
332        const char *symbol_cstr = symbol_name.GetCString();
333        const UniqueCStringMap<uint32_t>::Entry *entry_ptr;
334        for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr);
335             entry_ptr!= NULL;
336             entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr))
337        {
338            indexes.push_back (entry_ptr->value);
339        }
340        return indexes.size() - old_size;
341    }
342    return 0;
343}
344
345uint32_t
346Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
347{
348    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
349    if (symbol_name)
350    {
351        const size_t old_size = indexes.size();
352        if (m_name_to_index.IsEmpty())
353            InitNameIndexes();
354
355        const char *symbol_cstr = symbol_name.GetCString();
356        const UniqueCStringMap<uint32_t>::Entry *entry_ptr;
357        for (entry_ptr = m_name_to_index.FindFirstValueForName (symbol_cstr);
358             entry_ptr!= NULL;
359             entry_ptr = m_name_to_index.FindNextValueForName (symbol_cstr, entry_ptr))
360        {
361            if (CheckSymbolAtIndex(entry_ptr->value, symbol_debug_type, symbol_visibility))
362                indexes.push_back (entry_ptr->value);
363        }
364        return indexes.size() - old_size;
365    }
366    return 0;
367}
368
369uint32_t
370Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes)
371{
372    if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0)
373    {
374        std::vector<uint32_t>::iterator pos = indexes.begin();
375        while (pos != indexes.end())
376        {
377            if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
378                ++pos;
379            else
380                indexes.erase(pos);
381        }
382    }
383    return indexes.size();
384}
385
386uint32_t
387Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
388{
389    if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0)
390    {
391        std::vector<uint32_t>::iterator pos = indexes.begin();
392        while (pos != indexes.end())
393        {
394            if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type)
395                ++pos;
396            else
397                indexes.erase(pos);
398        }
399    }
400    return indexes.size();
401}
402
403
404uint32_t
405Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, std::vector<uint32_t>& indexes)
406{
407    uint32_t prev_size = indexes.size();
408    uint32_t sym_end = m_symbols.size();
409
410    for (int i = 0; i < sym_end; i++)
411    {
412        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
413        {
414            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
415            if (name)
416            {
417                if (regexp.Execute (name))
418                    indexes.push_back(i);
419            }
420        }
421    }
422    return indexes.size() - prev_size;
423
424}
425
426uint32_t
427Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression &regexp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes)
428{
429    uint32_t prev_size = indexes.size();
430    uint32_t sym_end = m_symbols.size();
431
432    for (int i = 0; i < sym_end; i++)
433    {
434        if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type)
435        {
436            if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
437                continue;
438
439            const char *name = m_symbols[i].GetMangled().GetName().AsCString();
440            if (name)
441            {
442                if (regexp.Execute (name))
443                    indexes.push_back(i);
444            }
445        }
446    }
447    return indexes.size() - prev_size;
448
449}
450
451Symbol *
452Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx)
453{
454    const size_t count = m_symbols.size();
455    for (uint32_t idx = start_idx; idx < count; ++idx)
456    {
457        if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type)
458        {
459            if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility))
460            {
461                start_idx = idx;
462                return &m_symbols[idx];
463            }
464        }
465    }
466    return NULL;
467}
468
469size_t
470Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes)
471{
472    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
473    // Initialize all of the lookup by name indexes before converting NAME
474    // to a uniqued string NAME_STR below.
475    if (m_name_to_index.IsEmpty())
476        InitNameIndexes();
477
478    if (name)
479    {
480        // The string table did have a string that matched, but we need
481        // to check the symbols and match the symbol_type if any was given.
482        AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes);
483    }
484    return symbol_indexes.size();
485}
486
487size_t
488Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
489{
490    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
491    // Initialize all of the lookup by name indexes before converting NAME
492    // to a uniqued string NAME_STR below.
493    if (m_name_to_index.IsEmpty())
494        InitNameIndexes();
495
496    if (name)
497    {
498        // The string table did have a string that matched, but we need
499        // to check the symbols and match the symbol_type if any was given.
500        AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
501    }
502    return symbol_indexes.size();
503}
504
505size_t
506Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression &regex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes)
507{
508    AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes);
509    return symbol_indexes.size();
510}
511
512Symbol *
513Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility)
514{
515    Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
516    if (m_name_to_index.IsEmpty())
517        InitNameIndexes();
518
519    if (name)
520    {
521        std::vector<uint32_t> matching_indexes;
522        // The string table did have a string that matched, but we need
523        // to check the symbols and match the symbol_type if any was given.
524        if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes))
525        {
526            std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end();
527            for (pos = matching_indexes.begin(); pos != end; ++pos)
528            {
529                Symbol *symbol = SymbolAtIndex(*pos);
530
531                if (symbol->Compare(name, symbol_type))
532                    return symbol;
533            }
534        }
535    }
536    return NULL;
537}
538
539typedef struct
540{
541    const Symtab *symtab;
542    const addr_t file_addr;
543    Symbol *match_symbol;
544    const uint32_t *match_index_ptr;
545    addr_t match_offset;
546} SymbolSearchInfo;
547
548static int
549SymbolWithFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
550{
551    const Symbol *curr_symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
552    if (curr_symbol == NULL)
553        return -1;
554
555    const addr_t info_file_addr = info->file_addr;
556
557    // lldb::Symbol::GetAddressRangePtr() will only return a non NULL address
558    // range if the symbol has a section!
559    const AddressRange *curr_range = curr_symbol->GetAddressRangePtr();
560    if (curr_range)
561    {
562        const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
563        if (info_file_addr < curr_file_addr)
564            return -1;
565        if (info_file_addr > curr_file_addr)
566            return +1;
567        info->match_symbol = const_cast<Symbol *>(curr_symbol);
568        info->match_index_ptr = index_ptr;
569        return 0;
570    }
571
572    return -1;
573}
574
575static int
576SymbolWithClosestFileAddress (SymbolSearchInfo *info, const uint32_t *index_ptr)
577{
578    const Symbol *symbol = info->symtab->SymbolAtIndex (index_ptr[0]);
579    if (symbol == NULL)
580        return -1;
581
582    const addr_t info_file_addr = info->file_addr;
583    const AddressRange *curr_range = symbol->GetAddressRangePtr();
584    if (curr_range)
585    {
586        const addr_t curr_file_addr = curr_range->GetBaseAddress().GetFileAddress();
587        if (info_file_addr < curr_file_addr)
588            return -1;
589
590        // Since we are finding the closest symbol that is greater than or equal
591        // to 'info->file_addr' we set the symbol here. This will get set
592        // multiple times, but after the search is done it will contain the best
593        // symbol match
594        info->match_symbol = const_cast<Symbol *>(symbol);
595        info->match_index_ptr = index_ptr;
596        info->match_offset = info_file_addr - curr_file_addr;
597
598        if (info_file_addr > curr_file_addr)
599            return +1;
600        return 0;
601    }
602    return -1;
603}
604
605static SymbolSearchInfo
606FindIndexPtrForSymbolContainingAddress(Symtab* symtab, addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
607{
608    SymbolSearchInfo info = { symtab, file_addr, NULL, NULL, 0 };
609    bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
610    return info;
611}
612
613
614void
615Symtab::InitAddressIndexes()
616{
617    if (m_addr_indexes.empty())
618    {
619        AppendSymbolIndexesWithType (eSymbolTypeCode, m_addr_indexes);
620        AppendSymbolIndexesWithType (eSymbolTypeTrampoline, m_addr_indexes);
621        AppendSymbolIndexesWithType (eSymbolTypeData, m_addr_indexes);
622        SortSymbolIndexesByValue(m_addr_indexes, true);
623        m_addr_indexes.push_back(UINT32_MAX);   // Terminator for bsearch since we might need to look at the next symbol
624    }
625}
626
627size_t
628Symtab::CalculateSymbolSize (Symbol *symbol)
629{
630    if (m_symbols.empty())
631        return 0;
632
633    // Make sure this symbol is from this symbol table...
634    if (symbol < &m_symbols.front() || symbol > &m_symbols.back())
635        return 0;
636
637    // See if this symbol already has a byte size?
638    size_t byte_size = symbol->GetByteSize();
639
640    if (byte_size)
641    {
642        // It does, just return it
643        return byte_size;
644    }
645
646    // Else if this is an address based symbol, figure out the delta between
647    // it and the next address based symbol
648    if (symbol->GetAddressRangePtr())
649    {
650        if (m_addr_indexes.empty())
651            InitAddressIndexes();
652        const size_t num_addr_indexes = m_addr_indexes.size();
653        SymbolSearchInfo info = FindIndexPtrForSymbolContainingAddress(this, symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress(), &m_addr_indexes.front(), num_addr_indexes);
654        if (info.match_index_ptr != NULL)
655        {
656            const lldb::addr_t curr_file_addr = symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
657            // We can figure out the address range of all symbols except the
658            // last one by taking the delta between the current symbol and
659            // the next symbol
660
661            for (uint32_t addr_index = info.match_index_ptr - &m_addr_indexes.front() + 1;
662                 addr_index < num_addr_indexes;
663                 ++addr_index)
664            {
665                Symbol *next_symbol = SymbolAtIndex(m_addr_indexes[addr_index]);
666                if (next_symbol == NULL)
667                    break;
668
669                assert (next_symbol->GetAddressRangePtr());
670                const lldb::addr_t next_file_addr = next_symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
671                if (next_file_addr > curr_file_addr)
672                {
673                    byte_size = next_file_addr - curr_file_addr;
674                    symbol->GetAddressRangePtr()->SetByteSize(byte_size);
675                    symbol->SetSizeIsSynthesized(true);
676                    break;
677                }
678            }
679        }
680    }
681    return byte_size;
682}
683
684Symbol *
685Symtab::FindSymbolWithFileAddress (addr_t file_addr)
686{
687    if (m_addr_indexes.empty())
688        InitAddressIndexes();
689
690    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
691
692    uint32_t* match = (uint32_t*)bsearch(&info, &m_addr_indexes[0], m_addr_indexes.size(), sizeof(uint32_t), (comparison_function)SymbolWithFileAddress);
693    if (match)
694        return SymbolAtIndex (*match);
695    return NULL;
696}
697
698
699Symbol *
700Symtab::FindSymbolContainingFileAddress (addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes)
701{
702    SymbolSearchInfo info = { this, file_addr, NULL, NULL, 0 };
703
704    bsearch(&info, indexes, num_indexes, sizeof(uint32_t), (comparison_function)SymbolWithClosestFileAddress);
705
706    if (info.match_symbol)
707    {
708        if (info.match_offset == 0)
709        {
710            // We found an exact match!
711            return info.match_symbol;
712        }
713
714        const size_t symbol_byte_size = CalculateSymbolSize(info.match_symbol);
715
716        if (symbol_byte_size == 0)
717        {
718            // We weren't able to find the size of the symbol so lets just go
719            // with that match we found in our search...
720            return info.match_symbol;
721        }
722
723        // We were able to figure out a symbol size so lets make sure our
724        // offset puts "file_addr" in the symbol's address range.
725        if (info.match_offset < symbol_byte_size)
726            return info.match_symbol;
727    }
728    return NULL;
729}
730
731Symbol *
732Symtab::FindSymbolContainingFileAddress (addr_t file_addr)
733{
734    if (m_addr_indexes.empty())
735        InitAddressIndexes();
736
737    return FindSymbolContainingFileAddress (file_addr, &m_addr_indexes[0], m_addr_indexes.size());
738}
739
740