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