1 //===-- MICmdCmdGdbSet.cpp --------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Overview: CMICmdCmdGdbSet implementation.
12 #include "MICmdCmdGdbSet.h"
13 #include "MICmdArgValListOfN.h"
14 #include "MICmdArgValOptionLong.h"
15 #include "MICmdArgValString.h"
16 #include "MICmnLLDBDebugSessionInfo.h"
17 #include "MICmnMIResultRecord.h"
18 #include "MICmnMIValueConst.h"
21 const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t
22 CMICmdCmdGdbSet::ms_mapGdbOptionNameToFnGdbOptionPtr = {
23 {"target-async", &CMICmdCmdGdbSet::OptionFnTargetAsync},
24 {"print", &CMICmdCmdGdbSet::OptionFnPrint},
25 // { "auto-solib-add", &CMICmdCmdGdbSet::OptionFnAutoSolibAdd }, //
26 // Example code if need to implement GDB set other options
27 {"output-radix", &CMICmdCmdGdbSet::OptionFnOutputRadix},
28 {"solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath},
29 {"disassembly-flavor", &CMICmdCmdGdbSet::OptionFnDisassemblyFlavor},
30 {"fallback", &CMICmdCmdGdbSet::OptionFnFallback},
31 {"breakpoint", &CMICmdCmdGdbSet::OptionFnBreakpoint}};
34 // Details: CMICmdCmdGdbSet constructor.
40 CMICmdCmdGdbSet::CMICmdCmdGdbSet()
41 : m_constStrArgNamedGdbOption("option"), m_bGdbOptionRecognised(true),
42 m_bGdbOptionFnSuccessful(false), m_bGbbOptionFnHasError(false),
43 m_strGdbOptionFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) {
44 // Command factory matches this name with that received from the stdin stream
45 m_strMiCmd = "gdb-set";
47 // Required by the CMICmdFactory when registering *this command
48 m_pSelfCreatorFn = &CMICmdCmdGdbSet::CreateSelf;
52 // Details: CMICmdCmdGdbSet destructor.
53 // Type: Overrideable.
58 CMICmdCmdGdbSet::~CMICmdCmdGdbSet() {}
61 // Details: The invoker requires this function. The parses the command line
63 // arguments to extract values for each of those arguments.
66 // Return: MIstatus::success - Functional succeeded.
67 // MIstatus::failure - Functional failed.
70 bool CMICmdCmdGdbSet::ParseArgs() {
71 m_setCmdArgs.Add(new CMICmdArgValListOfN(
72 m_constStrArgNamedGdbOption, true, true,
73 CMICmdArgValListBase::eArgValType_StringAnything));
74 return ParseValidateCmdOptions();
78 // Details: The invoker requires this function. The command is executed in this
80 // The command is likely to communicate with the LLDB SBDebugger in
84 // Return: MIstatus::success - Functional succeeded.
85 // MIstatus::failure - Functional failed.
88 bool CMICmdCmdGdbSet::Execute() {
89 CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption);
90 const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords(
91 pArgGdbOption->GetExpectedOptions());
93 // Get the gdb-set option to carry out. This option will be used as an action
94 // which should be done. Further arguments will be used as parameters for it.
95 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin();
96 const CMICmdArgValString *pOption =
97 static_cast<const CMICmdArgValString *>(*it);
98 const CMIUtilString strOption(pOption->GetValue());
101 // Retrieve the parameter(s) for the option
102 CMIUtilString::VecString_t vecWords;
103 while (it != rVecWords.end()) {
104 const CMICmdArgValString *pWord =
105 static_cast<const CMICmdArgValString *>(*it);
106 vecWords.push_back(pWord->GetValue());
112 FnGdbOptionPtr pPrintRequestFn = nullptr;
113 if (!GetOptionFn(strOption, pPrintRequestFn)) {
114 // For unimplemented option handlers, fallback on a generic handler
115 // ToDo: Remove this when ALL options have been implemented
116 if (!GetOptionFn("fallback", pPrintRequestFn)) {
117 m_bGdbOptionRecognised = false;
118 m_strGdbOptionName = "fallback"; // This would be the strOption name
119 return MIstatus::success;
123 m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords);
124 if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError)
125 return MIstatus::failure;
127 return MIstatus::success;
131 // Details: The invoker requires this function. The command prepares a MI Record
133 // for the work carried out in the Execute() method.
136 // Return: MIstatus::success - Functional succeeded.
137 // MIstatus::failure - Functional failed.
140 bool CMICmdCmdGdbSet::Acknowledge() {
141 // Print error if option isn't recognized:
142 // ^error,msg="The request '%s' was not recognized, not implemented"
143 if (!m_bGdbOptionRecognised) {
144 const CMICmnMIValueConst miValueConst(
145 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND),
146 m_strGdbOptionName.c_str()));
147 const CMICmnMIValueResult miValueResult("msg", miValueConst);
148 const CMICmnMIResultRecord miRecordResult(
149 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
151 m_miResultRecord = miRecordResult;
152 return MIstatus::success;
156 if (m_bGdbOptionFnSuccessful) {
157 const CMICmnMIResultRecord miRecordResult(
158 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
159 m_miResultRecord = miRecordResult;
160 return MIstatus::success;
163 // Print error if request failed:
164 // ^error,msg="The request '%s' failed.
165 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
166 MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strGdbOptionFnError.c_str()));
167 const CMICmnMIValueResult miValueResult("msg", miValueConst);
168 const CMICmnMIResultRecord miRecordResult(
169 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
171 m_miResultRecord = miRecordResult;
173 return MIstatus::success;
177 // Details: Required by the CMICmdFactory when registering *this command. The
179 // calls this function to create an instance of *this command.
180 // Type: Static method.
182 // Return: CMICmdBase * - Pointer to a new command.
185 CMICmdBase *CMICmdCmdGdbSet::CreateSelf() { return new CMICmdCmdGdbSet(); }
188 // Details: Retrieve the print function's pointer for the matching print
191 // Args: vrPrintFnName - (R) The info requested.
192 // vrwpFn - (W) The print function's pointer of the function
194 // Return: bool - True = Print request is implemented, false = not found.
197 bool CMICmdCmdGdbSet::GetOptionFn(const CMIUtilString &vrPrintFnName,
198 FnGdbOptionPtr &vrwpFn) const {
201 const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it =
202 ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName);
203 if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) {
204 vrwpFn = (*it).second;
212 // Details: Carry out work to complete the GDB set option 'target-async' to
214 // and send back information asked for.
216 // Args: vrWords - (R) List of additional parameters used by this option.
217 // Return: MIstatus::success - Function succeeded.
218 // MIstatus::failure - Function failed.
221 bool CMICmdCmdGdbSet::OptionFnTargetAsync(
222 const CMIUtilString::VecString_t &vrWords) {
223 bool bAsyncMode = false;
226 if (vrWords.size() > 1)
227 // Too many arguments.
229 else if (vrWords.size() == 0)
230 // If no arguments, default is "on".
232 else if (CMIUtilString::Compare(vrWords[0], "on"))
234 else if (CMIUtilString::Compare(vrWords[0], "off"))
237 // Unrecognized argument.
242 m_bGbbOptionFnHasError = true;
243 m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC);
244 return MIstatus::failure;
247 // Turn async mode on/off.
248 CMICmnLLDBDebugSessionInfo &rSessionInfo(
249 CMICmnLLDBDebugSessionInfo::Instance());
250 rSessionInfo.GetDebugger().SetAsync(bAsyncMode);
252 return MIstatus::success;
256 // Details: Carry out work to complete the GDB set option
257 // 'print-char-array-as-string' to
258 // prepare and send back information asked for.
260 // Args: vrWords - (R) List of additional parameters used by this option.
261 // Return: MIstatus::success - Function succeeded.
262 // MIstatus::failure - Function failed.
265 bool CMICmdCmdGdbSet::OptionFnPrint(const CMIUtilString::VecString_t &vrWords) {
266 const bool bAllArgs(vrWords.size() == 2);
267 const bool bArgOn(bAllArgs && (CMIUtilString::Compare(vrWords[1], "on") ||
268 CMIUtilString::Compare(vrWords[1], "1")));
269 const bool bArgOff(bAllArgs && (CMIUtilString::Compare(vrWords[1], "off") ||
270 CMIUtilString::Compare(vrWords[1], "0")));
271 if (!bAllArgs || (!bArgOn && !bArgOff)) {
272 m_bGbbOptionFnHasError = true;
273 m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS);
274 return MIstatus::failure;
277 const CMIUtilString strOption(vrWords[0]);
278 CMIUtilString strOptionKey;
279 if (CMIUtilString::Compare(strOption, "char-array-as-string"))
280 strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString;
281 else if (CMIUtilString::Compare(strOption, "expand-aggregates"))
282 strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates;
283 else if (CMIUtilString::Compare(strOption, "aggregate-field-names"))
284 strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames;
286 m_bGbbOptionFnHasError = true;
287 m_strGdbOptionFnError = CMIUtilString::Format(
288 MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION), strOption.c_str());
289 return MIstatus::failure;
292 const bool bOptionValue(bArgOn);
293 if (!m_rLLDBDebugSessionInfo.SharedDataAdd<bool>(strOptionKey,
295 m_bGbbOptionFnHasError = false;
296 SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
297 m_cmdData.strMiCmd.c_str(),
298 strOptionKey.c_str()));
299 return MIstatus::failure;
302 return MIstatus::success;
306 // Details: Carry out work to complete the GDB set option 'solib-search-path' to
308 // and send back information asked for.
310 // Args: vrWords - (R) List of additional parameters used by this option.
311 // Return: MIstatus::success - Functional succeeded.
312 // MIstatus::failure - Functional failed.
315 bool CMICmdCmdGdbSet::OptionFnSolibSearchPath(
316 const CMIUtilString::VecString_t &vrWords) {
317 // Check we have at least one argument
318 if (vrWords.size() < 1) {
319 m_bGbbOptionFnHasError = true;
320 m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH);
321 return MIstatus::failure;
323 const CMIUtilString &rStrValSolibPath(vrWords[0]);
325 // Add 'solib-search-path' to the shared data list
326 const CMIUtilString &rStrKeySolibPath(
327 m_rLLDBDebugSessionInfo.m_constStrSharedDataSolibPath);
328 if (!m_rLLDBDebugSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeySolibPath,
330 m_bGbbOptionFnHasError = false;
331 SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
332 m_cmdData.strMiCmd.c_str(),
333 rStrKeySolibPath.c_str()));
334 return MIstatus::failure;
337 return MIstatus::success;
341 // Details: Carry out work to complete the GDB set option 'output-radix' to
343 // and send back information asked for.
345 // Args: vrWords - (R) List of additional parameters used by this option.
346 // Return: MIstatus::success - Functional succeeded.
347 // MIstatus::failure - Functional failed.
350 bool CMICmdCmdGdbSet::OptionFnOutputRadix(
351 const CMIUtilString::VecString_t &vrWords) {
352 // Check we have at least one argument
353 if (vrWords.size() < 1) {
354 m_bGbbOptionFnHasError = true;
355 m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH);
356 return MIstatus::failure;
358 const CMIUtilString &rStrValOutputRadix(vrWords[0]);
360 CMICmnLLDBDebugSessionInfoVarObj::varFormat_e format =
361 CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid;
363 if (rStrValOutputRadix.ExtractNumber(radix)) {
366 format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Octal;
369 format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural;
372 format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Hex;
375 format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid;
379 if (format == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) {
380 m_bGbbOptionFnHasError = false;
381 SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
382 m_cmdData.strMiCmd.c_str(), "Output Radix"));
383 return MIstatus::failure;
385 CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat(format);
387 return MIstatus::success;
391 // Details: Carry out work to complete the GDB set option 'disassembly-flavor'
393 // and send back information asked for.
395 // Args: vrWords - (R) List of additional parameters used by this option.
396 // Return: MIstatus::success - Functional succeeded.
397 // MIstatus::failure - Functional failed.
400 bool CMICmdCmdGdbSet::OptionFnDisassemblyFlavor(
401 const CMIUtilString::VecString_t &vrWords) {
402 // Check we have at least one argument
403 if (vrWords.size() < 1) {
404 m_bGbbOptionFnHasError = true;
405 // m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH);
406 return MIstatus::failure;
408 const CMIUtilString &rStrValDisasmFlavor(vrWords[0]);
410 lldb::SBDebugger &rDbgr = m_rLLDBDebugSessionInfo.GetDebugger();
411 lldb::SBError error = lldb::SBDebugger::SetInternalVariable(
412 "target.x86-disassembly-flavor", rStrValDisasmFlavor.c_str(),
413 rDbgr.GetInstanceName());
415 m_strGdbOptionFnError = error.GetCString();
416 return MIstatus::failure;
419 return MIstatus::success;
423 // Details: Carry out work to complete the GDB set option 'breakpoint' to
425 // and send back information asked for.
427 // Args: vrWords - (R) List of additional parameters used by this option.
428 // Return: MIstatus::success - Function succeeded.
429 // MIstatus::failure - Function failed.
432 bool CMICmdCmdGdbSet::OptionFnBreakpoint(
433 const CMIUtilString::VecString_t &vrWords) {
434 bool bPending = false;
437 if (vrWords.size() != 2)
438 // Wrong number of arguments.
440 else if (CMIUtilString::Compare(vrWords[0], "pending") &&
441 (CMIUtilString::Compare(vrWords[1], "on") ||
442 CMIUtilString::Compare(vrWords[1], "1")))
444 else if (CMIUtilString::Compare(vrWords[0], "pending") &&
445 (CMIUtilString::Compare(vrWords[1], "off") ||
446 CMIUtilString::Compare(vrWords[1], "0")))
449 // Unrecognized argument(s).
454 m_bGbbOptionFnHasError = false;
455 SetError(MIRSRC(IDS_CMD_ERR_GDBSET_OPT_BREAKPOINT));
456 return MIstatus::failure;
459 CMIUtilString sPendingVal = bPending ? "on" : "off";
460 CMIUtilString sKey = "breakpoint.pending";
461 if (!m_rLLDBDebugSessionInfo.SharedDataAdd(sKey, sPendingVal)) {
462 m_bGbbOptionFnHasError = false;
463 SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
464 m_cmdData.strMiCmd.c_str(), sKey.c_str()));
465 return MIstatus::failure;
468 return MIstatus::success;
472 // Details: Carry out work to complete the GDB set option to prepare and send
474 // requested information.
477 // Return: MIstatus::success - Functional succeeded.
478 // MIstatus::failure - Functional failed.
481 bool CMICmdCmdGdbSet::OptionFnFallback(
482 const CMIUtilString::VecString_t &vrWords) {
485 // Do nothing - intentional. This is a fallback function to do nothing.
486 // This allows the search for gdb-set options to always succeed when the
488 // found (implemented).
490 return MIstatus::success;