From 53ca7e5e277bfe60db277824b25bfdf7c5e8f727 Mon Sep 17 00:00:00 2001 From: kurnevichstanislav Date: Tue, 28 Nov 2023 19:21:35 +0300 Subject: [PATCH 1/3] Init implementation of InspectorServer representation as a worker Signed-off-by: kurnevichstanislav --- .../runtime/tooling/inspector/BUILD.gn | 1 + .../runtime/tooling/inspector/CMakeLists.txt | 1 + .../tooling/inspector/connect_manager.cpp | 53 +++++++++ .../tooling/inspector/connect_manager.h | 106 ++++++++++++++++++ .../tooling/inspector/inspector_server.cpp | 7 ++ .../tooling/inspector/inspector_server.h | 4 +- 6 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 static_core/runtime/tooling/inspector/connect_manager.cpp create mode 100644 static_core/runtime/tooling/inspector/connect_manager.h diff --git a/static_core/runtime/tooling/inspector/BUILD.gn b/static_core/runtime/tooling/inspector/BUILD.gn index 76d05f6c85..80efb2f4c2 100644 --- a/static_core/runtime/tooling/inspector/BUILD.gn +++ b/static_core/runtime/tooling/inspector/BUILD.gn @@ -36,6 +36,7 @@ libarkinspector_sources = [ "types/object_preview.cpp", "types/remote_object.cpp", "types/scope.cpp", + "connect_manager.cpp", ] config("libarkinspector_config") { diff --git a/static_core/runtime/tooling/inspector/CMakeLists.txt b/static_core/runtime/tooling/inspector/CMakeLists.txt index 05dc2b86be..f243053811 100644 --- a/static_core/runtime/tooling/inspector/CMakeLists.txt +++ b/static_core/runtime/tooling/inspector/CMakeLists.txt @@ -16,6 +16,7 @@ cmake_minimum_required(VERSION 3.10) project(arkinspector) set(ARKINSPECTOR_ROOTS + connect_manager.cpp connection/endpoint_base.cpp connection/event_loop.cpp connection/server_endpoint_base.cpp diff --git a/static_core/runtime/tooling/inspector/connect_manager.cpp b/static_core/runtime/tooling/inspector/connect_manager.cpp new file mode 100644 index 0000000000..50c4d093a7 --- /dev/null +++ b/static_core/runtime/tooling/inspector/connect_manager.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "connect_manager.h" +#include "utils/json_builder.h" + +namespace panda::tooling::inspector { + +bool IDEConnectManager::AddWorkerInstance(int32_t instance_id, const std::string &instance_name) +{ + auto wait_for_connection = + connect_server_lib_.GetFunction("WaitForConnection"); + auto send_message = connect_server_lib_.GetFunction("SendMessage"); + auto store_message = connect_server_lib_.GetFunction("StoreMessage"); + + if (!wait_for_connection || !send_message || !store_message) { + return false; + } + + JsonObjectBuilder builder; + builder.AddProperty("type", "addInstance"); + builder.AddProperty("instanceId", std::to_string(instance_id)); + builder.AddProperty("name", instance_name); + builder.AddProperty("tid", std::to_string(os::thread::GetCurrentThreadId())); + builder.AddProperty("apiType", "stageMode"); + builder.AddProperty("language", "ArkTS"); + + std::string message = std::move(builder).Build(); + + store_message(instance_id, message); + + if (wait_for_connection()) { + return false; + } + + send_message(message); + + return true; +} + +} // namespace panda::tooling::inspector diff --git a/static_core/runtime/tooling/inspector/connect_manager.h b/static_core/runtime/tooling/inspector/connect_manager.h new file mode 100644 index 0000000000..cd9ca1a11d --- /dev/null +++ b/static_core/runtime/tooling/inspector/connect_manager.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PANDA_TOOLING_INSPECTOR_CONNECT_SERVER_MANAGER +#define PANDA_TOOLING_INSPECTOR_CONNECT_SERVER_MANAGER + +#include "macros.h" +#include "utils/logger.h" +#include "os/library_loader.h" + +#include + +namespace panda::tooling::inspector { + +// Help to work with OHOS library for connection with IDE libconnectserver_debugger.z.so +class ConnectServerLib final { +public: + // clang-format off + using StartServer = void (*)(const std::string&); + using SendMessage = void (*)(const std::string&); + using SendLayoutMessage = void (*)(const std::string&); + using StopServer = void (*)(const std::string&); + using StoreMessage = void (*)(int32_t, const std::string&); + using StoreInspectorInfo = void (*)(const std::string&, const std::string&); + using SetSwitchCallBack = void (*)(const std::function &setStatus, + const std::function &createLayoutInfo, + int32_t instanceId); + using RemoveMessage = void (*)(int32_t); + using WaitForConnection = bool (*)(); + // clang-format on + +public: + NO_COPY_SEMANTIC(ConnectServerLib); + NO_MOVE_SEMANTIC(ConnectServerLib); + + ConnectServerLib() + { + auto handle = os::library_loader::Load(CONNECTION_LIB_NAME); + if (!handle) { + LOG(FATAL, DEBUGGER) << "Failed to load : " << CONNECTION_LIB_NAME; + return; + } + connect_server_lib_handle_ = std::move(handle.Value()); + } + + ~ConnectServerLib() + { + os::library_loader::CloseHandle(connect_server_lib_handle_.GetNativeHandle()); + } + + template + T GetFunction(const std::string &sym) + { + if (!connect_server_lib_handle_.IsValid()) { + LOG(INFO, DEBUGGER) << "ConnectServerFunction::GetFunction connect_server_lib_handle_ is nullptr"; + return nullptr; + } + + auto handle = os::library_loader::ResolveSymbol(connect_server_lib_handle_, sym); + if (!handle) { + LOG(INFO, DEBUGGER) << "ConnectServerFunction::GetFunction failed to find symbol " << sym; + return nullptr; + } + + void *func_handle = handle.Value(); + + return reinterpret_cast(func_handle); + } + +private: + static constexpr const char *CONNECTION_LIB_NAME = "libconnectserver_debugger.z.so"; + + panda::os::library_loader::LibraryHandle connect_server_lib_handle_ {nullptr}; +}; + +class IDEConnectManager final { +public: + NO_COPY_SEMANTIC(IDEConnectManager); + NO_MOVE_SEMANTIC(IDEConnectManager); + + IDEConnectManager(); + ~IDEConnectManager(); + + // Represent thread to JSRuntime as JS worker + // In our case instance_id is equal to thread_id + bool AddWorkerInstance(int32_t instance_id, const std::string &instance_name); + +private: + ConnectServerLib connect_server_lib_; +}; + +} // namespace panda::tooling::inspector + +#endif // PANDA_TOOLING_INSPECTOR_CONNECT_SERVER_MANAGER diff --git a/static_core/runtime/tooling/inspector/inspector_server.cpp b/static_core/runtime/tooling/inspector/inspector_server.cpp index bee9ccbd4b..e9ebdfa366 100644 --- a/static_core/runtime/tooling/inspector/inspector_server.cpp +++ b/static_core/runtime/tooling/inspector/inspector_server.cpp @@ -44,6 +44,13 @@ void InspectorServer::Kill() void InspectorServer::Run() { + // TODO: add some option, like connectToDevEco = true/false + if (true) { + // static_cast is ok here, because function cast pid_t that is signed int to ThreadId (uint32_t) + int32_t instance_id = static_cast(os::thread::GetCurrentThreadId()); + ideConnectManager_.AddWorkerInstance(instance_id, "ArkEtsVM_InspectorServer"); + } + server_.Run(); } diff --git a/static_core/runtime/tooling/inspector/inspector_server.h b/static_core/runtime/tooling/inspector/inspector_server.h index 7ee1af44f7..6382476c3a 100644 --- a/static_core/runtime/tooling/inspector/inspector_server.h +++ b/static_core/runtime/tooling/inspector/inspector_server.h @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -28,6 +27,7 @@ #include "console_call_type.h" #include "include/tooling/pt_thread.h" +#include "connect_manager.h" #include "session_manager.h" #include "source_manager.h" #include "types/exception_details.h" @@ -121,6 +121,8 @@ private: Server &server_; SessionManager sessionManager_; SourceManager sourceManager_; + + IDEConnectManager ideConnectManager_; }; } // namespace ark::tooling::inspector -- Gitee From a085d5ea0860d652a47243f87b671f8d90ffef9a Mon Sep 17 00:00:00 2001 From: Denis Slynko Date: Tue, 5 Dec 2023 16:15:53 +0300 Subject: [PATCH 2/3] [PT] Notify instrumentation through OHOS ConnectManager Signed-off-by: Denis Slynko --- static_core/runtime/tooling/inspector/connect_manager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static_core/runtime/tooling/inspector/connect_manager.h b/static_core/runtime/tooling/inspector/connect_manager.h index cd9ca1a11d..c8e40c89a8 100644 --- a/static_core/runtime/tooling/inspector/connect_manager.h +++ b/static_core/runtime/tooling/inspector/connect_manager.h @@ -90,8 +90,8 @@ public: NO_COPY_SEMANTIC(IDEConnectManager); NO_MOVE_SEMANTIC(IDEConnectManager); - IDEConnectManager(); - ~IDEConnectManager(); + IDEConnectManager() = default; + ~IDEConnectManager() = default; // Represent thread to JSRuntime as JS worker // In our case instance_id is equal to thread_id -- Gitee From ee66520b16d79be2d116a98a49a6d9e9a615bc05 Mon Sep 17 00:00:00 2001 From: Denis Slynko Date: Tue, 12 Dec 2023 14:20:04 +0300 Subject: [PATCH 3/3] [PT] Start OHOS WsServer properly Change-Id: I79378b2f02ff1b9140b5082a8ab987892a35107d Signed-off-by: Denis Slynko --- static_core/BUILD.gn | 1 + static_core/runtime/runtime.cpp | 5 ++- .../tooling/inspector/connect_manager.cpp | 24 +++++++------- .../tooling/inspector/connect_manager.h | 33 ++++++++++--------- .../connection/ohos_ws/ohos_ws_server.cpp | 9 ++++- .../tooling/inspector/debug_info_cache.cpp | 1 + .../tooling/inspector/inspector_server.cpp | 5 ++- 7 files changed, 46 insertions(+), 32 deletions(-) diff --git a/static_core/BUILD.gn b/static_core/BUILD.gn index b1cbfd87f9..a14ad70a25 100644 --- a/static_core/BUILD.gn +++ b/static_core/BUILD.gn @@ -38,6 +38,7 @@ group("ark_packages") { "$ark_root/runtime/tooling/inspector:libarkinspector", "$ark_root/verification/verifier:verifier.config", "$ark_root/verification/verifier:verifier_bin", + "$ark_root/runtime/tooling/inspector:libarkinspector", ] if (enable_codegen) { deps += [ diff --git a/static_core/runtime/runtime.cpp b/static_core/runtime/runtime.cpp index 7c5d638202..7a34ccbab4 100644 --- a/static_core/runtime/runtime.cpp +++ b/static_core/runtime/runtime.cpp @@ -370,6 +370,8 @@ bool Runtime::Create(const RuntimeOptions &options) options.GetSamplingProfilerInterval()); } + // TODO(dslynko): call this method in proper place + instance_->NotifyAboutLoadedModules(); return true; } @@ -1191,7 +1193,8 @@ Expected Runtime::Execute(std::string_view entryPoint, cons return Unexpected(resolveRes.Error()); } - NotifyAboutLoadedModules(); + // TODO(dslynko): call this method in proper place + // NotifyAboutLoadedModules(); Method *method = resolveRes.Value(); diff --git a/static_core/runtime/tooling/inspector/connect_manager.cpp b/static_core/runtime/tooling/inspector/connect_manager.cpp index 50c4d093a7..ed2cbd1173 100644 --- a/static_core/runtime/tooling/inspector/connect_manager.cpp +++ b/static_core/runtime/tooling/inspector/connect_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,34 +18,34 @@ namespace panda::tooling::inspector { -bool IDEConnectManager::AddWorkerInstance(int32_t instance_id, const std::string &instance_name) +bool IDEConnectManager::AddWorkerInstance(int32_t instanceId, std::string_view instanceName) { - auto wait_for_connection = - connect_server_lib_.GetFunction("WaitForConnection"); - auto send_message = connect_server_lib_.GetFunction("SendMessage"); - auto store_message = connect_server_lib_.GetFunction("StoreMessage"); + auto waitForConnection = + connectServerLib_.GetFunction("WaitForConnection"); + auto sendMessage = connectServerLib_.GetFunction("SendMessage"); + auto storeMessage = connectServerLib_.GetFunction("StoreMessage"); - if (!wait_for_connection || !send_message || !store_message) { + if (!waitForConnection || !sendMessage || !storeMessage) { return false; } JsonObjectBuilder builder; builder.AddProperty("type", "addInstance"); - builder.AddProperty("instanceId", std::to_string(instance_id)); - builder.AddProperty("name", instance_name); + builder.AddProperty("instanceId", std::to_string(instanceId)); + builder.AddProperty("name", instanceName); builder.AddProperty("tid", std::to_string(os::thread::GetCurrentThreadId())); builder.AddProperty("apiType", "stageMode"); builder.AddProperty("language", "ArkTS"); std::string message = std::move(builder).Build(); - store_message(instance_id, message); + storeMessage(instanceId, message); - if (wait_for_connection()) { + if (waitForConnection()) { return false; } - send_message(message); + sendMessage(message); return true; } diff --git a/static_core/runtime/tooling/inspector/connect_manager.h b/static_core/runtime/tooling/inspector/connect_manager.h index c8e40c89a8..49bd368355 100644 --- a/static_core/runtime/tooling/inspector/connect_manager.h +++ b/static_core/runtime/tooling/inspector/connect_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -21,9 +21,12 @@ #include "os/library_loader.h" #include +#include namespace panda::tooling::inspector { +static constexpr std::string_view ARK_TS_INSPECTOR_NAME = "ArkEtsDebugger"; + // Help to work with OHOS library for connection with IDE libconnectserver_debugger.z.so class ConnectServerLib final { public: @@ -34,9 +37,9 @@ public: using StopServer = void (*)(const std::string&); using StoreMessage = void (*)(int32_t, const std::string&); using StoreInspectorInfo = void (*)(const std::string&, const std::string&); - using SetSwitchCallBack = void (*)(const std::function &setStatus, - const std::function &createLayoutInfo, - int32_t instanceId); + using SetSwitchCallBack = void (*)(const std::function &, + const std::function &, + int32_t); using RemoveMessage = void (*)(int32_t); using WaitForConnection = bool (*)(); // clang-format on @@ -52,37 +55,37 @@ public: LOG(FATAL, DEBUGGER) << "Failed to load : " << CONNECTION_LIB_NAME; return; } - connect_server_lib_handle_ = std::move(handle.Value()); + connectServerLibHandle_ = std::move(handle.Value()); } ~ConnectServerLib() { - os::library_loader::CloseHandle(connect_server_lib_handle_.GetNativeHandle()); + os::library_loader::CloseHandle(connectServerLibHandle_.GetNativeHandle()); } template T GetFunction(const std::string &sym) { - if (!connect_server_lib_handle_.IsValid()) { - LOG(INFO, DEBUGGER) << "ConnectServerFunction::GetFunction connect_server_lib_handle_ is nullptr"; + if (!connectServerLibHandle_.IsValid()) { + LOG(ERROR, DEBUGGER) << "ConnectServerFunction::GetFunction library handle is nullptr"; return nullptr; } - auto handle = os::library_loader::ResolveSymbol(connect_server_lib_handle_, sym); + auto handle = os::library_loader::ResolveSymbol(connectServerLibHandle_, sym); if (!handle) { LOG(INFO, DEBUGGER) << "ConnectServerFunction::GetFunction failed to find symbol " << sym; return nullptr; } - void *func_handle = handle.Value(); + void *funcHandle = handle.Value(); - return reinterpret_cast(func_handle); + return reinterpret_cast(funcHandle); } private: static constexpr const char *CONNECTION_LIB_NAME = "libconnectserver_debugger.z.so"; - panda::os::library_loader::LibraryHandle connect_server_lib_handle_ {nullptr}; + panda::os::library_loader::LibraryHandle connectServerLibHandle_ {nullptr}; }; class IDEConnectManager final { @@ -94,11 +97,11 @@ public: ~IDEConnectManager() = default; // Represent thread to JSRuntime as JS worker - // In our case instance_id is equal to thread_id - bool AddWorkerInstance(int32_t instance_id, const std::string &instance_name); + // In our case `instanceId` is equal to thread-id + bool AddWorkerInstance(int32_t instanceId, std::string_view instanceName); private: - ConnectServerLib connect_server_lib_; + ConnectServerLib connectServerLib_; }; } // namespace panda::tooling::inspector diff --git a/static_core/runtime/tooling/inspector/connection/ohos_ws/ohos_ws_server.cpp b/static_core/runtime/tooling/inspector/connection/ohos_ws/ohos_ws_server.cpp index 6e33d6ca51..75b7db9616 100644 --- a/static_core/runtime/tooling/inspector/connection/ohos_ws/ohos_ws_server.cpp +++ b/static_core/runtime/tooling/inspector/connection/ohos_ws/ohos_ws_server.cpp @@ -20,6 +20,8 @@ #include "os/thread.h" #include "utils/logger.h" +#include "connect_manager.h" + namespace ark::tooling::inspector { [[maybe_unused]] static constexpr std::string_view G_ARK_TS_INSPECTOR_NAME = "ArkEtsDebugger"; @@ -50,9 +52,14 @@ bool OhosWsServer::Start([[maybe_unused]] uint32_t port) uint32_t name = port; #else auto pid = os::thread::GetPid(); - std::string name = std::to_string(pid) + std::string(G_ARK_TS_INSPECTOR_NAME); + // TODO(dslynko): replace with correct launch scheme + auto instanceName = std::to_string(pid); + std::stringstream ss; + ss << pid << instanceName << ARK_TS_INSPECTOR_NAME; + std::string name = ss.str(); succeeded = endpoint_.InitUnixWebSocket(name); #endif + if (succeeded) { LOG(INFO, DEBUGGER) << "Inspector server listening on " << name; return true; diff --git a/static_core/runtime/tooling/inspector/debug_info_cache.cpp b/static_core/runtime/tooling/inspector/debug_info_cache.cpp index 679aaf9b1e..28942c4b53 100644 --- a/static_core/runtime/tooling/inspector/debug_info_cache.cpp +++ b/static_core/runtime/tooling/inspector/debug_info_cache.cpp @@ -348,6 +348,7 @@ std::string DebugInfoCache::GetSourceCode(std::string_view sourceFile) const panda_file::DebugInfoExtractor &DebugInfoCache::GetDebugInfo(const panda_file::File *file) { + ASSERT(file); os::memory::LockHolder lock(debugInfosMutex_); auto it = debugInfos_.find(file); ASSERT(it != debugInfos_.end()); diff --git a/static_core/runtime/tooling/inspector/inspector_server.cpp b/static_core/runtime/tooling/inspector/inspector_server.cpp index e9ebdfa366..d34a89764e 100644 --- a/static_core/runtime/tooling/inspector/inspector_server.cpp +++ b/static_core/runtime/tooling/inspector/inspector_server.cpp @@ -46,9 +46,8 @@ void InspectorServer::Run() { // TODO: add some option, like connectToDevEco = true/false if (true) { - // static_cast is ok here, because function cast pid_t that is signed int to ThreadId (uint32_t) - int32_t instance_id = static_cast(os::thread::GetCurrentThreadId()); - ideConnectManager_.AddWorkerInstance(instance_id, "ArkEtsVM_InspectorServer"); + auto pid = os::thread::GetPid(); + ideConnectManager_.AddWorkerInstance(pid, ARK_TS_INSPECTOR_NAME); } server_.Run(); -- Gitee