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