1 /*
2 * Copyright (c) 2021 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_INCLUDE_RUNTIME_H_
17 #define PANDA_RUNTIME_INCLUDE_RUNTIME_H_
18
19 #include <atomic>
20 #include <memory>
21 #include <string>
22 #include <signal.h> // NOLINTNEXTLINE(modernize-deprecated-headers)
23 #include <vector>
24
25 #include "libpandabase/mem/arena_allocator.h"
26 #include "libpandabase/os/mutex.h"
27 #include "libpandabase/os/library_loader.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_smart_pointers.h"
34 #include "runtime/include/runtime_options.h"
35 #include "runtime/include/gc_task.h"
36 #include "runtime/include/tooling/debug_interface.h"
37 #include "runtime/signal_handler.h"
38 #include "runtime/mem/allocator_adapter.h"
39 #include "runtime/mem/gc/gc.h"
40 #include "runtime/mem/gc/gc_trigger.h"
41 #include "runtime/mem/memory_manager.h"
42 #include "runtime/monitor_pool.h"
43 #include "runtime/string_table.h"
44 #include "runtime/thread_manager.h"
45 #include "verification/verification_options.h"
46
47 namespace panda {
48
49 class DProfiler;
50 class ClassLinker;
51 class CompilerInterface;
52 class RuntimeController;
53
54 class PandaVM;
55 class RuntimeNotificationManager;
56 class Trace;
57
58 namespace tooling {
59 class PtLangExt;
60 class Debugger;
61 } // namespace tooling
62
63 class Runtime {
64 public:
65 using ExitHook = void (*)(int32_t status);
66 using AbortHook = void (*)();
67
68 enum class Error {
69 PANDA_FILE_LOAD_ERROR,
70 INVALID_ENTRY_POINT,
71 CLASS_NOT_FOUND,
72 CLASS_NOT_INITIALIZED,
73 METHOD_NOT_FOUND,
74 CLASS_LINKER_EXTENSION_NOT_FOUND
75 };
76
77 LanguageContext GetLanguageContext(const std::string &runtime_type);
78 LanguageContext GetLanguageContext(const Method &method);
79 LanguageContext GetLanguageContext(const Class &cls);
80 LanguageContext GetLanguageContext(const BaseClass &cls);
81 LanguageContext GetLanguageContext(panda_file::ClassDataAccessor *cda);
82 LanguageContext GetLanguageContext(panda_file::SourceLang lang);
83
84 static bool CreateInstance(const RuntimeOptions &options, mem::InternalAllocatorPtr internal_allocator,
85 const std::vector<LanguageContextBase *> &ctxs);
86
87 PANDA_PUBLIC_API static bool Create(const RuntimeOptions &options,
88 const std::vector<LanguageContextBase *> &ctxs = {});
89
90 static bool DestroyUnderLockHolder();
91
92 PANDA_PUBLIC_API static bool Destroy();
93
94 PANDA_PUBLIC_API static Runtime *GetCurrent();
95
96 template <typename Handler>
GetCurrentSync(Handler && handler)97 static auto GetCurrentSync(Handler &&handler)
98 {
99 os::memory::LockHolder<os::memory::Mutex> lock(mutex);
100 return handler(*GetCurrent());
101 }
102
GetClassLinker()103 ClassLinker *GetClassLinker() const
104 {
105 return class_linker_;
106 }
107
GetNotificationManager()108 RuntimeNotificationManager *GetNotificationManager() const
109 {
110 return notification_manager_;
111 }
112
GetOptions()113 static const RuntimeOptions &GetOptions()
114 {
115 return options_;
116 }
117
SetZygoteNoThreadSection(bool val)118 void SetZygoteNoThreadSection(bool val)
119 {
120 zygote_no_threads_ = val;
121 }
122
123 coretypes::String *ResolveString(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
124
125 coretypes::String *ResolveString(PandaVM *vm, const panda_file::File &pf, panda_file::File::EntityId id,
126 LanguageContext ctx);
127
128 coretypes::String *ResolveString(PandaVM *vm, const uint8_t *mutf8, uint32_t length, LanguageContext ctx);
129
130 Class *GetClassRootForLiteralTag(const ClassLinkerExtension &ext, panda_file::LiteralTag tag) const;
131 static bool GetLiteralTagAndValue(const panda_file::File &pf, panda_file::File::EntityId id,
132 panda_file::LiteralTag *tag,
133 panda_file::LiteralDataAccessor::LiteralValue *value);
134
135 coretypes::Array *ResolveLiteralArray(PandaVM *vm, const Method &caller, panda_file::File::EntityId id);
136
137 coretypes::Array *ResolveLiteralArray(PandaVM *vm, const panda_file::File &pf, panda_file::File::EntityId id,
138 LanguageContext ctx);
139
140 void PreZygoteFork();
141
142 void PostZygoteFork();
143
144 Expected<int, Error> ExecutePandaFile(std::string_view filename, std::string_view entry_point,
145 const std::vector<std::string> &args);
146
147 int StartDProfiler(std::string_view app_name);
148
149 Expected<int, Error> Execute(std::string_view entry_point, const std::vector<std::string> &args);
150
151 int StartDProfiler(const PandaString &app_name);
152
IsDebugMode()153 bool IsDebugMode() const
154 {
155 return is_debug_mode_;
156 }
157
SetDebugMode(bool is_debug_mode)158 void SetDebugMode(bool is_debug_mode)
159 {
160 is_debug_mode_ = is_debug_mode;
161 }
162
SetDebuggerLibrary(os::library_loader::LibraryHandle debugger_library)163 void SetDebuggerLibrary(os::library_loader::LibraryHandle debugger_library)
164 {
165 debugger_library_ = std::move(debugger_library);
166 }
167
IsDebuggerConnected()168 bool IsDebuggerConnected() const
169 {
170 return is_debugger_connected_;
171 }
172
SetDebuggerConnected(bool dbg_connected_state)173 void SetDebuggerConnected(bool dbg_connected_state)
174 {
175 is_debugger_connected_ = dbg_connected_state;
176 }
177
178 PandaVector<PandaString> GetBootPandaFiles();
179
180 PandaVector<PandaString> GetPandaFiles();
181
182 // Additional VMInfo
183 void RegisterAppInfo(const PandaVector<PandaString> &code_paths, const PandaString &profile_output_filename);
184
185 // Returns true if profile saving is enabled.
186 bool SaveProfileInfo() const;
187
GetProcessPackageName()188 const std::string &GetProcessPackageName() const
189 {
190 return process_package_name_;
191 }
192
SetProcessPackageName(const char * package_name)193 void SetProcessPackageName(const char *package_name)
194 {
195 if (package_name == nullptr) {
196 process_package_name_.clear();
197 } else {
198 process_package_name_ = package_name;
199 }
200 }
201
GetProcessDataDirectory()202 const std::string &GetProcessDataDirectory() const
203 {
204 return process_data_directory_;
205 }
206
SetProcessDataDirectory(const char * data_dir)207 void SetProcessDataDirectory(const char *data_dir)
208 {
209 if (data_dir == nullptr) {
210 process_data_directory_.clear();
211 } else {
212 process_data_directory_ = data_dir;
213 }
214 }
215
GetPandaPath()216 std::string GetPandaPath()
217 {
218 return panda_path_string_;
219 }
220
221 void UpdateProcessState(int state);
222
IsZygote()223 bool IsZygote() const
224 {
225 return is_zygote_;
226 }
227
IsInitialized()228 bool IsInitialized() const
229 {
230 return is_initialized_;
231 }
232
GetVersion()233 static const char *GetVersion()
234 {
235 return "1.0.0";
236 }
237
GetFingerprint()238 PandaString GetFingerprint()
239 {
240 return fingerPrint_;
241 }
242
243 [[noreturn]] static void Halt(int32_t status);
244
SetExitHook(ExitHook exit_hook)245 void SetExitHook(ExitHook exit_hook)
246 {
247 ASSERT(exit_ == nullptr);
248 exit_ = exit_hook;
249 }
250
SetAbortHook(AbortHook abort_hook)251 void SetAbortHook(AbortHook abort_hook)
252 {
253 ASSERT(abort_ == nullptr);
254 abort_ = abort_hook;
255 }
256
257 [[noreturn]] static void Abort(const char *message = nullptr);
258
259 Expected<Method *, Error> ResolveEntryPoint(std::string_view entry_point);
260
261 void RegisterSensitiveThread() const;
262
GetPandaVM()263 PandaVM *GetPandaVM() const
264 {
265 return panda_vm_;
266 }
267
GetPtLangExt()268 tooling::PtLangExt *GetPtLangExt() const
269 {
270 return pt_lang_ext_;
271 }
272
GetVerificationOptions()273 const panda::verifier::VerificationOptions &GetVerificationOptions() const
274 {
275 return VerificationOptions_;
276 }
277
GetVerificationOptions()278 panda::verifier::VerificationOptions &GetVerificationOptions()
279 {
280 return VerificationOptions_;
281 }
282
283 void DumpForSigQuit(std::ostream &os);
284
IsDumpNativeCrash()285 bool IsDumpNativeCrash()
286 {
287 return is_dump_native_crash_;
288 }
289
IsChecksSuspend()290 bool IsChecksSuspend() const
291 {
292 return checks_suspend_;
293 }
294
IsChecksStack()295 bool IsChecksStack() const
296 {
297 return checks_stack_;
298 }
299
IsChecksNullptr()300 bool IsChecksNullptr() const
301 {
302 return checks_nullptr_;
303 }
304
IsStacktrace()305 bool IsStacktrace() const
306 {
307 return is_stacktrace_;
308 }
309
GetSignalManager()310 SignalManager *GetSignalManager()
311 {
312 return signal_manager_;
313 }
314
315 Trace *CreateTrace(LanguageContext ctx, PandaUniquePtr<os::unix::file::File> trace_file, size_t buffer_size);
316
317 void SetPtLangExt(tooling::PtLangExt *pt_lang_ext);
318
319 static mem::GCType GetGCType(const RuntimeOptions &options);
320
321 bool AttachDebugger();
322
GetInternalAllocator()323 mem::InternalAllocatorPtr GetInternalAllocator() const
324 {
325 return internal_allocator_;
326 }
327
328 PandaString GetMemoryStatistics();
329 PandaString GetFinalStatistics();
330
331 Expected<LanguageContext, Error> ExtractLanguageContext(const panda_file::File *pf, std::string_view entry_point);
332
333 private:
334 void NotifyAboutLoadedModules();
335
336 std::optional<Error> CreateApplicationClassLinkerContext(std::string_view filename, std::string_view entry_point);
337
338 bool LoadVerificationConfig();
339
340 bool CreatePandaVM(std::string_view runtime_type);
341
342 bool InitializePandaVM();
343
344 bool CheckOptionsConsistency();
345
346 void SetPandaPath();
347
348 bool Initialize();
349
350 bool Shutdown();
351
352 bool LoadBootPandaFiles(panda_file::File::OpenMode open_mode);
353
354 bool StartDebugger(const std::string &library_path);
355
356 bool IsEnableMemoryHooks() const;
357
358 static void CreateDfxController(const RuntimeOptions &options);
359
360 static void BlockSignals();
361
362 inline void InitializeVerificationResultCache(const RuntimeOptions &options);
363
364 Runtime(const RuntimeOptions &options, mem::InternalAllocatorPtr internal_allocator,
365 const std::vector<LanguageContextBase *> &ctxs);
366
367 ~Runtime();
368
369 static Runtime *instance;
370 static RuntimeOptions options_;
371 static os::memory::Mutex mutex;
372
373 mem::InternalAllocatorPtr internal_allocator_;
374 RuntimeNotificationManager *notification_manager_;
375 ClassLinker *class_linker_;
376 DProfiler *dprofiler_ = nullptr;
377
378 PandaVM *panda_vm_ = nullptr;
379
380 SignalManager *signal_manager_ {nullptr};
381
382 // Language context
383 static constexpr size_t LANG_EXTENSIONS_COUNT = static_cast<size_t>(panda_file::SourceLang::LAST) + 1;
384 std::array<LanguageContextBase *, LANG_EXTENSIONS_COUNT> language_contexts_ {nullptr};
385
386 // For IDE is really connected.
387 bool is_debug_mode_ {false};
388 bool is_debugger_connected_ {false};
389 tooling::PtLangExt *pt_lang_ext_ {nullptr};
390 tooling::DebugInterface *debugger_ {nullptr};
391 os::library_loader::LibraryHandle debugger_library_;
392
393 // Additional VMInfo
394 std::string process_package_name_;
395 std::string process_data_directory_;
396
397 // For saving class path.
398 std::string panda_path_string_;
399
400 AbortHook abort_ = nullptr;
401 ExitHook exit_ = nullptr;
402
403 bool zygote_no_threads_;
404 bool is_zygote_;
405 bool is_initialized_ {false};
406
407 bool save_profiling_info_;
408
409 bool checks_suspend_ {false};
410 bool checks_stack_ {true};
411 bool checks_nullptr_ {true};
412 bool is_stacktrace_ {false};
413
414 bool is_dump_native_crash_ {true};
415
416 PandaString fingerPrint_ = "unknown";
417
418 // Verification
419 panda::verifier::VerificationOptions VerificationOptions_;
420
421 struct AppContext {
422 ClassLinkerContext *ctx {nullptr};
423 std::optional<panda_file::SourceLang> lang;
424 };
425 AppContext app_context_ {};
426
427 NO_COPY_SEMANTIC(Runtime);
428 NO_MOVE_SEMANTIC(Runtime);
429 };
430
GetInternalAllocatorAdapter(const Runtime * runtime)431 inline mem::AllocatorAdapter<void> GetInternalAllocatorAdapter(const Runtime *runtime)
432 {
433 return runtime->GetInternalAllocator()->Adapter();
434 }
435
436 void InitSignals();
437
438 } // namespace panda
439
440 #endif // PANDA_RUNTIME_INCLUDE_RUNTIME_H_
441