1 //===-- MICmdCmdGdbSet.cpp --------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Overview: CMICmdCmdGdbSet implementation.
11
12 // In-house headers:
13 #include "MICmdCmdGdbSet.h"
14 #include "MICmdArgValListOfN.h"
15 #include "MICmdArgValOptionLong.h"
16 #include "MICmdArgValString.h"
17 #include "MICmnLLDBDebugSessionInfo.h"
18 #include "MICmnMIResultRecord.h"
19 #include "MICmnMIValueConst.h"
20
21 // Instantiations:
22 const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t
23 CMICmdCmdGdbSet::ms_mapGdbOptionNameToFnGdbOptionPtr = {
24 {"target-async", &CMICmdCmdGdbSet::OptionFnTargetAsync},
25 {"print", &CMICmdCmdGdbSet::OptionFnPrint},
26 // { "auto-solib-add", &CMICmdCmdGdbSet::OptionFnAutoSolibAdd }, //
27 // Example code if need to implement GDB set other options
28 {"output-radix", &CMICmdCmdGdbSet::OptionFnOutputRadix},
29 {"solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath},
30 {"disassembly-flavor", &CMICmdCmdGdbSet::OptionFnDisassemblyFlavor},
31 {"fallback", &CMICmdCmdGdbSet::OptionFnFallback},
32 {"breakpoint", &CMICmdCmdGdbSet::OptionFnBreakpoint}};
33
34 //++
35 //------------------------------------------------------------------------------------
36 // Details: CMICmdCmdGdbSet constructor.
37 // Type: Method.
38 // Args: None.
39 // Return: None.
40 // Throws: None.
41 //--
CMICmdCmdGdbSet()42 CMICmdCmdGdbSet::CMICmdCmdGdbSet()
43 : m_constStrArgNamedGdbOption("option"), m_bGdbOptionRecognised(true),
44 m_bGdbOptionFnSuccessful(false), m_bGbbOptionFnHasError(false),
45 m_strGdbOptionFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) {
46 // Command factory matches this name with that received from the stdin stream
47 m_strMiCmd = "gdb-set";
48
49 // Required by the CMICmdFactory when registering *this command
50 m_pSelfCreatorFn = &CMICmdCmdGdbSet::CreateSelf;
51 }
52
53 //++
54 //------------------------------------------------------------------------------------
55 // Details: CMICmdCmdGdbSet destructor.
56 // Type: Overrideable.
57 // Args: None.
58 // Return: None.
59 // Throws: None.
60 //--
~CMICmdCmdGdbSet()61 CMICmdCmdGdbSet::~CMICmdCmdGdbSet() {}
62
63 //++
64 //------------------------------------------------------------------------------------
65 // Details: The invoker requires this function. The parses the command line
66 // options
67 // arguments to extract values for each of those arguments.
68 // Type: Overridden.
69 // Args: None.
70 // Return: MIstatus::success - Functional succeeded.
71 // MIstatus::failure - Functional failed.
72 // Throws: None.
73 //--
ParseArgs()74 bool CMICmdCmdGdbSet::ParseArgs() {
75 m_setCmdArgs.Add(new CMICmdArgValListOfN(
76 m_constStrArgNamedGdbOption, true, true,
77 CMICmdArgValListBase::eArgValType_StringAnything));
78 return ParseValidateCmdOptions();
79 }
80
81 //++
82 //------------------------------------------------------------------------------------
83 // Details: The invoker requires this function. The command is executed in this
84 // function.
85 // The command is likely to communicate with the LLDB SBDebugger in
86 // here.
87 // Type: Overridden.
88 // Args: None.
89 // Return: MIstatus::success - Functional succeeded.
90 // MIstatus::failure - Functional failed.
91 // Throws: None.
92 //--
Execute()93 bool CMICmdCmdGdbSet::Execute() {
94 CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption);
95 const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords(
96 pArgGdbOption->GetExpectedOptions());
97
98 // Get the gdb-set option to carry out. This option will be used as an action
99 // which should be done. Further arguments will be used as parameters for it.
100 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin();
101 const CMICmdArgValString *pOption =
102 static_cast<const CMICmdArgValString *>(*it);
103 const CMIUtilString strOption(pOption->GetValue());
104 ++it;
105
106 // Retrieve the parameter(s) for the option
107 CMIUtilString::VecString_t vecWords;
108 while (it != rVecWords.end()) {
109 const CMICmdArgValString *pWord =
110 static_cast<const CMICmdArgValString *>(*it);
111 vecWords.push_back(pWord->GetValue());
112
113 // Next
114 ++it;
115 }
116
117 FnGdbOptionPtr pPrintRequestFn = nullptr;
118 if (!GetOptionFn(strOption, pPrintRequestFn)) {
119 // For unimplemented option handlers, fallback on a generic handler
120 // ToDo: Remove this when ALL options have been implemented
121 if (!GetOptionFn("fallback", pPrintRequestFn)) {
122 m_bGdbOptionRecognised = false;
123 m_strGdbOptionName = "fallback"; // This would be the strOption name
124 return MIstatus::success;
125 }
126 }
127
128 m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords);
129 if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError)
130 return MIstatus::failure;
131
132 return MIstatus::success;
133 }
134
135 //++
136 //------------------------------------------------------------------------------------
137 // Details: The invoker requires this function. The command prepares a MI Record
138 // Result
139 // for the work carried out in the Execute() method.
140 // Type: Overridden.
141 // Args: None.
142 // Return: MIstatus::success - Functional succeeded.
143 // MIstatus::failure - Functional failed.
144 // Throws: None.
145 //--
Acknowledge()146 bool CMICmdCmdGdbSet::Acknowledge() {
147 // Print error if option isn't recognized:
148 // ^error,msg="The request '%s' was not recognized, not implemented"
149 if (!m_bGdbOptionRecognised) {
150 const CMICmnMIValueConst miValueConst(
151 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND),
152 m_strGdbOptionName.c_str()));
153 const CMICmnMIValueResult miValueResult("msg", miValueConst);
154 const CMICmnMIResultRecord miRecordResult(
155 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
156 miValueResult);
157 m_miResultRecord = miRecordResult;
158 return MIstatus::success;
159 }
160
161 // ^done,value="%s"
162 if (m_bGdbOptionFnSuccessful) {
163 const CMICmnMIResultRecord miRecordResult(
164 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
165 m_miResultRecord = miRecordResult;
166 return MIstatus::success;
167 }
168
169 // Print error if request failed:
170 // ^error,msg="The request '%s' failed.
171 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(
172 MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strGdbOptionFnError.c_str()));
173 const CMICmnMIValueResult miValueResult("msg", miValueConst);
174 const CMICmnMIResultRecord miRecordResult(
175 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
176 miValueResult);
177 m_miResultRecord = miRecordResult;
178
179 return MIstatus::success;
180 }
181
182 //++
183 //------------------------------------------------------------------------------------
184 // Details: Required by the CMICmdFactory when registering *this command. The
185 // factory
186 // calls this function to create an instance of *this command.
187 // Type: Static method.
188 // Args: None.
189 // Return: CMICmdBase * - Pointer to a new command.
190 // Throws: None.
191 //--
CreateSelf()192 CMICmdBase *CMICmdCmdGdbSet::CreateSelf() { return new CMICmdCmdGdbSet(); }
193
194 //++
195 //------------------------------------------------------------------------------------
196 // Details: Retrieve the print function's pointer for the matching print
197 // request.
198 // Type: Method.
199 // Args: vrPrintFnName - (R) The info requested.
200 // vrwpFn - (W) The print function's pointer of the function
201 // to carry out
202 // Return: bool - True = Print request is implemented, false = not found.
203 // Throws: None.
204 //--
GetOptionFn(const CMIUtilString & vrPrintFnName,FnGdbOptionPtr & vrwpFn) const205 bool CMICmdCmdGdbSet::GetOptionFn(const CMIUtilString &vrPrintFnName,
206 FnGdbOptionPtr &vrwpFn) const {
207 vrwpFn = nullptr;
208
209 const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it =
210 ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName);
211 if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) {
212 vrwpFn = (*it).second;
213 return true;
214 }
215
216 return false;
217 }
218
219 //++
220 //------------------------------------------------------------------------------------
221 // Details: Carry out work to complete the GDB set option 'target-async' to
222 // prepare
223 // and send back information asked for.
224 // Type: Method.
225 // Args: vrWords - (R) List of additional parameters used by this option.
226 // Return: MIstatus::success - Function succeeded.
227 // MIstatus::failure - Function failed.
228 // Throws: None.
229 //--
OptionFnTargetAsync(const CMIUtilString::VecString_t & vrWords)230 bool CMICmdCmdGdbSet::OptionFnTargetAsync(
231 const CMIUtilString::VecString_t &vrWords) {
232 bool bAsyncMode = false;
233 bool bOk = true;
234
235 if (vrWords.size() > 1)
236 // Too many arguments.
237 bOk = false;
238 else if (vrWords.size() == 0)
239 // If no arguments, default is "on".
240 bAsyncMode = true;
241 else if (CMIUtilString::Compare(vrWords[0], "on"))
242 bAsyncMode = true;
243 else if (CMIUtilString::Compare(vrWords[0], "off"))
244 bAsyncMode = false;
245 else
246 // Unrecognized argument.
247 bOk = false;
248
249 if (!bOk) {
250 // Report error.
251 m_bGbbOptionFnHasError = true;
252 m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC);
253 return MIstatus::failure;
254 }
255
256 // Turn async mode on/off.
257 CMICmnLLDBDebugSessionInfo &rSessionInfo(
258 CMICmnLLDBDebugSessionInfo::Instance());
259 rSessionInfo.GetDebugger().SetAsync(bAsyncMode);
260
261 return MIstatus::success;
262 }
263
264 //++
265 //------------------------------------------------------------------------------------
266 // Details: Carry out work to complete the GDB set option
267 // 'print-char-array-as-string' to
268 // prepare and send back information asked for.
269 // Type: Method.
270 // Args: vrWords - (R) List of additional parameters used by this option.
271 // Return: MIstatus::success - Function succeeded.
272 // MIstatus::failure - Function failed.
273 // Throws: None.
274 //--
OptionFnPrint(const CMIUtilString::VecString_t & vrWords)275 bool CMICmdCmdGdbSet::OptionFnPrint(const CMIUtilString::VecString_t &vrWords) {
276 const bool bAllArgs(vrWords.size() == 2);
277 const bool bArgOn(bAllArgs && (CMIUtilString::Compare(vrWords[1], "on") ||
278 CMIUtilString::Compare(vrWords[1], "1")));
279 const bool bArgOff(bAllArgs && (CMIUtilString::Compare(vrWords[1], "off") ||
280 CMIUtilString::Compare(vrWords[1], "0")));
281 if (!bAllArgs || (!bArgOn && !bArgOff)) {
282 m_bGbbOptionFnHasError = true;
283 m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS);
284 return MIstatus::failure;
285 }
286
287 const CMIUtilString strOption(vrWords[0]);
288 CMIUtilString strOptionKey;
289 if (CMIUtilString::Compare(strOption, "char-array-as-string"))
290 strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString;
291 else if (CMIUtilString::Compare(strOption, "expand-aggregates"))
292 strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates;
293 else if (CMIUtilString::Compare(strOption, "aggregate-field-names"))
294 strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames;
295 else {
296 m_bGbbOptionFnHasError = true;
297 m_strGdbOptionFnError = CMIUtilString::Format(
298 MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION), strOption.c_str());
299 return MIstatus::failure;
300 }
301
302 const bool bOptionValue(bArgOn);
303 if (!m_rLLDBDebugSessionInfo.SharedDataAdd<bool>(strOptionKey,
304 bOptionValue)) {
305 m_bGbbOptionFnHasError = false;
306 SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
307 m_cmdData.strMiCmd.c_str(),
308 strOptionKey.c_str()));
309 return MIstatus::failure;
310 }
311
312 return MIstatus::success;
313 }
314
315 //++
316 //------------------------------------------------------------------------------------
317 // Details: Carry out work to complete the GDB set option 'solib-search-path' to
318 // prepare
319 // and send back information asked for.
320 // Type: Method.
321 // Args: vrWords - (R) List of additional parameters used by this option.
322 // Return: MIstatus::success - Functional succeeded.
323 // MIstatus::failure - Functional failed.
324 // Throws: None.
325 //--
OptionFnSolibSearchPath(const CMIUtilString::VecString_t & vrWords)326 bool CMICmdCmdGdbSet::OptionFnSolibSearchPath(
327 const CMIUtilString::VecString_t &vrWords) {
328 // Check we have at least one argument
329 if (vrWords.size() < 1) {
330 m_bGbbOptionFnHasError = true;
331 m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH);
332 return MIstatus::failure;
333 }
334 const CMIUtilString &rStrValSolibPath(vrWords[0]);
335
336 // Add 'solib-search-path' to the shared data list
337 const CMIUtilString &rStrKeySolibPath(
338 m_rLLDBDebugSessionInfo.m_constStrSharedDataSolibPath);
339 if (!m_rLLDBDebugSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeySolibPath,
340 rStrValSolibPath)) {
341 m_bGbbOptionFnHasError = false;
342 SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
343 m_cmdData.strMiCmd.c_str(),
344 rStrKeySolibPath.c_str()));
345 return MIstatus::failure;
346 }
347
348 return MIstatus::success;
349 }
350
351 //++
352 //------------------------------------------------------------------------------------
353 // Details: Carry out work to complete the GDB set option 'output-radix' to
354 // prepare
355 // and send back information asked for.
356 // Type: Method.
357 // Args: vrWords - (R) List of additional parameters used by this option.
358 // Return: MIstatus::success - Functional succeeded.
359 // MIstatus::failure - Functional failed.
360 // Throws: None.
361 //--
OptionFnOutputRadix(const CMIUtilString::VecString_t & vrWords)362 bool CMICmdCmdGdbSet::OptionFnOutputRadix(
363 const CMIUtilString::VecString_t &vrWords) {
364 // Check we have at least one argument
365 if (vrWords.size() < 1) {
366 m_bGbbOptionFnHasError = true;
367 m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH);
368 return MIstatus::failure;
369 }
370 const CMIUtilString &rStrValOutputRadix(vrWords[0]);
371
372 CMICmnLLDBDebugSessionInfoVarObj::varFormat_e format =
373 CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid;
374 MIint64 radix;
375 if (rStrValOutputRadix.ExtractNumber(radix)) {
376 switch (radix) {
377 case 8:
378 format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Octal;
379 break;
380 case 10:
381 format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural;
382 break;
383 case 16:
384 format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Hex;
385 break;
386 default:
387 format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid;
388 break;
389 }
390 }
391 if (format == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) {
392 m_bGbbOptionFnHasError = false;
393 SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
394 m_cmdData.strMiCmd.c_str(), "Output Radix"));
395 return MIstatus::failure;
396 }
397 CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat(format);
398
399 return MIstatus::success;
400 }
401
402 //++
403 //------------------------------------------------------------------------------------
404 // Details: Carry out work to complete the GDB set option 'disassembly-flavor'
405 // to prepare
406 // and send back information asked for.
407 // Type: Method.
408 // Args: vrWords - (R) List of additional parameters used by this option.
409 // Return: MIstatus::success - Functional succeeded.
410 // MIstatus::failure - Functional failed.
411 // Throws: None.
412 //--
OptionFnDisassemblyFlavor(const CMIUtilString::VecString_t & vrWords)413 bool CMICmdCmdGdbSet::OptionFnDisassemblyFlavor(
414 const CMIUtilString::VecString_t &vrWords) {
415 // Check we have at least one argument
416 if (vrWords.size() < 1) {
417 m_bGbbOptionFnHasError = true;
418 // m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH);
419 return MIstatus::failure;
420 }
421 const CMIUtilString &rStrValDisasmFlavor(vrWords[0]);
422
423 lldb::SBDebugger &rDbgr = m_rLLDBDebugSessionInfo.GetDebugger();
424 lldb::SBError error = lldb::SBDebugger::SetInternalVariable(
425 "target.x86-disassembly-flavor", rStrValDisasmFlavor.c_str(),
426 rDbgr.GetInstanceName());
427 if (error.Fail()) {
428 m_strGdbOptionFnError = error.GetCString();
429 return MIstatus::failure;
430 }
431
432 return MIstatus::success;
433 }
434
435 //++
436 //------------------------------------------------------------------------------------
437 // Details: Carry out work to complete the GDB set option 'breakpoint' to
438 // prepare
439 // and send back information asked for.
440 // Type: Method.
441 // Args: vrWords - (R) List of additional parameters used by this option.
442 // Return: MIstatus::success - Function succeeded.
443 // MIstatus::failure - Function failed.
444 // Throws: None.
445 //--
OptionFnBreakpoint(const CMIUtilString::VecString_t & vrWords)446 bool CMICmdCmdGdbSet::OptionFnBreakpoint(
447 const CMIUtilString::VecString_t &vrWords) {
448 bool bPending = false;
449 bool bOk = true;
450
451 if (vrWords.size() != 2)
452 // Wrong number of arguments.
453 bOk = false;
454 else if (CMIUtilString::Compare(vrWords[0], "pending") &&
455 (CMIUtilString::Compare(vrWords[1], "on") ||
456 CMIUtilString::Compare(vrWords[1], "1")))
457 bPending = true;
458 else if (CMIUtilString::Compare(vrWords[0], "pending") &&
459 (CMIUtilString::Compare(vrWords[1], "off") ||
460 CMIUtilString::Compare(vrWords[1], "0")))
461 bPending = false;
462 else
463 // Unrecognized argument(s).
464 bOk = false;
465
466 if (!bOk) {
467 // Report error.
468 m_bGbbOptionFnHasError = false;
469 SetError(MIRSRC(IDS_CMD_ERR_GDBSET_OPT_BREAKPOINT));
470 return MIstatus::failure;
471 }
472
473 CMIUtilString sPendingVal = bPending ? "on" : "off";
474 CMIUtilString sKey = "breakpoint.pending";
475 if (!m_rLLDBDebugSessionInfo.SharedDataAdd(sKey, sPendingVal)) {
476 m_bGbbOptionFnHasError = false;
477 SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
478 m_cmdData.strMiCmd.c_str(), sKey.c_str()));
479 return MIstatus::failure;
480 }
481
482 return MIstatus::success;
483 }
484
485 //++
486 //------------------------------------------------------------------------------------
487 // Details: Carry out work to complete the GDB set option to prepare and send
488 // back the
489 // requested information.
490 // Type: Method.
491 // Args: None.
492 // Return: MIstatus::success - Functional succeeded.
493 // MIstatus::failure - Functional failed.
494 // Throws: None.
495 //--
OptionFnFallback(const CMIUtilString::VecString_t & vrWords)496 bool CMICmdCmdGdbSet::OptionFnFallback(
497 const CMIUtilString::VecString_t &vrWords) {
498 MIunused(vrWords);
499
500 // Do nothing - intentional. This is a fallback function to do nothing.
501 // This allows the search for gdb-set options to always succeed when the
502 // option is not
503 // found (implemented).
504
505 return MIstatus::success;
506 }
507