1 //===-- SystemInitializerCommon.cpp ---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "lldb/Initialization/SystemInitializerCommon.h"
10
11 #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
12 #include "lldb/Host/FileSystem.h"
13 #include "lldb/Host/Host.h"
14 #include "lldb/Host/Socket.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/ReproducerProvider.h"
17 #include "lldb/Utility/Timer.h"
18 #include "lldb/lldb-private.h"
19
20 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
21 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
22 #endif
23
24 #if defined(_WIN32)
25 #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"
26 #include "lldb/Host/windows/windows.h"
27 #include <crtdbg.h>
28 #endif
29
30 #include "llvm/Support/TargetSelect.h"
31
32 #include <string>
33
34 using namespace lldb_private;
35 using namespace lldb_private::repro;
36
SystemInitializerCommon(HostInfo::SharedLibraryDirectoryHelper * helper)37 SystemInitializerCommon::SystemInitializerCommon(
38 HostInfo::SharedLibraryDirectoryHelper *helper)
39 : m_shlib_dir_helper(helper) {}
40
41 SystemInitializerCommon::~SystemInitializerCommon() = default;
42
43 /// Initialize the FileSystem based on the current reproducer mode.
InitializeFileSystem()44 static llvm::Error InitializeFileSystem() {
45 auto &r = repro::Reproducer::Instance();
46 if (repro::Loader *loader = r.GetLoader()) {
47 FileSpec vfs_mapping = loader->GetFile<FileProvider::Info>();
48 if (vfs_mapping) {
49 if (llvm::Error e = FileSystem::Initialize(vfs_mapping))
50 return e;
51 } else {
52 FileSystem::Initialize();
53 }
54
55 // Set the current working directory form the reproducer.
56 llvm::Expected<std::string> working_dir =
57 repro::GetDirectoryFrom<WorkingDirectoryProvider>(loader);
58 if (!working_dir)
59 return working_dir.takeError();
60 if (std::error_code ec = FileSystem::Instance()
61 .GetVirtualFileSystem()
62 ->setCurrentWorkingDirectory(*working_dir)) {
63 return llvm::errorCodeToError(ec);
64 }
65
66 // Set the home directory from the reproducer.
67 llvm::Expected<std::string> home_dir =
68 repro::GetDirectoryFrom<HomeDirectoryProvider>(loader);
69 if (!home_dir)
70 return home_dir.takeError();
71 FileSystem::Instance().SetHomeDirectory(*home_dir);
72
73 return llvm::Error::success();
74 }
75
76 if (repro::Generator *g = r.GetGenerator()) {
77 repro::VersionProvider &vp = g->GetOrCreate<repro::VersionProvider>();
78 vp.SetVersion(lldb_private::GetVersion());
79
80 repro::FileProvider &fp = g->GetOrCreate<repro::FileProvider>();
81 FileSystem::Initialize(fp.GetFileCollector());
82
83 fp.RecordInterestingDirectory(
84 g->GetOrCreate<repro::WorkingDirectoryProvider>().GetDirectory());
85 fp.RecordInterestingDirectory(
86 g->GetOrCreate<repro::HomeDirectoryProvider>().GetDirectory());
87
88 return llvm::Error::success();
89 }
90
91 FileSystem::Initialize();
92 return llvm::Error::success();
93 }
94
Initialize()95 llvm::Error SystemInitializerCommon::Initialize() {
96 #if defined(_WIN32)
97 const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG");
98 if (disable_crash_dialog_var &&
99 llvm::StringRef(disable_crash_dialog_var).equals_insensitive("true")) {
100 // This will prevent Windows from displaying a dialog box requiring user
101 // interaction when
102 // LLDB crashes. This is mostly useful when automating LLDB, for example
103 // via the test
104 // suite, so that a crash in LLDB does not prevent completion of the test
105 // suite.
106 ::SetErrorMode(GetErrorMode() | SEM_FAILCRITICALERRORS |
107 SEM_NOGPFAULTERRORBOX);
108
109 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
110 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
111 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
112 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
113 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
114 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
115 }
116 #endif
117
118 // If the reproducer wasn't initialized before, we can safely assume it's
119 // off.
120 if (!Reproducer::Initialized()) {
121 if (auto e = Reproducer::Initialize(ReproducerMode::Off, llvm::None))
122 return e;
123 }
124
125 if (auto e = InitializeFileSystem())
126 return e;
127
128 Log::Initialize();
129 HostInfo::Initialize(m_shlib_dir_helper);
130
131 llvm::Error error = Socket::Initialize();
132 if (error)
133 return error;
134
135 LLDB_SCOPED_TIMER();
136
137 process_gdb_remote::ProcessGDBRemoteLog::Initialize();
138
139 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
140 ProcessPOSIXLog::Initialize();
141 #endif
142 #if defined(_WIN32)
143 ProcessWindowsLog::Initialize();
144 #endif
145
146 return llvm::Error::success();
147 }
148
Terminate()149 void SystemInitializerCommon::Terminate() {
150 LLDB_SCOPED_TIMER();
151
152 #if defined(_WIN32)
153 ProcessWindowsLog::Terminate();
154 #endif
155
156 Socket::Terminate();
157 HostInfo::Terminate();
158 Log::DisableAllLogChannels();
159 FileSystem::Terminate();
160 Reproducer::Terminate();
161 }
162