]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp
Fix a memory leak in if_delgroups() introduced in r334118.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / tools / lldb-mi / MICmdCmdMiscellanous.cpp
1 //===-- MICmdCmdMiscellanous.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:    CMICmdCmdGdbExit                implementation.
10 //              CMICmdCmdListThreadGroups       implementation.
11 //              CMICmdCmdInterpreterExec        implementation.
12 //              CMICmdCmdInferiorTtySet         implementation.
13
14 // Third Party Headers:
15 #include "lldb/API/SBCommandInterpreter.h"
16 #include "lldb/API/SBThread.h"
17
18 // In-house headers:
19 #include "MICmdArgValFile.h"
20 #include "MICmdArgValListOfN.h"
21 #include "MICmdArgValNumber.h"
22 #include "MICmdArgValOptionLong.h"
23 #include "MICmdArgValOptionShort.h"
24 #include "MICmdArgValString.h"
25 #include "MICmdArgValThreadGrp.h"
26 #include "MICmdCmdMiscellanous.h"
27 #include "MICmnLLDBDebugSessionInfo.h"
28 #include "MICmnLLDBDebugger.h"
29 #include "MICmnMIOutOfBandRecord.h"
30 #include "MICmnMIResultRecord.h"
31 #include "MICmnMIValueConst.h"
32 #include "MICmnStreamStderr.h"
33 #include "MICmnStreamStdout.h"
34 #include "MIDriverBase.h"
35
36 //++
37 // Details: CMICmdCmdGdbExit constructor.
38 // Type:    Method.
39 // Args:    None.
40 // Return:  None.
41 // Throws:  None.
42 //--
43 CMICmdCmdGdbExit::CMICmdCmdGdbExit() {
44   // Command factory matches this name with that received from the stdin stream
45   m_strMiCmd = "gdb-exit";
46
47   // Required by the CMICmdFactory when registering *this command
48   m_pSelfCreatorFn = &CMICmdCmdGdbExit::CreateSelf;
49 }
50
51 //++
52 // Details: CMICmdCmdGdbExit destructor.
53 // Type:    Overrideable.
54 // Args:    None.
55 // Return:  None.
56 // Throws:  None.
57 //--
58 CMICmdCmdGdbExit::~CMICmdCmdGdbExit() {}
59
60 //++
61 // Details: The invoker requires this function. The command does work in this
62 // function.
63 //          The command is likely to communicate with the LLDB SBDebugger in
64 //          here.
65 // Type:    Overridden.
66 // Args:    None.
67 // Return:  MIstatus::success - Functional succeeded.
68 //          MIstatus::failure - Functional failed.
69 // Throws:  None.
70 //--
71 bool CMICmdCmdGdbExit::Execute() {
72   CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(true);
73   const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.GetProcess().Destroy();
74   // Do not check for sbErr.Fail() here, m_lldbProcess is likely !IsValid()
75
76   return MIstatus::success;
77 }
78
79 //++
80 // Details: The invoker requires this function. The command prepares a MI Record
81 // Result
82 //          for the work carried out in the Execute().
83 // Type:    Overridden.
84 // Args:    None.
85 // Return:  MIstatus::success - Functional succeeded.
86 //          MIstatus::failure - Functional failed.
87 // Throws:  None.
88 //--
89 bool CMICmdCmdGdbExit::Acknowledge() {
90   const CMICmnMIResultRecord miRecordResult(
91       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Exit);
92   m_miResultRecord = miRecordResult;
93
94   // Prod the client i.e. Eclipse with out-of-band results to help it 'continue'
95   // because it is using LLDB debugger
96   // Give the client '=thread-group-exited,id="i1"'
97   m_bHasResultRecordExtra = true;
98   const CMICmnMIValueConst miValueConst2("i1");
99   const CMICmnMIValueResult miValueResult2("id", miValueConst2);
100   const CMICmnMIOutOfBandRecord miOutOfBand(
101       CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult2);
102   m_miResultRecordExtra = miOutOfBand.GetString();
103
104   return MIstatus::success;
105 }
106
107 //++
108 // Details: Required by the CMICmdFactory when registering *this command. The
109 // factory
110 //          calls this function to create an instance of *this command.
111 // Type:    Static method.
112 // Args:    None.
113 // Return:  CMICmdBase * - Pointer to a new command.
114 // Throws:  None.
115 //--
116 CMICmdBase *CMICmdCmdGdbExit::CreateSelf() { return new CMICmdCmdGdbExit(); }
117
118
119 //++
120 // Details: CMICmdCmdListThreadGroups constructor.
121 // Type:    Method.
122 // Args:    None.
123 // Return:  None.
124 // Throws:  None.
125 //--
126 CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups()
127     : m_bIsI1(false), m_bHaveArgOption(false), m_bHaveArgRecurse(false),
128       m_constStrArgNamedAvailable("available"),
129       m_constStrArgNamedRecurse("recurse"), m_constStrArgNamedGroup("group"),
130       m_constStrArgNamedThreadGroup("i1") {
131   // Command factory matches this name with that received from the stdin stream
132   m_strMiCmd = "list-thread-groups";
133
134   // Required by the CMICmdFactory when registering *this command
135   m_pSelfCreatorFn = &CMICmdCmdListThreadGroups::CreateSelf;
136 }
137
138 //++
139 // Details: CMICmdCmdListThreadGroups destructor.
140 // Type:    Overrideable.
141 // Args:    None.
142 // Return:  None.
143 // Throws:  None.
144 //--
145 CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups() {
146   m_vecMIValueTuple.clear();
147 }
148
149 //++
150 // Details: The invoker requires this function. The parses the command line
151 // options
152 //          arguments to extract values for each of those arguments.
153 // Type:    Overridden.
154 // Args:    None.
155 // Return:  MIstatus::success - Functional succeeded.
156 //          MIstatus::failure - Functional failed.
157 // Throws:  None.
158 //--
159 bool CMICmdCmdListThreadGroups::ParseArgs() {
160   m_setCmdArgs.Add(
161       new CMICmdArgValOptionLong(m_constStrArgNamedAvailable, false, true));
162   m_setCmdArgs.Add(
163       new CMICmdArgValOptionLong(m_constStrArgNamedRecurse, false, true,
164                                  CMICmdArgValListBase::eArgValType_Number, 1));
165   m_setCmdArgs.Add(
166       new CMICmdArgValListOfN(m_constStrArgNamedGroup, false, true,
167                               CMICmdArgValListBase::eArgValType_Number));
168   m_setCmdArgs.Add(
169       new CMICmdArgValThreadGrp(m_constStrArgNamedThreadGroup, false, true));
170   return ParseValidateCmdOptions();
171 }
172
173 //++
174 // Details: The invoker requires this function. The command does work in this
175 // function.
176 //          The command is likely to communicate with the LLDB SBDebugger in
177 //          here.
178 //          Synopsis: -list-thread-groups [ --available ] [ --recurse 1 ] [
179 //          group ... ]
180 //          This command does not follow the MI documentation exactly. Has an
181 //          extra
182 //          argument "i1" to handle.
183 //          Ref:
184 // http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands
185 // Type:    Overridden.
186 // Args:    None.
187 // Return:  MIstatus::success - Functional succeeded.
188 //          MIstatus::failure - Functional failed.
189 // Throws:  None.
190 //--
191 bool CMICmdCmdListThreadGroups::Execute() {
192   if (m_setCmdArgs.IsArgContextEmpty())
193     // No options so "top level thread groups"
194     return MIstatus::success;
195
196   CMICMDBASE_GETOPTION(pArgAvailable, OptionLong, m_constStrArgNamedAvailable);
197   CMICMDBASE_GETOPTION(pArgRecurse, OptionLong, m_constStrArgNamedRecurse);
198   CMICMDBASE_GETOPTION(pArgThreadGroup, ThreadGrp,
199                        m_constStrArgNamedThreadGroup);
200
201   // Got some options so "threads"
202   if (pArgAvailable->GetFound()) {
203     if (pArgRecurse->GetFound()) {
204       m_bHaveArgRecurse = true;
205       return MIstatus::success;
206     }
207
208     m_bHaveArgOption = true;
209     return MIstatus::success;
210   }
211   // "i1" as first argument (pos 0 of possible arg)
212   if (!pArgThreadGroup->GetFound())
213     return MIstatus::success;
214   m_bIsI1 = true;
215
216   CMICmnLLDBDebugSessionInfo &rSessionInfo(
217       CMICmnLLDBDebugSessionInfo::Instance());
218   lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
219
220   // Note do not check for sbProcess is IsValid(), continue
221
222   m_vecMIValueTuple.clear();
223   const MIuint nThreads = sbProcess.GetNumThreads();
224   for (MIuint i = 0; i < nThreads; i++) {
225     //  GetThreadAtIndex() uses a base 0 index
226     //  GetThreadByIndexID() uses a base 1 index
227     lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
228
229     if (thread.IsValid()) {
230       CMICmnMIValueTuple miTuple;
231       if (!rSessionInfo.MIResponseFormThreadInfo(
232               m_cmdData, thread,
233               CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_NoFrames, miTuple))
234         return MIstatus::failure;
235
236       m_vecMIValueTuple.push_back(miTuple);
237     }
238   }
239
240   return MIstatus::success;
241 }
242
243 //++
244 // Details: The invoker requires this function. The command prepares a MI Record
245 // Result
246 //          for the work carried out in the Execute().
247 // Type:    Overridden.
248 // Args:    None.
249 // Return:  MIstatus::success - Functional succeeded.
250 //          MIstatus::failure - Functional failed.
251 // Throws:  None.
252 //--
253 bool CMICmdCmdListThreadGroups::Acknowledge() {
254   if (m_bHaveArgOption) {
255     if (m_bHaveArgRecurse) {
256       const CMICmnMIValueConst miValueConst(
257           MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS));
258       const CMICmnMIValueResult miValueResult("msg", miValueConst);
259       const CMICmnMIResultRecord miRecordResult(
260           m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
261           miValueResult);
262       m_miResultRecord = miRecordResult;
263
264       return MIstatus::success;
265     }
266
267     const CMICmnMIValueConst miValueConst1("i1");
268     const CMICmnMIValueResult miValueResult1("id", miValueConst1);
269     CMICmnMIValueTuple miTuple(miValueResult1);
270
271     const CMICmnMIValueConst miValueConst2("process");
272     const CMICmnMIValueResult miValueResult2("type", miValueConst2);
273     miTuple.Add(miValueResult2);
274
275     CMICmnLLDBDebugSessionInfo &rSessionInfo(
276         CMICmnLLDBDebugSessionInfo::Instance());
277     if (rSessionInfo.GetProcess().IsValid()) {
278       const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
279       const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
280       const CMICmnMIValueConst miValueConst3(strPid);
281       const CMICmnMIValueResult miValueResult3("pid", miValueConst3);
282       miTuple.Add(miValueResult3);
283     }
284
285     const CMICmnMIValueConst miValueConst4(
286         MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS));
287     const CMICmnMIValueResult miValueResult4("num_children", miValueConst4);
288     miTuple.Add(miValueResult4);
289
290     const CMICmnMIValueConst miValueConst5(
291         MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS));
292     const CMICmnMIValueResult miValueResult5("cores", miValueConst5);
293     miTuple.Add(miValueResult5);
294
295     const CMICmnMIValueList miValueList(miTuple);
296     const CMICmnMIValueResult miValueResult6("groups", miValueList);
297     const CMICmnMIResultRecord miRecordResult(
298         m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
299         miValueResult6);
300     m_miResultRecord = miRecordResult;
301
302     return MIstatus::success;
303   }
304
305   if (!m_bIsI1) {
306     const CMICmnMIValueConst miValueConst1("i1");
307     const CMICmnMIValueResult miValueResult1("id", miValueConst1);
308     CMICmnMIValueTuple miTuple(miValueResult1);
309
310     const CMICmnMIValueConst miValueConst2("process");
311     const CMICmnMIValueResult miValueResult2("type", miValueConst2);
312     miTuple.Add(miValueResult2);
313
314     CMICmnLLDBDebugSessionInfo &rSessionInfo(
315         CMICmnLLDBDebugSessionInfo::Instance());
316     if (rSessionInfo.GetProcess().IsValid()) {
317       const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
318       const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
319       const CMICmnMIValueConst miValueConst3(strPid);
320       const CMICmnMIValueResult miValueResult3("pid", miValueConst3);
321       miTuple.Add(miValueResult3);
322     }
323
324     if (rSessionInfo.GetTarget().IsValid()) {
325       lldb::SBTarget sbTrgt = rSessionInfo.GetTarget();
326       const char *pDir = sbTrgt.GetExecutable().GetDirectory();
327       const char *pFileName = sbTrgt.GetExecutable().GetFilename();
328       const CMIUtilString strFile(
329           CMIUtilString::Format("%s/%s",
330                                 CMIUtilString::WithNullAsEmpty(pDir),
331                                 CMIUtilString::WithNullAsEmpty(pFileName)));
332       const CMICmnMIValueConst miValueConst4(strFile);
333       const CMICmnMIValueResult miValueResult4("executable", miValueConst4);
334       miTuple.Add(miValueResult4);
335     }
336
337     const CMICmnMIValueList miValueList(miTuple);
338     const CMICmnMIValueResult miValueResult5("groups", miValueList);
339     const CMICmnMIResultRecord miRecordResult(
340         m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
341         miValueResult5);
342     m_miResultRecord = miRecordResult;
343     return MIstatus::success;
344   }
345
346   // Build up a list of thread information from tuples
347   VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin();
348   if (it == m_vecMIValueTuple.end()) {
349     const CMICmnMIValueConst miValueConst("[]");
350     const CMICmnMIValueResult miValueResult("threads", miValueConst);
351     const CMICmnMIResultRecord miRecordResult(
352         m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
353         miValueResult);
354     m_miResultRecord = miRecordResult;
355     return MIstatus::success;
356   }
357   CMICmnMIValueList miValueList(*it);
358   ++it;
359   while (it != m_vecMIValueTuple.end()) {
360     const CMICmnMIValueTuple &rTuple(*it);
361     miValueList.Add(rTuple);
362
363     // Next
364     ++it;
365   }
366
367   const CMICmnMIValueResult miValueResult("threads", miValueList);
368   const CMICmnMIResultRecord miRecordResult(
369       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
370       miValueResult);
371   m_miResultRecord = miRecordResult;
372
373   return MIstatus::success;
374 }
375
376 //++
377 // Details: Required by the CMICmdFactory when registering *this command. The
378 // factory
379 //          calls this function to create an instance of *this command.
380 // Type:    Static method.
381 // Args:    None.
382 // Return:  CMICmdBase * - Pointer to a new command.
383 // Throws:  None.
384 //--
385 CMICmdBase *CMICmdCmdListThreadGroups::CreateSelf() {
386   return new CMICmdCmdListThreadGroups();
387 }
388
389
390 //++
391 // Details: CMICmdCmdInterpreterExec constructor.
392 // Type:    Method.
393 // Args:    None.
394 // Return:  None.
395 // Throws:  None.
396 //--
397 CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec()
398     : m_constStrArgNamedInterpreter("interpreter"),
399       m_constStrArgNamedCommand("command") {
400   // Command factory matches this name with that received from the stdin stream
401   m_strMiCmd = "interpreter-exec";
402
403   // Required by the CMICmdFactory when registering *this command
404   m_pSelfCreatorFn = &CMICmdCmdInterpreterExec::CreateSelf;
405 }
406
407 //++
408 // Details: CMICmdCmdInterpreterExec destructor.
409 // Type:    Overrideable.
410 // Args:    None.
411 // Return:  None.
412 // Throws:  None.
413 //--
414 CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec() {}
415
416 //++
417 // Details: The invoker requires this function. The parses the command line
418 // options
419 //          arguments to extract values for each of those arguments.
420 // Type:    Overridden.
421 // Args:    None.
422 // Return:  MIstatus::success - Functional succeeded.
423 //          MIstatus::failure - Functional failed.
424 // Throws:  None.
425 //--
426 bool CMICmdCmdInterpreterExec::ParseArgs() {
427   m_setCmdArgs.Add(
428       new CMICmdArgValString(m_constStrArgNamedInterpreter, true, true));
429   m_setCmdArgs.Add(
430       new CMICmdArgValString(m_constStrArgNamedCommand, true, true, true));
431   return ParseValidateCmdOptions();
432 }
433
434 //++
435 // Details: The invoker requires this function. The command does work in this
436 // function.
437 //          The command is likely to communicate with the LLDB SBDebugger in
438 //          here.
439 // Type:    Overridden.
440 // Args:    None.
441 // Return:  MIstatus::success - Functional succeeded.
442 //          MIstatus::failure - Functional failed.
443 // Throws:  None.
444 //--
445 bool CMICmdCmdInterpreterExec::Execute() {
446   CMICMDBASE_GETOPTION(pArgInterpreter, String, m_constStrArgNamedInterpreter);
447   CMICMDBASE_GETOPTION(pArgCommand, String, m_constStrArgNamedCommand);
448
449   // Handle the interpreter parameter by do nothing on purpose (set to 'handled'
450   // in the arg definition above)
451   const CMIUtilString &rStrInterpreter(pArgInterpreter->GetValue());
452   MIunused(rStrInterpreter);
453
454   const CMIUtilString &rStrCommand(pArgCommand->GetValue());
455   CMICmnLLDBDebugSessionInfo &rSessionInfo(
456       CMICmnLLDBDebugSessionInfo::Instance());
457   const lldb::ReturnStatus rtn =
458       rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(
459           rStrCommand.c_str(), m_lldbResult, true);
460   MIunused(rtn);
461
462   return MIstatus::success;
463 }
464
465 //++
466 // Details: The invoker requires this function. The command prepares a MI Record
467 // Result
468 //          for the work carried out in the Execute().
469 // Type:    Overridden.
470 // Args:    None.
471 // Return:  MIstatus::success - Functional succeeded.
472 //          MIstatus::failure - Functional failed.
473 // Throws:  None.
474 //--
475 bool CMICmdCmdInterpreterExec::Acknowledge() {
476   if (m_lldbResult.GetOutputSize() > 0) {
477     const CMIUtilString line(m_lldbResult.GetOutput());
478     const bool bEscapeQuotes(true);
479     CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
480     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ConsoleStreamOutput, miValueConst);
481     const bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
482     if (!bOk)
483       return MIstatus::failure;
484   }
485   if (m_lldbResult.GetErrorSize() > 0) {
486     const CMIUtilString line(m_lldbResult.GetError());
487     const bool bEscapeQuotes(true);
488     CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
489     CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_LogStreamOutput, miValueConst);
490     const bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
491     if (!bOk)
492       return MIstatus::failure;
493   }
494
495   const CMICmnMIResultRecord miRecordResult(
496       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
497   m_miResultRecord = miRecordResult;
498
499   return MIstatus::success;
500 }
501
502 //++
503 // Details: Required by the CMICmdFactory when registering *this command. The
504 // factory
505 //          calls this function to create an instance of *this command.
506 // Type:    Static method.
507 // Args:    None.
508 // Return:  CMICmdBase * - Pointer to a new command.
509 // Throws:  None.
510 //--
511 CMICmdBase *CMICmdCmdInterpreterExec::CreateSelf() {
512   return new CMICmdCmdInterpreterExec();
513 }
514
515
516 //++
517 // Details: CMICmdCmdInferiorTtySet constructor.
518 // Type:    Method.
519 // Args:    None.
520 // Return:  None.
521 // Throws:  None.
522 //--
523 CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet() {
524   // Command factory matches this name with that received from the stdin stream
525   m_strMiCmd = "inferior-tty-set";
526
527   // Required by the CMICmdFactory when registering *this command
528   m_pSelfCreatorFn = &CMICmdCmdInferiorTtySet::CreateSelf;
529 }
530
531 //++
532 // Details: CMICmdCmdInferiorTtySet destructor.
533 // Type:    Overrideable.
534 // Args:    None.
535 // Return:  None.
536 // Throws:  None.
537 //--
538 CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet() {}
539
540 //++
541 // Details: The invoker requires this function. The command does work in this
542 // function.
543 //          The command is likely to communicate with the LLDB SBDebugger in
544 //          here.
545 // Type:    Overridden.
546 // Args:    None.
547 // Return:  MIstatus::success - Functional succeeded.
548 //          MIstatus::failure - Functional failed.
549 // Throws:  None.
550 //--
551 bool CMICmdCmdInferiorTtySet::Execute() {
552   // Do nothing
553
554   return MIstatus::success;
555 }
556
557 //++
558 // Details: The invoker requires this function. The command prepares a MI Record
559 // Result
560 //          for the work carried out in the Execute().
561 // Type:    Overridden.
562 // Args:    None.
563 // Return:  MIstatus::success - Functional succeeded.
564 //          MIstatus::failure - Functional failed.
565 // Throws:  None.
566 //--
567 bool CMICmdCmdInferiorTtySet::Acknowledge() {
568   const CMICmnMIResultRecord miRecordResult(
569       m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error);
570   m_miResultRecord = miRecordResult;
571
572   return MIstatus::success;
573 }
574
575 //++
576 // Details: Required by the CMICmdFactory when registering *this command. The
577 // factory
578 //          calls this function to create an instance of *this command.
579 // Type:    Static method.
580 // Args:    None.
581 // Return:  CMICmdBase * - Pointer to a new command.
582 // Throws:  None.
583 //--
584 CMICmdBase *CMICmdCmdInferiorTtySet::CreateSelf() {
585   return new CMICmdCmdInferiorTtySet();
586 }