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