• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "tooling/client/domain/debugger_client.h"
17 
18 #include <map>
19 
20 #include "common/log_wrapper.h"
21 #include "tooling/client/manager/breakpoint_manager.h"
22 #include "tooling/client/manager/source_manager.h"
23 #include "tooling/client/manager/stack_manager.h"
24 #include "tooling/base/pt_json.h"
25 #include "tooling/client/session/session.h"
26 
27 using PtJson = panda::ecmascript::tooling::PtJson;
28 namespace OHOS::ArkCompiler::Toolchain {
DispatcherCmd(const std::string & cmd)29 bool DebuggerClient::DispatcherCmd(const std::string &cmd)
30 {
31     std::map<std::string, std::function<int()>> dispatcherTable {
32         { "break", std::bind(&DebuggerClient::BreakCommand, this)},
33         { "backtrack", std::bind(&DebuggerClient::BacktrackCommand, this)},
34         { "continue", std::bind(&DebuggerClient::ResumeCommand, this)},
35         { "delete", std::bind(&DebuggerClient::DeleteCommand, this)},
36         { "jump", std::bind(&DebuggerClient::JumpCommand, this)},
37         { "disable", std::bind(&DebuggerClient::DisableCommand, this)},
38         { "display", std::bind(&DebuggerClient::DisplayCommand, this)},
39         { "enable", std::bind(&DebuggerClient::EnableCommand, this)},
40         { "finish", std::bind(&DebuggerClient::FinishCommand, this)},
41         { "frame", std::bind(&DebuggerClient::FrameCommand, this)},
42         { "ignore", std::bind(&DebuggerClient::IgnoreCommand, this)},
43         { "infobreakpoints", std::bind(&DebuggerClient::InfobreakpointsCommand, this)},
44         { "infosource", std::bind(&DebuggerClient::InfosourceCommand, this)},
45         { "list", std::bind(&DebuggerClient::ListCommand, this)},
46         { "next", std::bind(&DebuggerClient::NextCommand, this)},
47         { "ptype", std::bind(&DebuggerClient::PtypeCommand, this)},
48         { "run", std::bind(&DebuggerClient::RunCommand, this)},
49         { "setvar", std::bind(&DebuggerClient::SetvarCommand, this)},
50         { "step", std::bind(&DebuggerClient::StepCommand, this)},
51         { "undisplay", std::bind(&DebuggerClient::UndisplayCommand, this)},
52         { "watch", std::bind(&DebuggerClient::WatchCommand, this)},
53         { "resume", std::bind(&DebuggerClient::ResumeCommand, this)},
54         { "step-into", std::bind(&DebuggerClient::StepIntoCommand, this)},
55         { "step-out", std::bind(&DebuggerClient::StepOutCommand, this)},
56         { "step-over", std::bind(&DebuggerClient::StepOverCommand, this)},
57         { "enable-launch-accelerate", std::bind(&DebuggerClient::EnableLaunchAccelerateCommand, this)},
58         { "saveAllPossibleBreakpoints", std::bind(&DebuggerClient::SaveAllPossibleBreakpointsCommand, this)},
59     };
60 
61     auto entry = dispatcherTable.find(cmd);
62     if (entry != dispatcherTable.end()) {
63         entry->second();
64         LOGI("DebuggerClient DispatcherCmd cmd: %{public}s", cmd.c_str());
65         return true;
66     }
67 
68     LOGI("unknown command: %{public}s", cmd.c_str());
69     return false;
70 }
71 
BreakCommand()72 int DebuggerClient::BreakCommand()
73 {
74     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
75     uint32_t id = session->GetMessageId();
76 
77     std::unique_ptr<PtJson> request = PtJson::CreateObject();
78     request->Add("id", id);
79     request->Add("method", "Debugger.setBreakpointByUrl");
80 
81     std::unique_ptr<PtJson> params = PtJson::CreateObject();
82     params->Add("columnNumber", breakPointInfoList_.back().columnNumber);
83     params->Add("lineNumber", breakPointInfoList_.back().lineNumber);
84     params->Add("url", breakPointInfoList_.back().url.c_str());
85     request->Add("params", params);
86 
87     std::string message = request->Stringify();
88     if (session->ClientSendReq(message)) {
89         session->GetDomainManager().SetDomainById(id, "Debugger");
90     }
91     return 0;
92 }
93 
BacktrackCommand()94 int DebuggerClient::BacktrackCommand()
95 {
96     return 0;
97 }
98 
DeleteCommand()99 int DebuggerClient::DeleteCommand()
100 {
101     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
102     uint32_t id = session->GetMessageId();
103 
104     std::unique_ptr<PtJson> request = PtJson::CreateObject();
105     request->Add("id", id);
106     request->Add("method", "Debugger.removeBreakpoint");
107 
108     std::unique_ptr<PtJson> params = PtJson::CreateObject();
109     std::string breakpointId = breakPointInfoList_.back().url;
110     params->Add("breakpointId", breakpointId.c_str());
111     request->Add("params", params);
112 
113     std::string message = request->Stringify();
114     if (session->ClientSendReq(message)) {
115         session->GetDomainManager().SetDomainById(id, "Debugger");
116     }
117     return 0;
118 }
119 
DisableCommand()120 int DebuggerClient::DisableCommand()
121 {
122     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
123     uint32_t id = session->GetMessageId();
124 
125     std::unique_ptr<PtJson> request = PtJson::CreateObject();
126     request->Add("id", id);
127     request->Add("method", "Debugger.disable");
128 
129     std::unique_ptr<PtJson> params = PtJson::CreateObject();
130     request->Add("params", params);
131 
132     std::string message = request->Stringify();
133     if (session->ClientSendReq(message)) {
134         session->GetDomainManager().SetDomainById(id, "Debugger");
135     }
136     return 0;
137 }
138 
DisplayCommand()139 int DebuggerClient::DisplayCommand()
140 {
141     return 0;
142 }
143 
EnableCommand()144 int DebuggerClient::EnableCommand()
145 {
146     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
147     uint32_t id = session->GetMessageId();
148 
149     std::unique_ptr<PtJson> request = PtJson::CreateObject();
150     request->Add("id", id);
151     request->Add("method", "Debugger.enable");
152 
153     std::unique_ptr<PtJson> params = PtJson::CreateObject();
154     request->Add("params", params);
155 
156     std::string message = request->Stringify();
157     if (session->ClientSendReq(message)) {
158         session->GetDomainManager().SetDomainById(id, "Debugger");
159     }
160     return 0;
161 }
162 
FinishCommand()163 int DebuggerClient::FinishCommand()
164 {
165     return 0;
166 }
167 
FrameCommand()168 int DebuggerClient::FrameCommand()
169 {
170     return 0;
171 }
172 
IgnoreCommand()173 int DebuggerClient::IgnoreCommand()
174 {
175     return 0;
176 }
177 
InfobreakpointsCommand()178 int DebuggerClient::InfobreakpointsCommand()
179 {
180     return 0;
181 }
182 
InfosourceCommand()183 int DebuggerClient::InfosourceCommand()
184 {
185     return 0;
186 }
187 
JumpCommand()188 int DebuggerClient::JumpCommand()
189 {
190     return 0;
191 }
192 
NextCommand()193 int DebuggerClient::NextCommand()
194 {
195     return 0;
196 }
197 
ListCommand()198 int DebuggerClient::ListCommand()
199 {
200     return 0;
201 }
202 
PtypeCommand()203 int DebuggerClient::PtypeCommand()
204 {
205     return 0;
206 }
207 
RunCommand()208 int DebuggerClient::RunCommand()
209 {
210     return 0;
211 }
212 
SetvarCommand()213 int DebuggerClient::SetvarCommand()
214 {
215     return 0;
216 }
217 
StepCommand()218 int DebuggerClient::StepCommand()
219 {
220     return 0;
221 }
222 
UndisplayCommand()223 int DebuggerClient::UndisplayCommand()
224 {
225     return 0;
226 }
227 
WatchCommand()228 int DebuggerClient::WatchCommand()
229 {
230     return 0;
231 }
232 
ResumeCommand()233 int DebuggerClient::ResumeCommand()
234 {
235     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
236     uint32_t id = session->GetMessageId();
237 
238     std::unique_ptr<PtJson> request = PtJson::CreateObject();
239     request->Add("id", id);
240     request->Add("method", "Debugger.resume");
241 
242     std::unique_ptr<PtJson> params = PtJson::CreateObject();
243     request->Add("params", params);
244 
245     std::string message = request->Stringify();
246     if (session->ClientSendReq(message)) {
247         session->GetDomainManager().SetDomainById(id, "Debugger");
248     }
249     return 0;
250 }
251 
StepIntoCommand()252 int DebuggerClient::StepIntoCommand()
253 {
254     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
255     uint32_t id = session->GetMessageId();
256 
257     std::unique_ptr<PtJson> request = PtJson::CreateObject();
258     request->Add("id", id);
259     request->Add("method", "Debugger.stepInto");
260 
261     std::unique_ptr<PtJson> params = PtJson::CreateObject();
262     request->Add("params", params);
263 
264     std::string message = request->Stringify();
265     if (session->ClientSendReq(message)) {
266         session->GetDomainManager().SetDomainById(id, "Debugger");
267     }
268     return 0;
269 }
270 
StepOutCommand()271 int DebuggerClient::StepOutCommand()
272 {
273     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
274     uint32_t id = session->GetMessageId();
275 
276     std::unique_ptr<PtJson> request = PtJson::CreateObject();
277     request->Add("id", id);
278     request->Add("method", "Debugger.stepOut");
279 
280     std::unique_ptr<PtJson> params = PtJson::CreateObject();
281     request->Add("params", params);
282 
283     std::string message = request->Stringify();
284     if (session->ClientSendReq(message)) {
285         session->GetDomainManager().SetDomainById(id, "Debugger");
286     }
287     return 0;
288 }
289 
StepOverCommand()290 int DebuggerClient::StepOverCommand()
291 {
292     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
293     uint32_t id = session->GetMessageId();
294 
295     std::unique_ptr<PtJson> request = PtJson::CreateObject();
296     request->Add("id", id);
297     request->Add("method", "Debugger.stepOver");
298 
299     std::unique_ptr<PtJson> params = PtJson::CreateObject();
300     request->Add("params", params);
301 
302     std::string message = request->Stringify();
303     if (session->ClientSendReq(message)) {
304         session->GetDomainManager().SetDomainById(id, "Debugger");
305     }
306     return 0;
307 }
308 
AddBreakPointInfo(const std::string & url,const int & lineNumber,const int & columnNumber)309 void DebuggerClient::AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber)
310 {
311     BreakPointInfo breakPointInfo;
312     breakPointInfo.url = url;
313     breakPointInfo.lineNumber = lineNumber - 1;
314     breakPointInfo.columnNumber = columnNumber;
315     breakPointInfoList_.emplace_back(breakPointInfo);
316 }
317 
RecvReply(std::unique_ptr<PtJson> json)318 void DebuggerClient::RecvReply(std::unique_ptr<PtJson> json)
319 {
320     if (json == nullptr) {
321         LOGE("arkdb: json parse error");
322         return;
323     }
324 
325     if (!json->IsObject()) {
326         LOGE("arkdb: json parse format error");
327         json->ReleaseRoot();
328         return;
329     }
330 
331     std::string wholeMethod;
332     std::string method;
333     Result ret = json->GetString("method", &wholeMethod);
334     if (ret != Result::SUCCESS) {
335         LOGE("arkdb: find method error");
336     }
337 
338     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
339     SourceManager &sourceManager = session->GetSourceManager();
340     WatchManager &watchManager = session->GetWatchManager();
341 
342     std::string::size_type length = wholeMethod.length();
343     std::string::size_type indexPoint = 0;
344     indexPoint = wholeMethod.find_first_of('.', 0);
345     method = wholeMethod.substr(indexPoint + 1, length);
346     if (method == "paused") {
347         PausedReply(std::move(json));
348         return;
349     } else if (method == "scriptParsed") {
350         sourceManager.EnableReply(std::move(json));
351         return;
352     } else if (method == "resumed") {
353         watchManager.DebugFalseState();
354         return;
355     } else {
356         LOGI("arkdb: Debugger reply is: %{public}s", json->Stringify().c_str());
357     }
358     handleResponse(std::move(json));
359 }
360 
PausedReply(const std::unique_ptr<PtJson> json)361 void DebuggerClient::PausedReply(const std::unique_ptr<PtJson> json)
362 {
363     if (json == nullptr) {
364         LOGE("arkdb: json parse error");
365         return;
366     }
367 
368     if (!json->IsObject()) {
369         LOGE("arkdb: json parse format error");
370         json->ReleaseRoot();
371         return;
372     }
373 
374     std::unique_ptr<PtJson> params;
375     Result ret = json->GetObject("params", &params);
376     if (ret != Result::SUCCESS) {
377         LOGE("arkdb: find params error");
378         return;
379     }
380 
381     std::unique_ptr<PtJson> callFrames;
382     ret = params->GetArray("callFrames", &callFrames);
383     if (ret != Result::SUCCESS) {
384         LOGE("arkdb: find callFrames error");
385         return;
386     }
387 
388     std::map<int32_t, std::unique_ptr<CallFrame>> data;
389     for (int32_t i = 0; i < callFrames->GetSize(); i++) {
390         std::unique_ptr<CallFrame> callFrameInfo = CallFrame::Create(*(callFrames->Get(i)));
391         data.emplace(i + 1, std::move(callFrameInfo));
392     }
393 
394     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
395     StackManager& stackManager = session->GetStackManager();
396     SourceManager &sourceManager = session->GetSourceManager();
397     WatchManager &watchManager = session->GetWatchManager();
398     stackManager.ClearCallFrame();
399     stackManager.SetCallFrames(std::move(data));
400     sourceManager.GetDebugSources(callFrames->Get(0));
401     watchManager.RequestWatchInfo(callFrames->Get(0));
402     watchManager.DebugTrueState();
403 }
404 
handleResponse(std::unique_ptr<PtJson> json)405 void DebuggerClient::handleResponse(std::unique_ptr<PtJson> json)
406 {
407     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
408     SourceManager &sourceManager = session->GetSourceManager();
409     WatchManager &watchManager = session->GetWatchManager();
410     BreakPointManager& breakpoint = session->GetBreakPointManager();
411     std::unique_ptr<PtJson> result;
412     Result ret = json->GetObject("result", &result);
413     if (ret != Result::SUCCESS) {
414         LOGE("arkdb: find result error");
415         return;
416     }
417     int32_t id;
418     ret = json->GetInt("id", &id);
419     if (ret == Result::SUCCESS) {
420         std::string scriptSource;
421         ret = result->GetString("scriptSource", &scriptSource);
422         if (ret == Result::SUCCESS) {
423             sourceManager.SetFileSource(id, scriptSource);
424             return;
425         }
426     }
427     std::string breakpointId;
428     ret = result->GetString("breakpointId", &breakpointId);
429     if (ret == Result::SUCCESS) {
430         breakpoint.Createbreaklocation(std::move(json));
431         return;
432     }
433     if (watchManager.HandleWatchResult(std::move(json), id)) {
434         return;
435     }
436     return;
437 }
438 
SaveAllPossibleBreakpointsCommand()439 int DebuggerClient::SaveAllPossibleBreakpointsCommand()
440 {
441     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
442     uint32_t id = session->GetMessageId();
443 
444     std::unique_ptr<PtJson> request = PtJson::CreateObject();
445     request->Add("id", id);
446     request->Add("method", "Debugger.saveAllPossibleBreakpoints");
447 
448     std::unique_ptr<PtJson> params = PtJson::CreateObject();
449     std::unique_ptr<PtJson> locations = PtJson::CreateObject();
450     std::unique_ptr<PtJson> vector = PtJson::CreateArray();
451 
452     std::unique_ptr<PtJson> bp = PtJson::CreateObject();
453     bp->Add("lineNumber", breakPointInfoList_.back().lineNumber);
454     bp->Add("columnNumber", breakPointInfoList_.back().columnNumber);
455     vector->Push(bp);
456     locations->Add(breakPointInfoList_.back().url.c_str(), vector);
457     params->Add("locations", locations);
458     request->Add("params", params);
459 
460     std::string message = request->Stringify();
461     if (session->ClientSendReq(message)) {
462         session->GetDomainManager().SetDomainById(id, "Debugger");
463     }
464 
465     return 0;
466 }
467 
EnableLaunchAccelerateCommand()468 int DebuggerClient::EnableLaunchAccelerateCommand()
469 {
470     Session *session = SessionManager::getInstance().GetSessionById(sessionId_);
471     uint32_t id = session->GetMessageId();
472 
473     std::unique_ptr<PtJson> request = PtJson::CreateObject();
474     request->Add("id", id);
475     request->Add("method", "Debugger.enable");
476 
477     std::unique_ptr<PtJson> params = PtJson::CreateObject();
478     std::unique_ptr<PtJson> options = PtJson::CreateArray();
479 
480     options->Push("enableLaunchAccelerate");
481     params->Add("options", options);
482     request->Add("params", params);
483 
484     std::string message = request->Stringify();
485     if (session->ClientSendReq(message)) {
486         session->GetDomainManager().SetDomainById(id, "Debugger");
487     }
488 
489     return 0;
490 }
491 } // OHOS::ArkCompiler::Toolchain