• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "breakpoint_storage.h"
17 
18 #include "breakpoint.h"
19 #include "conditional_breakpoint.h"
20 #include "os/mutex.h"
21 
22 namespace ark::tooling::inspector {
23 
ShouldStopAtBreakpoint(const PtLocation & location,EvaluationEngine & engine)24 bool BreakpointStorage::ShouldStopAtBreakpoint(const PtLocation &location, EvaluationEngine &engine)
25 {
26     os::memory::ReadLockHolder lock(lock_);
27 
28     if (!breakpointsActive_) {
29         return false;
30     }
31 
32     auto rng = breakpointLocations_.equal_range(location);
33 
34     for (auto iter = rng.first; iter != rng.second; ++iter) {
35         BreakpointId bpId = iter->second;
36         bool shouldStop = breakpointStorage_[bpId]->ShouldStopAt(location, engine);
37         if (shouldStop) {
38             return true;
39         }
40     }
41     return false;
42 }
43 
ResolveBreakpoints(const panda_file::File & file,const panda_file::DebugInfoExtractor * debugInfoCache)44 void BreakpointStorage::ResolveBreakpoints(const panda_file::File &file,
45                                            const panda_file::DebugInfoExtractor *debugInfoCache)
46 {
47     os::memory::ReadLockHolder lock(lock_);
48 
49     for (auto &[_, bp] : breakpointStorage_) {
50         bp->TryResolve(file, debugInfoCache, breakpointLocations_);
51         // if bp resolved add locations
52     }
53 }
54 
RemoveBreakpoint(BreakpointId id)55 void BreakpointStorage::RemoveBreakpoint(BreakpointId id)
56 {
57     os::memory::WriteLockHolder lock(lock_);
58 
59     for (auto it = breakpointLocations_.begin(); it != breakpointLocations_.end();) {
60         if (it->second == id) {
61             it = breakpointLocations_.erase(it);
62         } else {
63             ++it;
64         }
65     }
66     breakpointStorage_.erase(id);
67 }
68 
SetBreakpoint(SourceFileFilter && sourceFilesFilter,size_t lineNumber,std::set<std::string_view> & sourceFiles,const std::string * condition,const DebugInfoCache & debugCache)69 std::optional<BreakpointId> BreakpointStorage::SetBreakpoint(SourceFileFilter &&sourceFilesFilter, size_t lineNumber,
70                                                              std::set<std::string_view> &sourceFiles,
71                                                              const std::string *condition,
72                                                              const DebugInfoCache &debugCache)
73 {
74     os::memory::WriteLockHolder lock(lock_);
75 
76     auto id = nextBreakpointId_;
77     std::unique_ptr<BreakpointBase> bbp;
78 
79     if (condition == nullptr) {
80         bbp = std::make_unique<Breakpoint>(id, std::move(sourceFilesFilter), lineNumber, true);
81     } else {
82         bbp = std::make_unique<ConditionalBreakpoint>(id, std::move(sourceFilesFilter), lineNumber, condition);
83     }
84 
85     if (!bbp->SetLocations(sourceFiles, debugCache, breakpointLocations_)) {
86         // Only if many locations for conditional bp, it will be destroyed, no need to increase id.
87         return std::nullopt;
88     }
89     // bp with correct locations, or pending with no locations
90     ++nextBreakpointId_;
91     breakpointStorage_[id] = std::move(bbp);
92     return id;
93 }
94 
Reset()95 void BreakpointStorage::Reset()
96 {
97     os::memory::WriteLockHolder lock(lock_);
98 
99     breakpointsActive_ = true;
100     nextBreakpointId_ = 0;
101     breakpointLocations_.clear();
102     breakpointStorage_.clear();
103 }
104 
SetBreakpointsActive(bool active)105 void BreakpointStorage::SetBreakpointsActive(bool active)
106 {
107     os::memory::WriteLockHolder lock(lock_);
108 
109     breakpointsActive_ = active;
110 }
111 
GetBreakpointsByLocation(const PtLocation & location) const112 std::vector<BreakpointId> BreakpointStorage::GetBreakpointsByLocation(const PtLocation &location) const
113 {
114     os::memory::ReadLockHolder lock(lock_);
115 
116     std::vector<BreakpointId> hitBreakpoints;
117 
118     auto range = breakpointLocations_.equal_range(location);
119     std::transform(range.first, range.second, std::back_inserter(hitBreakpoints), [](auto &p) { return p.second; });
120 
121     return hitBreakpoints;
122 }
123 
RemoveBreakpoints(const std::function<bool (const PtLocation & loc)> & filter)124 void BreakpointStorage::RemoveBreakpoints(const std::function<bool(const PtLocation &loc)> &filter)
125 {
126     os::memory::WriteLockHolder lock(lock_);
127 
128     std::vector<BreakpointId> breakpointsToRemove;
129     for (const auto &[loc, id] : breakpointLocations_) {
130         if (filter(loc)) {
131             breakpointsToRemove.emplace_back(id);
132         }
133     }
134 
135     for (auto id : breakpointsToRemove) {
136         for (auto it = breakpointLocations_.begin(); it != breakpointLocations_.end();) {
137             if (it->second == id) {
138                 it = breakpointLocations_.erase(it);
139             } else {
140                 ++it;
141             }
142         }
143         breakpointStorage_.erase(id);
144     }
145 }
146 
147 }  // namespace ark::tooling::inspector
148