AddressResolverName.cpp revision 12bec71b323dc520f0e985a86e09c4712559e115
1//===-- AddressResolverName.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 "lldb/Core/AddressResolverName.h"
11
12// Project includes
13#include "lldb/Core/Log.h"
14#include "lldb/Core/StreamString.h"
15#include "lldb/lldb-private-log.h"
16
17using namespace lldb;
18using namespace lldb_private;
19
20AddressResolverName::AddressResolverName
21(
22    const char *func_name,
23    AddressResolver::MatchType type
24) :
25    AddressResolver (),
26    m_func_name (func_name),
27    m_class_name (NULL),
28    m_regex (),
29    m_match_type (type)
30{
31    if (m_match_type == AddressResolver::Regexp)
32    {
33        if (!m_regex.Compile (m_func_name.AsCString()))
34        {
35            Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
36
37            if (log)
38                log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
39        }
40    }
41}
42
43AddressResolverName::AddressResolverName
44(
45    RegularExpression &func_regex
46) :
47    AddressResolver (),
48    m_func_name (NULL),
49    m_class_name (NULL),
50    m_regex (func_regex),
51    m_match_type (AddressResolver::Regexp)
52{
53
54}
55
56AddressResolverName::AddressResolverName
57(
58    const char *class_name,
59    const char *method,
60    AddressResolver::MatchType type
61) :
62    AddressResolver (),
63    m_func_name (method),
64    m_class_name (class_name),
65    m_regex (),
66    m_match_type (type)
67{
68
69}
70
71AddressResolverName::~AddressResolverName ()
72{
73}
74
75// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
76// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
77// lookup.  At that point, we should switch the depth to CompileUnit, and look in these tables.
78
79Searcher::CallbackReturn
80AddressResolverName::SearchCallback
81(
82    SearchFilter &filter,
83    SymbolContext &context,
84    Address *addr,
85    bool containing
86)
87{
88    SymbolContextList func_list;
89    SymbolContextList sym_list;
90
91    bool skip_prologue = true;
92    uint32_t i;
93    SymbolContext sc;
94    Address func_addr;
95
96    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
97
98    if (m_class_name)
99    {
100        if (log)
101            log->Warning ("Class/method function specification not supported yet.\n");
102        return Searcher::eCallbackReturnStop;
103    }
104
105    switch (m_match_type)
106    {
107      case AddressResolver::Exact:
108        if (context.module_sp)
109        {
110            context.module_sp->FindSymbolsWithNameAndType (m_func_name,
111                                                           eSymbolTypeCode,
112                                                           sym_list);
113            context.module_sp->FindFunctions (m_func_name,
114                                              eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
115                                              false,
116                                              func_list);
117        }
118        break;
119      case AddressResolver::Regexp:
120        if (context.module_sp)
121        {
122            context.module_sp->FindSymbolsMatchingRegExAndType (m_regex,
123                                                                eSymbolTypeCode,
124                                                                sym_list);
125            context.module_sp->FindFunctions (m_regex,
126                                              true,
127                                              func_list);
128        }
129        break;
130      case AddressResolver::Glob:
131        if (log)
132            log->Warning ("glob is not supported yet.");
133        break;
134    }
135
136    // Remove any duplicates between the funcion list and the symbol list
137    if (func_list.GetSize())
138    {
139        for (i = 0; i < func_list.GetSize(); i++)
140        {
141            if (func_list.GetContextAtIndex(i, sc) == false)
142                continue;
143
144            if (sc.function == NULL)
145                continue;
146            uint32_t j = 0;
147            while (j < sym_list.GetSize())
148            {
149                SymbolContext symbol_sc;
150                if (sym_list.GetContextAtIndex(j, symbol_sc))
151                {
152                    if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
153                    {
154                        if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
155                        {
156                            sym_list.RemoveContextAtIndex(j);
157                            continue;   // Don't increment j
158                        }
159                    }
160                }
161
162                j++;
163            }
164        }
165
166        for (i = 0; i < func_list.GetSize(); i++)
167        {
168            if (func_list.GetContextAtIndex(i, sc))
169            {
170                if (sc.function)
171                {
172                    func_addr = sc.function->GetAddressRange().GetBaseAddress();
173                    addr_t byte_size = sc.function->GetAddressRange().GetByteSize();
174                    if (skip_prologue)
175                    {
176                        const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
177                        if (prologue_byte_size)
178                        {
179                            func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size);
180                            byte_size -= prologue_byte_size;
181                        }
182                    }
183
184                    if (filter.AddressPasses (func_addr))
185                    {
186                        AddressRange new_range (func_addr, byte_size);
187                        m_address_ranges.push_back (new_range);
188                    }
189                }
190            }
191        }
192    }
193
194    for (i = 0; i < sym_list.GetSize(); i++)
195    {
196        if (sym_list.GetContextAtIndex(i, sc))
197        {
198            if (sc.symbol && sc.symbol->GetAddressRangePtr())
199            {
200                func_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
201                addr_t byte_size = sc.symbol->GetAddressRangePtr()->GetByteSize();
202
203                if (skip_prologue)
204                {
205                    const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
206                    if (prologue_byte_size)
207                    {
208                        func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size);
209                        byte_size -= prologue_byte_size;
210                    }
211                }
212
213                if (filter.AddressPasses (func_addr))
214                {
215                    AddressRange new_range (func_addr, byte_size);
216                    m_address_ranges.push_back (new_range);
217                }
218            }
219        }
220    }
221    return Searcher::eCallbackReturnContinue;
222}
223
224Searcher::Depth
225AddressResolverName::GetDepth()
226{
227    return Searcher::eDepthModule;
228}
229
230void
231AddressResolverName::GetDescription (Stream *s)
232{
233    s->PutCString("Address by function name: ");
234
235    if (m_match_type == AddressResolver::Regexp)
236        s->Printf("'%s' (regular expression)", m_regex.GetText());
237    else
238        s->Printf("'%s'", m_func_name.AsCString());
239}
240
241