!10 migrate debugger to arkcompiler toolchain

Merge pull request !10 from buzhuyu/master
This commit is contained in:
openharmony_ci 2022-09-02 11:48:07 +00:00 committed by Gitee
commit c159788e3e
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 260 additions and 53 deletions

View File

@ -11,7 +11,7 @@
"destPath": "arkcompiler/toolchain"
},
"component": {
"name": "arkcompiler_toolchain",
"name": "toolchain",
"subsystem": "ark",
"syscap": [],
"features": [],
@ -25,7 +25,9 @@
"third_party": []
},
"build": {
"sub_component": [],
"sub_component": [
"//arkcompiler/toolchain/inspector:ark_debugger"
],
"inner_kits": [],
"test": []
}

View File

@ -34,23 +34,44 @@ ohos_shared_library("ark_debugger") {
defines += [ "ACE_LOG_TAG=\"ArkDebugger\"" ]
external_deps = hilog_deps
if (is_mingw || is_mac) {
cflags = [ "-std=c++17" ]
if (is_mingw) {
platform = "windows"
defines += [ "WINDOWS_PLATFORM" ]
ldflags = [
"-lwsock32",
"-lws2_32",
]
} else {
platform = "mac"
defines += [
"MAC_PLATFORM",
"UNIX_PLATFORM",
]
}
deps = [
"//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_$platform",
]
} else {
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
defines += [ "UNIX_PLATFORM" ]
}
include_dirs = [
"$toolchain_root",
"$ace_root/frameworks",
".",
"//third_party/boost",
"//third_party/boost/boost",
]
sources = [
"$ace_root/adapter/ohos/osal/log_wrapper.cpp",
"inspector.cpp",
"library_loader.cpp",
"ws_server.cpp",
]
configs = [ ":ark_debugger_config" ]
subsystem_name = "arkcompiler"
subsystem_name = "ark"
part_name = "toolchain"
}

50
inspector/hilog_wrapper.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2022 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 ARKCOMPILER_TOOLCHAIN_INSPECTOR_HILOG_WRAPPER_H
#define ARKCOMPILER_TOOLCHAIN_INSPECTOR_HILOG_WRAPPER_H
#include "hilog/log.h"
namespace OHOS::ArkCompiler::Toolchain {
#ifdef LOGF
#undef LOGF
#endif
#ifdef LOGE
#undef LOGE
#endif
#ifdef LOGW
#undef LOGW
#endif
#ifdef LOGI
#undef LOGI
#endif
#ifdef LOGD
#undef LOGD
#endif
static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
LOG_CORE,
0xD003F00,
"ArkCompiler"
};
#define LOGF(fmt, ...) OHOS::HiviewDFX::HiLog::Fatal(LABEL, fmt, ##__VA_ARGS__)
#define LOGE(fmt, ...) OHOS::HiviewDFX::HiLog::Error(LABEL, fmt, ##__VA_ARGS__)
#define LOGW(fmt, ...) OHOS::HiviewDFX::HiLog::Warn(LABEL, fmt, ##__VA_ARGS__)
#define LOGI(fmt, ...) OHOS::HiviewDFX::HiLog::Info(LABEL, fmt, ##__VA_ARGS__)
#define LOGD(fmt, ...) OHOS::HiviewDFX::HiLog::Debug(LABEL, fmt, ##__VA_ARGS__)
} // namespace OHOS::ArkCompiler::Toolchain
#endif // ARKCOMPILER_TOOLCHAIN_INSPECTOR_HILOG_WRAPPER_H

View File

