BreakpointResolverFileRegex.cpp revision 321369
1314564Sdim//===-- BreakpointResolverFileRegex.cpp -------------------------*- C++-*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste// C++ Includes
14254721Semaste// Other libraries and framework includes
15254721Semaste// Project includes
16254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h"
17254721Semaste#include "lldb/Core/SourceManager.h"
18254721Semaste#include "lldb/Symbol/CompileUnit.h"
19254721Semaste#include "lldb/Target/Target.h"
20321369Sdim#include "lldb/Utility/Log.h"
21321369Sdim#include "lldb/Utility/StreamString.h"
22254721Semaste
23254721Semasteusing namespace lldb;
24254721Semasteusing namespace lldb_private;
25254721Semaste
26254721Semaste//----------------------------------------------------------------------
27254721Semaste// BreakpointResolverFileRegex:
28254721Semaste//----------------------------------------------------------------------
29314564SdimBreakpointResolverFileRegex::BreakpointResolverFileRegex(
30314564Sdim    Breakpoint *bkpt, RegularExpression &regex,
31314564Sdim    const std::unordered_set<std::string> &func_names, bool exact_match)
32314564Sdim    : BreakpointResolver(bkpt, BreakpointResolver::FileRegexResolver),
33314564Sdim      m_regex(regex), m_exact_match(exact_match), m_function_names(func_names) {
34254721Semaste}
35254721Semaste
36314564SdimBreakpointResolverFileRegex::~BreakpointResolverFileRegex() {}
37314564Sdim
38314564SdimBreakpointResolver *BreakpointResolverFileRegex::CreateFromStructuredData(
39314564Sdim    Breakpoint *bkpt, const StructuredData::Dictionary &options_dict,
40321369Sdim    Status &error) {
41314564Sdim  bool success;
42314564Sdim
43321369Sdim  llvm::StringRef regex_string;
44314564Sdim  success = options_dict.GetValueForKeyAsString(
45314564Sdim      GetKey(OptionNames::RegexString), regex_string);
46314564Sdim  if (!success) {
47314564Sdim    error.SetErrorString("BRFR::CFSD: Couldn't find regex entry.");
48314564Sdim    return nullptr;
49314564Sdim  }
50314564Sdim  RegularExpression regex(regex_string);
51314564Sdim
52314564Sdim  bool exact_match;
53314564Sdim  success = options_dict.GetValueForKeyAsBoolean(
54314564Sdim      GetKey(OptionNames::ExactMatch), exact_match);
55314564Sdim  if (!success) {
56314564Sdim    error.SetErrorString("BRFL::CFSD: Couldn't find exact match entry.");
57314564Sdim    return nullptr;
58314564Sdim  }
59314564Sdim
60314564Sdim  // The names array is optional:
61314564Sdim  std::unordered_set<std::string> names_set;
62314564Sdim  StructuredData::Array *names_array;
63314564Sdim  success = options_dict.GetValueForKeyAsArray(
64314564Sdim      GetKey(OptionNames::SymbolNameArray), names_array);
65314564Sdim  if (success && names_array) {
66314564Sdim    size_t num_names = names_array->GetSize();
67314564Sdim    for (size_t i = 0; i < num_names; i++) {
68321369Sdim      llvm::StringRef name;
69314564Sdim      success = names_array->GetItemAtIndexAsString(i, name);
70314564Sdim      if (!success) {
71314564Sdim        error.SetErrorStringWithFormat(
72314564Sdim            "BRFR::CFSD: Malformed element %zu in the names array.", i);
73314564Sdim        return nullptr;
74314564Sdim      }
75314564Sdim      names_set.insert(name);
76314564Sdim    }
77314564Sdim  }
78314564Sdim
79314564Sdim  return new BreakpointResolverFileRegex(bkpt, regex, names_set, exact_match);
80254721Semaste}
81254721Semaste
82314564SdimStructuredData::ObjectSP
83314564SdimBreakpointResolverFileRegex::SerializeToStructuredData() {
84314564Sdim  StructuredData::DictionarySP options_dict_sp(
85314564Sdim      new StructuredData::Dictionary());
86314564Sdim
87314564Sdim  options_dict_sp->AddStringItem(GetKey(OptionNames::RegexString),
88314564Sdim                                 m_regex.GetText());
89314564Sdim  options_dict_sp->AddBooleanItem(GetKey(OptionNames::ExactMatch),
90314564Sdim                                  m_exact_match);
91314564Sdim  if (!m_function_names.empty()) {
92314564Sdim    StructuredData::ArraySP names_array_sp(new StructuredData::Array());
93314564Sdim    for (std::string name : m_function_names) {
94314564Sdim      StructuredData::StringSP item(new StructuredData::String(name));
95314564Sdim      names_array_sp->AddItem(item);
96314564Sdim    }
97314564Sdim    options_dict_sp->AddItem(GetKey(OptionNames::LineNumber), names_array_sp);
98314564Sdim  }
99314564Sdim
100314564Sdim  return WrapOptionsDict(options_dict_sp);
101314564Sdim}
102314564Sdim
103254721SemasteSearcher::CallbackReturn
104314564SdimBreakpointResolverFileRegex::SearchCallback(SearchFilter &filter,
105314564Sdim                                            SymbolContext &context,
106314564Sdim                                            Address *addr, bool containing) {
107254721Semaste
108314564Sdim  assert(m_breakpoint != NULL);
109314564Sdim  if (!context.target_sp)
110314564Sdim    return eCallbackReturnContinue;
111254721Semaste
112314564Sdim  CompileUnit *cu = context.comp_unit;
113314564Sdim  FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu));
114314564Sdim  std::vector<uint32_t> line_matches;
115314564Sdim  context.target_sp->GetSourceManager().FindLinesMatchingRegex(
116314564Sdim      cu_file_spec, m_regex, 1, UINT32_MAX, line_matches);
117314564Sdim
118314564Sdim  uint32_t num_matches = line_matches.size();
119314564Sdim  for (uint32_t i = 0; i < num_matches; i++) {
120314564Sdim    SymbolContextList sc_list;
121314564Sdim    const bool search_inlines = false;
122314564Sdim
123314564Sdim    cu->ResolveSymbolContext(cu_file_spec, line_matches[i], search_inlines,
124314564Sdim                             m_exact_match, eSymbolContextEverything, sc_list);
125314564Sdim    // Find all the function names:
126314564Sdim    if (!m_function_names.empty()) {
127314564Sdim      std::vector<size_t> sc_to_remove;
128314564Sdim      for (size_t i = 0; i < sc_list.GetSize(); i++) {
129314564Sdim        SymbolContext sc_ctx;
130314564Sdim        sc_list.GetContextAtIndex(i, sc_ctx);
131314564Sdim        std::string name(
132314564Sdim            sc_ctx
133314564Sdim                .GetFunctionName(
134314564Sdim                    Mangled::NamePreference::ePreferDemangledWithoutArguments)
135314564Sdim                .AsCString());
136314564Sdim        if (!m_function_names.count(name)) {
137314564Sdim          sc_to_remove.push_back(i);
138309124Sdim        }
139314564Sdim      }
140314564Sdim
141314564Sdim      if (!sc_to_remove.empty()) {
142314564Sdim        std::vector<size_t>::reverse_iterator iter;
143314564Sdim        std::vector<size_t>::reverse_iterator rend = sc_to_remove.rend();
144314564Sdim        for (iter = sc_to_remove.rbegin(); iter != rend; iter++) {
145314564Sdim          sc_list.RemoveContextAtIndex(*iter);
146314564Sdim        }
147314564Sdim      }
148254721Semaste    }
149254721Semaste
150314564Sdim    const bool skip_prologue = true;
151314564Sdim
152314564Sdim    BreakpointResolver::SetSCMatchesByLine(filter, sc_list, skip_prologue,
153314564Sdim                                           m_regex.GetText());
154314564Sdim  }
155314564Sdim  assert(m_breakpoint != NULL);
156314564Sdim
157314564Sdim  return Searcher::eCallbackReturnContinue;
158254721Semaste}
159254721Semaste
160314564SdimSearcher::Depth BreakpointResolverFileRegex::GetDepth() {
161314564Sdim  return Searcher::eDepthCompUnit;
162254721Semaste}
163254721Semaste
164314564Sdimvoid BreakpointResolverFileRegex::GetDescription(Stream *s) {
165314564Sdim  s->Printf("source regex = \"%s\", exact_match = %d",
166314564Sdim            m_regex.GetText().str().c_str(), m_exact_match);
167254721Semaste}
168254721Semaste
169314564Sdimvoid BreakpointResolverFileRegex::Dump(Stream *s) const {}
170254721Semaste
171280031Sdimlldb::BreakpointResolverSP
172314564SdimBreakpointResolverFileRegex::CopyForBreakpoint(Breakpoint &breakpoint) {
173314564Sdim  lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileRegex(
174314564Sdim      &breakpoint, m_regex, m_function_names, m_exact_match));
175314564Sdim  return ret_sp;
176280031Sdim}
177280031Sdim
178314564Sdimvoid BreakpointResolverFileRegex::AddFunctionName(const char *func_name) {
179314564Sdim  m_function_names.insert(func_name);
180309124Sdim}
181