]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MICmdCmdGdbSet.cpp
1 //===-- MICmdCmdGdbSet.cpp --------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 // Overview:    CMICmdCmdGdbSet implementation.
10
11 // In-house headers:
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"
19
20 // Instantiations:
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}};
32
33 //++
34 // Details: CMICmdCmdGdbSet constructor.
35 // Type:    Method.
36 // Args:    None.
37 // Return:  None.
38 // Throws:  None.
39 //--
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";
46
47   // Required by the CMICmdFactory when registering *this command
48   m_pSelfCreatorFn = &CMICmdCmdGdbSet::CreateSelf;
49 }
50
51 //++
52 // Details: CMICmdCmdGdbSet destructor.
53 // Type:    Overrideable.
54 // Args:    None.
55 // Return:  None.
56 // Throws:  None.
57 //--
58 CMICmdCmdGdbSet::~CMICmdCmdGdbSet() {}
59
60 //++
61 // Details: The invoker requires this function. The parses the command line
62 // options
63 //          arguments to extract values for each of those arguments.
64 // Type:    Overridden.
65 // Args:    None.
66 // Return:  MIstatus::success - Functional succeeded.
67 //          MIstatus::failure - Functional failed.
68 // Throws:  None.
69 //--
70 bool CMICmdCmdGdbSet::ParseArgs() {
71   m_setCmdArgs.Add(new CMICmdArgValListOfN(
72       m_constStrArgNamedGdbOption, true, true,
73       CMICmdArgValListBase::eArgValType_StringAnything));
74   return ParseValidateCmdOptions();
75 }
76
77 //++
78 // Details: The invoker requires this function. The command is executed in this
79 // function.
80 //          The command is likely to communicate with the LLDB SBDebugger in
81 //          here.
82 // Type:    Overridden.
83 // Args:    None.
84 // Return:  MIstatus::success - Functional succeeded.
85 //          MIstatus::failure - Functional failed.
86 // Throws:  None.
87 //--
88 bool CMICmdCmdGdbSet::Execute() {
89   CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption);
90   const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords(
91       pArgGdbOption->GetExpectedOptions());
92
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());
99   ++it;
100
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());
107
108     // Next
109     ++it;
110   }
111
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;
120     }
121   }
122
123   m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords);
124   if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError)
125     return MIstatus::failure;
126
127   return MIstatus::success;
128 }
129
130 //++
131 // Details: The invoker requires this function. The command prepares a MI Record
132 // Result
133 //          for the work carried out in the Execute() method.
134 // Type:    Overridden.
135 // Args:    None.
136 // Return:  MIstatus::success - Functional succeeded.
137 //          MIstatus::failure - Functional failed.
138 // Throws:  None.
139 //--
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,
150         miValueResult);
151     m_miResultRecord = miRecordResult;
152     return MIstatus::success;
153   }
154
155   // ^done,value="%s"
156   if (m_bGdbOptionFnSuccessful) {
157     const CMICmnMIResultRecord miRecordResult(
158         m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
159     m_miResultRecord = miRecordResult;
160     return MIstatus::success;
161   }
162
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,
170       miValueResult);
171   m_miResultRecord = miRecordResult;
172
173   return MIstatus::success;
174 }
175
176 //++
177 // Details: Required by the CMICmdFactory when registering *this command. The
178 // factory
179 //          calls this function to create an instance of *this command.
180 // Type:    Static method.
181 // Args:    None.
182 // Return:  CMICmdBase * - Pointer to a new command.
183 // Throws:  None.
184 //--
185 CMICmdBase *CMICmdCmdGdbSet::CreateSelf() { return new CMICmdCmdGdbSet(); }
186
187 //++
188 // Details: Retrieve the print function's pointer for the matching print
189 // request.
190 // Type:    Method.
191 // Args:    vrPrintFnName   - (R) The info requested.
192 //          vrwpFn          - (W) The print function's pointer of the function
193 //          to carry out
194 // Return:  bool    - True = Print request is implemented, false = not found.
195 // Throws:  None.
196 //--
197 bool CMICmdCmdGdbSet::GetOptionFn(const CMIUtilString &vrPrintFnName,
198                                   FnGdbOptionPtr &vrwpFn) const {
199   vrwpFn = nullptr;
200
201   const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it =
202       ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName);
203   if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) {
204     vrwpFn = (*it).second;
205     return true;
206   }
207
208   return false;
209 }
210
211 //++
212 // Details: Carry out work to complete the GDB set option 'target-async' to
213 // prepare
214 //          and send back information asked for.
215 // Type:    Method.
216 // Args:    vrWords - (R) List of additional parameters used by this option.
217 // Return:  MIstatus::success - Function succeeded.
218 //          MIstatus::failure - Function failed.
219 // Throws:  None.
220 //--
221 bool CMICmdCmdGdbSet::OptionFnTargetAsync(
222     const CMIUtilString::VecString_t &vrWords) {
223   bool bAsyncMode = false;
224   bool bOk = true;
225
226   if (vrWords.size() > 1)
227     // Too many arguments.
228     bOk = false;
229   else if (vrWords.size() == 0)
230     // If no arguments, default is "on".
231     bAsyncMode = true;
232   else if (CMIUtilString::Compare(vrWords[0], "on"))
233     bAsyncMode = true;
234   else if (CMIUtilString::Compare(vrWords[0], "off"))
235     bAsyncMode = false;
236   else
237     // Unrecognized argument.
238     bOk = false;
239
240   if (!bOk) {
241     // Report error.
242     m_bGbbOptionFnHasError = true;
243     m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC);
244     return MIstatus::failure;
245   }
246
247   // Turn async mode on/off.
248   CMICmnLLDBDebugSessionInfo &rSessionInfo(
249       CMICmnLLDBDebugSessionInfo::Instance());
250   rSessionInfo.GetDebugger().SetAsync(bAsyncMode);
251
252   return MIstatus::success;
253 }
254
255 //++
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.
259 // Type:    Method.
260 // Args:    vrWords - (R) List of additional parameters used by this option.
261 // Return:  MIstatus::success - Function succeeded.
262 //          MIstatus::failure - Function failed.
263 // Throws:  None.
264 //--
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;
275   }
276
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;
285   else {
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;
290   }
291
292   const bool bOptionValue(bArgOn);
293   if (!m_rLLDBDebugSessionInfo.SharedDataAdd<bool>(strOptionKey,
294                                                    bOptionValue)) {
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;
300   }
301
302   return MIstatus::success;
303 }
304
305 //++
306 // Details: Carry out work to complete the GDB set option 'solib-search-path' to
307 // prepare
308 //          and send back information asked for.
309 // Type:    Method.
310 // Args:    vrWords - (R) List of additional parameters used by this option.
311 // Return:  MIstatus::success - Functional succeeded.
312 //          MIstatus::failure - Functional failed.
313 // Throws:  None.
314 //--
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;
322   }
323   const CMIUtilString &rStrValSolibPath(vrWords[0]);
324
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,
329                                                             rStrValSolibPath)) {
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;
335   }
336
337   return MIstatus::success;
338 }
339
340 //++
341 // Details: Carry out work to complete the GDB set option 'output-radix' to
342 // prepare
343 //          and send back information asked for.
344 // Type:    Method.
345 // Args:    vrWords - (R) List of additional parameters used by this option.
346 // Return:  MIstatus::success - Functional succeeded.
347 //          MIstatus::failure - Functional failed.
348 // Throws:  None.
349 //--
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;
357   }
358   const CMIUtilString &rStrValOutputRadix(vrWords[0]);
359
360   CMICmnLLDBDebugSessionInfoVarObj::varFormat_e format =
361       CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid;
362   MIint64 radix;
363   if (rStrValOutputRadix.ExtractNumber(radix)) {
364     switch (radix) {
365     case 8:
366       format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Octal;
367       break;
368     case 10:
369       format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural;
370       break;
371     case 16:
372       format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Hex;
373       break;
374     default:
375       format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid;
376       break;
377     }
378   }
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;
384   }
385   CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat(format);
386
387   return MIstatus::success;
388 }
389
390 //++
391 // Details: Carry out work to complete the GDB set option 'disassembly-flavor'
392 // to prepare
393 //          and send back information asked for.
394 // Type:    Method.
395 // Args:    vrWords - (R) List of additional parameters used by this option.
396 // Return:  MIstatus::success - Functional succeeded.
397 //          MIstatus::failure - Functional failed.
398 // Throws:  None.
399 //--
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;
407   }
408   const CMIUtilString &rStrValDisasmFlavor(vrWords[0]);
409
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());
414   if (error.Fail()) {
415     m_strGdbOptionFnError = error.GetCString();
416     return MIstatus::failure;
417   }
418
419   return MIstatus::success;
420 }
421
422 //++
423 // Details: Carry out work to complete the GDB set option 'breakpoint' to
424 // prepare
425 //          and send back information asked for.
426 // Type:    Method.
427 // Args:    vrWords - (R) List of additional parameters used by this option.
428 // Return:  MIstatus::success - Function succeeded.
429 //          MIstatus::failure - Function failed.
430 // Throws:  None.
431 //--
432 bool CMICmdCmdGdbSet::OptionFnBreakpoint(
433     const CMIUtilString::VecString_t &vrWords) {
434   bool bPending = false;
435   bool bOk = true;
436
437   if (vrWords.size() != 2)
438     // Wrong number of arguments.
439     bOk = false;
440   else if (CMIUtilString::Compare(vrWords[0], "pending") &&
441            (CMIUtilString::Compare(vrWords[1], "on") ||
442             CMIUtilString::Compare(vrWords[1], "1")))
443     bPending = true;
444   else if (CMIUtilString::Compare(vrWords[0], "pending") &&
445            (CMIUtilString::Compare(vrWords[1], "off") ||
446             CMIUtilString::Compare(vrWords[1], "0")))
447     bPending = false;
448   else
449     // Unrecognized argument(s).
450     bOk = false;
451
452   if (!bOk) {
453     // Report error.
454     m_bGbbOptionFnHasError = false;
455     SetError(MIRSRC(IDS_CMD_ERR_GDBSET_OPT_BREAKPOINT));
456     return MIstatus::failure;
457   }
458
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;
466   }
467
468   return MIstatus::success;
469 }
470
471 //++
472 // Details: Carry out work to complete the GDB set option to prepare and send
473 // back the
474 //          requested information.
475 // Type:    Method.
476 // Args:    None.
477 // Return:  MIstatus::success - Functional succeeded.
478 //          MIstatus::failure - Functional failed.
479 // Throws:  None.
480 //--
481 bool CMICmdCmdGdbSet::OptionFnFallback(
482     const CMIUtilString::VecString_t &vrWords) {
483   MIunused(vrWords);
484
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
487   // option is not
488   // found (implemented).
489
490   return MIstatus::success;
491 }