1 //===-- MIDriverMain.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 // File: MIDriverMain.cpp
13 // Overview: Defines the entry point for the console application.
14 // The MI application (project name MI) runs in two modes:
15 // An LLDB native driver mode where it acts no different from the LLDB driver.
16 // The other mode is the MI when it finds on the command line
17 // the --interpreter option. Command line argument --help on its own will give
18 // help for the LLDB driver. If entered with --interpreter then MI help will
20 // To implement new MI commands derive a new command class from the command base
21 // class. To enable the new command for interpretation add the new command class
22 // to the command factory. The files of relevance are:
26 // Versions: 1.0.0.1 First version from scratch 28/1/2014 to 28/3/2014. MI not complete.
27 // 1.0.0.2 First deliverable to client 7/3/2014. MI not complete.
28 // 1.0.0.3 Code refactor tidy. Release to community for evaluation 17/5/2014. MI not complete.
29 // 1.0.0.4 Post release to the community for evaluation 17/5/2014. MI not complete.
30 // 1.0.0.5 Second deliverable to client 16/6/2014.
31 // 1.0.0.6 Post release of second deliverable to client 16/6/2014.
32 // Released to the community 24/6/2014.
33 // 1.0.0.7 Post release to the community.
34 // Delivered to client 30/6/2014.
35 // 1.0.0.8 Delivered to client 29/7/2014.
36 // 1.0.0.9 Post release to client 29/7/2014.
37 // See MIreadme.txt for list of MI commands implemented.
39 // Environment: Compilers: Visual C++ 12.
40 // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
41 // Libraries: See MIReadme.txt.
46 #if defined( _MSC_VER )
47 #define _INC_SIGNAL // Stop window's signal.h being included - CODETAG_IOR_SIGNALS
50 // Third party headers:
52 #include <lldb/API/SBHostOS.h>
55 #include "MICmnConfig.h"
56 #include "Platform.h" // Define signals - CODETAG_IOR_SIGNALS
58 #include "MIDriverMgr.h"
60 #include "MICmnResources.h"
61 #include "MICmnStreamStdin.h"
62 #include "MIUtilDebug.h"
65 #if MICONFIG_COMPILE_MIDRIVER_VERSION
67 #if defined( _MSC_VER )
68 #pragma warning( once : 4530 ) // Warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
71 // ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent
72 // CODETAG_IOR_SIGNALS
73 //++ ------------------------------------------------------------------------------------
74 // Details: The SIGWINCH signal is sent to a process when its controlling terminal
75 // changes its size (a window change).
77 // Args: vSigno - (R) Signal number.
81 void sigwinch_handler( int vSigno )
85 struct winsize window_size;
86 if( ::isatty( STDIN_FILENO ) && ::ioctl( STDIN_FILENO, TIOCGWINSZ, &window_size ) == 0 )
88 CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
89 if( window_size.ws_col > 0 )
91 rDriverMgr.DriverResizeWindow( (uint32_t) window_size.ws_col );
95 CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGWINCH", vSigno ) );
98 // CODETAG_IOR_SIGNALS
99 //++ ------------------------------------------------------------------------------------
100 // Details: The SIGINT signal is sent to a process by its controlling terminal when a
101 // user wishes to interrupt the process. This is typically initiated by pressing
102 // Control-C, but on some systems, the "delete" character or "break" key can be
104 // Be aware this function may be called on another thread besides the main thread.
106 // Args: vSigno - (R) Signal number.
110 void sigint_handler( int vSigno )
112 static bool g_interrupt_sent = false;
113 CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
114 lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger();
115 if( pDebugger != nullptr )
117 if( !g_interrupt_sent )
119 g_interrupt_sent = true;
120 pDebugger->DispatchInputInterrupt();
121 g_interrupt_sent = false;
125 CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGINT", vSigno ) );
127 // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
128 // Signal MI to shutdown or halt a running debug session
129 CMICmnStreamStdin::Instance().SetCtrlCHit();
132 // ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent
133 // CODETAG_IOR_SIGNALS
134 //++ ------------------------------------------------------------------------------------
135 // Details: The SIGTSTP signal is sent to a process by its controlling terminal to
136 // request it to stop temporarily. It is commonly initiated by the user pressing
137 // Control-Z. Unlike SIGSTOP, the process can register a signal handler for or
138 // ignore the signal.
139 // *** The function does not behave ATM like the UNIX equivalent ***
141 // Args: vSigno - (R) Signal number.
145 void sigtstp_handler( int vSigno )
147 CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
148 lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger();
149 if( pDebugger != nullptr )
151 pDebugger->SaveInputTerminalState();
154 CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGTSTP", vSigno ) );
156 // Signal MI to shutdown
157 CMICmnStreamStdin::Instance().SetCtrlCHit();
160 // ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent
161 // CODETAG_IOR_SIGNALS
162 //++ ------------------------------------------------------------------------------------
163 // Details: The SIGCONT signal instructs the operating system to continue (restart) a
164 // process previously paused by the SIGSTOP or SIGTSTP signal. One important use
165 // of this signal is in job control in the UNIX shell.
166 // *** The function does not behave ATM like the UNIX equivalent ***
168 // Args: vSigno - (R) Signal number.
172 void sigcont_handler( int vSigno )
174 CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
175 lldb::SBDebugger * pDebugger = rDriverMgr.DriverGetTheDebugger();
176 if( pDebugger != nullptr )
178 pDebugger->RestoreInputTerminalState();
181 CMICmnLog::Instance().WriteLog( CMIUtilString::Format( MIRSRC( IDS_PROCESS_SIGNAL_RECEIVED ), "SIGCONT", vSigno ) );
183 // Signal MI to shutdown
184 CMICmnStreamStdin::Instance().SetCtrlCHit();
187 //++ ------------------------------------------------------------------------------------
188 // Details: Init the MI driver system. Initialize the whole driver system which includes
189 // both the original LLDB driver and the MI driver.
192 // Return: MIstatus::success - Functional succeeded.
193 // MIstatus::failure - Functional failed.
196 bool DriverSystemInit( void )
198 bool bOk = MIstatus::success;
200 #if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
201 Driver * pDriver = Driver::CreateSelf();
202 if( pDriver == nullptr )
203 return MIstatus::failure;
204 #endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
206 CMIDriver & rMIDriver = CMIDriver::Instance();
207 CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
208 bOk = rDriverMgr.Initialize();
210 // Register MIDriver first as it needs to initialize and be ready
211 // for the Driver to get information from MIDriver when it initializes
212 // (LLDB Driver is registered with the Driver Manager in MI's Initialize())
213 bOk = bOk && rDriverMgr.RegisterDriver( rMIDriver, "MIDriver" ); // Will be main driver
218 //++ ------------------------------------------------------------------------------------
219 // Details: Shutdown the debugger system. Release / terminate resources external to
220 // specifically the MI driver.
222 // Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!).
223 // Return: MIstatus::success - Functional succeeded.
224 // MIstatus::failure - Functional failed.
227 bool DriverSystemShutdown( const bool vbAppExitOk )
229 bool bOk = MIstatus::success;
231 // *** Order is important here ***
232 CMIDriverMgr::Instance().Shutdown();
234 #if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
237 #endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER
244 sigwinch_handler (int signo)
246 struct winsize window_size;
247 if (isatty (STDIN_FILENO)
248 && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
250 if ((window_size.ws_col > 0) && g_driver != NULL)
252 g_driver->ResizeWindow (window_size.ws_col);
258 sigint_handler (int signo)
260 static bool g_interrupt_sent = false;
263 if (!g_interrupt_sent)
265 g_interrupt_sent = true;
266 g_driver->GetDebugger().DispatchInputInterrupt();
267 g_interrupt_sent = false;
276 sigtstp_handler (int signo)
278 g_driver->GetDebugger().SaveInputTerminalState();
279 signal (signo, SIG_DFL);
280 kill (getpid(), signo);
281 signal (signo, sigtstp_handler);
285 sigcont_handler (int signo)
287 g_driver->GetDebugger().RestoreInputTerminalState();
288 signal (signo, SIG_DFL);
289 kill (getpid(), signo);
290 signal (signo, sigcont_handler);
292 #endif // #if MICONFIG_COMPILE_MIDRIVER_VERSION
294 //++ ------------------------------------------------------------------------------------
295 // Details: MI's application start point of execution. The applicaton runs in two modes.
296 // An LLDB native driver mode where it acts no different from the LLDB driver.
297 // The other mode is the MI when it finds on the command line
298 // the --interpreter option. Command line argument --help on its own will give
299 // help for the LLDB driver. If entered with --interpreter then application
300 // help will provided.
302 // Args: argc - (R) An integer that contains the count of arguments that follow in
303 // argv. The argc parameter is always greater than or equal to 1.
304 // argv - (R) An array of null-terminated strings representing command-line
305 // arguments entered by the user of the program. By convention,
306 // argv[0] is the command with which the program is invoked.
307 // Return: int - 0 = Normal exit, program success.
308 // >0 = Program success with status i.e. Control-C signal status
309 // <0 = Program failed.
310 // -1 = Program failed reason not specified here, see MI log file.
311 // -1000 = Program failed did not initailize successfully.
314 #if MICONFIG_COMPILE_MIDRIVER_VERSION
315 int main( int argc, char const *argv[] )
317 #if MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
319 CMIUtilDebug::ShowDlgWaitForDbgAttach();
321 CMIUtilDebug::WaitForDbgAttachInfinteLoop();
323 #endif // MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
325 // *** Order is important here ***
326 bool bOk = DriverSystemInit();
329 DriverSystemShutdown( bOk );
333 // CODETAG_IOR_SIGNALS
334 signal( SIGPIPE, SIG_IGN );
335 signal( SIGWINCH, sigwinch_handler );
336 signal( SIGINT, sigint_handler );
337 signal( SIGTSTP, sigtstp_handler );
338 signal( SIGCONT, sigcont_handler );
340 bool bExiting = false;
341 CMIDriverMgr & rDriverMgr = CMIDriverMgr::Instance();
342 bOk = bOk && rDriverMgr.ParseArgs( argc, argv, bExiting );
343 if( bOk && !bExiting )
344 bOk = rDriverMgr.DriverParseArgs( argc, argv, stdout, bExiting );
345 if( bOk && !bExiting )
346 bOk = rDriverMgr.DriverMainLoop();
348 // Logger and other resources shutdown now
349 DriverSystemShutdown( bOk );
351 const int appResult = bOk ? 0 : -1;
355 #else // Operate the lldb Driver only version of the code
356 int main(int argc, char const *argv[], char *envp[])
359 using namespace lldb;
360 SBDebugger::Initialize();
362 SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
364 signal (SIGPIPE, SIG_IGN);
365 signal (SIGWINCH, sigwinch_handler);
366 signal (SIGINT, sigint_handler);
367 signal (SIGTSTP, sigtstp_handler);
368 signal (SIGCONT, sigcont_handler);
370 // Create a scope for driver so that the driver object will destroy itself
371 // before SBDebugger::Terminate() is called.
375 bool exiting = false;
376 SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
379 const char *error_cstr = error.GetCString ();
381 ::fprintf (stderr, "error: %s\n", error_cstr);
389 SBDebugger::Terminate();
392 #endif // MICONFIG_COMPILE_MIDRIVER_VERSION