1 //===-- MIDriverMgr.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 //===----------------------------------------------------------------------===//
10 // Third Party Headers:
11 #include "lldb/API/SBError.h"
15 #include "MICmnLogMediumFile.h"
16 #include "MICmnResources.h"
17 #include "MICmnStreamStdout.h"
19 #include "MIDriverMgr.h"
20 #include "MIUtilSingletonHelper.h"
23 //------------------------------------------------------------------------------------
24 // Details: CMIDriverMgr constructor.
30 CMIDriverMgr::CMIDriverMgr() : m_pDriverCurrent(nullptr), m_bInMi2Mode(false) {}
33 //------------------------------------------------------------------------------------
34 // Details: CMIDriverMgr destructor.
40 CMIDriverMgr::~CMIDriverMgr() { Shutdown(); }
43 //------------------------------------------------------------------------------------
44 // Details: Initialize *this manager.
47 // Return: MIstatus::success - Functional succeeded.
48 // MIstatus::failure - Functional failed.
51 bool CMIDriverMgr::Initialize() {
52 m_clientUsageRefCnt++;
54 ClrErrorDescription();
57 return MIstatus::success;
59 bool bOk = MIstatus::success;
62 // Note initialisation order is important here as some resources depend on
64 MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg);
65 MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg);
70 CMIUtilString strInitError(CMIUtilString::Format(
71 MIRSRC(IDS_MI_INIT_ERR_DRIVERMGR), errMsg.c_str()));
72 SetErrorDescription(strInitError);
73 return MIstatus::failure;
80 //------------------------------------------------------------------------------------
81 // Details: Unbind detach or release resources used by this server in general
83 // functionality shared between versions of any server interfaces
86 // Args: vbAppExitOk - (R) True = No problems, false = App exiting with
87 // problems (investigate!).
88 // Return: MIstatus::success - Functional succeeded.
89 // MIstatus::failure - Functional failed.
92 bool CMIDriverMgr::Shutdown() {
93 // Do not want a ref counter because this function needs to be called how ever
95 // application stops running
96 // if( --m_clientUsageRefCnt > 0 )
97 // return MIstatus::success;
99 ClrErrorDescription();
102 return MIstatus::success;
104 m_bInitialized = false;
106 bool bOk = MIstatus::success;
107 CMIUtilString errMsg;
110 UnregisterDriverAll();
112 // Note shutdown order is important here
113 MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg);
114 MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg);
117 SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_DRIVERMGR), errMsg.c_str());
123 //------------------------------------------------------------------------------------
124 // Details: Unregister all the Driver registered with *this manager. The manager
129 // Return: MIstatus::success - Functional succeeded.
130 // MIstatus::failure - Functional failed.
133 bool CMIDriverMgr::UnregisterDriverAll() {
134 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
135 while (it != m_mapDriverIdToDriver.end()) {
136 IDriver *pDriver = (*it).second;
137 pDriver->DoShutdown();
143 m_mapDriverIdToDriver.clear();
144 m_pDriverCurrent = NULL;
146 return MIstatus::success;
150 //------------------------------------------------------------------------------------
151 // Details: Register a driver with *this Driver Manager. Call
152 // SetUseThisDriverToDoWork()
153 // inform the manager which driver is the one to the work. The manager
155 // the driver's init function which must be successful in order to
159 // Args: vrDriver - (R) The driver to register.
160 // vrDriverID - (R) The driver's ID to lookup by.
161 // Return: MIstatus::success - Functional succeeded.
162 // MIstatus::failure - Functional failed.
165 bool CMIDriverMgr::RegisterDriver(const IDriver &vrDriver,
166 const CMIUtilString &vrDriverID) {
167 if (HaveDriverAlready(vrDriver))
168 return MIstatus::success;
170 IDriver *pDriver = const_cast<IDriver *>(&vrDriver);
171 if (!pDriver->SetId(vrDriverID))
172 return MIstatus::failure;
173 if (!pDriver->DoInitialize()) {
174 SetErrorDescriptionn(MIRSRC(IDS_DRIVERMGR_DRIVER_ERR_INIT),
175 pDriver->GetName().c_str(), vrDriverID.c_str(),
176 pDriver->GetError().c_str());
177 return MIstatus::failure;
180 MapPairDriverIdToDriver_t pr(vrDriverID, pDriver);
181 m_mapDriverIdToDriver.insert(pr);
183 return MIstatus::success;
187 //------------------------------------------------------------------------------------
188 // Details: Query the Driver Manager to see if *this manager has the driver
192 // Args: vrDriver - (R) The driver to query.
193 // Return: True - registered.
194 // False - not registered.
197 bool CMIDriverMgr::HaveDriverAlready(const IDriver &vrDriver) const {
198 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
199 while (it != m_mapDriverIdToDriver.end()) {
200 const IDriver *pDrvr = (*it).second;
201 if (pDrvr == &vrDriver)
212 //------------------------------------------------------------------------------------
213 // Details: Unregister a driver from the Driver Manager. Call the
214 // SetUseThisDriverToDoWork()
215 // function to define another driver to do work if the one being
217 // the work previously.
219 // Args: vrDriver - (R) The driver to unregister.
220 // Return: MIstatus::success - Functional succeeded.
221 // MIstatus::failure - Functional failed.
224 bool CMIDriverMgr::UnregisterDriver(const IDriver &vrDriver) {
225 const IDriver *pDrvr = nullptr;
226 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
227 while (it != m_mapDriverIdToDriver.end()) {
228 pDrvr = (*it).second;
229 if (pDrvr == &vrDriver)
235 m_mapDriverIdToDriver.erase(it);
237 if (m_pDriverCurrent == pDrvr)
238 m_pDriverCurrent = nullptr;
240 return MIstatus::success;
244 //------------------------------------------------------------------------------------
245 // Details: Specify the driver to do work. The Driver Manager drives this
247 // previous driver doing work is not called anymore (so be sure the
249 // driver is in a tidy state before stopping it working).
251 // Args: vrADriver - (R) A lldb::SBBroadcaster/IDriver derived object.
252 // Return: MIstatus::success - Functional succeeded.
253 // MIstatus::failure - Functional failed.
256 bool CMIDriverMgr::SetUseThisDriverToDoWork(const IDriver &vrADriver) {
257 m_pDriverCurrent = const_cast<IDriver *>(&vrADriver);
259 const CMIUtilString msg(
260 CMIUtilString::Format(MIRSRC(IDS_DRIVER_SAY_DRIVER_USING),
261 m_pDriverCurrent->GetName().c_str()));
262 m_pLog->Write(msg, CMICmnLog::eLogVerbosity_Log);
264 m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver();
266 return MIstatus::success;
270 //------------------------------------------------------------------------------------
271 // Details: Ask *this manager which driver is currently doing the work.
274 // Return: IDriver * - Pointer to a driver, NULL if there is no current working
278 CMIDriverMgr::IDriver *CMIDriverMgr::GetUseThisDriverToDoWork() const {
279 return m_pDriverCurrent;
283 //------------------------------------------------------------------------------------
284 // Details: Call this function puts *this driver to work.
287 // Return: MIstatus::success - Functional succeeded.
288 // MIstatus::failure - Functional failed.
291 bool CMIDriverMgr::DriverMainLoop() {
292 if (m_pDriverCurrent != nullptr) {
293 if (!m_pDriverCurrent->DoMainLoop()) {
294 const CMIUtilString errMsg(
295 CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_MAINLOOP),
296 m_pDriverCurrent->GetError().c_str()));
297 CMICmnStreamStdout::Instance().Write(errMsg, true);
298 return MIstatus::failure;
301 const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
302 CMICmnStreamStdout::Instance().Write(errMsg, true);
303 return MIstatus::failure;
306 return MIstatus::success;
310 //------------------------------------------------------------------------------------
311 // Details: Get the current driver to validate executable command line
314 // Args: argc - (R) An integer that contains the count of arguments
316 // argv. The argc parameter is always greater than
318 // argv - (R) An array of null-terminated strings representing
320 // arguments entered by the user of the program. By
322 // argv[0] is the command with which the program is
324 // vpStdOut - (R) Point to a standard output stream.
325 // vwbExiting - (W) True = *this want to exit, false = continue to
327 // Return: MIstatus::success - Functional succeeded.
328 // MIstatus::failure - Functional failed.
331 bool CMIDriverMgr::DriverParseArgs(const int argc, const char *argv[],
332 FILE *vpStdOut, bool &vwbExiting) {
333 if (m_pDriverCurrent == nullptr) {
334 const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
335 CMICmnStreamStdout::Instance().Write(errMsg, true);
336 return MIstatus::failure;
339 const lldb::SBError error(
340 m_pDriverCurrent->DoParseArgs(argc, argv, vpStdOut, vwbExiting));
341 bool bOk = !error.Fail();
343 CMIUtilString errMsg;
344 const char *pErrorCstr = error.GetCString();
345 if (pErrorCstr != nullptr)
346 errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS),
347 m_pDriverCurrent->GetName().c_str(),
350 errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN),
351 m_pDriverCurrent->GetName().c_str());
353 bOk = CMICmnStreamStdout::Instance().Write(errMsg, true);
360 //------------------------------------------------------------------------------------
361 // Details: Retrieve the current driver's last error condition.
364 // Return: CMIUtilString - Text description.
367 CMIUtilString CMIDriverMgr::DriverGetError() const {
368 if (m_pDriverCurrent != nullptr)
369 return m_pDriverCurrent->GetError();
371 const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
372 CMICmnStreamStdout::Instance().Write(errMsg, true);
375 return CMIUtilString();
379 //------------------------------------------------------------------------------------
380 // Details: Retrieve the current driver's name.
383 // Return: CMIUtilString - Driver name.
384 // Empty string = no current working driver specified.
387 CMIUtilString CMIDriverMgr::DriverGetName() const {
388 if (m_pDriverCurrent != nullptr)
389 return m_pDriverCurrent->GetName();
391 const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
392 CMICmnStreamStdout::Instance().Write(errMsg, true);
395 return CMIUtilString();
399 //------------------------------------------------------------------------------------
400 // Details: Retrieve the current driver's debugger object.
403 // Return: lldb::SBDebugger * - Ptr to driver's debugger object.
404 // - NULL = no current working driver specified.
407 lldb::SBDebugger *CMIDriverMgr::DriverGetTheDebugger() {
408 lldb::SBDebugger *pDebugger = nullptr;
409 if (m_pDriverCurrent != nullptr)
410 pDebugger = &m_pDriverCurrent->GetTheDebugger();
412 const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET));
413 CMICmnStreamStdout::Instance().Write(errMsg, true);
420 //------------------------------------------------------------------------------------
421 // Details: Check the arguments given on the command line. The main purpose of
423 // function is to check for the presence of the --interpreter option.
425 // this option present tells *this manager to set the CMIDriver to do
427 // not use the LLDB driver. The following are options that are only
429 // the CMIDriverMgr are:
437 // The above arguments are not handled by any driver object except for
439 // The options --interpreter and --executable in code act very similar.
441 // --executable is necessary to differentiate whither the MI Driver is
443 // by a client i.e. Eclipse or from the command line. Eclipse issues
445 // --interpreter and also passes additional arguments which can be
447 // executable if called from the command line. Using --executable tells
449 // Driver is being called the command line and that the executable
450 // argument is indeed
451 // a specified executable an so actions commands to set up the
453 // debug session. Using --interpreter on the command line does not
455 // commands to initialise a debug session and so be able to launch the
456 // process. The directory
457 // where the log file is created is specified using --log-dir.
459 // Args: argc - (R) An integer that contains the count of arguments
461 // argv. The argc parameter is always greater than
463 // argv - (R) An array of null-terminated strings representing
465 // arguments entered by the user of the program. By
467 // argv[0] is the command with which the program is
469 // vwbExiting - (W) True = *this want to exit, Reasons: help,
471 // version information only.
472 // False = Continue to work, start debugger i.e.
475 // Return: lldb::SBError - LLDB current error status.
478 bool CMIDriverMgr::ParseArgs(const int argc, const char *argv[],
480 bool bOk = MIstatus::success;
484 // Print MI application path to the Log file
485 const CMIUtilString appPath(
486 CMIUtilString::Format(MIRSRC(IDS_MI_APP_FILEPATHNAME), argv[0]));
487 bOk = m_pLog->Write(appPath, CMICmnLog::eLogVerbosity_Log);
489 // Print application arguments to the Log file
490 const bool bHaveArgs(argc >= 2);
491 CMIUtilString strArgs(MIRSRC(IDS_MI_APP_ARGS));
493 strArgs += MIRSRC(IDS_WORD_NONE);
494 bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log);
496 for (MIint i = 1; i < argc; i++) {
497 strArgs += CMIUtilString::Format("%d:'%s' ", i, argv[i]);
499 bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log);
502 // Look for the command line options
503 bool bHaveArgInterpret = false;
504 bool bHaveArgVersion = false;
505 bool bHaveArgVersionLong = false;
506 bool bHaveArgLog = false;
507 bool bHaveArgLogDir = false;
508 bool bHaveArgHelp = false;
509 CMIUtilString strLogDir;
511 bHaveArgInterpret = true;
513 // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING
514 for (MIint i = 1; i < argc; i++) {
515 // *** Add args to help in GetHelpOnCmdLineArgOptions() ***
516 const CMIUtilString strArg(argv[i]);
518 // Argument "--executable" is also check for in CMIDriver::ParseArgs()
519 if (("--interpreter" == strArg) || // Given by the client such as Eclipse
520 ("--executable" == strArg)) // Used to specify that there
521 // is executable argument also
522 // on the command line
523 { // See fn description.
524 bHaveArgInterpret = true;
526 if ("--version" == strArg) {
527 bHaveArgVersion = true;
529 if ("--versionLong" == strArg) {
530 bHaveArgVersionLong = true;
532 if ("--log" == strArg) {
535 if (0 == strArg.compare(0, 10, "--log-dir=")) {
536 strLogDir = strArg.substr(10, CMIUtilString::npos);
537 bHaveArgLogDir = true;
539 if (("--help" == strArg) || ("-h" == strArg)) {
546 CMICmnLog::Instance().SetEnabled(true);
549 if (bHaveArgLogDir) {
550 bOk = bOk && CMICmnLogMediumFile::Instance().SetDirectory(strLogDir);
553 // Todo: Remove this output when MI is finished. It is temporary to persuade
554 // Eclipse plugin to work.
555 // Eclipse reads this literally and will not work unless it gets this
556 // exact version text.
557 // Handle --version option (ignore the --interpreter option if present)
558 if (bHaveArgVersion) {
561 CMICmnStreamStdout::Instance().WriteMIResponse(
562 MIRSRC(IDE_MI_VERSION_GDB));
566 // Todo: Make this the --version when the above --version version is removed
567 // Handle --versionlong option (ignore the --interpreter option if present)
568 if (bHaveArgVersionLong) {
571 bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetAppVersion());
575 // Both '--help' and '--interpreter' means give help for MI only. Without
576 // '--interpreter' help the LLDB driver is working and so help is for that.
577 if (bHaveArgHelp && bHaveArgInterpret) {
580 CMICmnStreamStdout::Instance().WriteMIResponse(
581 GetHelpOnCmdLineArgOptions());
585 // This makes the assumption that there is at least one MI compatible
586 // driver registered and one LLDB driver registered and the CMIDriver
587 // is the first one found.
588 // ToDo: Implement a better solution that handle any order, any number
589 // of drivers. Or this 'feature' may be removed if deemed not required.
590 IDriver *pLldbDriver = GetFirstNonMIDriver();
591 IDriver *pMi2Driver = GetFirstMIDriver();
592 if (bHaveArgInterpret && (pMi2Driver != nullptr))
593 bOk = bOk && SetUseThisDriverToDoWork(*pMi2Driver);
594 else if (pLldbDriver != nullptr)
595 bOk = bOk && SetUseThisDriverToDoWork(*pLldbDriver);
599 const CMIUtilString msg(MIRSRC(IDS_DRIVER_ERR_NON_REGISTERED));
600 bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(msg);
608 //------------------------------------------------------------------------------------
609 // Details: Return formatted application version and name information.
612 // Return: CMIUtilString - Text data.
615 CMIUtilString CMIDriverMgr::GetAppVersion() const {
616 const CMIUtilString strProj(MIRSRC(IDS_PROJNAME));
617 const CMIUtilString strVsn(CMIDriver::Instance().GetVersionDescription());
618 const CMIUtilString strGdb(MIRSRC(IDE_MI_VERSION_GDB));
619 const CMIUtilString strVrsnInfo(CMIUtilString::Format(
620 "%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str()));
626 //------------------------------------------------------------------------------------
627 // Details: Return formatted help information on all the MI command line
631 // Return: CMIUtilString - Text data.
634 CMIUtilString CMIDriverMgr::GetHelpOnCmdLineArgOptions() const {
635 const CMIUtilString pHelp[] = {
636 MIRSRC(IDE_MI_APP_DESCRIPTION), MIRSRC(IDE_MI_APP_INFORMATION),
637 MIRSRC(IDE_MI_APP_ARG_USAGE), MIRSRC(IDE_MI_APP_ARG_HELP),
638 MIRSRC(IDE_MI_APP_ARG_VERSION), MIRSRC(IDE_MI_APP_ARG_VERSION_LONG),
639 MIRSRC(IDE_MI_APP_ARG_INTERPRETER), MIRSRC(IDE_MI_APP_ARG_SOURCE),
640 MIRSRC(IDE_MI_APP_ARG_EXECUTEABLE),
641 MIRSRC(IDE_MI_APP_ARG_SYNCHRONOUS),
642 CMIUtilString::Format(
643 MIRSRC(IDE_MI_APP_ARG_APP_LOG),
644 CMICmnLogMediumFile::Instance().GetFileName().c_str()),
645 MIRSRC(IDE_MI_APP_ARG_APP_LOG_DIR), MIRSRC(IDE_MI_APP_ARG_EXECUTABLE),
646 MIRSRC(IDS_CMD_QUIT_HELP), MIRSRC(IDE_MI_APP_ARG_EXAMPLE)};
647 const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[0];
648 CMIUtilString strHelp;
649 for (MIuint i = 0; i < nHelpItems; i++) {
658 //------------------------------------------------------------------------------------
659 // Details: Search the registered drivers and return the first driver which says
661 // GDB/MI compatible i.e. the CMIDriver class.
664 // Return: IDriver * - Ptr to driver, NULL = no driver found.
667 CMIDriverMgr::IDriver *CMIDriverMgr::GetFirstMIDriver() const {
668 IDriver *pDriver = nullptr;
669 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
670 while (it != m_mapDriverIdToDriver.end()) {
671 const CMIUtilString &rDrvId = (*it).first;
673 IDriver *pDvr = (*it).second;
674 if (pDvr->GetDriverIsGDBMICompatibleDriver()) {
687 //------------------------------------------------------------------------------------
688 // Details: Search the registered drivers and return the first driver which says
690 // not GDB/MI compatible i.e. the LLDB Driver class.
693 // Return: IDriver * - Ptr to driver, NULL = no driver found.
696 CMIDriverMgr::IDriver *CMIDriverMgr::GetFirstNonMIDriver() const {
697 IDriver *pDriver = nullptr;
698 MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin();
699 while (it != m_mapDriverIdToDriver.end()) {
700 const CMIUtilString &rDrvId = (*it).first;
702 IDriver *pDvr = (*it).second;
703 if (!pDvr->GetDriverIsGDBMICompatibleDriver()) {
716 //------------------------------------------------------------------------------------
717 // Details: Search the registered drivers and return driver with the specified
720 // Args: vrDriverId - (R) ID of a driver.
721 // Return: IDriver * - Ptr to driver, NULL = no driver found.
724 CMIDriverMgr::IDriver *
725 CMIDriverMgr::GetDriver(const CMIUtilString &vrDriverId) const {
726 MapDriverIdToDriver_t::const_iterator it =
727 m_mapDriverIdToDriver.find(vrDriverId);
728 if (it == m_mapDriverIdToDriver.end())
731 IDriver *pDriver = (*it).second;
737 //------------------------------------------------------------------------------------
738 // Details: Gets called when lldb-mi gets a signal. Passed signal to current
742 // Args: signal that was delivered
746 void CMIDriverMgr::DeliverSignal(int signal) {
747 if (m_pDriverCurrent != nullptr)
748 m_pDriverCurrent->DeliverSignal(signal);