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 27using PtJson = panda::ecmascript::tooling::PtJson; 28namespace OHOS::ArkCompiler::Toolchain { 29bool 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 }; 58 59 auto entry = dispatcherTable.find(cmd); 60 if (entry != dispatcherTable.end()) { 61 entry->second(); 62 LOGI("DebuggerClient DispatcherCmd cmd: %{public}s", cmd.c_str()); 63 return true; 64 } 65 66 LOGI("unknown command: %{public}s", cmd.c_str()); 67 return false; 68} 69 70int DebuggerClient::BreakCommand() 71{ 72 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 73 uint32_t id = session->GetMessageId(); 74 75 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 76 request->Add("id", id); 77 request->Add("method", "Debugger.setBreakpointByUrl"); 78 79 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 80 params->Add("columnNumber", breakPointInfoList_.back().columnNumber); 81 params->Add("lineNumber", breakPointInfoList_.back().lineNumber); 82 params->Add("url", breakPointInfoList_.back().url.c_str()); 83 request->Add("params", params); 84 85 std::string message = request->Stringify(); 86 if (session->ClientSendReq(message)) { 87 session->GetDomainManager().SetDomainById(id, "Debugger"); 88 } 89 return 0; 90} 91 92int DebuggerClient::BacktrackCommand() 93{ 94 return 0; 95} 96 97int DebuggerClient::DeleteCommand() 98{ 99 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 100 uint32_t id = session->GetMessageId(); 101 102 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 103 request->Add("id", id); 104 request->Add("method", "Debugger.removeBreakpoint"); 105 106 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 107 std::string breakpointId = breakPointInfoList_.back().url; 108 params->Add("breakpointId", breakpointId.c_str()); 109 request->Add("params", params); 110 111 std::string message = request->Stringify(); 112 if (session->ClientSendReq(message)) { 113 session->GetDomainManager().SetDomainById(id, "Debugger"); 114 } 115 return 0; 116} 117 118int DebuggerClient::DisableCommand() 119{ 120 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 121 uint32_t id = session->GetMessageId(); 122 123 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 124 request->Add("id", id); 125 request->Add("method", "Debugger.disable"); 126 127 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 128 request->Add("params", params); 129 130 std::string message = request->Stringify(); 131 if (session->ClientSendReq(message)) { 132 session->GetDomainManager().SetDomainById(id, "Debugger"); 133 } 134 return 0; 135} 136 137int DebuggerClient::DisplayCommand() 138{ 139 return 0; 140} 141 142int DebuggerClient::EnableCommand() 143{ 144 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 145 uint32_t id = session->GetMessageId(); 146 147 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 148 request->Add("id", id); 149 request->Add("method", "Debugger.enable"); 150 151 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 152 request->Add("params", params); 153 154 std::string message = request->Stringify(); 155 if (session->ClientSendReq(message)) { 156 session->GetDomainManager().SetDomainById(id, "Debugger"); 157 } 158 return 0; 159} 160 161int DebuggerClient::FinishCommand() 162{ 163 return 0; 164} 165 166int DebuggerClient::FrameCommand() 167{ 168 return 0; 169} 170 171int DebuggerClient::IgnoreCommand() 172{ 173 return 0; 174} 175 176int DebuggerClient::InfobreakpointsCommand() 177{ 178 return 0; 179} 180 181int DebuggerClient::InfosourceCommand() 182{ 183 return 0; 184} 185 186int DebuggerClient::JumpCommand() 187{ 188 return 0; 189} 190 191int DebuggerClient::NextCommand() 192{ 193 return 0; 194} 195 196int DebuggerClient::ListCommand() 197{ 198 return 0; 199} 200 201int DebuggerClient::PtypeCommand() 202{ 203 return 0; 204} 205 206int DebuggerClient::RunCommand() 207{ 208 return 0; 209} 210 211int DebuggerClient::SetvarCommand() 212{ 213 return 0; 214} 215 216int DebuggerClient::StepCommand() 217{ 218 return 0; 219} 220 221int DebuggerClient::UndisplayCommand() 222{ 223 return 0; 224} 225 226int DebuggerClient::WatchCommand() 227{ 228 return 0; 229} 230 231int DebuggerClient::ResumeCommand() 232{ 233 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 234 uint32_t id = session->GetMessageId(); 235 236 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 237 request->Add("id", id); 238 request->Add("method", "Debugger.resume"); 239 240 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 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 250int DebuggerClient::StepIntoCommand() 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.stepInto"); 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 269int DebuggerClient::StepOutCommand() 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.stepOut"); 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 288int DebuggerClient::StepOverCommand() 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.stepOver"); 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 307void DebuggerClient::AddBreakPointInfo(const std::string& url, const int& lineNumber, const int& columnNumber) 308{ 309 BreakPointInfo breakPointInfo; 310 breakPointInfo.url = url; 311 breakPointInfo.lineNumber = lineNumber - 1; 312 breakPointInfo.columnNumber = columnNumber; 313 breakPointInfoList_.emplace_back(breakPointInfo); 314} 315 316void DebuggerClient::RecvReply(std::unique_ptr<PtJson> json) 317{ 318 if (json == nullptr) { 319 LOGE("arkdb: json parse error"); 320 return; 321 } 322 323 if (!json->IsObject()) { 324 LOGE("arkdb: json parse format error"); 325 json->ReleaseRoot(); 326 return; 327 } 328 329 std::string wholeMethod; 330 std::string method; 331 Result ret = json->GetString("method", &wholeMethod); 332 if (ret != Result::SUCCESS) { 333 LOGE("arkdb: find method error"); 334 } 335 336 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 337 SourceManager &sourceManager = session->GetSourceManager(); 338 WatchManager &watchManager = session->GetWatchManager(); 339 340 std::string::size_type length = wholeMethod.length(); 341 std::string::size_type indexPoint = 0; 342 indexPoint = wholeMethod.find_first_of('.', 0); 343 method = wholeMethod.substr(indexPoint + 1, length); 344 if (method == "paused") { 345 PausedReply(std::move(json)); 346 return; 347 } else if (method == "scriptParsed") { 348 sourceManager.EnableReply(std::move(json)); 349 return; 350 } else if (method == "resumed") { 351 watchManager.DebugFalseState(); 352 return; 353 } else { 354 LOGI("arkdb: Debugger reply is: %{public}s", json->Stringify().c_str()); 355 } 356 handleResponse(std::move(json)); 357} 358 359void DebuggerClient::PausedReply(const std::unique_ptr<PtJson> json) 360{ 361 if (json == nullptr) { 362 LOGE("arkdb: json parse error"); 363 return; 364 } 365 366 if (!json->IsObject()) { 367 LOGE("arkdb: json parse format error"); 368 json->ReleaseRoot(); 369 return; 370 } 371 372 std::unique_ptr<PtJson> params; 373 Result ret = json->GetObject("params", ¶ms); 374 if (ret != Result::SUCCESS) { 375 LOGE("arkdb: find params error"); 376 return; 377 } 378 379 std::unique_ptr<PtJson> callFrames; 380 ret = params->GetArray("callFrames", &callFrames); 381 if (ret != Result::SUCCESS) { 382 LOGE("arkdb: find callFrames error"); 383 return; 384 } 385 386 std::map<int32_t, std::unique_ptr<CallFrame>> data; 387 for (int32_t i = 0; i < callFrames->GetSize(); i++) { 388 std::unique_ptr<CallFrame> callFrameInfo = CallFrame::Create(*(callFrames->Get(i))); 389 data.emplace(i + 1, std::move(callFrameInfo)); 390 } 391 392 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 393 StackManager& stackManager = session->GetStackManager(); 394 SourceManager &sourceManager = session->GetSourceManager(); 395 WatchManager &watchManager = session->GetWatchManager(); 396 stackManager.ClearCallFrame(); 397 stackManager.SetCallFrames(std::move(data)); 398 sourceManager.GetDebugSources(callFrames->Get(0)); 399 watchManager.RequestWatchInfo(callFrames->Get(0)); 400 watchManager.DebugTrueState(); 401} 402 403void DebuggerClient::handleResponse(std::unique_ptr<PtJson> json) 404{ 405 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 406 SourceManager &sourceManager = session->GetSourceManager(); 407 WatchManager &watchManager = session->GetWatchManager(); 408 BreakPointManager& breakpoint = session->GetBreakPointManager(); 409 std::unique_ptr<PtJson> result; 410 Result ret = json->GetObject("result", &result); 411 if (ret != Result::SUCCESS) { 412 LOGE("arkdb: find result error"); 413 return; 414 } 415 int32_t id; 416 ret = json->GetInt("id", &id); 417 if (ret == Result::SUCCESS) { 418 std::string scriptSource; 419 ret = result->GetString("scriptSource", &scriptSource); 420 if (ret == Result::SUCCESS) { 421 sourceManager.SetFileSource(id, scriptSource); 422 return; 423 } 424 } 425 std::string breakpointId; 426 ret = result->GetString("breakpointId", &breakpointId); 427 if (ret == Result::SUCCESS) { 428 breakpoint.Createbreaklocation(std::move(json)); 429 return; 430 } 431 if (watchManager.HandleWatchResult(std::move(json), id)) { 432 return; 433 } 434 return; 435} 436} // OHOS::ArkCompiler::Toolchain