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