blob: 768662078294856b09ffe8432de121cc8e2f44f1 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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>
Greg Clayton81040f42011-02-01 01:13:32 +000014
Chris Lattner24943d22010-06-08 16:52:24 +000015// C++ Includes
16// Other libraries and framework includes
17// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000018#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/Debugger.h"
Jim Inghamd60d94a2011-03-11 03:53:59 +000020#include "lldb/Core/InputReader.h"
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "lldb/Core/Timer.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#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"
Jim Inghamd60d94a2011-03-11 03:53:59 +000027#include "lldb/Target/ThreadSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000028
29using namespace lldb;
30using namespace lldb_private;
31
32#pragma mark CommandObjectTargetImageSearchPaths
33
34class CommandObjectTargetImageSearchPathsAdd : public CommandObject
35{
36public:
37
Greg Clayton238c0a12010-09-18 01:14:36 +000038 CommandObjectTargetImageSearchPathsAdd (CommandInterpreter &interpreter) :
39 CommandObject (interpreter,
40 "target image-search-paths add",
Chris Lattner24943d22010-06-08 16:52:24 +000041 "Add new image search paths substitution pairs to the current target.",
Caroline Tice43b014a2010-10-04 22:28:36 +000042 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +000043 {
Caroline Tice43b014a2010-10-04 22:28:36 +000044 CommandArgumentEntry arg;
45 CommandArgumentData old_prefix_arg;
46 CommandArgumentData new_prefix_arg;
47
48 // Define the first variant of this arg pair.
49 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
50 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
51
52 // Define the first variant of this arg pair.
53 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
54 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
55
56 // There are two required arguments that must always occur together, i.e. an argument "pair". Because they
57 // must always occur together, they are treated as two variants of one argument rather than two independent
58 // arguments. Push them both into the first argument position for m_arguments...
59
60 arg.push_back (old_prefix_arg);
61 arg.push_back (new_prefix_arg);
62
63 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +000064 }
65
66 ~CommandObjectTargetImageSearchPathsAdd ()
67 {
68 }
69
70 bool
Greg Clayton238c0a12010-09-18 01:14:36 +000071 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +000072 CommandReturnObject &result)
73 {
Greg Clayton238c0a12010-09-18 01:14:36 +000074 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +000075 if (target)
76 {
77 uint32_t argc = command.GetArgumentCount();
78 if (argc & 1)
79 {
80 result.AppendError ("add requires an even number of arguments");
81 result.SetStatus (eReturnStatusFailed);
82 }
83 else
84 {
85 for (uint32_t i=0; i<argc; i+=2)
86 {
87 const char *from = command.GetArgumentAtIndex(i);
88 const char *to = command.GetArgumentAtIndex(i+1);
89
90 if (from[0] && to[0])
91 {
92 bool last_pair = ((argc - i) == 2);
Greg Clayton63094e02010-06-23 01:19:29 +000093 target->GetImageSearchPathList().Append (ConstString(from),
94 ConstString(to),
95 last_pair); // Notify if this is the last pair
Johnny Chen4d661352011-02-03 00:30:19 +000096 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +000097 }
98 else
99 {
100 if (from[0])
101 result.AppendError ("<path-prefix> can't be empty");
102 else
103 result.AppendError ("<new-path-prefix> can't be empty");
104 result.SetStatus (eReturnStatusFailed);
105 }
106 }
107 }
108 }
109 else
110 {
111 result.AppendError ("invalid target");
112 result.SetStatus (eReturnStatusFailed);
113 }
114 return result.Succeeded();
115 }
116};
117
118class CommandObjectTargetImageSearchPathsClear : public CommandObject
119{
120public:
121
Greg Clayton238c0a12010-09-18 01:14:36 +0000122 CommandObjectTargetImageSearchPathsClear (CommandInterpreter &interpreter) :
123 CommandObject (interpreter,
124 "target image-search-paths clear",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000125 "Clear all current image search path substitution pairs from the current target.",
Chris Lattner24943d22010-06-08 16:52:24 +0000126 "target image-search-paths clear")
127 {
128 }
129
130 ~CommandObjectTargetImageSearchPathsClear ()
131 {
132 }
133
134 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000135 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000136 CommandReturnObject &result)
137 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000138 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000139 if (target)
140 {
141 bool notify = true;
142 target->GetImageSearchPathList().Clear(notify);
Johnny Chen4d661352011-02-03 00:30:19 +0000143 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000144 }
145 else
146 {
147 result.AppendError ("invalid target");
148 result.SetStatus (eReturnStatusFailed);
149 }
150 return result.Succeeded();
151 }
152};
153
154class CommandObjectTargetImageSearchPathsInsert : public CommandObject
155{
156public:
157
Greg Clayton238c0a12010-09-18 01:14:36 +0000158 CommandObjectTargetImageSearchPathsInsert (CommandInterpreter &interpreter) :
159 CommandObject (interpreter,
160 "target image-search-paths insert",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000161 "Insert a new image search path substitution pair into the current target at the specified index.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000162 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000163 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000164 CommandArgumentEntry arg1;
165 CommandArgumentEntry arg2;
166 CommandArgumentData index_arg;
167 CommandArgumentData old_prefix_arg;
168 CommandArgumentData new_prefix_arg;
169
170 // Define the first and only variant of this arg.
171 index_arg.arg_type = eArgTypeIndex;
172 index_arg.arg_repetition = eArgRepeatPlain;
173
174 // Put the one and only variant into the first arg for m_arguments:
175 arg1.push_back (index_arg);
176
177 // Define the first variant of this arg pair.
178 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
179 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
180
181 // Define the first variant of this arg pair.
182 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
183 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
184
185 // There are two required arguments that must always occur together, i.e. an argument "pair". Because they
186 // must always occur together, they are treated as two variants of one argument rather than two independent
187 // arguments. Push them both into the same argument position for m_arguments...
188
189 arg2.push_back (old_prefix_arg);
190 arg2.push_back (new_prefix_arg);
191
192 // Add arguments to m_arguments.
193 m_arguments.push_back (arg1);
194 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000195 }
196
197 ~CommandObjectTargetImageSearchPathsInsert ()
198 {
199 }
200
201 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000202 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000203 CommandReturnObject &result)
204 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000205 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000206 if (target)
207 {
208 uint32_t argc = command.GetArgumentCount();
209 // check for at least 3 arguments and an odd nubmer of parameters
210 if (argc >= 3 && argc & 1)
211 {
212 bool success = false;
213
214 uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
215
216 if (!success)
217 {
218 result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0));
219 result.SetStatus (eReturnStatusFailed);
220 return result.Succeeded();
221 }
222
223 // shift off the index
224 command.Shift();
225 argc = command.GetArgumentCount();
226
227 for (uint32_t i=0; i<argc; i+=2, ++insert_idx)
228 {
229 const char *from = command.GetArgumentAtIndex(i);
230 const char *to = command.GetArgumentAtIndex(i+1);
231
232 if (from[0] && to[0])
233 {
234 bool last_pair = ((argc - i) == 2);
235 target->GetImageSearchPathList().Insert (ConstString(from),
236 ConstString(to),
237 insert_idx,
238 last_pair);
Johnny Chen4d661352011-02-03 00:30:19 +0000239 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000240 }
241 else
242 {
243 if (from[0])
244 result.AppendError ("<path-prefix> can't be empty");
245 else
246 result.AppendError ("<new-path-prefix> can't be empty");
247 result.SetStatus (eReturnStatusFailed);
248 return false;
249 }
250 }
251 }
252 else
253 {
254 result.AppendError ("insert requires at least three arguments");
255 result.SetStatus (eReturnStatusFailed);
256 return result.Succeeded();
257 }
258
259 }
260 else
261 {
262 result.AppendError ("invalid target");
263 result.SetStatus (eReturnStatusFailed);
264 }
265 return result.Succeeded();
266 }
267};
268
269class CommandObjectTargetImageSearchPathsList : public CommandObject
270{
271public:
272
Greg Clayton238c0a12010-09-18 01:14:36 +0000273 CommandObjectTargetImageSearchPathsList (CommandInterpreter &interpreter) :
274 CommandObject (interpreter,
275 "target image-search-paths list",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000276 "List all current image search path substitution pairs in the current target.",
Chris Lattner24943d22010-06-08 16:52:24 +0000277 "target image-search-paths list")
278 {
279 }
280
281 ~CommandObjectTargetImageSearchPathsList ()
282 {
283 }
284
285 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000286 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000287 CommandReturnObject &result)
288 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000289 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000290 if (target)
291 {
292 if (command.GetArgumentCount() != 0)
293 {
294 result.AppendError ("list takes no arguments");
295 result.SetStatus (eReturnStatusFailed);
296 return result.Succeeded();
297 }
298
299 target->GetImageSearchPathList().Dump(&result.GetOutputStream());
Johnny Chen4d661352011-02-03 00:30:19 +0000300 result.SetStatus (eReturnStatusSuccessFinishResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000301 }
302 else
303 {
304 result.AppendError ("invalid target");
305 result.SetStatus (eReturnStatusFailed);
306 }
307 return result.Succeeded();
308 }
309};
310
311class CommandObjectTargetImageSearchPathsQuery : public CommandObject
312{
313public:
314
Greg Clayton238c0a12010-09-18 01:14:36 +0000315 CommandObjectTargetImageSearchPathsQuery (CommandInterpreter &interpreter) :
316 CommandObject (interpreter,
317 "target image-search-paths query",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000318 "Transform a path using the first applicable image search path.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000319 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000320 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000321 CommandArgumentEntry arg;
322 CommandArgumentData path_arg;
323
324 // Define the first (and only) variant of this arg.
325 path_arg.arg_type = eArgTypePath;
326 path_arg.arg_repetition = eArgRepeatPlain;
327
328 // There is only one variant this argument could be; put it into the argument entry.
329 arg.push_back (path_arg);
330
331 // Push the data for the first argument into the m_arguments vector.
332 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000333 }
334
335 ~CommandObjectTargetImageSearchPathsQuery ()
336 {
337 }
338
339 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000340 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000341 CommandReturnObject &result)
342 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000343 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000344 if (target)
345 {
346 if (command.GetArgumentCount() != 1)
347 {
348 result.AppendError ("query requires one argument");
349 result.SetStatus (eReturnStatusFailed);
350 return result.Succeeded();
351 }
352
353 ConstString orig(command.GetArgumentAtIndex(0));
354 ConstString transformed;
355 if (target->GetImageSearchPathList().RemapPath(orig, transformed))
356 result.GetOutputStream().Printf("%s\n", transformed.GetCString());
357 else
358 result.GetOutputStream().Printf("%s\n", orig.GetCString());
Johnny Chen4d661352011-02-03 00:30:19 +0000359
360 result.SetStatus (eReturnStatusSuccessFinishResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000361 }
362 else
363 {
364 result.AppendError ("invalid target");
365 result.SetStatus (eReturnStatusFailed);
366 }
367 return result.Succeeded();
368 }
369};
370
371// TODO: implement the target select later when we start doing multiple targets
372//#pragma mark CommandObjectTargetSelect
373//
374////-------------------------------------------------------------------------
375//// CommandObjectTargetSelect
376////-------------------------------------------------------------------------
377//
378//class CommandObjectTargetSelect : public CommandObject
379//{
380//public:
381//
382// CommandObjectTargetSelect () :
Greg Clayton238c0a12010-09-18 01:14:36 +0000383// CommandObject (interpreter,
384// frame select",
Chris Lattner24943d22010-06-08 16:52:24 +0000385// "Select the current frame by index in the current thread.",
386// "frame select <frame-index>")
387// {
388// }
389//
390// ~CommandObjectTargetSelect ()
391// {
392// }
393//
394// bool
395// Execute (Args& command,
Greg Clayton63094e02010-06-23 01:19:29 +0000396// Debugger *context,
Greg Clayton238c0a12010-09-18 01:14:36 +0000397// CommandInterpreter &m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000398// CommandReturnObject &result)
399// {
400// ExecutionContext exe_ctx (context->GetExecutionContext());
401// if (exe_ctx.thread)
402// {
403// if (command.GetArgumentCount() == 1)
404// {
405// const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
406//
407// const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
408// const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
409// if (frame_idx < num_frames)
410// {
Jim Inghamc8332952010-08-26 21:32:51 +0000411// exe_ctx.thread->SetSelectedFrameByIndex (frame_idx);
412// exe_ctx.frame = exe_ctx.thread->GetSelectedFrame ().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000413//
414// if (exe_ctx.frame)
415// {
416// if (DisplayFrameForExecutionContext (exe_ctx.thread,
417// exe_ctx.frame,
Greg Clayton238c0a12010-09-18 01:14:36 +0000418// m_interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000419// result.GetOutputStream(),
420// true,
421// true,
422// 3,
423// 3))
424// {
425// result.SetStatus (eReturnStatusSuccessFinishResult);
426// return result.Succeeded();
427// }
428// }
429// }
430// if (frame_idx == UINT32_MAX)
431// result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
432// else
433// result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
434// }
435// else
436// {
437// result.AppendError ("invalid arguments");
438// result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
439// }
440// }
441// else
442// {
443// result.AppendError ("no current thread");
444// }
445// result.SetStatus (eReturnStatusFailed);
446// return false;
447// }
448//};
449
450
Jim Inghamd60d94a2011-03-11 03:53:59 +0000451#pragma mark CommandObjectMultiwordImageSearchPaths
Chris Lattner24943d22010-06-08 16:52:24 +0000452
453//-------------------------------------------------------------------------
454// CommandObjectMultiwordImageSearchPaths
455//-------------------------------------------------------------------------
456
457class CommandObjectMultiwordImageSearchPaths : public CommandObjectMultiword
458{
459public:
460
Greg Clayton63094e02010-06-23 01:19:29 +0000461 CommandObjectMultiwordImageSearchPaths (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000462 CommandObjectMultiword (interpreter,
463 "target image-search-paths",
Chris Lattner24943d22010-06-08 16:52:24 +0000464 "A set of commands for operating on debugger target image search paths.",
465 "target image-search-paths <subcommand> [<subcommand-options>]")
466 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000467 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetImageSearchPathsAdd (interpreter)));
468 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTargetImageSearchPathsClear (interpreter)));
469 LoadSubCommand ("insert", CommandObjectSP (new CommandObjectTargetImageSearchPathsInsert (interpreter)));
470 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetImageSearchPathsList (interpreter)));
471 LoadSubCommand ("query", CommandObjectSP (new CommandObjectTargetImageSearchPathsQuery (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +0000472 }
473
474 ~CommandObjectMultiwordImageSearchPaths()
475 {
476 }
477};
478
Jim Inghamd60d94a2011-03-11 03:53:59 +0000479#pragma mark CommandObjectTargetStopHookAdd
480
481//-------------------------------------------------------------------------
482// CommandObjectTargetStopHookAdd
483//-------------------------------------------------------------------------
484
485class CommandObjectTargetStopHookAdd : public CommandObject
486{
487public:
488
489 class CommandOptions : public Options
490 {
491 public:
Greg Claytonf15996e2011-04-07 22:46:35 +0000492 CommandOptions (CommandInterpreter &interpreter) :
493 Options(interpreter),
Jim Inghamd60d94a2011-03-11 03:53:59 +0000494 m_line_start(0),
495 m_line_end (UINT_MAX),
496 m_func_name_type_mask (eFunctionNameTypeAuto),
497 m_sym_ctx_specified (false),
498 m_thread_specified (false)
499 {
500 }
501
502 ~CommandOptions () {}
503
Greg Claytonb3448432011-03-24 21:19:54 +0000504 const OptionDefinition*
Jim Inghamd60d94a2011-03-11 03:53:59 +0000505 GetDefinitions ()
506 {
507 return g_option_table;
508 }
509
510 virtual Error
511 SetOptionValue (int option_idx, const char *option_arg)
512 {
513 Error error;
514 char short_option = (char) m_getopt_table[option_idx].val;
515 bool success;
516
517 switch (short_option)
518 {
519 case 'c':
520 m_class_name = option_arg;
521 m_sym_ctx_specified = true;
522 break;
523
524 case 'e':
525 m_line_end = Args::StringToUInt32 (option_arg, UINT_MAX, 0, &success);
526 if (!success)
527 {
528 error.SetErrorStringWithFormat ("Invalid end line number: \"%s\".", option_arg);
529 break;
530 }
531 m_sym_ctx_specified = true;
532 break;
533
534 case 'l':
535 m_line_start = Args::StringToUInt32 (option_arg, 0, 0, &success);
536 if (!success)
537 {
538 error.SetErrorStringWithFormat ("Invalid start line number: \"%s\".", option_arg);
539 break;
540 }
541 m_sym_ctx_specified = true;
542 break;
543
544 case 'n':
545 m_function_name = option_arg;
546 m_func_name_type_mask |= eFunctionNameTypeAuto;
547 m_sym_ctx_specified = true;
548 break;
549
550 case 'f':
551 m_file_name = option_arg;
552 m_sym_ctx_specified = true;
553 break;
554 case 's':
555 m_module_name = option_arg;
556 m_sym_ctx_specified = true;
557 break;
558 case 't' :
559 {
Jim Ingham7a4c8ea2011-03-22 01:53:33 +0000560 m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
Jim Inghamd60d94a2011-03-11 03:53:59 +0000561 if (m_thread_id == LLDB_INVALID_THREAD_ID)
Jim Ingham7a4c8ea2011-03-22 01:53:33 +0000562 error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", option_arg);
Jim Inghamd60d94a2011-03-11 03:53:59 +0000563 m_thread_specified = true;
564 }
565 break;
566 case 'T':
567 m_thread_name = option_arg;
568 m_thread_specified = true;
569 break;
570 case 'q':
571 m_queue_name = option_arg;
572 m_thread_specified = true;
573 break;
574 case 'x':
575 {
Jim Ingham7a4c8ea2011-03-22 01:53:33 +0000576 m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
Jim Inghamd60d94a2011-03-11 03:53:59 +0000577 if (m_thread_id == UINT32_MAX)
Jim Ingham7a4c8ea2011-03-22 01:53:33 +0000578 error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", option_arg);
Jim Inghamd60d94a2011-03-11 03:53:59 +0000579 m_thread_specified = true;
580 }
581 break;
582 default:
583 error.SetErrorStringWithFormat ("Unrecognized option %c.");
584 break;
585 }
586 return error;
587 }
588
589 void
590 ResetOptionValues ()
591 {
592 m_class_name.clear();
593 m_function_name.clear();
594 m_line_start = 0;
595 m_line_end = UINT_MAX;
596 m_file_name.clear();
597 m_module_name.clear();
598 m_func_name_type_mask = eFunctionNameTypeAuto;
599 m_thread_id = LLDB_INVALID_THREAD_ID;
600 m_thread_index = UINT32_MAX;
601 m_thread_name.clear();
602 m_queue_name.clear();
603
604 m_sym_ctx_specified = false;
605 m_thread_specified = false;
606 }
607
608
Greg Claytonb3448432011-03-24 21:19:54 +0000609 static OptionDefinition g_option_table[];
Jim Inghamd60d94a2011-03-11 03:53:59 +0000610
611 std::string m_class_name;
612 std::string m_function_name;
613 uint32_t m_line_start;
614 uint32_t m_line_end;
615 std::string m_file_name;
616 std::string m_module_name;
617 uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
618 lldb::tid_t m_thread_id;
619 uint32_t m_thread_index;
620 std::string m_thread_name;
621 std::string m_queue_name;
622 bool m_sym_ctx_specified;
623 bool m_thread_specified;
624
625 };
626
627 Options *
628 GetOptions ()
629 {
630 return &m_options;
631 }
632
633 CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) :
634 CommandObject (interpreter,
635 "target stop-hook add ",
636 "Add a hook to be executed when the target stops.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000637 "target stop-hook add"),
638 m_options (interpreter)
Jim Inghamd60d94a2011-03-11 03:53:59 +0000639 {
640 }
641
642 ~CommandObjectTargetStopHookAdd ()
643 {
644 }
645
646 static size_t
647 ReadCommandsCallbackFunction (void *baton,
648 InputReader &reader,
649 lldb::InputReaderAction notification,
650 const char *bytes,
651 size_t bytes_len)
652 {
653 File &out_file = reader.GetDebugger().GetOutputFile();
654 Target::StopHook *new_stop_hook = ((Target::StopHook *) baton);
655
656 switch (notification)
657 {
658 case eInputReaderActivate:
659 out_file.Printf ("%s\n", "Enter your stop hook command(s). Type 'DONE' to end.");
660 if (reader.GetPrompt())
661 out_file.Printf ("%s", reader.GetPrompt());
662 out_file.Flush();
663 break;
664
665 case eInputReaderDeactivate:
666 break;
667
668 case eInputReaderReactivate:
669 if (reader.GetPrompt())
670 {
671 out_file.Printf ("%s", reader.GetPrompt());
672 out_file.Flush();
673 }
674 break;
675
676 case eInputReaderGotToken:
677 if (bytes && bytes_len && baton)
678 {
679 StringList *commands = new_stop_hook->GetCommandPointer();
680 if (commands)
681 {
682 commands->AppendString (bytes, bytes_len);
683 }
684 }
685 if (!reader.IsDone() && reader.GetPrompt())
686 {
687 out_file.Printf ("%s", reader.GetPrompt());
688 out_file.Flush();
689 }
690 break;
691
692 case eInputReaderInterrupt:
693 {
694 // Finish, and cancel the stop hook.
695 new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID());
696 out_file.Printf ("Stop hook cancelled.\n");
697
698 reader.SetIsDone (true);
699 }
700 break;
701
702 case eInputReaderEndOfFile:
703 reader.SetIsDone (true);
704 break;
705
706 case eInputReaderDone:
707 out_file.Printf ("Stop hook #%d added.\n", new_stop_hook->GetID());
708 break;
709 }
710
711 return bytes_len;
712 }
713
714 bool
715 Execute (Args& command,
716 CommandReturnObject &result)
717 {
718 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
719 if (target)
720 {
721 Target::StopHookSP new_hook_sp;
722 target->AddStopHook (new_hook_sp);
723
724 // First step, make the specifier.
725 std::auto_ptr<SymbolContextSpecifier> specifier_ap;
726 if (m_options.m_sym_ctx_specified)
727 {
728 specifier_ap.reset(new SymbolContextSpecifier(m_interpreter.GetDebugger().GetSelectedTarget()));
729
730 if (!m_options.m_module_name.empty())
731 {
732 specifier_ap->AddSpecification (m_options.m_module_name.c_str(), SymbolContextSpecifier::eModuleSpecified);
733 }
734
735 if (!m_options.m_class_name.empty())
736 {
737 specifier_ap->AddSpecification (m_options.m_class_name.c_str(), SymbolContextSpecifier::eClassOrNamespaceSpecified);
738 }
739
740 if (!m_options.m_file_name.empty())
741 {
742 specifier_ap->AddSpecification (m_options.m_file_name.c_str(), SymbolContextSpecifier::eFileSpecified);
743 }
744
745 if (m_options.m_line_start != 0)
746 {
747 specifier_ap->AddLineSpecification (m_options.m_line_start, SymbolContextSpecifier::eLineStartSpecified);
748 }
749
750 if (m_options.m_line_end != UINT_MAX)
751 {
752 specifier_ap->AddLineSpecification (m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
753 }
754
755 if (!m_options.m_function_name.empty())
756 {
757 specifier_ap->AddSpecification (m_options.m_function_name.c_str(), SymbolContextSpecifier::eFunctionSpecified);
758 }
759 }
760
761 if (specifier_ap.get())
762 new_hook_sp->SetSpecifier (specifier_ap.release());
763
764 // Next see if any of the thread options have been entered:
765
766 if (m_options.m_thread_specified)
767 {
768 ThreadSpec *thread_spec = new ThreadSpec();
769
770 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
771 {
772 thread_spec->SetTID (m_options.m_thread_id);
773 }
774
775 if (m_options.m_thread_index != UINT32_MAX)
776 thread_spec->SetIndex (m_options.m_thread_index);
777
778 if (!m_options.m_thread_name.empty())
779 thread_spec->SetName (m_options.m_thread_name.c_str());
780
781 if (!m_options.m_queue_name.empty())
782 thread_spec->SetQueueName (m_options.m_queue_name.c_str());
783
784 new_hook_sp->SetThreadSpecifier (thread_spec);
785
786 }
787 // Next gather up the command list, we'll push an input reader and suck the data from that directly into
788 // the new stop hook's command string.
789
790 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
791 if (!reader_sp)
792 {
793 result.AppendError("out of memory");
794 result.SetStatus (eReturnStatusFailed);
795 target->RemoveStopHookByID (new_hook_sp->GetID());
796 return false;
797 }
798
799 Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction,
800 new_hook_sp.get(), // baton
801 eInputReaderGranularityLine, // token size, to pass to callback function
802 "DONE", // end token
803 "> ", // prompt
804 true)); // echo input
805 if (!err.Success())
806 {
807 result.AppendError (err.AsCString());
808 result.SetStatus (eReturnStatusFailed);
809 target->RemoveStopHookByID (new_hook_sp->GetID());
810 return false;
811 }
812 m_interpreter.GetDebugger().PushInputReader (reader_sp);
813
814 result.SetStatus (eReturnStatusSuccessFinishNoResult);
815 }
816 else
817 {
818 result.AppendError ("invalid target");
819 result.SetStatus (eReturnStatusFailed);
820 }
821
822 return result.Succeeded();
823 }
824private:
825 CommandOptions m_options;
826};
827
Greg Claytonb3448432011-03-24 21:19:54 +0000828OptionDefinition
Jim Inghamd60d94a2011-03-11 03:53:59 +0000829CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] =
830{
831 { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName,
832 "Set the module within which the stop-hook is to be run."},
833 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, NULL, eArgTypeThreadIndex,
834 "The stop hook is run only for the thread whose index matches this argument."},
835 { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, NULL, eArgTypeThreadID,
836 "The stop hook is run only for the thread whose TID matches this argument."},
837 { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, NULL, eArgTypeThreadName,
838 "The stop hook is run only for the thread whose thread name matches this argument."},
839 { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName,
840 "The stop hook is run only for threads in the queue whose name is given by this argument."},
841 { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename,
842 "Specify the source file within which the stop-hook is to be run." },
843 { LLDB_OPT_SET_1, false, "start-line", 'l', required_argument, NULL, 0, eArgTypeLineNum,
844 "Set the start of the line range for which the stop-hook is to be run."},
845 { LLDB_OPT_SET_1, false, "end-line", 'e', required_argument, NULL, 0, eArgTypeLineNum,
846 "Set the end of the line range for which the stop-hook is to be run."},
847 { LLDB_OPT_SET_2, false, "classname", 'c', required_argument, NULL, NULL, eArgTypeClassName,
848 "Specify the class within which the stop-hook is to be run." },
849 { LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
850 "Set the function name within which the stop hook will be run." },
851 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
852};
853
854#pragma mark CommandObjectTargetStopHookDelete
855
856//-------------------------------------------------------------------------
857// CommandObjectTargetStopHookDelete
858//-------------------------------------------------------------------------
859
860class CommandObjectTargetStopHookDelete : public CommandObject
861{
862public:
863
864 CommandObjectTargetStopHookDelete (CommandInterpreter &interpreter) :
865 CommandObject (interpreter,
866 "target stop-hook delete [<id>]",
867 "Delete a stop-hook.",
868 "target stop-hook delete")
869 {
870 }
871
872 ~CommandObjectTargetStopHookDelete ()
873 {
874 }
875
876 bool
877 Execute (Args& command,
878 CommandReturnObject &result)
879 {
880 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
881 if (target)
882 {
883 // FIXME: see if we can use the breakpoint id style parser?
884 size_t num_args = command.GetArgumentCount();
885 if (num_args == 0)
886 {
887 if (!m_interpreter.Confirm ("Delete all stop hooks?", true))
888 {
889 result.SetStatus (eReturnStatusFailed);
890 return false;
891 }
892 else
893 {
894 target->RemoveAllStopHooks();
895 }
896 }
897 else
898 {
899 bool success;
900 for (size_t i = 0; i < num_args; i++)
901 {
902 lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success);
903 if (!success)
904 {
905 result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".", command.GetArgumentAtIndex(i));
906 result.SetStatus(eReturnStatusFailed);
907 return false;
908 }
909 success = target->RemoveStopHookByID (user_id);
910 if (!success)
911 {
912 result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".", command.GetArgumentAtIndex(i));
913 result.SetStatus(eReturnStatusFailed);
914 return false;
915 }
916 }
917 }
918 result.SetStatus (eReturnStatusSuccessFinishNoResult);
919 }
920 else
921 {
922 result.AppendError ("invalid target");
923 result.SetStatus (eReturnStatusFailed);
924 }
925
926 return result.Succeeded();
927 }
928};
929#pragma mark CommandObjectTargetStopHookEnableDisable
930
931//-------------------------------------------------------------------------
932// CommandObjectTargetStopHookEnableDisable
933//-------------------------------------------------------------------------
934
935class CommandObjectTargetStopHookEnableDisable : public CommandObject
936{
937public:
938
939 CommandObjectTargetStopHookEnableDisable (CommandInterpreter &interpreter, bool enable, const char *name, const char *help, const char *syntax) :
940 CommandObject (interpreter,
941 name,
942 help,
943 syntax),
944 m_enable (enable)
945 {
946 }
947
948 ~CommandObjectTargetStopHookEnableDisable ()
949 {
950 }
951
952 bool
953 Execute (Args& command,
954 CommandReturnObject &result)
955 {
956 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
957 if (target)
958 {
959 // FIXME: see if we can use the breakpoint id style parser?
960 size_t num_args = command.GetArgumentCount();
961 bool success;
962
963 if (num_args == 0)
964 {
965 target->SetAllStopHooksActiveState (m_enable);
966 }
967 else
968 {
969 for (size_t i = 0; i < num_args; i++)
970 {
971 lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success);
972 if (!success)
973 {
974 result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".", command.GetArgumentAtIndex(i));
975 result.SetStatus(eReturnStatusFailed);
976 return false;
977 }
978 success = target->SetStopHookActiveStateByID (user_id, m_enable);
979 if (!success)
980 {
981 result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".", command.GetArgumentAtIndex(i));
982 result.SetStatus(eReturnStatusFailed);
983 return false;
984 }
985 }
986 }
987 result.SetStatus (eReturnStatusSuccessFinishNoResult);
988 }
989 else
990 {
991 result.AppendError ("invalid target");
992 result.SetStatus (eReturnStatusFailed);
993 }
994 return result.Succeeded();
995 }
996private:
997 bool m_enable;
998};
999
1000#pragma mark CommandObjectTargetStopHookList
1001
1002//-------------------------------------------------------------------------
1003// CommandObjectTargetStopHookList
1004//-------------------------------------------------------------------------
1005
1006class CommandObjectTargetStopHookList : public CommandObject
1007{
1008public:
1009
1010 CommandObjectTargetStopHookList (CommandInterpreter &interpreter) :
1011 CommandObject (interpreter,
1012 "target stop-hook list [<type>]",
1013 "List all stop-hooks.",
1014 "target stop-hook list")
1015 {
1016 }
1017
1018 ~CommandObjectTargetStopHookList ()
1019 {
1020 }
1021
1022 bool
1023 Execute (Args& command,
1024 CommandReturnObject &result)
1025 {
1026 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1027 if (target)
1028 {
1029 bool notify = true;
1030 target->GetImageSearchPathList().Clear(notify);
1031 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1032 }
1033 else
1034 {
1035 result.AppendError ("invalid target");
1036 result.SetStatus (eReturnStatusFailed);
1037 }
1038
1039 size_t num_hooks = target->GetNumStopHooks ();
1040 if (num_hooks == 0)
1041 {
1042 result.GetOutputStream().PutCString ("No stop hooks.\n");
1043 }
1044 else
1045 {
1046 for (size_t i = 0; i < num_hooks; i++)
1047 {
1048 Target::StopHookSP this_hook = target->GetStopHookAtIndex (i);
1049 if (i > 0)
1050 result.GetOutputStream().PutCString ("\n");
1051 this_hook->GetDescription (&(result.GetOutputStream()), eDescriptionLevelFull);
1052 }
1053 }
1054 return result.Succeeded();
1055 }
1056};
1057
1058#pragma mark CommandObjectMultiwordTargetStopHooks
1059//-------------------------------------------------------------------------
1060// CommandObjectMultiwordTargetStopHooks
1061//-------------------------------------------------------------------------
1062
1063class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword
1064{
1065public:
1066
1067 CommandObjectMultiwordTargetStopHooks (CommandInterpreter &interpreter) :
1068 CommandObjectMultiword (interpreter,
1069 "target stop-hook",
1070 "A set of commands for operating on debugger target stop-hooks.",
1071 "target stop-hook <subcommand> [<subcommand-options>]")
1072 {
1073 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetStopHookAdd (interpreter)));
1074 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTargetStopHookDelete (interpreter)));
1075 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter,
1076 false,
1077 "target stop-hook disable [<id>]",
1078 "Disable a stop-hook.",
1079 "target stop-hook disable")));
1080 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter,
1081 true,
1082 "target stop-hook enable [<id>]",
1083 "Enable a stop-hook.",
1084 "target stop-hook enable")));
1085 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetStopHookList (interpreter)));
1086 }
1087
1088 ~CommandObjectMultiwordTargetStopHooks()
1089 {
1090 }
1091};
1092
1093
Chris Lattner24943d22010-06-08 16:52:24 +00001094
1095#pragma mark CommandObjectMultiwordTarget
1096
1097//-------------------------------------------------------------------------
1098// CommandObjectMultiwordTarget
1099//-------------------------------------------------------------------------
1100
Greg Clayton63094e02010-06-23 01:19:29 +00001101CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001102 CommandObjectMultiword (interpreter,
1103 "target",
Chris Lattner24943d22010-06-08 16:52:24 +00001104 "A set of commands for operating on debugger targets.",
1105 "target <subcommand> [<subcommand-options>]")
1106{
Greg Clayton238c0a12010-09-18 01:14:36 +00001107 LoadSubCommand ("image-search-paths", CommandObjectSP (new CommandObjectMultiwordImageSearchPaths (interpreter)));
Jim Inghamd60d94a2011-03-11 03:53:59 +00001108 LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001109}
1110
1111CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget ()
1112{
1113}
1114