1 //===-- MIDriverMain.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Overview: Defines the entry point for the console application.
11 // The MI application (project name MI) runs in two modes:
12 // An LLDB native driver mode where it acts no different from the
13 // LLDB driver.
14 // The other mode is the MI when it finds on the command line
15 // the --interpreter option. Command line argument --help on its
16 // own will give
17 // help for the LLDB driver. If entered with --interpreter then MI
18 // help will
19 // provided.
20 // To implement new MI commands derive a new command class from the
21 // command base
22 // class. To enable the new command for interpretation add the new
23 // command class
24 // to the command factory. The files of relevance are:
25 // MICmdCommands.cpp
26 // MICmdBase.h / .cpp
27 // MICmdCmd.h / .cpp
28
29 // Third party headers:
30 #include "lldb/API/SBHostOS.h"
31 #include "llvm/ADT/StringRef.h"
32 #include "llvm/Support/PrettyStackTrace.h"
33 #include "llvm/Support/Signals.h"
34 #include <atomic>
35 #include <csignal>
36 #include <stdio.h>
37
38 // In house headers:
39 #include "MICmnConfig.h"
40 #include "MICmnResources.h"
41 #include "MICmnStreamStdin.h"
42 #include "MIDriver.h"
43 #include "MIDriverMgr.h"
44 #include "MIUtilDebug.h"
45 #include "Platform.h"
46
47 #if defined(_MSC_VER)
48 #pragma warning( \
49 once : 4530) // Warning C4530: C++ exception handler used, but unwind
50 // semantics are not enabled. Specify /EHsc
51 #endif // _MSC_VER
52
53 // CODETAG_IOR_SIGNALS
54 //++
55 //------------------------------------------------------------------------------------
56 // Details: The SIGINT signal is sent to a process by its controlling terminal
57 // when a
58 // user wishes to interrupt the process. This is typically initiated by
59 // pressing
60 // Control-C, but on some systems, the "delete" character or "break"
61 // key can be
62 // used.
63 // Be aware this function may be called on another thread besides the
64 // main thread.
65 // Type: Function.
66 // Args: vSigno - (R) Signal number.
67 // Return: None.
68 // Throws: None.
69 //--
sigint_handler(int vSigno)70 void sigint_handler(int vSigno) {
71 #ifdef _WIN32 // Restore handler as it is not persistent on Windows
72 signal(SIGINT, sigint_handler);
73 #endif
74 static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
75 CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance();
76 lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger();
77 if (pDebugger != nullptr) {
78 if (!g_interrupt_sent.test_and_set()) {
79 pDebugger->DispatchInputInterrupt();
80 g_interrupt_sent.clear();
81 }
82 }
83
84 // Send signal to driver so that it can take suitable action
85 rDriverMgr.DeliverSignal(vSigno);
86 }
87
88 //++
89 //------------------------------------------------------------------------------------
90 // Details: Init the MI driver system. Initialize the whole driver system which
91 // includes
92 // both the original LLDB driver and the MI driver.
93 // Type: Function.
94 // Args: None.
95 // Return: MIstatus::success - Functional succeeded.
96 // MIstatus::failure - Functional failed.
97 // Throws: None.
98 //--
DriverSystemInit()99 bool DriverSystemInit() {
100 bool bOk = MIstatus::success;
101 CMIDriver &rMIDriver = CMIDriver::Instance();
102 CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance();
103 bOk = rDriverMgr.Initialize();
104
105 // Register MIDriver first as it needs to initialize and be ready
106 // for the Driver to get information from MIDriver when it initializes
107 // (LLDB Driver is registered with the Driver Manager in MI's Initialize())
108 bOk = bOk &&
109 rDriverMgr.RegisterDriver(rMIDriver, "MIDriver"); // Will be main driver
110
111 return bOk;
112 }
113
114 //++
115 //------------------------------------------------------------------------------------
116 // Details: Shutdown the debugger system. Release / terminate resources external
117 // to
118 // specifically the MI driver.
119 // Type: Function.
120 // Args: vbAppExitOk - (R) True = No problems, false = App exiting with
121 // problems (investigate!).
122 // Return: MIstatus::success - Functional succeeded.
123 // MIstatus::failure - Functional failed.
124 // Throws: None.
125 //--
DriverSystemShutdown(const bool vbAppExitOk)126 bool DriverSystemShutdown(const bool vbAppExitOk) {
127 bool bOk = MIstatus::success;
128
129 // *** Order is important here ***
130 CMIDriverMgr::Instance().Shutdown();
131 return bOk;
132 }
133
134 //++
135 //------------------------------------------------------------------------------------
136 // Details: MI's application start point of execution. The application runs in
137 // two modes.
138 // An LLDB native driver mode where it acts no different from the LLDB
139 // driver.
140 // The other mode is the MI when it finds on the command line
141 // the --interpreter option. Command line argument --help on its own
142 // will give
143 // help for the LLDB driver. If entered with --interpreter then
144 // application
145 // help will provided.
146 // Type: Method.
147 // Args: argc - (R) An integer that contains the count of arguments that
148 // follow in
149 // argv. The argc parameter is always greater than or
150 // equal to 1.
151 // argv - (R) An array of null-terminated strings representing
152 // command-line
153 // arguments entered by the user of the program. By
154 // convention,
155 // argv[0] is the command with which the program is
156 // invoked.
157 // Return: int - 0 = Normal exit, program success.
158 // >0 = Program success with status i.e. Control-C signal
159 // status
160 // <0 = Program failed.
161 // -1 = Program failed reason not specified here, see MI log
162 // file.
163 // -1000 = Program failed did not initialize successfully.
164 // Throws: None.
165 //--
main(int argc,char const * argv[])166 int main(int argc, char const *argv[]) {
167 #if MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
168 CMIUtilDebug::WaitForDbgAttachInfinteLoop();
169 #endif // MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
170
171 llvm::StringRef ToolName = argv[0];
172 llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
173 llvm::PrettyStackTraceProgram X(argc, argv);
174
175 // *** Order is important here ***
176 bool bOk = DriverSystemInit();
177 if (!bOk) {
178 DriverSystemShutdown(bOk);
179 return -1000;
180 }
181
182 // CODETAG_IOR_SIGNALS
183 signal(SIGINT, sigint_handler);
184
185 bool bExiting = false;
186 CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance();
187 bOk = bOk && rDriverMgr.ParseArgs(argc, argv, bExiting);
188 if (bOk && !bExiting)
189 bOk = rDriverMgr.DriverParseArgs(argc, argv, stdout, bExiting);
190 if (bOk && !bExiting)
191 bOk = rDriverMgr.DriverMainLoop();
192
193 // Logger and other resources shutdown now
194 DriverSystemShutdown(bOk);
195
196 const int appResult = bOk ? 0 : -1;
197
198 return appResult;
199 }
200