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