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/runtime_client.h" 17 18#include "common/log_wrapper.h" 19#include "tooling/client/manager/variable_manager.h" 20#include "tooling/client/manager/watch_manager.h" 21#include "tooling/base/pt_json.h" 22#include "tooling/client/session/session.h" 23#include "tooling/utils/utils.h" 24 25using PtJson = panda::ecmascript::tooling::PtJson; 26namespace OHOS::ArkCompiler::Toolchain { 27bool RuntimeClient::DispatcherCmd(const std::string &cmd) 28{ 29 std::map<std::string, std::function<int()>> dispatcherTable { 30 { "heapusage", std::bind(&RuntimeClient::HeapusageCommand, this)}, 31 { "runtime-enable", std::bind(&RuntimeClient::RuntimeEnableCommand, this)}, 32 { "runtime-disable", std::bind(&RuntimeClient::RuntimeDisableCommand, this)}, 33 { "print", std::bind(&RuntimeClient::GetPropertiesCommand, this)}, 34 { "run", std::bind(&RuntimeClient::RunIfWaitingForDebuggerCommand, this)}, 35 }; 36 37 auto entry = dispatcherTable.find(cmd); 38 if (entry != dispatcherTable.end()) { 39 entry->second(); 40 LOGI("RuntimeClient DispatcherCmd reqStr1: %{public}s", cmd.c_str()); 41 return true; 42 } else { 43 LOGI("Unknown commond: %{public}s", cmd.c_str()); 44 return false; 45 } 46} 47 48int RuntimeClient::HeapusageCommand() 49{ 50 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 51 uint32_t id = session->GetMessageId(); 52 53 idMethodMap_[id] = std::make_tuple("getHeapUsage", ""); 54 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 55 request->Add("id", id); 56 request->Add("method", "Runtime.getHeapUsage"); 57 58 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 59 request->Add("params", params); 60 61 std::string message = request->Stringify(); 62 if (session->ClientSendReq(message)) { 63 session->GetDomainManager().SetDomainById(id, "Runtime"); 64 } 65 return 0; 66} 67 68int RuntimeClient::RuntimeEnableCommand() 69{ 70 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 71 uint32_t id = session->GetMessageId(); 72 73 idMethodMap_[id] = std::make_tuple("enable", ""); 74 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 75 request->Add("id", id); 76 request->Add("method", "Runtime.enable"); 77 78 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 79 request->Add("params", params); 80 81 std::string message = request->Stringify(); 82 if (session->ClientSendReq(message)) { 83 session->GetDomainManager().SetDomainById(id, "Runtime"); 84 } 85 return 0; 86} 87 88int RuntimeClient::RuntimeDisableCommand() 89{ 90 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 91 uint32_t id = session->GetMessageId(); 92 93 idMethodMap_[id] = std::make_tuple("disable", ""); 94 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 95 request->Add("id", id); 96 request->Add("method", "Runtime.disable"); 97 98 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 99 request->Add("params", params); 100 101 std::string message = request->Stringify(); 102 if (session->ClientSendReq(message)) { 103 session->GetDomainManager().SetDomainById(id, "Runtime"); 104 } 105 return 0; 106} 107 108int RuntimeClient::RunIfWaitingForDebuggerCommand() 109{ 110 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 111 uint32_t id = session->GetMessageId(); 112 113 idMethodMap_[id] = std::make_tuple("runIfWaitingForDebugger", ""); 114 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 115 request->Add("id", id); 116 request->Add("method", "Runtime.runIfWaitingForDebugger"); 117 118 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 119 request->Add("params", params); 120 121 std::string message = request->Stringify(); 122 if (session->ClientSendReq(message)) { 123 session->GetDomainManager().SetDomainById(id, "Runtime"); 124 } 125 WatchManager &watchManager = session->GetWatchManager(); 126 watchManager.DebugFalseState(); 127 return 0; 128} 129 130int RuntimeClient::GetPropertiesCommand() 131{ 132 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 133 uint32_t id = session->GetMessageId(); 134 135 idMethodMap_[id] = std::make_tuple("getProperties", objectId_); 136 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 137 request->Add("id", id); 138 request->Add("method", "Runtime.getProperties"); 139 140 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 141 params->Add("accessorPropertiesOnly", false); 142 params->Add("generatePreview", true); 143 params->Add("objectId", objectId_.c_str()); 144 params->Add("ownProperties", true); 145 request->Add("params", params); 146 147 std::string message = request->Stringify(); 148 if (session->ClientSendReq(message)) { 149 session->GetDomainManager().SetDomainById(id, "Runtime"); 150 } 151 return 0; 152} 153 154int RuntimeClient::GetPropertiesCommand2() 155{ 156 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 157 uint32_t id = session->GetMessageId(); 158 159 idMethodMap_[id] = std::make_tuple("getProperties", objectId_); 160 std::unique_ptr<PtJson> request = PtJson::CreateObject(); 161 request->Add("id", id); 162 request->Add("method", "Runtime.getProperties"); 163 164 std::unique_ptr<PtJson> params = PtJson::CreateObject(); 165 params->Add("accessorPropertiesOnly", true); 166 params->Add("generatePreview", true); 167 params->Add("objectId", "0"); 168 params->Add("ownProperties", false); 169 request->Add("params", params); 170 171 std::string message = request->Stringify(); 172 if (session->ClientSendReq(message)) { 173 session->GetDomainManager().SetDomainById(id, "Runtime"); 174 } 175 return 0; 176} 177 178void RuntimeClient::RecvReply(std::unique_ptr<PtJson> json) 179{ 180 if (json == nullptr) { 181 LOGE("arkdb: json parse error"); 182 return; 183 } 184 185 if (!json->IsObject()) { 186 LOGE("arkdb: json parse format error"); 187 json->ReleaseRoot(); 188 return; 189 } 190 191 int replyId; 192 Result ret = json->GetInt("id", &replyId); 193 if (ret != Result::SUCCESS) { 194 LOGE("arkdb: find id error"); 195 return; 196 } 197 198 if (GetMethodById(replyId) == "getHeapUsage") { 199 HandleHeapUsage(std::move(json)); 200 } else if (GetMethodById(replyId) == "getProperties") { 201 HandleGetProperties(std::move(json), replyId); 202 } else { 203 LOGI("arkdb: Runtime replay message is %{public}s", json->Stringify().c_str()); 204 } 205} 206 207std::string RuntimeClient::GetMethodById(const int &id) 208{ 209 auto it = idMethodMap_.find(id); 210 if (it != idMethodMap_.end()) { 211 return std::get<0>(it->second); 212 } 213 return ""; 214} 215 216std::string RuntimeClient::GetRequestObjectIdById(const int &id) 217{ 218 auto it = idMethodMap_.find(id); 219 if (it != idMethodMap_.end()) { 220 return std::get<1>(it->second); 221 } 222 return ""; 223} 224 225void RuntimeClient::HandleGetProperties(std::unique_ptr<PtJson> json, const int &id) 226{ 227 if (json == nullptr) { 228 LOGE("arkdb: json parse error"); 229 return; 230 } 231 232 if (!json->IsObject()) { 233 LOGE("arkdb: json parse format error"); 234 json->ReleaseRoot(); 235 return; 236 } 237 238 std::unique_ptr<PtJson> result; 239 Result ret = json->GetObject("result", &result); 240 if (ret != Result::SUCCESS) { 241 LOGE("arkdb: find result error"); 242 return; 243 } 244 245 std::unique_ptr<PtJson> innerResult; 246 ret = result->GetArray("result", &innerResult); 247 if (ret != Result::SUCCESS) { 248 LOGE("arkdb: find innerResult error"); 249 return; 250 } 251 252 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 253 StackManager &stackManager = session->GetStackManager(); 254 VariableManager &variableManager = session->GetVariableManager(); 255 std::map<int32_t, std::map<int32_t, std::string>> treeInfo = stackManager.GetScopeChainInfo(); 256 if (isInitializeTree_) { 257 variableManager.ClearVariableInfo(); 258 variableManager.InitializeTree(treeInfo); 259 } 260 std::string requestObjectIdStr = GetRequestObjectIdById(id); 261 TreeNode *node = nullptr; 262 if (!isInitializeTree_) { 263 int32_t requestObjectId; 264 if (!Utils::StrToInt32(requestObjectIdStr, requestObjectId)) { 265 LOGE("arkdb: convert 'requestObjectId' from string to int error"); 266 return; 267 } 268 node = variableManager.FindNodeWithObjectId(requestObjectId); 269 } else { 270 node = variableManager.FindNodeObjectZero(); 271 } 272 273 for (int32_t i = 0; i < innerResult->GetSize(); i++) { 274 std::unique_ptr<PropertyDescriptor> variableInfo = PropertyDescriptor::Create(*(innerResult->Get(i))); 275 variableManager.AddVariableInfo(node, std::move(variableInfo)); 276 } 277 278 std::cout << std::endl; 279 variableManager.PrintVariableInfo(); 280} 281 282void RuntimeClient::HandleHeapUsage(std::unique_ptr<PtJson> json) 283{ 284 if (json == nullptr) { 285 LOGE("arkdb: json parse error"); 286 return; 287 } 288 289 if (!json->IsObject()) { 290 LOGE("arkdb: json parse format error"); 291 json->ReleaseRoot(); 292 return; 293 } 294 295 std::unique_ptr<PtJson> result; 296 Result ret = json->GetObject("result", &result); 297 if (ret != Result::SUCCESS) { 298 LOGE("arkdb: find result error"); 299 return; 300 } 301 302 Session *session = SessionManager::getInstance().GetSessionById(sessionId_); 303 VariableManager &variableManager = session->GetVariableManager(); 304 std::unique_ptr<GetHeapUsageReturns> heapUsageReturns = GetHeapUsageReturns::Create(*result); 305 variableManager.SetHeapUsageInfo(std::move(heapUsageReturns)); 306 variableManager.ShowHeapUsageInfo(); 307} 308} // OHOS::ArkCompiler::Toolchain