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