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/Core/Args.h"
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/Timer.h"
21 #include "lldb/Interpreter/CommandContext.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 () :
38         CommandObject ("target image-search-paths add",
39                        "Add new image search paths substitution pairs to the current target.",
40                        "target image-search-paths add <path-prefix> <new-path-prefix> [<path-prefix> <new-path-prefix>] ...")
41     {
42     }
43 
44     ~CommandObjectTargetImageSearchPathsAdd ()
45     {
46     }
47 
48     bool
49     Execute (Args& command,
50              CommandContext *context,
51              CommandInterpreter *interpreter,
52              CommandReturnObject &result)
53     {
54         Target * target = context->GetTarget();
55         if (target)
56         {
57             uint32_t argc = command.GetArgumentCount();
58             if (argc & 1)
59             {
60                 result.AppendError ("add requires an even number of arguments");
61                 result.SetStatus (eReturnStatusFailed);
62             }
63             else
64             {
65                 for (uint32_t i=0; i<argc; i+=2)
66                 {
67                     const char *from = command.GetArgumentAtIndex(i);
68                     const char *to = command.GetArgumentAtIndex(i+1);
69 
70                     if (from[0] && to[0])
71                     {
72                         bool last_pair = ((argc - i) == 2);
73                         target->GetImageSearchPathList().Append(ConstString(from),
74                                                                 ConstString(to),
75                                                                 last_pair); // Notify if this is the last pair
76                     }
77                     else
78                     {
79                         if (from[0])
80                             result.AppendError ("<path-prefix> can't be empty");
81                         else
82                             result.AppendError ("<new-path-prefix> can't be empty");
83                         result.SetStatus (eReturnStatusFailed);
84                     }
85                 }
86             }
87         }
88         else
89         {
90             result.AppendError ("invalid target");
91             result.SetStatus (eReturnStatusFailed);
92         }
93         return result.Succeeded();
94     }
95 };
96 
97 class CommandObjectTargetImageSearchPathsClear : public CommandObject
98 {
99 public:
100 
101     CommandObjectTargetImageSearchPathsClear () :
102         CommandObject ("target image-search-paths clear",
103                        "Clears all current image search paths substitution pairs from the current target.",
104                        "target image-search-paths clear")
105     {
106     }
107 
108     ~CommandObjectTargetImageSearchPathsClear ()
109     {
110     }
111 
112     bool
113     Execute (Args& command,
114              CommandContext *context,
115              CommandInterpreter *interpreter,
116              CommandReturnObject &result)
117     {
118         Target * target = context->GetTarget();
119         if (target)
120         {
121             bool notify = true;
122             target->GetImageSearchPathList().Clear(notify);
123         }
124         else
125         {
126             result.AppendError ("invalid target");
127             result.SetStatus (eReturnStatusFailed);
128         }
129         return result.Succeeded();
130     }
131 };
132 
133 class CommandObjectTargetImageSearchPathsInsert : public CommandObject
134 {
135 public:
136 
137     CommandObjectTargetImageSearchPathsInsert () :
138         CommandObject ("target image-search-paths insert",
139                        "Inserts a new image search paths substitution pair to the current target at the specified index.",
140                        "target image-search-paths insert <index> <path-prefix> <new-path-prefix> [<path-prefix> <new-path-prefix>] ...")
141     {
142     }
143 
144     ~CommandObjectTargetImageSearchPathsInsert ()
145     {
146     }
147 
148     bool
149     Execute (Args& command,
150              CommandContext *context,
151              CommandInterpreter *interpreter,
152              CommandReturnObject &result)
153     {
154         Target * target = context->GetTarget();
155         if (target)
156         {
157             uint32_t argc = command.GetArgumentCount();
158             // check for at least 3 arguments and an odd nubmer of parameters
159             if (argc >= 3 && argc & 1)
160             {
161                 bool success = false;
162 
163                 uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
164 
165                 if (!success)
166                 {
167                     result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0));
168                     result.SetStatus (eReturnStatusFailed);
169                     return result.Succeeded();
170                 }
171 
172                 // shift off the index
173                 command.Shift();
174                 argc = command.GetArgumentCount();
175 
176                 for (uint32_t i=0; i<argc; i+=2, ++insert_idx)
177                 {
178                     const char *from = command.GetArgumentAtIndex(i);
179                     const char *to = command.GetArgumentAtIndex(i+1);
180 
181                     if (from[0] && to[0])
182                     {
183                         bool last_pair = ((argc - i) == 2);
184                         target->GetImageSearchPathList().Insert (ConstString(from),
185                                                                  ConstString(to),
186                                                                  insert_idx,
187                                                                  last_pair);
188                     }
189                     else
190                     {
191                         if (from[0])
192                             result.AppendError ("<path-prefix> can't be empty");
193                         else
194                             result.AppendError ("<new-path-prefix> can't be empty");
195                         result.SetStatus (eReturnStatusFailed);
196                         return false;
197                     }
198                 }
199             }
200             else
201             {
202                 result.AppendError ("insert requires at least three arguments");
203                 result.SetStatus (eReturnStatusFailed);
204                 return result.Succeeded();
205             }
206 
207         }
208         else
209         {
210             result.AppendError ("invalid target");
211             result.SetStatus (eReturnStatusFailed);
212         }
213         return result.Succeeded();
214     }
215 };
216 
217 class CommandObjectTargetImageSearchPathsList : public CommandObject
218 {
219 public:
220 
221     CommandObjectTargetImageSearchPathsList () :
222         CommandObject ("target image-search-paths list",
223                        "Lists all current image search paths substitution pairs in the current target.",
224                        "target image-search-paths list")
225     {
226     }
227 
228     ~CommandObjectTargetImageSearchPathsList ()
229     {
230     }
231 
232     bool
233     Execute (Args& command,
234              CommandContext *context,
235              CommandInterpreter *interpreter,
236              CommandReturnObject &result)
237     {
238         Target * target = context->GetTarget();
239         if (target)
240         {
241             if (command.GetArgumentCount() != 0)
242             {
243                 result.AppendError ("list takes no arguments");
244                 result.SetStatus (eReturnStatusFailed);
245                 return result.Succeeded();
246             }
247 
248             target->GetImageSearchPathList().Dump(&result.GetOutputStream());
249         }
250         else
251         {
252             result.AppendError ("invalid target");
253             result.SetStatus (eReturnStatusFailed);
254         }
255         return result.Succeeded();
256     }
257 };
258 
259 class CommandObjectTargetImageSearchPathsQuery : public CommandObject
260 {
261 public:
262 
263     CommandObjectTargetImageSearchPathsQuery () :
264     CommandObject ("target image-search-paths query",
265                    "Transforms a path using the first applicable image search path.",
266                    "target image-search-paths query <path>")
267     {
268     }
269 
270     ~CommandObjectTargetImageSearchPathsQuery ()
271     {
272     }
273 
274     bool
275     Execute (Args& command,
276              CommandContext *context,
277              CommandInterpreter *interpreter,
278              CommandReturnObject &result)
279     {
280         Target * target = context->GetTarget();
281         if (target)
282         {
283             if (command.GetArgumentCount() != 1)
284             {
285                 result.AppendError ("query requires one argument");
286                 result.SetStatus (eReturnStatusFailed);
287                 return result.Succeeded();
288             }
289 
290             ConstString orig(command.GetArgumentAtIndex(0));
291             ConstString transformed;
292             if (target->GetImageSearchPathList().RemapPath(orig, transformed))
293                 result.GetOutputStream().Printf("%s\n", transformed.GetCString());
294             else
295                 result.GetOutputStream().Printf("%s\n", orig.GetCString());
296         }
297         else
298         {
299             result.AppendError ("invalid target");
300             result.SetStatus (eReturnStatusFailed);
301         }
302         return result.Succeeded();
303     }
304 };
305 
306 // TODO: implement the target select later when we start doing multiple targets
307 //#pragma mark CommandObjectTargetSelect
308 //
309 ////-------------------------------------------------------------------------
310 //// CommandObjectTargetSelect
311 ////-------------------------------------------------------------------------
312 //
313 //class CommandObjectTargetSelect : public CommandObject
314 //{
315 //public:
316 //
317 //    CommandObjectTargetSelect () :
318 //    CommandObject ("frame select",
319 //                   "Select the current frame by index in the current thread.",
320 //                   "frame select <frame-index>")
321 //    {
322 //    }
323 //
324 //    ~CommandObjectTargetSelect ()
325 //    {
326 //    }
327 //
328 //    bool
329 //    Execute (Args& command,
330 //             CommandContext *context,
331 //             CommandInterpreter *interpreter,
332 //             CommandReturnObject &result)
333 //    {
334 //        ExecutionContext exe_ctx (context->GetExecutionContext());
335 //        if (exe_ctx.thread)
336 //        {
337 //            if (command.GetArgumentCount() == 1)
338 //            {
339 //                const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
340 //
341 //                const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
342 //                const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
343 //                if (frame_idx < num_frames)
344 //                {
345 //                    exe_ctx.thread->SetCurrentFrameByIndex (frame_idx);
346 //                    exe_ctx.frame = exe_ctx.thread->GetCurrentFrame ().get();
347 //
348 //                    if (exe_ctx.frame)
349 //                    {
350 //                        if (DisplayFrameForExecutionContext (exe_ctx.thread,
351 //                                                             exe_ctx.frame,
352 //                                                             interpreter,
353 //                                                             result.GetOutputStream(),
354 //                                                             true,
355 //                                                             true,
356 //                                                             3,
357 //                                                             3))
358 //                        {
359 //                            result.SetStatus (eReturnStatusSuccessFinishResult);
360 //                            return result.Succeeded();
361 //                        }
362 //                    }
363 //                }
364 //                if (frame_idx == UINT32_MAX)
365 //                    result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
366 //                else
367 //                    result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
368 //            }
369 //            else
370 //            {
371 //                result.AppendError ("invalid arguments");
372 //                result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
373 //            }
374 //        }
375 //        else
376 //        {
377 //            result.AppendError ("no current thread");
378 //        }
379 //        result.SetStatus (eReturnStatusFailed);
380 //        return false;
381 //    }
382 //};
383 
384 
385 #pragma mark CommandObjectMultiwordTarget
386 
387 //-------------------------------------------------------------------------
388 // CommandObjectMultiwordImageSearchPaths
389 //-------------------------------------------------------------------------
390 
391 class CommandObjectMultiwordImageSearchPaths : public CommandObjectMultiword
392 {
393 public:
394 
395     CommandObjectMultiwordImageSearchPaths (CommandInterpreter *interpreter) :
396         CommandObjectMultiword ("target image-search-paths",
397                                 "A set of commands for operating on debugger target image search paths.",
398                                 "target image-search-paths <subcommand> [<subcommand-options>]")
399     {
400         LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsAdd ()), "add", interpreter);
401         LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsClear ()), "clear", interpreter);
402         LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsInsert ()), "insert", interpreter);
403         LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsList ()), "list", interpreter);
404         LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsQuery ()), "query", interpreter);
405     }
406 
407     ~CommandObjectMultiwordImageSearchPaths()
408     {
409     }
410 };
411 
412 
413 #pragma mark CommandObjectMultiwordTarget
414 
415 //-------------------------------------------------------------------------
416 // CommandObjectMultiwordTarget
417 //-------------------------------------------------------------------------
418 
419 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter *interpreter) :
420     CommandObjectMultiword ("target",
421                             "A set of commands for operating on debugger targets.",
422                             "target <subcommand> [<subcommand-options>]")
423 {
424     LoadSubCommand (CommandObjectSP (new CommandObjectMultiwordImageSearchPaths (interpreter)), "image-search-paths", interpreter);
425 }
426 
427 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget ()
428 {
429 }
430 
431