diff --git a/static_core/BUILD.gn b/static_core/BUILD.gn index b1cbfd87f973b8efc7c2b48fe58da00a828359fa..a14ad70a25da2c229ca6890922d72d80a0ae497c 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 7c5d638202247789e8d253652da91ef810769d86..7a34ccbab4e6e3e13977bc050de1eacb2df4c284 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/BUILD.gn b/static_core/runtime/tooling/inspector/BUILD.gn index 76d05f6c8537aa7d7179c5712d373a7a6fa15f8c..80efb2f4c2f67d6c3d236eb3c7e6d39d259d9625 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 05dc2b86be8c34130b8579ae40c7855873b3d6fc..f24305381131f9d2f6749f999ff2da5035c9fa0a 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 0000000000000000000000000000000000000000..ed2cbd1173ab3443c0d3b6e8692f15056a70fa23 --- /dev/null +++ b/static_core/runtime/tooling/inspector/connect_manager.cpp @@ -0,0 +1,53 @@ +/* + * 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 + * + * 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 instanceId, std::string_view instanceName) +{ + auto waitForConnection = + connectServerLib_.GetFunction("WaitForConnection"); + auto sendMessage = connectServerLib_.GetFunction("SendMessage"); + auto storeMessage = connectServerLib_.GetFunction("StoreMessage"); + + if (!waitForConnection || !sendMessage || !storeMessage) { + return false; + } + + JsonObjectBuilder builder; + builder.AddProperty("type", "addInstance"); + 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(); + + storeMessage(instanceId, message); + + if (waitForConnection()) { + return false; + } + + sendMessage(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 0000000000000000000000000000000000000000..49bd368355772842615531cba198a286026c42fc --- /dev/null +++ b/static_core/runtime/tooling/inspector/connect_manager.h @@ -0,0 +1,109 @@ +/* + * 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 + * + * 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 +#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: + // 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 &, + const std::function &, + int32_t); + 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; + } + connectServerLibHandle_ = std::move(handle.Value()); + } + + ~ConnectServerLib() + { + os::library_loader::CloseHandle(connectServerLibHandle_.GetNativeHandle()); + } + + template + T GetFunction(const std::string &sym) + { + if (!connectServerLibHandle_.IsValid()) { + LOG(ERROR, DEBUGGER) << "ConnectServerFunction::GetFunction library handle is nullptr"; + return nullptr; + } + + auto handle = os::library_loader::ResolveSymbol(connectServerLibHandle_, sym); + if (!handle) { + LOG(INFO, DEBUGGER) << "ConnectServerFunction::GetFunction failed to find symbol " << sym; + return nullptr; + } + + void *funcHandle = handle.Value(); + + return reinterpret_cast(funcHandle); + } + +private: + static constexpr const char *CONNECTION_LIB_NAME = "libconnectserver_debugger.z.so"; + + panda::os::library_loader::LibraryHandle connectServerLibHandle_ {nullptr}; +}; + +class IDEConnectManager final { +public: + NO_COPY_SEMANTIC(IDEConnectManager); + NO_MOVE_SEMANTIC(IDEConnectManager); + + IDEConnectManager() = default; + ~IDEConnectManager() = default; + + // Represent thread to JSRuntime as JS worker + // In our case `instanceId` is equal to thread-id + bool AddWorkerInstance(int32_t instanceId, std::string_view instanceName); + +private: + ConnectServerLib connectServerLib_; +}; + +} // namespace panda::tooling::inspector + +#endif // PANDA_TOOLING_INSPECTOR_CONNECT_SERVER_MANAGER 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 6e33d6ca516c20d1f875fc1e3f263d51b4bb435b..75b7db9616e64ba55ab90e7075cb8fafc881b743 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 679aaf9b1eebaa00feee8ac4a81909192cc18d94..28942c4b53568a8bb947e5abeb5ee530d7ae1fb0 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 bee9ccbd4b063d1323ce0c477f3fb13f4df99945..d34a89764e11282489374b377f5a63039ae7831d 100644 --- a/static_core/runtime/tooling/inspector/inspector_server.cpp +++ b/static_core/runtime/tooling/inspector/inspector_server.cpp @@ -44,6 +44,12 @@ void InspectorServer::Kill() void InspectorServer::Run() { + // TODO: add some option, like connectToDevEco = true/false + if (true) { + auto pid = os::thread::GetPid(); + ideConnectManager_.AddWorkerInstance(pid, ARK_TS_INSPECTOR_NAME); + } + server_.Run(); } diff --git a/static_core/runtime/tooling/inspector/inspector_server.h b/static_core/runtime/tooling/inspector/inspector_server.h index 7ee1af44f7fc4a814617ecd090d3e97e97983df0..6382476c3a4d5cf690afe35749793067f2ff43b0 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