@ -13,15 +13,15 @@
* limitations under the License.
*/
#include "inspector/inspector.h"
#include "inspector.h"
#include <dlfcn.h>
#include <chrono>
#include <shared_mutex>
#include <unistd.h>
#include <thread>
#include <unordered_map>
#include "base/log/log.h"
#include "inspector/ws_server.h"
#include "hilog_wrapper.h"
#include "library_loader.h"
namespace OHOS::ArkCompiler::Toolchain {
namespace {
@ -34,11 +34,11 @@ enum DispatchStatus : int32_t {
using InitializeDebugger = void(*)(void*, const std::function<void(const void*, const std::string&)>&);
using UninitializeDebugger = void(*)(void*);
using WaitForDebugger = void(*)(void*);
using DispatchMessage = void(*)(void*, std::string&&);
using OnMessage = void(*)(void*, std::string&&);
using ProcessMessage = void(*)(void*);
using GetDispatchStatus = int32_t(*)(void*);
DispatchMessage g_dispatchMessage = nullptr;
OnMessage g_onMessage = nullptr;
InitializeDebugger g_initializeDebugger = nullptr;
UninitializeDebugger g_uninitializeDebugger = nullptr;
WaitForDebugger g_waitForDebugger = nullptr;
@ -52,7 +52,13 @@ std::shared_mutex g_mutex;
thread_local void* g_handle = nullptr;
thread_local void* g_vm = nullptr;
#if defined(WINDOWS_PLATFORM)
constexpr char ARK_DEBUGGER_SHARED_LIB[] = "libark_ecma_debugger.dll";
#elif defined(MAC_PLATFORM)
constexpr char ARK_DEBUGGER_SHARED_LIB[] = "libark_ecma_debugger.dylib";
#else
constexpr char ARK_DEBUGGER_SHARED_LIB[] = "libark_ecma_debugger.so";
#endif
void* HandleClient(void* const server)
{
@ -71,9 +77,8 @@ bool LoadArkDebuggerLibrary()
LOGE("Already opened");
return false;
}
g_handle = dlopen(ARK_DEBUGGER_SHARED_LIB, RTLD_LAZY);
g_handle = Load(ARK_DEBUGGER_SHARED_LIB);
if (g_handle == nullptr) {
LOGE("Failed to open %{public}s, reason: %{public}sn", ARK_DEBUGGER_SHARED_LIB, dlerror());
return false;
}
return true;
@ -81,11 +86,7 @@ bool LoadArkDebuggerLibrary()
void* GetArkDynFunction(const char* symbol)
{
auto function = dlsym(g_handle, symbol);
if (function == nullptr) {
LOGE("Failed to get symbol %{public}s in %{public}s", symbol, ARK_DEBUGGER_SHARED_LIB);
}
return function;
return ResolveSymbol(g_handle, symbol);
}
void SendReply(const void* vm, const std::string& message)
@ -109,7 +110,7 @@ void ResetServiceLocked()
g_inspectors.erase(iter);
}
if (g_handle != nullptr) {
dlclose(g_handle);
CloseHandle(g_handle);
g_handle = nullptr;
}
}
@ -175,9 +176,9 @@ bool InitializeArkFunctions()
ResetServiceLocked();
return false;
}
g_dispatchMessage = reinterpret_cast<DispatchMessage>(
GetArkDynFunction("DispatchMessage"));
if (g_dispatchMessage == nullptr) {
g_onMessage = reinterpret_cast<OnMessage>(
GetArkDynFunction("OnMessage"));
if (g_onMessage == nullptr) {
ResetServiceLocked();
return false;
}
@ -201,13 +202,13 @@ bool InitializeArkFunctions()
void Inspector::OnMessage(std::string&& msg)
{
g_dispatchMessage(vm_, std::move(msg));
g_onMessage(vm_, std::move(msg));
// message will be processed soon if the debugger thread is in running or waiting status
if (g_getDispatchStatus(vm_) != DispatchStatus::UNKNOWN) {
return;
}
usleep(DELAY_CHECK_DISPATCH_STATUS);
std::this_thread::sleep_for(std::chrono::microseconds(DELAY_CHECK_DISPATCH_STATUS));
if (g_getDispatchStatus(vm_) != DispatchStatus::UNKNOWN) {
return;
}
@ -229,7 +230,6 @@ void Inspector::OnMessage(std::string&& msg)
bool StartDebug(const std::string& componentName, void* vm, bool isDebugMode, int32_t instanceId,
const DebuggerPostTask& debuggerPostTask)
{
LOGI("StartDebug: %{private}s", componentName.c_str());
g_vm = vm;
if (!LoadArkDebuggerLibrary()) {
return false;
@ -249,7 +249,6 @@ bool StartDebug(const std::string& componentName, void* vm, bool isDebugMode, in
if (isDebugMode) {
g_waitForDebugger(vm);
}
LOGI("StartDebug Continue");
return true;
}

View File

@ -20,6 +20,8 @@
#include <string>
#include <pthread.h>
namespace panda::ecmascript {
class EcmaVM;
} // namespace panda::ecmascript
@ -28,22 +30,18 @@ namespace OHOS::ArkCompiler::Toolchain {
using EcmaVM = panda::ecmascript::EcmaVM;
using DebuggerPostTask = std::function<void(std::function<void()>&&)>;
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
bool StartDebug(const std::string& componentName, void* vm, bool isDebugMode, int32_t instanceId,
const DebuggerPostTask& debuggerPostTask);
void StopDebug(const std::string& componentName);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
class Inspector {
public:

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2022 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 "library_loader.h"
#include "hilog_wrapper.h"
#if defined(UNIX_PLATFORM)
#include <dlfcn.h>
#elif defined(WINDOWS_PLATFORM)
#include <windows.h>
#else
#error "Unsupported platform"
#endif
#include <string>
namespace OHOS::ArkCompiler::Toolchain {
#ifdef WINDOWS_PLATFORM
void* Load(std::string_view libraryName)
{
HMODULE module = LoadLibrary(libraryName.data());
void* handle = reinterpret_cast<void*>(module);
if (handle != nullptr) {
return handle;
}
LOGE("Failed to open %{public}s, reason:%{public}sn", libraryName.data(),
std::to_string(GetLastError()).c_str());
return nullptr;
}
void* ResolveSymbol(void* handle, std::string_view symbol)
{
HMODULE module = reinterpret_cast<HMODULE>(handle);
void* addr = reinterpret_cast<void*>(GetProcAddress(module, symbol.data()));
if (addr != nullptr) {
return addr;
}
LOGE("Failed to get symbol:%{public}s, reason:%{public}s", symbol.data(),
std::to_string(GetLastError()).c_str());
return nullptr;
}
void CloseHandle(void* handle)
{
if (handle != nullptr) {
FreeLibrary(reinterpret_cast<HMODULE>(handle));
}
}
#else // UNIX_PLATFORM
void* Load(std::string_view libraryName)
{
void* handle = dlopen(libraryName.data(), RTLD_LAZY);
if (handle != nullptr) {
return handle;
}
LOGE("Failed to open %{public}s, reason:%{public}sn", libraryName.data(), dlerror());
return nullptr;
}
void* ResolveSymbol(void* handle, std::string_view symbol)
{
void* addr = dlsym(handle, symbol.data());
if (addr != nullptr) {
return addr;
}
LOGE("Failed to get symbol:%{public}s, reason:%{public}sn", symbol.data(), dlerror());
return nullptr;
}
void CloseHandle(void* handle)
{
if (handle != nullptr) {
dlclose(handle);
}
}
#endif
}

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2022 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 ARKCOMPILER_TOOLCHAIN_INSPECTOR_LIBRARY_LOADER_H
#define ARKCOMPILER_TOOLCHAIN_INSPECTOR_LIBRARY_LOADER_H
#include <string_view>
namespace OHOS::ArkCompiler::Toolchain {
void* Load(std::string_view filename);
void* ResolveSymbol(void* handle, std::string_view name);
void CloseHandle(void* handle);
} // namespace OHOS::ArkCompiler::Toolchain
#endif // ARKCOMPILER_TOOLCHAIN_INSPECTOR_LIBRARY_LOADER_H

View File

@ -13,25 +13,27 @@
* limitations under the License.
*/
#include "inspector/ws_server.h"
#include "ws_server.h"
#include <fstream>
#include <iostream>
#include <sys/types.h>
#include "base/log/log.h"
#include "hilog_wrapper.h"
namespace OHOS::ArkCompiler::Toolchain {
void WsServer::RunServer()
{
terminateExecution_ = false;
try {
ioContext_ = std::make_unique<boost::asio::io_context>();
int appPid = getpid();
tid_ = pthread_self();
#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
constexpr int32_t DEFAULT_INSEPTOR_PORT = 9230;
CommProtocol::endpoint endPoint(CommProtocol::v4(), DEFAULT_INSEPTOR_PORT);
#else
int appPid = getpid();
std::string pidStr = std::to_string(appPid);
std::string instanceIdStr("");
auto& connectFlag = connectState_;
/**
* The old version of IDE is not compatible with the new images due to the connect server.
* The First instance will use "pid" instead of "pid + instanceId" to avoid this.
@ -42,9 +44,12 @@ void WsServer::RunServer()
}
std::string sockName = '\0' + pidStr + instanceIdStr + componentName_;
LOGI("WsServer RunServer: %{public}d%{public}d%{public}s", appPid, instanceId_, componentName_.c_str());
localSocket::endpoint endPoint(sockName);
localSocket::socket socket(*ioContext_);
localSocket::acceptor acceptor(*ioContext_, endPoint);
CommProtocol::endpoint endPoint(sockName);
#endif
ioContext_ = std::make_unique<boost::asio::io_context>();
CommProtocol::socket socket(*ioContext_);
CommProtocol::acceptor acceptor(*ioContext_, endPoint);
auto& connectFlag = connectState_;
acceptor.async_accept(socket, [&connectFlag](const boost::system::error_code& error) {
if (!error) {
connectFlag = true;
@ -54,8 +59,8 @@ void WsServer::RunServer()
if (terminateExecution_ || !connectState_) {
return;
}
webSocket_ = std::unique_ptr<websocket::stream<localSocket::socket>>(
std::make_unique<websocket::stream<localSocket::socket>>(std::move(socket)));
webSocket_ = std::unique_ptr<websocket::stream<CommProtocol::socket>>(
std::make_unique<websocket::stream<CommProtocol::socket>>(std::move(socket)));
webSocket_->accept();
while (!terminateExecution_) {
beast::flat_buffer buffer;
@ -72,7 +77,7 @@ void WsServer::RunServer()
} catch (const beast::system_error& se) {
if (se.code() != websocket::error::closed) {
webSocket_.reset();
LOGE("Error system_error");
LOGE("Error system_error, %{public}s", se.what());
}
} catch (const std::exception& e) {
LOGE("Error exception, %{public}s", e.what());
@ -85,15 +90,19 @@ void WsServer::StopServer()
terminateExecution_ = true;
if (!connectState_) {
ioContext_->stop();
} else {
} else if (webSocket_ != nullptr) {
boost::system::error_code error;
webSocket_->close(websocket::close_code::normal, error);
}
pthread_join(tid_, NULL);
pthread_join(tid_, nullptr);
}
void WsServer::SendReply(const std::string& message) const
{
if (webSocket_ == nullptr) {
LOGE("WsServer SendReply websocket has been closed unexpectedly");
return;
}
LOGI("WsServer SendReply: %{public}s", message.c_str());
try {
boost::beast::multi_buffer buffer;

View File

@ -16,19 +16,28 @@
#ifndef ARKCOMPILER_TOOLCHAIN_INSPECTOR_WS_SERVER_H
#define ARKCOMPILER_TOOLCHAIN_INSPECTOR_WS_SERVER_H
#include <boost/asio/error.hpp>
#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
#include <boost/asio/ip/tcp.hpp>
#else
#include <boost/asio/local/stream_protocol.hpp>
#endif
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <functional>
#include <iostream>
#include <queue>
#include <boost/asio/error.hpp>
#include <boost/asio/local/stream_protocol.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <pthread.h>
namespace OHOS::ArkCompiler::Toolchain {
namespace beast = boost::beast;
namespace websocket = beast::websocket;
using localSocket = boost::asio::local::stream_protocol;
#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
using CommProtocol = boost::asio::ip::tcp;
#else
using CommProtocol = boost::asio::local::stream_protocol;
#endif
class WsServer {
public:
@ -43,11 +52,11 @@ public:
private:
std::atomic<bool> connectState_ {false};
std::atomic<bool> terminateExecution_ { false };
int32_t instanceId_ {0};
[[maybe_unused]] int32_t instanceId_ {0};
pthread_t tid_ {0};
std::string componentName_ {};
std::function<void(std::string&&)> wsOnMessage_ {};
std::unique_ptr<websocket::stream<localSocket::socket>> webSocket_ { nullptr };
std::unique_ptr<websocket::stream<CommProtocol::socket>> webSocket_ { nullptr };
std::unique_ptr<boost::asio::io_context> ioContext_ { nullptr };
};
} // namespace OHOS::ArkCompiler::Toolchain