]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp
MFV r350898, r351075: 8423 8199 7432 Implement large_dnode pool feature
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmdCmdGdbSet.cpp
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 //--
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 //--
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 //--
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 //--
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 //--
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 //--
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 //--
205 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 //--
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 //--
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 //--
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 //--
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 //--
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 //--
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 //--
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 }