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 <memory>
21 #include <string>
22 #include <csignal>
23 #include <vector>
24
25 #include "libpandabase/mem/arena_allocator.h"
26 #include "libpandabase/os/mutex.h"
27 #include "libpandabase/utils/expected.h"
28 #include "libpandafile/file_items.h"
29 #include "libpandafile/literal_data_accessor.h"
30 #include "runtime/include/class_linker.h"
31 #include "runtime/include/mem/panda_containers.h"
32 #include "runtime/include/mem/panda_smart_pointers.h"
33 #include "runtime/include/mem/panda_string.h"
34 #include "runtime/include/method.h"
35 #include "runtime/include/relayout_profiler.h"
36 #include "runtime/include/runtime_options.h"
37 #include "runtime/include/gc_task.h"
38 #include "runtime/include/tooling/debug_interface.h"
39 #include "runtime/mem/allocator_adapter.h"
40 #include "runtime/mem/gc/gc.h"
41 #include "runtime/mem/gc/gc_trigger.h"
42 #include "runtime/mem/memory_manager.h"
43 #include "runtime/monitor_pool.h"
44 #include "runtime/string_table.h"
45 #include "runtime/thread_manager.h"
46 #include "verification/verification_options.h"
47 #include "libpandabase/os/native_stack.h"
48 #include "libpandabase/os/library_loader.h"
49 #include "runtime/include/loadable_agent.h"
50
51 namespace panda {
52
53 class DProfiler;
54 class CompilerInterface;
55 class ClassHierarchyAnalysis;
56 class RuntimeController;
57 class PandaVM;
58 class RuntimeNotificationManager;
59 class Trace;
60
61 namespace tooling {
62 class Debugger;
63 } // namespace tooling
64
65 using UnwindStackFn = os::unix::native_stack::FUNC_UNWINDSTACK;
66
67 class Runtime {
68 public:
69 using ExitHook = void (*)(int32_t status);
70 using AbortHook = void (*)();
71
72 enum class Error {
73 PANDA_FILE_LOAD_ERROR,
74 INVALID_ENTRY_POINT,
75 CLASS_NOT_FOUND,
76 CLASS_NOT_INITIALIZED,
77 METHOD_NOT_FOUND,
78 CLASS_LINKER_EXTENSION_NOT_FOUND
79 };
80
81 class DebugSession final {
82 public:
83 explicit DebugSession(Runtime &runtime);
84 ~DebugSession();
85
86 tooling::DebugInterface &GetDebugger();
87
88 private:
89 Runtime &runtime_;
90 bool is_jit_enabled_;
91 os::memory::LockHolder<os::memory::Mutex> lock_;
92 PandaUniquePtr<tooling::DebugInterface> debugger_;
93
94 NO_COPY_SEMANTIC(DebugSession);
95 NO_MOVE_SEMANTIC(DebugSession);
96 };
97
98 using DebugSessionHandle = std::shared_ptr<DebugSession>;
99
100 LanguageContext GetLanguageContext(const std::string &runtime_type);
101 LanguageContext GetLanguageContext(const Method &method);
102 LanguageContext GetLanguageContext(const Class &cls);
103 LanguageContext GetLanguageContext(const BaseClass &cls);
104 LanguageContext GetLanguageContext(panda_file::ClassDataAccessor *cda);
105 LanguageContext GetLanguageContext(panda_file::SourceLang lang);
106
107 static bool CreateInstance(const RuntimeOptions &options, mem::InternalAllocatorPtr internal_allocator);
108
109 PANDA_PUBLIC_API static bool Create(const RuntimeOptions &options);
110
111 // Deprecated. Only for capability with ets_runtime.
112 PANDA_PUBLIC_API static bool Create(const RuntimeOptions &options, const std::vector<LanguageContextBase *> &ctxs);
113
114 static bool DestroyUnderLockHolder();
115
116 PANDA_PUBLIC_API static bool Destroy();
117
118 PANDA_PUBLIC_API static Runtime *GetCurrent();
119
120 template <typename Handler>
GetCurrentSync(Handler && handler)121 static auto GetCurrentSync(Handler &&handler)
122 {
123 os::memory::LockHolder<os::memory::Mutex> lock(mutex);
124 return handler(*GetCurrent());
125 }
126
GetClassLinker()127 ClassLinker *GetClassLinker() const
128 {
129 return class_linker_;
130 }
131
GetNotificationManager()132 RuntimeNotificationManager *GetNotificationManager() const
133 {
134 return notification_manager_;
135 }
136
GetOptions()137 static const RuntimeOptions &GetOptions()
138 {
139 return options_;
140 }
141
SetZygoteNoThreadSection(bool val)142 void SetZygoteNoThreadSection(bool val)
143 {
144 zygote_no_threads_ = val;
145 }
146
147 coretypes::String *ResolveString(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
148
149 coretypes::String *ResolveStringFromCompiledCode(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
150
151 coretypes::String *ResolveString(PandaVM *vm, const panda_file::File &pf, panda_file::File::EntityId id,
152 const LanguageContext &ctx);
153
154 coretypes::String *ResolveString(PandaVM *vm, const uint8_t *mutf8, uint32_t length, const LanguageContext &ctx);
155
156 Class *GetClassRootForLiteralTag(const ClassLinkerExtension &ext, panda_file::LiteralTag tag) const;
157
158 static bool GetLiteralTagAndValue(const panda_file::File &pf, uint32_t id, panda_file::LiteralTag *tag,
159 panda_file::LiteralDataAccessor::LiteralValue *value);
160
161 uintptr_t GetPointerToConstArrayData(const panda_file::File &pf, uint32_t id) const;
162
163 coretypes::Array *ResolveLiteralArray(PandaVM *vm, const Method &caller, uint32_t id);
164 coretypes::Array *ResolveLiteralArray(PandaVM *vm, const panda_file::File &pf, uint32_t id,
165 const LanguageContext &ctx);
166
167 void PreZygoteFork();
168
169 void PostZygoteFork();
170
171 Expected<int, Error> ExecutePandaFile(std::string_view filename, std::string_view entry_point,
172 const std::vector<std::string> &args);
173
174 int StartDProfiler(std::string_view app_name);
175
176 Expected<int, Error> Execute(std::string_view entry_point, const std::vector<std::string> &args);
177
178 int StartDProfiler(const PandaString &app_name);
179
IsDebugMode()180 bool IsDebugMode() const
181 {
182 return is_debug_mode_;
183 }
184
SetDebugMode(bool is_debug_mode)185 void SetDebugMode(bool is_debug_mode)
186 {
187 is_debug_mode_ = is_debug_mode;
188 }
189
IsDebuggerConnected()190 bool IsDebuggerConnected() const
191 {
192 return is_debugger_connected_;
193 }
194
SetDebuggerConnected(bool dbg_connected_state)195 void SetDebuggerConnected(bool dbg_connected_state)
196 {
197 is_debugger_connected_ = dbg_connected_state;
198 }
199
IsProfileableFromShell()200 bool IsProfileableFromShell() const
201 {
202 return is_profileable_from_shell_;
203 }
204
SetProfileableFromShell(bool profileable_from_shell)205 void SetProfileableFromShell(bool profileable_from_shell)
206 {
207 is_profileable_from_shell_ = profileable_from_shell;
208 }
209
210 PandaVector<PandaString> GetBootPandaFiles();
211
212 PandaVector<PandaString> GetPandaFiles();
213
214 // Returns true if profile saving is enabled.
215 bool SaveProfileInfo() const;
216
GetPandaPath()217 std::string GetPandaPath()
218 {
219 return panda_path_string_;
220 }
221
GetRuntimeType()222 static const std::string &GetRuntimeType()
223 {
224 return runtime_type_;
225 }
226
227 void UpdateProcessState(int state);
228
IsZygote()229 bool IsZygote() const
230 {
231 return is_zygote_;
232 }
233
IsInitialized()234 bool IsInitialized() const
235 {
236 return is_initialized_;
237 }
238
239 // TODO: lack NativeBridgeAction action
240 void InitNonZygoteOrPostFork(bool is_system_server, const char *isa, bool profile_system_server = false);
241
GetVersion()242 static const char *GetVersion()
243 {
244 // TODO(chenmudan): change to the correct version when we have one;
245 return "1.0.0";
246 }
247
GetFingerprint()248 PandaString GetFingerprint()
249 {
250 return fingerPrint_;
251 }
252
253 [[noreturn]] static void Halt(int32_t status);
254
SetExitHook(ExitHook exit_hook)255 void SetExitHook(ExitHook exit_hook)
256 {
257 ASSERT(exit_ == nullptr);
258 exit_ = exit_hook;
259 }
260
SetAbortHook(AbortHook abort_hook)261 void SetAbortHook(AbortHook abort_hook)
262 {
263 ASSERT(abort_ == nullptr);
264 abort_ = abort_hook;
265 }
266
267 [[noreturn]] static void Abort(const char *message = nullptr);
268
269 Expected<Method *, Error> ResolveEntryPoint(std::string_view entry_point);
270
271 void RegisterSensitiveThread() const;
272
273 // Deprecated.
274 // Get VM instance from the thread. In multi-vm runtime this method returns
275 // the first VM. It is undeterminated which VM will be first.
GetPandaVM()276 PandaVM *GetPandaVM() const
277 {
278 return panda_vm_;
279 }
280
GetCha()281 ClassHierarchyAnalysis *GetCha() const
282 {
283 return cha_;
284 }
285
GetVerificationOptions()286 const panda::verifier::VerificationOptions &GetVerificationOptions() const
287 {
288 return VerificationOptions_;
289 }
290
GetVerificationOptions()291 panda::verifier::VerificationOptions &GetVerificationOptions()
292 {
293 return VerificationOptions_;
294 }
295
IsDebuggerAttached()296 bool IsDebuggerAttached()
297 {
298 return debug_session_.use_count() > 0;
299 }
300
301 void DumpForSigQuit(std::ostream &os);
302
IsDumpNativeCrash()303 bool IsDumpNativeCrash()
304 {
305 return is_dump_native_crash_;
306 }
307
IsChecksSuspend()308 bool IsChecksSuspend() const
309 {
310 return checks_suspend_;
311 }
312
IsChecksStack()313 bool IsChecksStack() const
314 {
315 return checks_stack_;
316 }
317
IsChecksNullptr()318 bool IsChecksNullptr() const
319 {
320 return checks_nullptr_;
321 }
322
IsStacktrace()323 bool IsStacktrace() const
324 {
325 return is_stacktrace_;
326 }
327
IsJitEnabled()328 bool IsJitEnabled() const
329 {
330 return is_jit_enabled_;
331 }
332
ForceEnableJit()333 void ForceEnableJit()
334 {
335 is_jit_enabled_ = true;
336 }
337
ForceDisableJit()338 void ForceDisableJit()
339 {
340 is_jit_enabled_ = false;
341 }
342
343 static mem::GCType GetGCType(const RuntimeOptions &options, panda_file::SourceLang lang);
344
345 static void SetDaemonMemoryLeakThreshold(uint32_t daemon_memory_leak_threshold);
346
347 DebugSessionHandle StartDebugSession();
348
GetInternalAllocator()349 mem::InternalAllocatorPtr GetInternalAllocator() const
350 {
351 return internal_allocator_;
352 }
353
354 PandaString GetMemoryStatistics();
355 PandaString GetFinalStatistics();
356
357 Expected<LanguageContext, Error> ExtractLanguageContext(const panda_file::File *pf, std::string_view entry_point);
358
GetUnwindStackFn()359 UnwindStackFn GetUnwindStackFn() const
360 {
361 return unwind_stack_fn_;
362 }
363
SetUnwindStackFn(UnwindStackFn unwind_stack_fn)364 void SetUnwindStackFn(UnwindStackFn unwind_stack_fn)
365 {
366 unwind_stack_fn_ = unwind_stack_fn;
367 }
368
GetRelayoutProfiler()369 RelayoutProfiler *GetRelayoutProfiler()
370 {
371 return relayout_profiler_;
372 }
373
374 private:
375 void NotifyAboutLoadedModules();
376
377 std::optional<Error> CreateApplicationClassLinkerContext(std::string_view filename, std::string_view entry_point);
378
379 bool LoadVerificationConfig();
380
381 bool CreatePandaVM(std::string_view runtime_type);
382
383 bool InitializePandaVM();
384
385 bool HandleAotOptions();
386
387 void HandleJitOptions();
388
389 bool CheckOptionsConsistency();
390
391 void SetPandaPath();
392
393 bool Initialize();
394
395 bool Shutdown();
396
397 bool LoadBootPandaFiles(panda_file::File::OpenMode open_mode);
398
399 static void BlockSignals();
400
401 inline void InitializeVerificationResultCache();
402
403 Runtime(const RuntimeOptions &options, mem::InternalAllocatorPtr internal_allocator);
404
405 ~Runtime();
406
407 static Runtime *instance;
408 static RuntimeOptions options_;
409 static std::string runtime_type_;
410 static os::memory::Mutex mutex;
411
412 // TODO(dtrubenk): put all of it in the permanent space
413 mem::InternalAllocatorPtr internal_allocator_;
414 RuntimeNotificationManager *notification_manager_;
415 ClassLinker *class_linker_;
416 ClassHierarchyAnalysis *cha_;
417 DProfiler *dprofiler_ = nullptr;
418
419 PandaVM *panda_vm_ = nullptr;
420
421 // For IDE is real connected.
422 bool is_debug_mode_ {false};
423 bool is_debugger_connected_ {false};
424 bool is_profileable_from_shell_ {false};
425 os::memory::Mutex debug_session_creation_mutex_ {};
426 os::memory::Mutex debug_session_uniqueness_mutex_ {};
427 DebugSessionHandle debug_session_ {};
428
429 // For saving class path.
430 std::string panda_path_string_;
431
432 AbortHook abort_ = nullptr;
433 ExitHook exit_ = nullptr;
434
435 bool zygote_no_threads_;
436 bool is_zygote_;
437 bool is_initialized_ {false};
438
439 bool save_profiling_info_;
440
441 bool checks_suspend_ {false};
442 bool checks_stack_ {true};
443 bool checks_nullptr_ {true};
444 bool is_stacktrace_ {false};
445 bool is_jit_enabled_ {false};
446
447 bool is_dump_native_crash_ {true};
448
449 PandaString fingerPrint_ = "unknown";
450
451 // Verification
452 panda::verifier::VerificationOptions VerificationOptions_;
453
454 struct AppContext {
455 ClassLinkerContext *ctx {nullptr};
456 std::optional<panda_file::SourceLang> lang;
457 };
458 AppContext app_context_ {};
459
460 RuntimeController *runtime_controller_ {nullptr};
461 UnwindStackFn unwind_stack_fn_ {nullptr};
462
463 RelayoutProfiler *relayout_profiler_ {nullptr};
464
465 NO_COPY_SEMANTIC(Runtime);
466 NO_MOVE_SEMANTIC(Runtime);
467 };
468
GetInternalAllocatorAdapter(const Runtime * runtime)469 inline mem::AllocatorAdapter<void> GetInternalAllocatorAdapter(const Runtime *runtime)
470 {
471 return runtime->GetInternalAllocator()->Adapter();
472 }
473
474 void InitSignals();
475
476 } // namespace panda
477
478 #endif // PANDA_RUNTIME_RUNTIME_H_
479