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