|  | //===-- MICmdCmdGdbShow.cpp -------------------------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | // Overview:    CMICmdCmdGdbShow implementation. | 
|  |  | 
|  | // Third party headers: | 
|  | #include "lldb/API/SBCompileUnit.h" | 
|  | #include "lldb/API/SBFrame.h" | 
|  | #include "lldb/API/SBLanguageRuntime.h" | 
|  | #include "lldb/API/SBThread.h" | 
|  |  | 
|  | // In-house headers: | 
|  | #include "MICmdArgValListOfN.h" | 
|  | #include "MICmdArgValOptionLong.h" | 
|  | #include "MICmdArgValString.h" | 
|  | #include "MICmdCmdGdbShow.h" | 
|  | #include "MICmnLLDBDebugSessionInfo.h" | 
|  | #include "MICmnMIResultRecord.h" | 
|  | #include "MICmnMIValueConst.h" | 
|  |  | 
|  | // Instantiations: | 
|  | const CMICmdCmdGdbShow::MapGdbOptionNameToFnGdbOptionPtr_t | 
|  | CMICmdCmdGdbShow::ms_mapGdbOptionNameToFnGdbOptionPtr = { | 
|  | {"target-async", &CMICmdCmdGdbShow::OptionFnTargetAsync}, | 
|  | {"print", &CMICmdCmdGdbShow::OptionFnPrint}, | 
|  | {"language", &CMICmdCmdGdbShow::OptionFnLanguage}, | 
|  | {"fallback", &CMICmdCmdGdbShow::OptionFnFallback}}; | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: CMICmdCmdGdbShow constructor. | 
|  | // Type:    Method. | 
|  | // Args:    None. | 
|  | // Return:  None. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | CMICmdCmdGdbShow::CMICmdCmdGdbShow() | 
|  | : m_constStrArgNamedGdbOption("option"), m_bGdbOptionRecognised(true), | 
|  | m_bGdbOptionFnSuccessful(false), m_bGbbOptionFnHasError(false), | 
|  | m_strGdbOptionFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) { | 
|  | // Command factory matches this name with that received from the stdin stream | 
|  | m_strMiCmd = "gdb-show"; | 
|  |  | 
|  | // Required by the CMICmdFactory when registering *this command | 
|  | m_pSelfCreatorFn = &CMICmdCmdGdbShow::CreateSelf; | 
|  | } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: CMICmdCmdGdbShow destructor. | 
|  | // Type:    Overrideable. | 
|  | // Args:    None. | 
|  | // Return:  None. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | CMICmdCmdGdbShow::~CMICmdCmdGdbShow() {} | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: The invoker requires this function. The parses the command line | 
|  | // options | 
|  | //          arguments to extract values for each of those arguments. | 
|  | // Type:    Overridden. | 
|  | // Args:    None. | 
|  | // Return:  MIstatus::success - Function succeeded. | 
|  | //          MIstatus::failure - Function failed. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | bool CMICmdCmdGdbShow::ParseArgs() { | 
|  | m_setCmdArgs.Add(new CMICmdArgValListOfN( | 
|  | m_constStrArgNamedGdbOption, true, true, | 
|  | CMICmdArgValListBase::eArgValType_StringAnything)); | 
|  | return ParseValidateCmdOptions(); | 
|  | } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: The invoker requires this function. The command is executed in this | 
|  | // function. | 
|  | // Type:    Overridden. | 
|  | // Args:    None. | 
|  | // Return:  MIstatus::success - Function succeeded. | 
|  | //          MIstatus::failure - Function failed. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | bool CMICmdCmdGdbShow::Execute() { | 
|  | CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption); | 
|  | const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords( | 
|  | pArgGdbOption->GetExpectedOptions()); | 
|  |  | 
|  | // Get the gdb-show option to carry out. This option will be used as an action | 
|  | // which should be done. Further arguments will be used as parameters for it. | 
|  | CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin(); | 
|  | const CMICmdArgValString *pOption = | 
|  | static_cast<const CMICmdArgValString *>(*it); | 
|  | const CMIUtilString strOption(pOption->GetValue()); | 
|  | ++it; | 
|  |  | 
|  | // Retrieve the parameter(s) for the option | 
|  | CMIUtilString::VecString_t vecWords; | 
|  | while (it != rVecWords.end()) { | 
|  | const CMICmdArgValString *pWord = | 
|  | static_cast<const CMICmdArgValString *>(*it); | 
|  | vecWords.push_back(pWord->GetValue()); | 
|  |  | 
|  | // Next | 
|  | ++it; | 
|  | } | 
|  |  | 
|  | FnGdbOptionPtr pPrintRequestFn = nullptr; | 
|  | if (!GetOptionFn(strOption, pPrintRequestFn)) { | 
|  | // For unimplemented option handlers, fallback to a generic handler | 
|  | // ToDo: Remove this when ALL options have been implemented | 
|  | if (!GetOptionFn("fallback", pPrintRequestFn)) { | 
|  | m_bGdbOptionRecognised = false; | 
|  | m_strGdbOptionName = "fallback"; // This would be the strOption name | 
|  | return MIstatus::success; | 
|  | } | 
|  | } | 
|  |  | 
|  | m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords); | 
|  | if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError) | 
|  | return MIstatus::failure; | 
|  |  | 
|  | return MIstatus::success; | 
|  | } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: The invoker requires this function. The command prepares a MI Record | 
|  | // Result | 
|  | //          for the work carried out in the Execute() method. | 
|  | // Type:    Overridden. | 
|  | // Args:    None. | 
|  | // Return:  MIstatus::success - Function succeeded. | 
|  | //          MIstatus::failure - Function failed. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | bool CMICmdCmdGdbShow::Acknowledge() { | 
|  | // Print error if option isn't recognized: | 
|  | // ^error,msg="The request '%s' was not recognized, not implemented" | 
|  | if (!m_bGdbOptionRecognised) { | 
|  | const CMICmnMIValueConst miValueConst( | 
|  | CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), | 
|  | m_strGdbOptionName.c_str())); | 
|  | const CMICmnMIValueResult miValueResult("msg", miValueConst); | 
|  | const CMICmnMIResultRecord miRecordResult( | 
|  | m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, | 
|  | miValueResult); | 
|  | m_miResultRecord = miRecordResult; | 
|  | return MIstatus::success; | 
|  | } | 
|  |  | 
|  | // ^done,value="%s" | 
|  | if (m_bGdbOptionFnSuccessful && !m_strValue.empty()) { | 
|  | const CMICmnMIValueConst miValueConst(m_strValue); | 
|  | const CMICmnMIValueResult miValueResult("value", miValueConst); | 
|  | const CMICmnMIResultRecord miRecordResult( | 
|  | m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, | 
|  | miValueResult); | 
|  | m_miResultRecord = miRecordResult; | 
|  | return MIstatus::success; | 
|  | } else if (m_bGdbOptionFnSuccessful) { | 
|  | // Ignore empty value (for fallback) | 
|  | const CMICmnMIResultRecord miRecordResult( | 
|  | m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); | 
|  | m_miResultRecord = miRecordResult; | 
|  | return MIstatus::success; | 
|  | } | 
|  |  | 
|  | // Print error if request failed: | 
|  | // ^error,msg="The request '%s' failed. | 
|  | const CMICmnMIValueConst miValueConst(CMIUtilString::Format( | 
|  | MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strGdbOptionFnError.c_str())); | 
|  | const CMICmnMIValueResult miValueResult("msg", miValueConst); | 
|  | const CMICmnMIResultRecord miRecordResult( | 
|  | m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, | 
|  | miValueResult); | 
|  | m_miResultRecord = miRecordResult; | 
|  |  | 
|  | return MIstatus::success; | 
|  | } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: Required by the CMICmdFactory when registering *this command. The | 
|  | // factory | 
|  | //          calls this function to create an instance of *this command. | 
|  | // Type:    Static method. | 
|  | // Args:    None. | 
|  | // Return:  CMICmdBase * - Pointer to a new command. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | CMICmdBase *CMICmdCmdGdbShow::CreateSelf() { return new CMICmdCmdGdbShow(); } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: Retrieve the print function's pointer for the matching print | 
|  | // request. | 
|  | // Type:    Method. | 
|  | // Args:    vrPrintFnName   - (R) The info requested. | 
|  | //          vrwpFn          - (W) The print function's pointer of the function | 
|  | //          to carry out | 
|  | // Return:  bool    - True = Print request is implemented, false = not found. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | bool CMICmdCmdGdbShow::GetOptionFn(const CMIUtilString &vrPrintFnName, | 
|  | FnGdbOptionPtr &vrwpFn) const { | 
|  | vrwpFn = nullptr; | 
|  |  | 
|  | const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it = | 
|  | ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName); | 
|  | if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) { | 
|  | vrwpFn = (*it).second; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: Carry out work to complete the GDB show option 'target-async' to | 
|  | // prepare | 
|  | //          and send back the requested information. | 
|  | // Type:    Method. | 
|  | // Args:    vrWords - (R) List of additional parameters used by this option. | 
|  | // Return:  MIstatus::success - Function succeeded. | 
|  | //          MIstatus::failure - Function failed. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | bool CMICmdCmdGdbShow::OptionFnTargetAsync( | 
|  | const CMIUtilString::VecString_t &vrWords) { | 
|  | MIunused(vrWords); | 
|  |  | 
|  | // Get async mode | 
|  | CMICmnLLDBDebugSessionInfo &rSessionInfo( | 
|  | CMICmnLLDBDebugSessionInfo::Instance()); | 
|  | const bool bAsyncMode = rSessionInfo.GetDebugger().GetAsync(); | 
|  |  | 
|  | m_strValue = bAsyncMode ? "on" : "off"; | 
|  | return MIstatus::success; | 
|  | } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: Carry out work to complete the GDB show option 'print' to prepare | 
|  | // and send | 
|  | //          back the requested information. | 
|  | // Type:    Method. | 
|  | // Args:    vrWords - (R) List of additional parameters used by this option. | 
|  | // Return:  MIstatus::success - Function succeeded. | 
|  | //          MIstatus::failure - Function failed. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | bool CMICmdCmdGdbShow::OptionFnPrint( | 
|  | const CMIUtilString::VecString_t &vrWords) { | 
|  | const bool bAllArgs(vrWords.size() == 1); | 
|  | if (!bAllArgs) { | 
|  | m_bGbbOptionFnHasError = true; | 
|  | m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS); | 
|  | return MIstatus::failure; | 
|  | } | 
|  |  | 
|  | const CMIUtilString strOption(vrWords[0]); | 
|  | CMIUtilString strOptionKey; | 
|  | bool bOptionValueDefault = false; | 
|  | if (CMIUtilString::Compare(strOption, "char-array-as-string")) | 
|  | strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString; | 
|  | else if (CMIUtilString::Compare(strOption, "expand-aggregates")) | 
|  | strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates; | 
|  | else if (CMIUtilString::Compare(strOption, "aggregate-field-names")) { | 
|  | strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames; | 
|  | bOptionValueDefault = true; | 
|  | } else { | 
|  | m_bGbbOptionFnHasError = true; | 
|  | m_strGdbOptionFnError = CMIUtilString::Format( | 
|  | MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION), | 
|  | strOption.c_str()); | 
|  | return MIstatus::failure; | 
|  | } | 
|  |  | 
|  | bool bOptionValue = false; | 
|  | bOptionValue = bOptionValueDefault | 
|  | ? !m_rLLDBDebugSessionInfo.SharedDataRetrieve<bool>( | 
|  | strOptionKey, bOptionValue) || | 
|  | bOptionValue | 
|  | : m_rLLDBDebugSessionInfo.SharedDataRetrieve<bool>( | 
|  | strOptionKey, bOptionValue) && | 
|  | bOptionValue; | 
|  |  | 
|  | m_strValue = bOptionValue ? "on" : "off"; | 
|  | return MIstatus::success; | 
|  | } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: Carry out work to complete the GDB show option 'language' to prepare | 
|  | //          and send back the requested information. | 
|  | // Type:    Method. | 
|  | // Args:    vrWords - (R) List of additional parameters used by this option. | 
|  | // Return:  MIstatus::success - Function succeeded. | 
|  | //          MIstatus::failure - Function failed. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | bool CMICmdCmdGdbShow::OptionFnLanguage( | 
|  | const CMIUtilString::VecString_t &vrWords) { | 
|  | MIunused(vrWords); | 
|  |  | 
|  | // Get current language | 
|  | CMICmnLLDBDebugSessionInfo &rSessionInfo( | 
|  | CMICmnLLDBDebugSessionInfo::Instance()); | 
|  | lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread(); | 
|  | const lldb::SBFrame sbFrame = sbThread.GetSelectedFrame(); | 
|  | lldb::SBCompileUnit sbCompileUnit = sbFrame.GetCompileUnit(); | 
|  | const lldb::LanguageType eLanguageType = sbCompileUnit.GetLanguage(); | 
|  |  | 
|  | m_strValue = lldb::SBLanguageRuntime::GetNameForLanguageType(eLanguageType); | 
|  | return MIstatus::success; | 
|  | } | 
|  |  | 
|  | //++ | 
|  | //------------------------------------------------------------------------------------ | 
|  | // Details: Carry out work to complete the GDB show option to prepare and send | 
|  | // back the | 
|  | //          requested information. | 
|  | // Type:    Method. | 
|  | // Args:    None. | 
|  | // Return:  MIstatus::success - Function succeeded. | 
|  | //          MIstatus::failure - Function failed. | 
|  | // Throws:  None. | 
|  | //-- | 
|  | bool CMICmdCmdGdbShow::OptionFnFallback( | 
|  | const CMIUtilString::VecString_t &vrWords) { | 
|  | MIunused(vrWords); | 
|  |  | 
|  | // Do nothing - intentional. This is a fallback function to do nothing. | 
|  | // This allows the search for gdb-show options to always succeed when the | 
|  | // option is not | 
|  | // found (implemented). | 
|  |  | 
|  | return MIstatus::success; | 
|  | } |