1 //===-- CommandObjectTarget.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 #include "CommandObjectTarget.h"
11 
12 // C Includes
13 #include <errno.h>
14 #include <sys/errno.h>
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Interpreter/Args.h"
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/Timer.h"
21 #include "lldb/Core/Debugger.h"
22 #include "lldb/Interpreter/CommandInterpreter.h"
23 #include "lldb/Interpreter/CommandReturnObject.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/StackFrame.h"
26 #include "lldb/Target/Thread.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 #pragma mark CommandObjectTargetImageSearchPaths
32 
33 class CommandObjectTargetImageSearchPathsAdd : public CommandObject
34 {
35 public:
36 
37     CommandObjectTargetImageSearchPathsAdd (CommandInterpreter &interpreter) :
38         CommandObject (interpreter,
39                        "target image-search-paths add",
40                        "Add new image search paths substitution pairs to the current target.",
41                        NULL)
42     {
43         CommandArgumentEntry arg;
44         CommandArgumentData old_prefix_arg;
45         CommandArgumentData new_prefix_arg;
46 
47         // Define the first variant of this arg pair.
48         old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
49         old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
50 
51         // Define the first variant of this arg pair.
52         new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
53         new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
54 
55         // There are two required arguments that must always occur together, i.e. an argument "pair".  Because they
56         // must always occur together, they are treated as two variants of one argument rather than two independent
57         // arguments.  Push them both into the first argument position for m_arguments...
58 
59         arg.push_back (old_prefix_arg);
60         arg.push_back (new_prefix_arg);
61 
62         m_arguments.push_back (arg);
63     }
64 
65     ~CommandObjectTargetImageSearchPathsAdd ()
66     {
67     }
68 
69     bool
70     Execute (Args& command,
71              CommandReturnObject &result)
72     {
73         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
74         if (target)
75         {
76             uint32_t argc = command.GetArgumentCount();
77             if (argc & 1)
78             {
79                 result.AppendError ("add requires an even number of arguments");
80                 result.SetStatus (eReturnStatusFailed);
81             }
82             else
83             {
84                 for (uint32_t i=0; i<argc; i+=2)
85                 {
86                     const char *from = command.GetArgumentAtIndex(i);
87                     const char *to = command.GetArgumentAtIndex(i+1);
88 
89                     if (from[0] && to[0])
90                     {
91                         bool last_pair = ((argc - i) == 2);
92                         target->GetImageSearchPathList().Append (ConstString(from),
93                                                                  ConstString(to),
94                                                                  last_pair); // Notify if this is the last pair
95                     }
96                     else
97                     {
98                         if (from[0])
99                             result.AppendError ("<path-prefix> can't be empty");
100                         else
101                             result.AppendError ("<new-path-prefix> can't be empty");
102                         result.SetStatus (eReturnStatusFailed);
103                     }
104                 }
105             }
106         }
107         else
108         {
109             result.AppendError ("invalid target");
110             result.SetStatus (eReturnStatusFailed);
111         }
112         return result.Succeeded();
113     }
114 };
115 
116 class CommandObjectTargetImageSearchPathsClear : public CommandObject
117 {
118 public:
119 
120     CommandObjectTargetImageSearchPathsClear (CommandInterpreter &interpreter) :
121         CommandObject (interpreter,
122                        "target image-search-paths clear",
123                        "Clear all current image search path substitution pairs from the current target.",
124                        "target image-search-paths clear")
125     {
126     }
127 
128     ~CommandObjectTargetImageSearchPathsClear ()
129     {
130     }
131 
132     bool
133     Execute (Args& command,
134              CommandReturnObject &result)
135     {
136         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
137         if (target)
138         {
139             bool notify = true;
140             target->GetImageSearchPathList().Clear(notify);
141         }
142         else
143         {
144             result.AppendError ("invalid target");
145             result.SetStatus (eReturnStatusFailed);
146         }
147         return result.Succeeded();
148     }
149 };
150 
151 class CommandObjectTargetImageSearchPathsInsert : public CommandObject
152 {
153 public:
154 
155     CommandObjectTargetImageSearchPathsInsert (CommandInterpreter &interpreter) :
156         CommandObject (interpreter,
157                        "target image-search-paths insert",
158                        "Insert a new image search path substitution pair into the current target at the specified index.",
159                        NULL)
160     {
161         CommandArgumentEntry arg1;
162         CommandArgumentEntry arg2;
163         CommandArgumentData index_arg;
164         CommandArgumentData old_prefix_arg;
165         CommandArgumentData new_prefix_arg;
166 
167         // Define the first and only variant of this arg.
168         index_arg.arg_type = eArgTypeIndex;
169         index_arg.arg_repetition = eArgRepeatPlain;
170 
171         // Put the one and only variant into the first arg for m_arguments:
172         arg1.push_back (index_arg);
173 
174         // Define the first variant of this arg pair.
175         old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
176         old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
177 
178         // Define the first variant of this arg pair.
179         new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
180         new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
181 
182         // There are two required arguments that must always occur together, i.e. an argument "pair".  Because they
183         // must always occur together, they are treated as two variants of one argument rather than two independent
184         // arguments.  Push them both into the same argument position for m_arguments...
185 
186         arg2.push_back (old_prefix_arg);
187         arg2.push_back (new_prefix_arg);
188 
189         // Add arguments to m_arguments.
190         m_arguments.push_back (arg1);
191         m_arguments.push_back (arg2);
192     }
193 
194     ~CommandObjectTargetImageSearchPathsInsert ()
195     {
196     }
197 
198     bool
199     Execute (Args& command,
200              CommandReturnObject &result)
201     {
202         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
203         if (target)
204         {
205             uint32_t argc = command.GetArgumentCount();
206             // check for at least 3 arguments and an odd nubmer of parameters
207             if (argc >= 3 && argc & 1)
208             {
209                 bool success = false;
210 
211                 uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
212 
213                 if (!success)
214                 {
215                     result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0));
216                     result.SetStatus (eReturnStatusFailed);
217                     return result.Succeeded();
218                 }
219 
220                 // shift off the index
221                 command.Shift();
222                 argc = command.GetArgumentCount();
223 
224                 for (uint32_t i=0; i<argc; i+=2, ++insert_idx)
225                 {
226                     const char *from = command.GetArgumentAtIndex(i);
227                     const char *to = command.GetArgumentAtIndex(i+1);
228 
229                     if (from[0] && to[0])
230                     {
231                         bool last_pair = ((argc - i) == 2);
232                         target->GetImageSearchPathList().Insert (ConstString(from),
233                                                                  ConstString(to),
234                                                                  insert_idx,
235                                                                  last_pair);
236                     }
237                     else
238                     {
239                         if (from[0])
240                             result.AppendError ("<path-prefix> can't be empty");
241                         else
242                             result.AppendError ("<new-path-prefix> can't be empty");
243                         result.SetStatus (eReturnStatusFailed);
244                         return false;
245                     }
246                 }
247             }
248             else
249             {
250                 result.AppendError ("insert requires at least three arguments");
251                 result.SetStatus (eReturnStatusFailed);
252                 return result.Succeeded();
253             }
254 
255         }
256         else
257         {
258             result.AppendError ("invalid target");
259             result.SetStatus (eReturnStatusFailed);
260         }
261         return result.Succeeded();
262     }
263 };
264 
265 class CommandObjectTargetImageSearchPathsList : public CommandObject
266 {
267 public:
268 
269     CommandObjectTargetImageSearchPathsList (CommandInterpreter &interpreter) :
270         CommandObject (interpreter,
271                        "target image-search-paths list",
272                        "List all current image search path substitution pairs in the current target.",
273                        "target image-search-paths list")
274     {
275     }
276 
277     ~CommandObjectTargetImageSearchPathsList ()
278     {
279     }
280 
281     bool
282     Execute (Args& command,
283              CommandReturnObject &result)
284     {
285         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
286         if (target)
287         {
288             if (command.GetArgumentCount() != 0)
289             {
290                 result.AppendError ("list takes no arguments");
291                 result.SetStatus (eReturnStatusFailed);
292                 return result.Succeeded();
293             }
294 
295             target->GetImageSearchPathList().Dump(&result.GetOutputStream());
296         }
297         else
298         {
299             result.AppendError ("invalid target");
300             result.SetStatus (eReturnStatusFailed);
301         }
302         return result.Succeeded();
303     }
304 };
305 
306 class CommandObjectTargetImageSearchPathsQuery : public CommandObject
307 {
308 public:
309 
310     CommandObjectTargetImageSearchPathsQuery (CommandInterpreter &interpreter) :
311     CommandObject (interpreter,
312                    "target image-search-paths query",
313                    "Transform a path using the first applicable image search path.",
314                    NULL)
315     {
316         CommandArgumentEntry arg;
317         CommandArgumentData path_arg;
318 
319         // Define the first (and only) variant of this arg.
320         path_arg.arg_type = eArgTypePath;
321         path_arg.arg_repetition = eArgRepeatPlain;
322 
323         // There is only one variant this argument could be; put it into the argument entry.
324         arg.push_back (path_arg);
325 
326         // Push the data for the first argument into the m_arguments vector.
327         m_arguments.push_back (arg);
328     }
329 
330     ~CommandObjectTargetImageSearchPathsQuery ()
331     {
332     }
333 
334     bool
335     Execute (Args& command,
336              CommandReturnObject &result)
337     {
338         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
339         if (target)
340         {
341             if (command.GetArgumentCount() != 1)
342             {
343                 result.AppendError ("query requires one argument");
344                 result.SetStatus (eReturnStatusFailed);
345                 return result.Succeeded();
346             }
347 
348             ConstString orig(command.GetArgumentAtIndex(0));
349             ConstString transformed;
350             if (target->GetImageSearchPathList().RemapPath(orig, transformed))
351                 result.GetOutputStream().Printf("%s\n", transformed.GetCString());
352             else
353                 result.GetOutputStream().Printf("%s\n", orig.GetCString());
354         }
355         else
356         {
357             result.AppendError ("invalid target");
358             result.SetStatus (eReturnStatusFailed);
359         }
360         return result.Succeeded();
361     }
362 };
363 
364 // TODO: implement the target select later when we start doing multiple targets
365 //#pragma mark CommandObjectTargetSelect
366 //
367 ////-------------------------------------------------------------------------
368 //// CommandObjectTargetSelect
369 ////-------------------------------------------------------------------------
370 //
371 //class CommandObjectTargetSelect : public CommandObject
372 //{
373 //public:
374 //
375 //    CommandObjectTargetSelect () :
376 //    CommandObject (interpreter,
377 //                   frame select",
378 //                   "Select the current frame by index in the current thread.",
379 //                   "frame select <frame-index>")
380 //    {
381 //    }
382 //
383 //    ~CommandObjectTargetSelect ()
384 //    {
385 //    }
386 //
387 //    bool
388 //    Execute (Args& command,
389 //             Debugger *context,
390 //             CommandInterpreter &m_interpreter,
391 //             CommandReturnObject &result)
392 //    {
393 //        ExecutionContext exe_ctx (context->GetExecutionContext());
394 //        if (exe_ctx.thread)
395 //        {
396 //            if (command.GetArgumentCount() == 1)
397 //            {
398 //                const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
399 //
400 //                const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
401 //                const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
402 //                if (frame_idx < num_frames)
403 //                {
404 //                    exe_ctx.thread->SetSelectedFrameByIndex (frame_idx);
405 //                    exe_ctx.frame = exe_ctx.thread->GetSelectedFrame ().get();
406 //
407 //                    if (exe_ctx.frame)
408 //                    {
409 //                        if (DisplayFrameForExecutionContext (exe_ctx.thread,
410 //                                                             exe_ctx.frame,
411 //                                                             m_interpreter,
412 //                                                             result.GetOutputStream(),
413 //                                                             true,
414 //                                                             true,
415 //                                                             3,
416 //                                                             3))
417 //                        {
418 //                            result.SetStatus (eReturnStatusSuccessFinishResult);
419 //                            return result.Succeeded();
420 //                        }
421 //                    }
422 //                }
423 //                if (frame_idx == UINT32_MAX)
424 //                    result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
425 //                else
426 //                    result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
427 //            }
428 //            else
429 //            {
430 //                result.AppendError ("invalid arguments");
431 //                result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
432 //            }
433 //        }
434 //        else
435 //        {
436 //            result.AppendError ("no current thread");
437 //        }
438 //        result.SetStatus (eReturnStatusFailed);
439 //        return false;
440 //    }
441 //};
442 
443 
444 #pragma mark CommandObjectMultiwordTarget
445 
446 //-------------------------------------------------------------------------
447 // CommandObjectMultiwordImageSearchPaths
448 //-------------------------------------------------------------------------
449 
450 class CommandObjectMultiwordImageSearchPaths : public CommandObjectMultiword
451 {
452 public:
453 
454     CommandObjectMultiwordImageSearchPaths (CommandInterpreter &interpreter) :
455         CommandObjectMultiword (interpreter,
456                                 "target image-search-paths",
457                                 "A set of commands for operating on debugger target image search paths.",
458                                 "target image-search-paths <subcommand> [<subcommand-options>]")
459     {
460         LoadSubCommand ("add",     CommandObjectSP (new CommandObjectTargetImageSearchPathsAdd (interpreter)));
461         LoadSubCommand ("clear",   CommandObjectSP (new CommandObjectTargetImageSearchPathsClear (interpreter)));
462         LoadSubCommand ("insert",  CommandObjectSP (new CommandObjectTargetImageSearchPathsInsert (interpreter)));
463         LoadSubCommand ("list",    CommandObjectSP (new CommandObjectTargetImageSearchPathsList (interpreter)));
464         LoadSubCommand ("query",   CommandObjectSP (new CommandObjectTargetImageSearchPathsQuery (interpreter)));
465     }
466 
467     ~CommandObjectMultiwordImageSearchPaths()
468     {
469     }
470 };
471 
472 
473 #pragma mark CommandObjectMultiwordTarget
474 
475 //-------------------------------------------------------------------------
476 // CommandObjectMultiwordTarget
477 //-------------------------------------------------------------------------
478 
479 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter &interpreter) :
480     CommandObjectMultiword (interpreter,
481                             "target",
482                             "A set of commands for operating on debugger targets.",
483                             "target <subcommand> [<subcommand-options>]")
484 {
485     LoadSubCommand ("image-search-paths", CommandObjectSP (new CommandObjectMultiwordImageSearchPaths (interpreter)));
486 }
487 
488 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget ()
489 {
490 }
491 
492