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
25 using PtJson = panda::ecmascript::tooling::PtJson;
26 namespace OHOS::ArkCompiler::Toolchain {
DispatcherCmd(const std::string &cmd)27 bool 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
HeapusageCommand()48 int 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
RuntimeEnableCommand()68 int 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
RuntimeDisableCommand()88 int 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
RunIfWaitingForDebuggerCommand()108 int 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
GetPropertiesCommand()130 int 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
GetPropertiesCommand2()154 int 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
RecvReply(std::unique_ptr<PtJson> json)178 void 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
GetMethodById(const int &id)207 std::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
GetRequestObjectIdById(const int &id)216 std::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
HandleGetProperties(std::unique_ptr<PtJson> json, const int &id)225 void 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
HandleHeapUsage(std::unique_ptr<PtJson> json)282 void 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