1 /**
2 * Copyright (c) 2021-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 #ifndef PANDA_RUNTIME_RUNTIME_H_
17 #define PANDA_RUNTIME_RUNTIME_H_
18
19 #include <atomic>
20 #include <csignal>
21 #include <memory>
22 #include <string>
23 #include <vector>
24
25 #include "libpandabase/mem/arena_allocator.h"
26 #include "libpandabase/os/mutex.h"
27 #include "libpandabase/taskmanager/task_scheduler.h"
28 #include "libpandabase/utils/expected.h"
29 #include "libpandabase/utils/dfx.h"
30 #include "libpandafile/file_items.h"
31 #include "libpandafile/literal_data_accessor.h"
32 #include "runtime/include/class_linker.h"
33 #include "runtime/include/mem/panda_containers.h"
34 #include "runtime/include/mem/panda_smart_pointers.h"
35 #include "runtime/include/mem/panda_string.h"
36 #include "runtime/include/method.h"
37 #include "runtime/include/runtime_options.h"
38 #include "runtime/include/gc_task.h"
39 #ifndef PANDA_TARGET_WINDOWS
40 #include "runtime/signal_handler.h"
41 #endif
42 #include "runtime/mem/allocator_adapter.h"
43 #include "runtime/mem/gc/gc.h"
44 #include "runtime/mem/gc/gc_trigger.h"
45 #include "runtime/mem/memory_manager.h"
46 #include "runtime/monitor_pool.h"
47 #include "runtime/string_table.h"
48 #include "runtime/thread_manager.h"
49 #include "verification/public.h"
50 #include "libpandabase/os/native_stack.h"
51 #include "libpandabase/os/library_loader.h"
52 #include "runtime/include/loadable_agent.h"
53 #include "runtime/tooling/tools.h"
54
55 namespace ark {
56
57 class DProfiler;
58 class CompilerInterface;
59 class ClassHierarchyAnalysis;
60 class RuntimeController;
61 class PandaVM;
62 class RuntimeNotificationManager;
63 class Trace;
64
65 namespace tooling {
66 class DebugInterface;
67 class MemoryAllocationDumper;
68 } // namespace tooling
69
70 using UnwindStackFn = os::native_stack::FuncUnwindstack;
71
72 class PANDA_PUBLIC_API Runtime {
73 public:
74 using ExitHook = void (*)(int32_t status);
75 using AbortHook = void (*)();
76
77 enum class Error {
78 PANDA_FILE_LOAD_ERROR,
79 INVALID_ENTRY_POINT,
80 CLASS_NOT_FOUND,
81 CLASS_NOT_INITIALIZED,
82 METHOD_NOT_FOUND,
83 CLASS_LINKER_EXTENSION_NOT_FOUND
84 };
85
86 class DebugSession final {
87 public:
88 explicit DebugSession(Runtime &runtime);
89 ~DebugSession();
90
91 tooling::DebugInterface &GetDebugger();
92
93 private:
94 Runtime &runtime_;
95 bool isJitEnabled_;
96 os::memory::LockHolder<os::memory::Mutex> lock_;
97 PandaUniquePtr<tooling::DebugInterface> debugger_;
98
99 NO_COPY_SEMANTIC(DebugSession);
100 NO_MOVE_SEMANTIC(DebugSession);
101 };
102
103 using DebugSessionHandle = std::shared_ptr<DebugSession>;
104
105 LanguageContext GetLanguageContext(const std::string &runtimeType);
106 LanguageContext GetLanguageContext(const Method &method);
107 LanguageContext GetLanguageContext(const Class &cls);
108 LanguageContext GetLanguageContext(const BaseClass &cls);
109 LanguageContext GetLanguageContext(panda_file::ClassDataAccessor *cda);
110 LanguageContext GetLanguageContext(panda_file::SourceLang lang);
111
112 static bool CreateInstance(const RuntimeOptions &options, mem::InternalAllocatorPtr internalAllocator);
113
114 static bool Create(const RuntimeOptions &options);
115
116 // Deprecated. Only for capability with js_runtime.
117 static bool Create(const RuntimeOptions &options, const std::vector<LanguageContextBase *> &ctxs);
118
119 static bool DestroyUnderLockHolder();
120
121 static bool Destroy();
122
123 static Runtime *GetCurrent();
124
125 template <typename Handler>
GetCurrentSync(Handler && handler)126 static auto GetCurrentSync(Handler &&handler)
127 {
128 os::memory::LockHolder lock(mutex_);
129 return handler(*GetCurrent());
130 }
131
GetRuntimeLock()132 static os::memory::Mutex *GetRuntimeLock()
133 {
134 return &mutex_;
135 }
136
GetClassLinker()137 ClassLinker *GetClassLinker() const
138 {
139 return classLinker_;
140 }
141
GetNotificationManager()142 RuntimeNotificationManager *GetNotificationManager() const
143 {
144 return notificationManager_;
145 }
146
GetOptions()147 static const RuntimeOptions &GetOptions()
148 {
149 return options_;
150 }
151
SetZygoteNoThreadSection(bool val)152 void SetZygoteNoThreadSection(bool val)
153 {
154 zygoteNoThreads_ = val;
155 }
156
IsTaskManagerUsed()157 static bool IsTaskManagerUsed()
158 {
159 return isTaskManagerUsed_;
160 }
161
SetTaskManagerUsed(bool value)162 static void SetTaskManagerUsed(bool value)
163 {
164 isTaskManagerUsed_ = value;
165 }
166
167 coretypes::String *ResolveString(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
168
169 coretypes::String *ResolveStringFromCompiledCode(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
170
171 coretypes::String *ResolveString(PandaVM *vm, const panda_file::File &pf, panda_file::File::EntityId id,
172 const LanguageContext &ctx);
173
174 coretypes::String *ResolveString(PandaVM *vm, const uint8_t *mutf8, uint32_t length, const LanguageContext &ctx);
175
176 Class *GetClassRootForLiteralTag(const ClassLinkerExtension &ext, panda_file::LiteralTag tag) const;
177
178 static bool GetLiteralTagAndValue(const panda_file::File &pf, uint32_t id, panda_file::LiteralTag *tag,
179 panda_file::LiteralDataAccessor::LiteralValue *value);
180
181 uintptr_t GetPointerToConstArrayData(const panda_file::File &pf, uint32_t id) const;
182
183 coretypes::Array *ResolveLiteralArray(PandaVM *vm, const Method &caller, uint32_t id);
184 coretypes::Array *ResolveLiteralArray(PandaVM *vm, const panda_file::File &pf, uint32_t id,
185 const LanguageContext &ctx);
186
187 void PreZygoteFork();
188
189 void PostZygoteFork();
190
191 Expected<int, Error> ExecutePandaFile(std::string_view filename, std::string_view entryPoint,
192 const std::vector<std::string> &args);
193
194 int StartDProfiler(std::string_view appName);
195
196 int StartMemAllocDumper(const PandaString &dumpFile);
197
198 Expected<int, Error> Execute(std::string_view entryPoint, const std::vector<std::string> &args);
199
200 int StartDProfiler(const PandaString &appName);
201
IsDebugMode()202 bool IsDebugMode() const
203 {
204 return isDebugMode_;
205 }
206
SetDebugMode(bool isDebugMode)207 void SetDebugMode(bool isDebugMode)
208 {
209 isDebugMode_ = isDebugMode;
210 }
211
IsDebuggerConnected()212 bool IsDebuggerConnected() const
213 {
214 return isDebuggerConnected_;
215 }
216
SetDebuggerConnected(bool dbgConnectedState)217 void SetDebuggerConnected(bool dbgConnectedState)
218 {
219 isDebuggerConnected_ = dbgConnectedState;
220 }
221
IsProfileableFromShell()222 bool IsProfileableFromShell() const
223 {
224 return isProfileableFromShell_;
225 }
226
SetProfileableFromShell(bool profileableFromShell)227 void SetProfileableFromShell(bool profileableFromShell)
228 {
229 isProfileableFromShell_ = profileableFromShell;
230 }
231
232 PandaVector<PandaString> GetBootPandaFiles();
233
234 PandaVector<PandaString> GetPandaFiles();
235
236 // Returns true if profile saving is enabled.
237 bool SaveProfileInfo() const;
238
GetProcessPackageName()239 const std::string &GetProcessPackageName() const
240 {
241 return processPackageName_;
242 }
243
SetProcessPackageName(const char * packageName)244 void SetProcessPackageName(const char *packageName)
245 {
246 if (packageName == nullptr) {
247 processPackageName_.clear();
248 } else {
249 processPackageName_ = packageName;
250 }
251 }
252
GetProcessDataDirectory()253 const std::string &GetProcessDataDirectory() const
254 {
255 return processDataDirectory_;
256 }
257
SetProcessDataDirectory(const char * dataDir)258 void SetProcessDataDirectory(const char *dataDir)
259 {
260 if (dataDir == nullptr) {
261 processDataDirectory_.clear();
262 } else {
263 processDataDirectory_ = dataDir;
264 }
265 }
266
GetPandaPath()267 std::string GetPandaPath()
268 {
269 return pandaPathString_;
270 }
271
GetRuntimeType()272 static const std::string &GetRuntimeType()
273 {
274 return runtimeType_;
275 }
276
277 void UpdateProcessState(int state);
278
IsZygote()279 bool IsZygote() const
280 {
281 return isZygote_;
282 }
283
IsInitialized()284 bool IsInitialized() const
285 {
286 return isInitialized_;
287 }
288
289 // NOTE(00510180): lack NativeBridgeAction action
290 void InitNonZygoteOrPostFork(bool isSystemServer, const char *isa, const std::function<void()> &initHook = {},
291 bool profileSystemServer = false);
292
GetVersion()293 static const char *GetVersion()
294 {
295 // NOTE(chenmudan): change to the correct version when we have one;
296 return "1.0.0";
297 }
298
GetFingerprint()299 PandaString GetFingerprint()
300 {
301 return fingerPrint_;
302 }
303
304 [[noreturn]] static void Halt(int32_t status);
305
SetExitHook(ExitHook exitHook)306 void SetExitHook(ExitHook exitHook)
307 {
308 ASSERT(exit_ == nullptr);
309 exit_ = exitHook;
310 }
311
SetAbortHook(AbortHook abortHook)312 void SetAbortHook(AbortHook abortHook)
313 {
314 ASSERT(abort_ == nullptr);
315 abort_ = abortHook;
316 }
317
318 [[noreturn]] static void Abort(const char *message = nullptr);
319
320 Expected<Method *, Error> ResolveEntryPoint(std::string_view entryPoint);
321
322 void RegisterSensitiveThread() const;
323
324 // Deprecated.
325 // Get VM instance from the thread. In multi-vm runtime this method returns
326 // the first VM. It is undeterminated which VM will be first.
GetPandaVM()327 PandaVM *GetPandaVM() const
328 {
329 return pandaVm_;
330 }
331
GetCha()332 ClassHierarchyAnalysis *GetCha() const
333 {
334 return cha_;
335 }
336
GetVerificationConfig()337 ark::verifier::Config const *GetVerificationConfig() const
338 {
339 return verifierConfig_;
340 }
341
GetVerificationConfig()342 ark::verifier::Config *GetVerificationConfig()
343 {
344 return verifierConfig_;
345 }
346
GetVerifierService()347 ark::verifier::Service *GetVerifierService()
348 {
349 return verifierService_;
350 }
351
IsDebuggerAttached()352 bool IsDebuggerAttached()
353 {
354 return debugSession_.use_count() > 0;
355 }
356
357 void DumpForSigQuit(std::ostream &os);
358
IsDumpNativeCrash()359 bool IsDumpNativeCrash()
360 {
361 return isDumpNativeCrash_;
362 }
363
IsChecksSuspend()364 bool IsChecksSuspend() const
365 {
366 return checksSuspend_;
367 }
368
IsChecksStack()369 bool IsChecksStack() const
370 {
371 return checksStack_;
372 }
373
IsChecksNullptr()374 bool IsChecksNullptr() const
375 {
376 return checksNullptr_;
377 }
378
IsStacktrace()379 bool IsStacktrace() const
380 {
381 return isStacktrace_;
382 }
383
IsJitEnabled()384 bool IsJitEnabled() const
385 {
386 return isJitEnabled_;
387 }
388
IsProfilerEnabled()389 bool IsProfilerEnabled() const
390 {
391 return isProfilerEnabled_ || isJitEnabled_;
392 }
393
ForceEnableJit()394 void ForceEnableJit()
395 {
396 isJitEnabled_ = true;
397 }
398
ForceDisableJit()399 void ForceDisableJit()
400 {
401 isJitEnabled_ = false;
402 }
403
404 #ifndef PANDA_TARGET_WINDOWS
GetSignalManager()405 SignalManager *GetSignalManager()
406 {
407 return signalManager_;
408 }
409 #endif
410
411 static mem::GCType GetGCType(const RuntimeOptions &options, panda_file::SourceLang lang);
412
413 static void SetDaemonMemoryLeakThreshold(uint32_t daemonMemoryLeakThreshold);
414
415 static void SetDaemonThreadsCount(uint32_t daemonThreadsCnt);
416
417 DebugSessionHandle StartDebugSession();
418
GetInternalAllocator()419 mem::InternalAllocatorPtr GetInternalAllocator() const
420 {
421 return internalAllocator_;
422 }
423
424 PandaString GetMemoryStatistics();
425 PandaString GetFinalStatistics();
426
427 Expected<LanguageContext, Error> ExtractLanguageContext(const panda_file::File *pf, std::string_view entryPoint);
428
GetUnwindStackFn()429 UnwindStackFn GetUnwindStackFn() const
430 {
431 return unwindStackFn_;
432 }
433
SetUnwindStackFn(UnwindStackFn unwindStackFn)434 void SetUnwindStackFn(UnwindStackFn unwindStackFn)
435 {
436 unwindStackFn_ = unwindStackFn;
437 }
438
GetTools()439 inline tooling::Tools &GetTools()
440 {
441 return tools_;
442 }
443
444 private:
445 void NotifyAboutLoadedModules();
446
447 std::optional<Error> CreateApplicationClassLinkerContext(std::string_view filename, std::string_view entryPoint);
448
449 bool LoadVerificationConfig();
450
451 bool CreatePandaVM(std::string_view runtimeType);
452
453 bool InitializePandaVM();
454
455 bool HandleAotOptions();
456
457 void HandleJitOptions();
458
459 bool CheckOptionsConsistency();
460
461 void CheckOptionsFromOs() const;
462
463 void SetPandaPath();
464
465 void SetThreadClassPointers();
466
467 bool Initialize();
468
469 bool Shutdown();
470
471 bool LoadBootPandaFiles(panda_file::File::OpenMode openMode);
472
473 void CheckBootPandaFiles();
474
475 bool IsEnableMemoryHooks() const;
476
477 /**
478 * @brief Unload debugger library and destroy debug session.
479 * As side effect, `Debugger` instance will be destroyed. Hence the method must be called
480 * during runtime destruction after sending `VmDeath` event and before uninitializing threads.
481 */
482 void UnloadDebugger();
483
484 static void CreateDfxController(const RuntimeOptions &options);
485
486 static void BlockSignals();
487
488 inline void InitializeVerifierRuntime();
489
490 Runtime(const RuntimeOptions &options, mem::InternalAllocatorPtr internalAllocator);
491
492 ~Runtime();
493
494 static Runtime *instance_;
495 static RuntimeOptions options_;
496 static std::string runtimeType_;
497 static os::memory::Mutex mutex_;
498 static bool isTaskManagerUsed_;
499
500 // NOTE(dtrubenk): put all of it in the permanent space
501 mem::InternalAllocatorPtr internalAllocator_;
502 RuntimeNotificationManager *notificationManager_;
503 ClassLinker *classLinker_;
504 ClassHierarchyAnalysis *cha_;
505 DProfiler *dprofiler_ = nullptr;
506 tooling::MemoryAllocationDumper *memAllocDumper_ = nullptr;
507
508 PandaVM *pandaVm_ = nullptr;
509
510 #ifndef PANDA_TARGET_WINDOWS
511 SignalManager *signalManager_ {nullptr};
512 #endif
513
514 // For IDE is real connected.
515 bool isDebugMode_ {false};
516 bool isDebuggerConnected_ {false};
517 bool isProfileableFromShell_ {false};
518 os::memory::Mutex debugSessionCreationMutex_ {};
519 os::memory::Mutex debugSessionUniquenessMutex_ {};
520 DebugSessionHandle debugSession_ {};
521
522 // Additional VMInfo
523 std::string processPackageName_;
524 std::string processDataDirectory_;
525
526 // For saving class path.
527 std::string pandaPathString_;
528
529 AbortHook abort_ = nullptr;
530 ExitHook exit_ = nullptr;
531
532 bool zygoteNoThreads_ {false};
533 bool isZygote_;
534 bool isInitialized_ {false};
535
536 bool saveProfilingInfo_;
537
538 bool checksSuspend_ {false};
539 bool checksStack_ {true};
540 bool checksNullptr_ {true};
541 bool isStacktrace_ {false};
542 bool isJitEnabled_ {false};
543 bool isProfilerEnabled_ {false};
544
545 bool isDumpNativeCrash_ {true};
546
547 PandaString fingerPrint_ = "unknown";
548
549 // Verification
550 ark::verifier::Config *verifierConfig_ = nullptr;
551 ark::verifier::Service *verifierService_ = nullptr;
552
553 struct AppContext {
554 ClassLinkerContext *ctx {nullptr};
555 std::optional<panda_file::SourceLang> lang;
556 };
557 AppContext appContext_ {};
558
559 RuntimeController *runtimeController_ {nullptr};
560 UnwindStackFn unwindStackFn_ {nullptr};
561
562 tooling::Tools tools_;
563
564 NO_COPY_SEMANTIC(Runtime);
565 NO_MOVE_SEMANTIC(Runtime);
566 };
567
GetInternalAllocatorAdapter(const Runtime * runtime)568 inline mem::AllocatorAdapter<void> GetInternalAllocatorAdapter(const Runtime *runtime)
569 {
570 return runtime->GetInternalAllocator()->Adapter();
571 }
572
573 void InitSignals();
574
575 } // namespace ark
576
577 #endif // PANDA_RUNTIME_RUNTIME_H_
578