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