//===-- MIDriverMain.cpp ----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Overview: Defines the entry point for the console application. // The MI application (project name MI) runs in two modes: // An LLDB native driver mode where it acts no different from the // LLDB driver. // The other mode is the MI when it finds on the command line // the --interpreter option. Command line argument --help on its // own will give // help for the LLDB driver. If entered with --interpreter then MI // help will // provided. // To implement new MI commands derive a new command class from the // command base // class. To enable the new command for interpretation add the new // command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp // Third party headers: #include "lldb/API/SBHostOS.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include #include #include // In house headers: #include "MICmnConfig.h" #include "MICmnResources.h" #include "MICmnStreamStdin.h" #include "MIDriver.h" #include "MIDriverMgr.h" #include "MIUtilDebug.h" #include "Platform.h" #if defined(_MSC_VER) #pragma warning( \ once : 4530) // Warning C4530: C++ exception handler used, but unwind // semantics are not enabled. Specify /EHsc #endif // _MSC_VER // CODETAG_IOR_SIGNALS //++ // Details: The SIGINT signal is sent to a process by its controlling terminal // when a // user wishes to interrupt the process. This is typically initiated by // pressing // Control-C, but on some systems, the "delete" character or "break" // key can be // used. // Be aware this function may be called on another thread besides the // main thread. // Type: Function. // Args: vSigno - (R) Signal number. // Return: None. // Throws: None. //-- void sigint_handler(int vSigno) { #ifdef _WIN32 // Restore handler as it is not persistent on Windows signal(SIGINT, sigint_handler); #endif static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); if (pDebugger != nullptr) { if (!g_interrupt_sent.test_and_set()) { pDebugger->DispatchInputInterrupt(); g_interrupt_sent.clear(); } } // Send signal to driver so that it can take suitable action rDriverMgr.DeliverSignal(vSigno); } //++ // Details: Init the MI driver system. Initialize the whole driver system which // includes // both the original LLDB driver and the MI driver. // Type: Function. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool DriverSystemInit() { bool bOk = MIstatus::success; CMIDriver &rMIDriver = CMIDriver::Instance(); CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); bOk = rDriverMgr.Initialize(); // Register MIDriver first as it needs to initialize and be ready // for the Driver to get information from MIDriver when it initializes // (LLDB Driver is registered with the Driver Manager in MI's Initialize()) bOk = bOk && rDriverMgr.RegisterDriver(rMIDriver, "MIDriver"); // Will be main driver return bOk; } //++ // Details: Shutdown the debugger system. Release / terminate resources external // to // specifically the MI driver. // Type: Function. // Args: vbAppExitOk - (R) True = No problems, false = App exiting with // problems (investigate!). // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool DriverSystemShutdown(const bool vbAppExitOk) { bool bOk = MIstatus::success; // *** Order is important here *** CMIDriverMgr::Instance().Shutdown(); return bOk; } //++ // Details: MI's application start point of execution. The application runs in // two modes. // An LLDB native driver mode where it acts no different from the LLDB // driver. // The other mode is the MI when it finds on the command line // the --interpreter option. Command line argument --help on its own // will give // help for the LLDB driver. If entered with --interpreter then // application // help will provided. // Type: Method. // Args: argc - (R) An integer that contains the count of arguments that // follow in // argv. The argc parameter is always greater than or // equal to 1. // argv - (R) An array of null-terminated strings representing // command-line // arguments entered by the user of the program. By // convention, // argv[0] is the command with which the program is // invoked. // Return: int - 0 = Normal exit, program success. // >0 = Program success with status i.e. Control-C signal // status // <0 = Program failed. // -1 = Program failed reason not specified here, see MI log // file. // -1000 = Program failed did not initialize successfully. // Throws: None. //-- int main(int argc, char const *argv[]) { #if MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG CMIUtilDebug::WaitForDbgAttachInfinteLoop(); #endif // MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG llvm::StringRef ToolName = argv[0]; llvm::sys::PrintStackTraceOnErrorSignal(ToolName); llvm::PrettyStackTraceProgram X(argc, argv); // *** Order is important here *** bool bOk = DriverSystemInit(); if (!bOk) { DriverSystemShutdown(bOk); return -1000; } // CODETAG_IOR_SIGNALS signal(SIGINT, sigint_handler); bool bExiting = false; CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); bOk = bOk && rDriverMgr.ParseArgs(argc, argv, bExiting); if (bOk && !bExiting) bOk = rDriverMgr.DriverParseArgs(argc, argv, stdout, bExiting); if (bOk && !bExiting) bOk = rDriverMgr.DriverMainLoop(); // Logger and other resources shutdown now DriverSystemShutdown(bOk); const int appResult = bOk ? 0 : -1; return appResult; }