15ffd83dbSDimitry Andric //===-- SystemInitializerCommon.cpp ---------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "lldb/Initialization/SystemInitializerCommon.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
120b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
130b57cec5SDimitry Andric #include "lldb/Host/Host.h"
140b57cec5SDimitry Andric #include "lldb/Host/Socket.h"
150b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
16af732203SDimitry Andric #include "lldb/Utility/ReproducerProvider.h"
170b57cec5SDimitry Andric #include "lldb/Utility/Timer.h"
180b57cec5SDimitry Andric #include "lldb/lldb-private.h"
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
210b57cec5SDimitry Andric #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
220b57cec5SDimitry Andric #endif
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric #if defined(_WIN32)
250b57cec5SDimitry Andric #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"
260b57cec5SDimitry Andric #include "lldb/Host/windows/windows.h"
279dba64beSDimitry Andric #include <crtdbg.h>
280b57cec5SDimitry Andric #endif
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h"
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric #include <string>
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric using namespace lldb_private;
350b57cec5SDimitry Andric using namespace lldb_private::repro;
360b57cec5SDimitry Andric
SystemInitializerCommon(HostInfo::SharedLibraryDirectoryHelper * helper)37*5f7ddb14SDimitry Andric SystemInitializerCommon::SystemInitializerCommon(
38*5f7ddb14SDimitry Andric HostInfo::SharedLibraryDirectoryHelper *helper)
39*5f7ddb14SDimitry Andric : m_shlib_dir_helper(helper) {}
400b57cec5SDimitry Andric
41*5f7ddb14SDimitry Andric SystemInitializerCommon::~SystemInitializerCommon() = default;
420b57cec5SDimitry Andric
43af732203SDimitry Andric /// Initialize the FileSystem based on the current reproducer mode.
InitializeFileSystem()44af732203SDimitry Andric static llvm::Error InitializeFileSystem() {
45af732203SDimitry Andric auto &r = repro::Reproducer::Instance();
46af732203SDimitry Andric if (repro::Loader *loader = r.GetLoader()) {
47af732203SDimitry Andric FileSpec vfs_mapping = loader->GetFile<FileProvider::Info>();
48af732203SDimitry Andric if (vfs_mapping) {
49af732203SDimitry Andric if (llvm::Error e = FileSystem::Initialize(vfs_mapping))
50af732203SDimitry Andric return e;
51af732203SDimitry Andric } else {
52af732203SDimitry Andric FileSystem::Initialize();
53af732203SDimitry Andric }
54af732203SDimitry Andric
55af732203SDimitry Andric // Set the current working directory form the reproducer.
56af732203SDimitry Andric llvm::Expected<std::string> working_dir =
57af732203SDimitry Andric repro::GetDirectoryFrom<WorkingDirectoryProvider>(loader);
58af732203SDimitry Andric if (!working_dir)
59af732203SDimitry Andric return working_dir.takeError();
60af732203SDimitry Andric if (std::error_code ec = FileSystem::Instance()
61af732203SDimitry Andric .GetVirtualFileSystem()
62af732203SDimitry Andric ->setCurrentWorkingDirectory(*working_dir)) {
63af732203SDimitry Andric return llvm::errorCodeToError(ec);
64af732203SDimitry Andric }
65af732203SDimitry Andric
66af732203SDimitry Andric // Set the home directory from the reproducer.
67af732203SDimitry Andric llvm::Expected<std::string> home_dir =
68af732203SDimitry Andric repro::GetDirectoryFrom<HomeDirectoryProvider>(loader);
69af732203SDimitry Andric if (!home_dir)
70af732203SDimitry Andric return home_dir.takeError();
71af732203SDimitry Andric FileSystem::Instance().SetHomeDirectory(*home_dir);
72af732203SDimitry Andric
73af732203SDimitry Andric return llvm::Error::success();
74af732203SDimitry Andric }
75af732203SDimitry Andric
76af732203SDimitry Andric if (repro::Generator *g = r.GetGenerator()) {
77af732203SDimitry Andric repro::VersionProvider &vp = g->GetOrCreate<repro::VersionProvider>();
78af732203SDimitry Andric vp.SetVersion(lldb_private::GetVersion());
79af732203SDimitry Andric
80af732203SDimitry Andric repro::FileProvider &fp = g->GetOrCreate<repro::FileProvider>();
81af732203SDimitry Andric FileSystem::Initialize(fp.GetFileCollector());
82af732203SDimitry Andric
83af732203SDimitry Andric fp.RecordInterestingDirectory(
84af732203SDimitry Andric g->GetOrCreate<repro::WorkingDirectoryProvider>().GetDirectory());
85af732203SDimitry Andric fp.RecordInterestingDirectory(
86af732203SDimitry Andric g->GetOrCreate<repro::HomeDirectoryProvider>().GetDirectory());
87af732203SDimitry Andric
88af732203SDimitry Andric return llvm::Error::success();
89af732203SDimitry Andric }
90af732203SDimitry Andric
91af732203SDimitry Andric FileSystem::Initialize();
92af732203SDimitry Andric return llvm::Error::success();
93af732203SDimitry Andric }
94af732203SDimitry Andric
Initialize()950b57cec5SDimitry Andric llvm::Error SystemInitializerCommon::Initialize() {
960b57cec5SDimitry Andric #if defined(_WIN32)
970b57cec5SDimitry Andric const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG");
980b57cec5SDimitry Andric if (disable_crash_dialog_var &&
99*5f7ddb14SDimitry Andric llvm::StringRef(disable_crash_dialog_var).equals_insensitive("true")) {
1000b57cec5SDimitry Andric // This will prevent Windows from displaying a dialog box requiring user
1010b57cec5SDimitry Andric // interaction when
1020b57cec5SDimitry Andric // LLDB crashes. This is mostly useful when automating LLDB, for example
1030b57cec5SDimitry Andric // via the test
1040b57cec5SDimitry Andric // suite, so that a crash in LLDB does not prevent completion of the test
1050b57cec5SDimitry Andric // suite.
1060b57cec5SDimitry Andric ::SetErrorMode(GetErrorMode() | SEM_FAILCRITICALERRORS |
1070b57cec5SDimitry Andric SEM_NOGPFAULTERRORBOX);
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
1100b57cec5SDimitry Andric _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
1110b57cec5SDimitry Andric _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
1120b57cec5SDimitry Andric _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1130b57cec5SDimitry Andric _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1140b57cec5SDimitry Andric _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric #endif
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric // If the reproducer wasn't initialized before, we can safely assume it's
1190b57cec5SDimitry Andric // off.
1200b57cec5SDimitry Andric if (!Reproducer::Initialized()) {
1210b57cec5SDimitry Andric if (auto e = Reproducer::Initialize(ReproducerMode::Off, llvm::None))
1220b57cec5SDimitry Andric return e;
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
125af732203SDimitry Andric if (auto e = InitializeFileSystem())
1260b57cec5SDimitry Andric return e;
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric Log::Initialize();
129*5f7ddb14SDimitry Andric HostInfo::Initialize(m_shlib_dir_helper);
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric llvm::Error error = Socket::Initialize();
1320b57cec5SDimitry Andric if (error)
1330b57cec5SDimitry Andric return error;
1340b57cec5SDimitry Andric
135af732203SDimitry Andric LLDB_SCOPED_TIMER();
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric process_gdb_remote::ProcessGDBRemoteLog::Initialize();
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
1400b57cec5SDimitry Andric ProcessPOSIXLog::Initialize();
1410b57cec5SDimitry Andric #endif
1420b57cec5SDimitry Andric #if defined(_WIN32)
1430b57cec5SDimitry Andric ProcessWindowsLog::Initialize();
1440b57cec5SDimitry Andric #endif
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric return llvm::Error::success();
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric
Terminate()1490b57cec5SDimitry Andric void SystemInitializerCommon::Terminate() {
150af732203SDimitry Andric LLDB_SCOPED_TIMER();
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric #if defined(_WIN32)
1530b57cec5SDimitry Andric ProcessWindowsLog::Terminate();
1540b57cec5SDimitry Andric #endif
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric Socket::Terminate();
1570b57cec5SDimitry Andric HostInfo::Terminate();
1580b57cec5SDimitry Andric Log::DisableAllLogChannels();
1590b57cec5SDimitry Andric FileSystem::Terminate();
1600b57cec5SDimitry Andric Reproducer::Terminate();
1610b57cec5SDimitry Andric }
162