1 //===-- BreakpointResolverFileRegex.cpp -----------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
11 #include "lldb/Breakpoint/BreakpointLocation.h"
12 #include "lldb/Core/SourceManager.h"
13 #include "lldb/Symbol/CompileUnit.h"
14 #include "lldb/Target/Target.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/StreamString.h"
19 using namespace lldb_private
;
21 // BreakpointResolverFileRegex:
22 BreakpointResolverFileRegex::BreakpointResolverFileRegex(
23 const lldb::BreakpointSP
&bkpt
, RegularExpression regex
,
24 const std::unordered_set
<std::string
> &func_names
, bool exact_match
)
25 : BreakpointResolver(bkpt
, BreakpointResolver::FileRegexResolver
),
26 m_regex(std::move(regex
)), m_exact_match(exact_match
),
27 m_function_names(func_names
) {}
29 BreakpointResolver
*BreakpointResolverFileRegex::CreateFromStructuredData(
30 const lldb::BreakpointSP
&bkpt
, const StructuredData::Dictionary
&options_dict
,
34 llvm::StringRef regex_string
;
35 success
= options_dict
.GetValueForKeyAsString(
36 GetKey(OptionNames::RegexString
), regex_string
);
38 error
.SetErrorString("BRFR::CFSD: Couldn't find regex entry.");
41 RegularExpression
regex(regex_string
);
44 success
= options_dict
.GetValueForKeyAsBoolean(
45 GetKey(OptionNames::ExactMatch
), exact_match
);
47 error
.SetErrorString("BRFL::CFSD: Couldn't find exact match entry.");
51 // The names array is optional:
52 std::unordered_set
<std::string
> names_set
;
53 StructuredData::Array
*names_array
;
54 success
= options_dict
.GetValueForKeyAsArray(
55 GetKey(OptionNames::SymbolNameArray
), names_array
);
56 if (success
&& names_array
) {
57 size_t num_names
= names_array
->GetSize();
58 for (size_t i
= 0; i
< num_names
; i
++) {
60 success
= names_array
->GetItemAtIndexAsString(i
, name
);
62 error
.SetErrorStringWithFormat(
63 "BRFR::CFSD: Malformed element %zu in the names array.", i
);
66 names_set
.insert(std::string(name
));
70 return new BreakpointResolverFileRegex(bkpt
, std::move(regex
), names_set
,
74 StructuredData::ObjectSP
75 BreakpointResolverFileRegex::SerializeToStructuredData() {
76 StructuredData::DictionarySP
options_dict_sp(
77 new StructuredData::Dictionary());
79 options_dict_sp
->AddStringItem(GetKey(OptionNames::RegexString
),
81 options_dict_sp
->AddBooleanItem(GetKey(OptionNames::ExactMatch
),
83 if (!m_function_names
.empty()) {
84 StructuredData::ArraySP
names_array_sp(new StructuredData::Array());
85 for (std::string name
: m_function_names
) {
86 StructuredData::StringSP
item(new StructuredData::String(name
));
87 names_array_sp
->AddItem(item
);
89 options_dict_sp
->AddItem(GetKey(OptionNames::LineNumber
), names_array_sp
);
92 return WrapOptionsDict(options_dict_sp
);
95 Searcher::CallbackReturn
BreakpointResolverFileRegex::SearchCallback(
96 SearchFilter
&filter
, SymbolContext
&context
, Address
*addr
) {
98 if (!context
.target_sp
)
99 return eCallbackReturnContinue
;
101 CompileUnit
*cu
= context
.comp_unit
;
102 FileSpec cu_file_spec
= cu
->GetPrimaryFile();
103 std::vector
<uint32_t> line_matches
;
104 context
.target_sp
->GetSourceManager().FindLinesMatchingRegex(
105 cu_file_spec
, m_regex
, 1, UINT32_MAX
, line_matches
);
107 uint32_t num_matches
= line_matches
.size();
108 for (uint32_t i
= 0; i
< num_matches
; i
++) {
109 SymbolContextList sc_list
;
110 // TODO: Handle SourceLocationSpec column information
111 SourceLocationSpec
location_spec(cu_file_spec
, line_matches
[i
],
112 /*column=*/std::nullopt
,
113 /*check_inlines=*/false, m_exact_match
);
114 cu
->ResolveSymbolContext(location_spec
, eSymbolContextEverything
, sc_list
);
115 // Find all the function names:
116 if (!m_function_names
.empty()) {
117 std::vector
<size_t> sc_to_remove
;
118 for (size_t i
= 0; i
< sc_list
.GetSize(); i
++) {
119 SymbolContext sc_ctx
;
120 sc_list
.GetContextAtIndex(i
, sc_ctx
);
124 Mangled::NamePreference::ePreferDemangledWithoutArguments
)
126 if (!m_function_names
.count(name
)) {
127 sc_to_remove
.push_back(i
);
131 if (!sc_to_remove
.empty()) {
132 std::vector
<size_t>::reverse_iterator iter
;
133 std::vector
<size_t>::reverse_iterator rend
= sc_to_remove
.rend();
134 for (iter
= sc_to_remove
.rbegin(); iter
!= rend
; iter
++) {
135 sc_list
.RemoveContextAtIndex(*iter
);
140 const bool skip_prologue
= true;
142 BreakpointResolver::SetSCMatchesByLine(filter
, sc_list
, skip_prologue
,
146 return Searcher::eCallbackReturnContinue
;
149 lldb::SearchDepth
BreakpointResolverFileRegex::GetDepth() {
150 return lldb::eSearchDepthCompUnit
;
153 void BreakpointResolverFileRegex::GetDescription(Stream
*s
) {
154 s
->Printf("source regex = \"%s\", exact_match = %d",
155 m_regex
.GetText().str().c_str(), m_exact_match
);
158 void BreakpointResolverFileRegex::Dump(Stream
*s
) const {}
160 lldb::BreakpointResolverSP
161 BreakpointResolverFileRegex::CopyForBreakpoint(BreakpointSP
&breakpoint
) {
162 lldb::BreakpointResolverSP
ret_sp(new BreakpointResolverFileRegex(
163 breakpoint
, m_regex
, m_function_names
, m_exact_match
));
167 void BreakpointResolverFileRegex::AddFunctionName(const char *func_name
) {
168 m_function_names
.insert(func_name
);