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