1168404Spjd//===-- AddressResolverName.cpp ---------------------------------*- C++ -*-===//
2168404Spjd//
3168404Spjd//                     The LLVM Compiler Infrastructure
4168404Spjd//
5168404Spjd// This file is distributed under the University of Illinois Open Source
6168404Spjd// License. See LICENSE.TXT for details.
7168404Spjd//
8168404Spjd//===----------------------------------------------------------------------===//
9168404Spjd
10168404Spjd#include "lldb/Core/AddressResolverName.h"
11168404Spjd
12168404Spjd// Project includes
13168404Spjd#include "lldb/Core/Log.h"
14168404Spjd#include "lldb/Core/Module.h"
15168404Spjd#include "lldb/Core/StreamString.h"
16168404Spjd#include "lldb/Symbol/ClangNamespaceDecl.h"
17168404Spjd#include "lldb/Symbol/Function.h"
18168404Spjd#include "lldb/Symbol/SymbolContext.h"
19168404Spjd#include "lldb/Symbol/Symbol.h"
20168404Spjd#include "lldb/lldb-private-log.h"
21168404Spjd
22168404Spjdusing namespace lldb;
23168404Spjdusing namespace lldb_private;
24168404Spjd
25168404SpjdAddressResolverName::AddressResolverName
26168404Spjd(
27168404Spjd    const char *func_name,
28168404Spjd    AddressResolver::MatchType type
29168404Spjd) :
30168404Spjd    AddressResolver (),
31168404Spjd    m_func_name (func_name),
32168404Spjd    m_class_name (NULL),
33168404Spjd    m_regex (),
34168404Spjd    m_match_type (type)
35168404Spjd{
36168404Spjd    if (m_match_type == AddressResolver::Regexp)
37168404Spjd    {
38168404Spjd        if (!m_regex.Compile (m_func_name.AsCString()))
39168404Spjd        {
40168404Spjd            Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
41168404Spjd
42168404Spjd            if (log)
43168404Spjd                log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
44168404Spjd        }
45168404Spjd    }
46168404Spjd}
47168404Spjd
48168404SpjdAddressResolverName::AddressResolverName
49168404Spjd(
50168404Spjd    RegularExpression &func_regex
51168404Spjd) :
52168404Spjd    AddressResolver (),
53168404Spjd    m_func_name (NULL),
54168404Spjd    m_class_name (NULL),
55168404Spjd    m_regex (func_regex),
56168404Spjd    m_match_type (AddressResolver::Regexp)
57168404Spjd{
58168404Spjd
59168404Spjd}
60168404Spjd
61168404SpjdAddressResolverName::AddressResolverName
62168404Spjd(
63168404Spjd    const char *class_name,
64168404Spjd    const char *method,
65168404Spjd    AddressResolver::MatchType type
66168404Spjd) :
67168404Spjd    AddressResolver (),
68168404Spjd    m_func_name (method),
69168404Spjd    m_class_name (class_name),
70168404Spjd    m_regex (),
71168404Spjd    m_match_type (type)
72168404Spjd{
73168404Spjd
74168404Spjd}
75168404Spjd
76168404SpjdAddressResolverName::~AddressResolverName ()
77168404Spjd{
78168404Spjd}
79168404Spjd
80168404Spjd// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
81168404Spjd// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
82168404Spjd// lookup.  At that point, we should switch the depth to CompileUnit, and look in these tables.
83168404Spjd
84168404SpjdSearcher::CallbackReturn
85168404SpjdAddressResolverName::SearchCallback
86168404Spjd(
87168404Spjd    SearchFilter &filter,
88168404Spjd    SymbolContext &context,
89168404Spjd    Address *addr,
90168404Spjd    bool containing
91168404Spjd)
92168404Spjd{
93168404Spjd    SymbolContextList func_list;
94168404Spjd    SymbolContextList sym_list;
95168404Spjd
96168404Spjd    bool skip_prologue = true;
97168404Spjd    uint32_t i;
98168404Spjd    SymbolContext sc;
99168404Spjd    Address func_addr;
100168404Spjd
101168404Spjd    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
102168404Spjd
103168404Spjd    if (m_class_name)
104168404Spjd    {
105168404Spjd        if (log)
106168404Spjd            log->Warning ("Class/method function specification not supported yet.\n");
107168404Spjd        return Searcher::eCallbackReturnStop;
108168404Spjd    }
109168404Spjd
110168404Spjd    const bool include_symbols = false;
111168404Spjd    const bool include_inlines = true;
112168404Spjd    const bool append = false;
113168404Spjd    switch (m_match_type)
114168404Spjd    {
115168404Spjd    case AddressResolver::Exact:
116168404Spjd        if (context.module_sp)
117168404Spjd        {
118168404Spjd            context.module_sp->FindSymbolsWithNameAndType (m_func_name,
119168404Spjd                                                           eSymbolTypeCode,
120168404Spjd                                                           sym_list);
121168404Spjd            context.module_sp->FindFunctions (m_func_name,
122168404Spjd                                              NULL,
123168404Spjd                                              eFunctionNameTypeAuto,
124168404Spjd                                              include_symbols,
125168404Spjd                                              include_inlines,
126168404Spjd                                              append,
127168404Spjd                                              func_list);
128168404Spjd        }
129168404Spjd        break;
130168404Spjd
131168404Spjd    case AddressResolver::Regexp:
132168404Spjd        if (context.module_sp)
133168404Spjd        {
134168404Spjd            context.module_sp->FindSymbolsMatchingRegExAndType (m_regex,
135168404Spjd                                                                eSymbolTypeCode,
136168404Spjd                                                                sym_list);
137168404Spjd            context.module_sp->FindFunctions (m_regex,
138168404Spjd                                              include_symbols,
139168404Spjd                                              include_inlines,
140168404Spjd                                              append,
141168404Spjd                                              func_list);
142168404Spjd        }
143168404Spjd        break;
144168404Spjd
145168404Spjd    case AddressResolver::Glob:
146168404Spjd        if (log)
147168404Spjd            log->Warning ("glob is not supported yet.");
148168404Spjd        break;
149168404Spjd    }
150168404Spjd
151168404Spjd    // Remove any duplicates between the funcion list and the symbol list
152168404Spjd    if (func_list.GetSize())
153168404Spjd    {
154168404Spjd        for (i = 0; i < func_list.GetSize(); i++)
155168404Spjd        {
156168404Spjd            if (func_list.GetContextAtIndex(i, sc) == false)
157168404Spjd                continue;
158168404Spjd
159168404Spjd            if (sc.function == NULL)
160168404Spjd                continue;
161168404Spjd            uint32_t j = 0;
162168404Spjd            while (j < sym_list.GetSize())
163168404Spjd            {
164168404Spjd                SymbolContext symbol_sc;
165168404Spjd                if (sym_list.GetContextAtIndex(j, symbol_sc))
166168404Spjd                {
167168404Spjd                    if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress())
168168404Spjd                    {
169168404Spjd                        if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress())
170168404Spjd                        {
171168404Spjd                            sym_list.RemoveContextAtIndex(j);
172168404Spjd                            continue;   // Don't increment j
173168404Spjd                        }
174168404Spjd                    }
175168404Spjd                }
176168404Spjd
177168404Spjd                j++;
178168404Spjd            }
179168404Spjd        }
180168404Spjd
181168404Spjd        for (i = 0; i < func_list.GetSize(); i++)
182168404Spjd        {
183168404Spjd            if (func_list.GetContextAtIndex(i, sc))
184168404Spjd            {
185168404Spjd                if (sc.function)
186168404Spjd                {
187168404Spjd                    func_addr = sc.function->GetAddressRange().GetBaseAddress();
188168404Spjd                    addr_t byte_size = sc.function->GetAddressRange().GetByteSize();
189168404Spjd                    if (skip_prologue)
190168404Spjd                    {
191168404Spjd                        const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
192168404Spjd                        if (prologue_byte_size)
193168404Spjd                        {
194168404Spjd                            func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size);
195168404Spjd                            byte_size -= prologue_byte_size;
196168404Spjd                        }
197168404Spjd                    }
198168404Spjd
199168404Spjd                    if (filter.AddressPasses (func_addr))
200168404Spjd                    {
201168404Spjd                        AddressRange new_range (func_addr, byte_size);
202168404Spjd                        m_address_ranges.push_back (new_range);
203168404Spjd                    }
204168404Spjd                }
205168404Spjd            }
206168404Spjd        }
207168404Spjd    }
208168404Spjd
209168404Spjd    for (i = 0; i < sym_list.GetSize(); i++)
210168404Spjd    {
211168404Spjd        if (sym_list.GetContextAtIndex(i, sc))
212168404Spjd        {
213168404Spjd            if (sc.symbol && sc.symbol->ValueIsAddress())
214168404Spjd            {
215168404Spjd                func_addr = sc.symbol->GetAddress();
216168404Spjd                addr_t byte_size = sc.symbol->GetByteSize();
217168404Spjd
218168404Spjd                if (skip_prologue)
219168404Spjd                {
220168404Spjd                    const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
221168404Spjd                    if (prologue_byte_size)
222168404Spjd                    {
223168404Spjd                        func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size);
224168404Spjd                        byte_size -= prologue_byte_size;
225168404Spjd                    }
226168404Spjd                }
227168404Spjd
228168404Spjd                if (filter.AddressPasses (func_addr))
229168404Spjd                {
230168404Spjd                    AddressRange new_range (func_addr, byte_size);
231168404Spjd                    m_address_ranges.push_back (new_range);
232168404Spjd                }
233168404Spjd            }
234168404Spjd        }
235168404Spjd    }
236168404Spjd    return Searcher::eCallbackReturnContinue;
237168404Spjd}
238168404Spjd
239168404SpjdSearcher::Depth
240168404SpjdAddressResolverName::GetDepth()
241168404Spjd{
242168404Spjd    return Searcher::eDepthModule;
243168404Spjd}
244168404Spjd
245168404Spjdvoid
246168404SpjdAddressResolverName::GetDescription (Stream *s)
247168404Spjd{
248168404Spjd    s->PutCString("Address by function name: ");
249168404Spjd
250168404Spjd    if (m_match_type == AddressResolver::Regexp)
251168404Spjd        s->Printf("'%s' (regular expression)", m_regex.GetText());
252168404Spjd    else
253168404Spjd        s->Printf("'%s'", m_func_name.AsCString());
254168404Spjd}
255168404Spjd
256168404Spjd