1 /**
2 * Copyright (c) 2025 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 "debugger_arkapi.h"
17 #include <fstream>
18 #include <string_view>
19 #include "os/mutex.h"
20 #include "runtime/include/panda_vm.h"
21
22 namespace ark {
23 constexpr std::string_view ARK_DEBUGGER_LIB_PATH = "libark_inspector.z.so";
24 void *ArkDebugNativeAPI::gHybridDebuggerHandle_ = nullptr;
25 #ifdef PANDA_TARGET_WINDOWS
Load(std::string_view libraryName)26 static void *Load(std::string_view libraryName)
27 {
28 HMODULE module = LoadLibrary(libraryName.data());
29 void *handle = reinterpret_cast<void *>(module);
30 return handle;
31 }
32
ResolveSymbol(void * handle,std::string_view symbol)33 static void *ResolveSymbol(void *handle, std::string_view symbol)
34 {
35 HMODULE module = reinterpret_cast<HMODULE>(handle);
36 void *addr = reinterpret_cast<void *>(GetProcAddress(module, symbol.data()));
37 return addr;
38 }
39 #else // UNIX_PLATFORM
Load(std::string_view libraryName)40 static void *Load(std::string_view libraryName)
41 {
42 void *handle = dlopen(libraryName.data(), RTLD_LAZY);
43 return handle;
44 }
45
ResolveSymbol(void * handle,std::string_view symbol)46 static void *ResolveSymbol(void *handle, std::string_view symbol)
47 {
48 void *addr = dlsym(handle, symbol.data());
49 return addr;
50 }
51 #endif
52
NotifyDebugMode(int tid,int32_t instanceId,bool debugApp,void * vm,DebuggerPostTask & debuggerPostTask)53 bool ArkDebugNativeAPI::NotifyDebugMode([[maybe_unused]] int tid, [[maybe_unused]] int32_t instanceId,
54 [[maybe_unused]] bool debugApp, [[maybe_unused]] void *vm,
55 [[maybe_unused]] DebuggerPostTask &debuggerPostTask)
56 {
57 LOG(INFO, DEBUGGER) << "ArkDebugNativeAPI::NotifyDebugMode, tid = " << tid << ", debugApp = " << debugApp
58 << ", instanceId = " << instanceId;
59 if ((!debugApp) || (!Runtime::GetOptions().IsDebuggerEnable())) {
60 LOG(ERROR, DEBUGGER) << "Runtime::GetOptions().IsDebuggerEnable()" << Runtime::GetOptions().IsDebuggerEnable();
61 return true;
62 }
63 if (!debuggerPostTask) {
64 LOG(ERROR, DEBUGGER) << "ArkDebugNativeAPI::NotifyDebugMode, debuggerPostTask is nullptr";
65 return false;
66 }
67
68 gHybridDebuggerHandle_ = Load(ARK_DEBUGGER_LIB_PATH);
69 if (gHybridDebuggerHandle_ == nullptr) {
70 LOG(ERROR, DEBUGGER) << "[NotifyDebugMode] gHybridDebuggerHandle_ load fail";
71 return false;
72 }
73 Runtime::GetCurrent()->SetDebugMode(true);
74
75 // store debugger postTask in inspector.
76 using StoreDebuggerInfo = void (*)(int, void *, const DebuggerPostTask &);
77 auto symOfStoreDebuggerInfo =
78 reinterpret_cast<StoreDebuggerInfo>(ResolveSymbol(gHybridDebuggerHandle_, "StoreDebuggerInfo"));
79 if (symOfStoreDebuggerInfo == nullptr) {
80 LOG(ERROR, DEBUGGER) << "[NotifyDebugMode] Resolve StoreDebuggerInfo symbol fail: " << dlerror();
81 return false;
82 }
83 symOfStoreDebuggerInfo(tid, vm, debuggerPostTask);
84
85 #ifndef PANDA_TARGET_ARM32
86 // Initialize debugger
87 using InitializeDebuggerForSocketpair = bool (*)(void *, bool);
88 auto sym = reinterpret_cast<InitializeDebuggerForSocketpair>(
89 ResolveSymbol(gHybridDebuggerHandle_, "InitializeDebuggerForSocketpair"));
90 if (sym == nullptr) {
91 LOG(ERROR, DEBUGGER) << "[NotifyDebugMode] InitializeDebuggerForSocketpair symbol fail: " << dlerror();
92 return false;
93 }
94 if (!sym(vm, true)) {
95 LOG(ERROR, DEBUGGER) << "[NotifyDebugMode] InitializeDebuggerForSocketpair fail";
96 return false;
97 }
98 #endif
99
100 using WaitForDebugger = void (*)(void *);
101 auto symOfWaitForDebugger =
102 reinterpret_cast<WaitForDebugger>(ResolveSymbol(gHybridDebuggerHandle_, "WaitForDebugger"));
103 if (symOfWaitForDebugger == nullptr) {
104 LOG(ERROR, DEBUGGER) << "Resolve symbol WaitForDebugger fail: " << dlerror();
105 return false;
106 }
107 symOfWaitForDebugger(vm);
108
109 return true;
110 }
111
StopDebugger(void * vm)112 bool ArkDebugNativeAPI::StopDebugger([[maybe_unused]] void *vm)
113 {
114 LOG(INFO, DEBUGGER) << "ArkDebugNativeAPI::StopDebugger";
115
116 using StopDebug = void (*)(void *);
117 auto sym = reinterpret_cast<StopDebug>(ResolveSymbol(gHybridDebuggerHandle_, "StopDebug"));
118 if (sym == nullptr) {
119 LOG(ERROR, DEBUGGER) << "g_initializeInspectorForStatic load error" << dlerror();
120 return false;
121 }
122
123 sym(vm);
124 ark::Runtime::GetCurrent()->SetDebugMode(false);
125 return true;
126 }
127
StartDebuggerForSocketPair(int tid,int socketfd)128 bool ArkDebugNativeAPI::StartDebuggerForSocketPair([[maybe_unused]] int tid, [[maybe_unused]] int socketfd)
129 {
130 LOG(INFO, DEBUGGER) << "ArkDebugNativeAPI::StartDebugForSocketPair, tid = " << tid << " socketfd is " << socketfd;
131 if (!Runtime::GetOptions().IsDebuggerEnable()) {
132 LOG(ERROR, DEBUGGER) << "Runtime::GetOptions().IsDebuggerEnable() " << Runtime::GetOptions().IsDebuggerEnable();
133 return false;
134 }
135 using StartDebuggerForSocketpair = bool (*)(int, int, bool);
136 auto sym =
137 reinterpret_cast<StartDebuggerForSocketpair>(ResolveSymbol(gHybridDebuggerHandle_, "StartDebugForSocketpair"));
138 if (sym == nullptr) {
139 LOG(ERROR, DEBUGGER) << "g_initializeInspectorForStatic load error:%{public}s" << dlerror();
140 return false;
141 }
142 bool ret = sym(tid, socketfd, true);
143 if (!ret) {
144 // Reset the config
145 ark::Runtime::GetCurrent()->SetDebugMode(false);
146 }
147 return ret;
148 }
149
IsDebugModeEnabled()150 bool ArkDebugNativeAPI::IsDebugModeEnabled()
151 {
152 LOG(INFO, DEBUGGER) << "ArkDebugNativeAPI::IsDebugModeEnabled is " << ark::Runtime::GetCurrent()->IsDebugMode();
153
154 return ark::Runtime::GetCurrent()->IsDebugMode();
155 }
156 } // namespace ark
157