1 //===-- SBDebugger.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 "SBDebugger.h" 11 12 #include "lldb/lldb-include.h" 13 #include "lldb/Core/Args.h" 14 #include "lldb/Core/Debugger.h" 15 #include "lldb/Core/State.h" 16 #include "lldb/Target/Process.h" 17 #include "lldb/Target/TargetList.h" 18 19 #include "SBListener.h" 20 #include "SBBroadcaster.h" 21 #include "SBCommandInterpreter.h" 22 #include "SBCommandReturnObject.h" 23 #include "SBEvent.h" 24 #include "SBFrame.h" 25 #include "SBTarget.h" 26 #include "SBProcess.h" 27 #include "SBThread.h" 28 #include "SBSourceManager.h" 29 #include "SBInputReader.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 void 35 SBDebugger::Initialize () 36 { 37 Debugger::Initialize(); 38 } 39 40 void 41 SBDebugger::Terminate () 42 { 43 Debugger::Terminate(); 44 } 45 46 void 47 SBDebugger::SetAsync (bool b) 48 { 49 static bool value_set_once = false; 50 51 if (!value_set_once) 52 { 53 value_set_once = true; 54 Debugger::GetSharedInstance().SetAsyncExecution(b); 55 } 56 } 57 58 void 59 SBDebugger::SetInputFile (const char *tty_name) 60 { 61 // DEPRECATED: will be removed in next submission 62 FILE *fh = ::fopen (tty_name, "r"); 63 SetInputFileHandle (fh, true); 64 } 65 66 void 67 SBDebugger::SetOutputFile (const char *tty_name) 68 { 69 // DEPRECATED: will be removed in next submission 70 FILE *fh = ::fopen (tty_name, "w"); 71 SetOutputFileHandle (fh, true); 72 SetErrorFileHandle (fh, false); 73 } 74 75 void 76 SBDebugger::SetErrorFile (const char *tty_name) 77 { 78 // DEPRECATED: will be removed in next submission 79 } 80 81 82 // Shouldn't really be settable after initialization as this could cause lots of problems; don't want users 83 // trying to switch modes in the middle of a debugging session. 84 void 85 SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership) 86 { 87 Debugger::GetSharedInstance().SetInputFileHandle (fh, transfer_ownership); 88 } 89 90 void 91 SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership) 92 { 93 Debugger::GetSharedInstance().SetOutputFileHandle (fh, transfer_ownership); 94 } 95 96 void 97 SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership) 98 { 99 Debugger::GetSharedInstance().SetErrorFileHandle (fh, transfer_ownership); 100 } 101 102 FILE * 103 SBDebugger::GetInputFileHandle () 104 { 105 return Debugger::GetSharedInstance().GetInputFileHandle(); 106 } 107 108 FILE * 109 SBDebugger::GetOutputFileHandle () 110 { 111 return Debugger::GetSharedInstance().GetOutputFileHandle(); 112 } 113 114 FILE * 115 SBDebugger::GetErrorFileHandle () 116 { 117 return Debugger::GetSharedInstance().GetErrorFileHandle(); 118 } 119 120 SBCommandInterpreter 121 SBDebugger::GetCommandInterpreter () 122 { 123 SBCommandInterpreter sb_interpreter(Debugger::GetSharedInstance().GetCommandInterpreter()); 124 return sb_interpreter; 125 } 126 127 void 128 SBDebugger::HandleCommand (const char *command) 129 { 130 SBProcess process; 131 SBCommandInterpreter sb_interpreter(Debugger::GetSharedInstance().GetCommandInterpreter()); 132 SBCommandReturnObject result; 133 134 sb_interpreter.HandleCommand (command, result, false); 135 136 if (GetErrorFileHandle() != NULL) 137 result.PutError (GetErrorFileHandle()); 138 if (GetOutputFileHandle() != NULL) 139 result.PutOutput (GetOutputFileHandle()); 140 141 if (Debugger::GetSharedInstance().GetAsyncExecution() == false) 142 { 143 process = GetCommandInterpreter().GetProcess (); 144 if (process.IsValid()) 145 { 146 EventSP event_sp; 147 Listener &lldb_listener = Debugger::GetSharedInstance().GetListener(); 148 while (lldb_listener.GetNextEventForBroadcaster (process.get(), event_sp)) 149 { 150 SBEvent event(event_sp); 151 HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle()); 152 } 153 } 154 } 155 } 156 157 SBListener 158 SBDebugger::GetListener () 159 { 160 SBListener sb_listener(Debugger::GetSharedInstance().GetListener()); 161 return sb_listener; 162 } 163 164 void 165 SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err) 166 { 167 const uint32_t event_type = event.GetType(); 168 char stdio_buffer[1024]; 169 size_t len; 170 171 if (event_type & Process::eBroadcastBitSTDOUT) 172 { 173 while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) 174 if (out != NULL) 175 ::fwrite (stdio_buffer, 1, len, out); 176 } 177 else if (event_type & Process::eBroadcastBitSTDERR) 178 { 179 while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) 180 if (out != NULL) 181 ::fwrite (stdio_buffer, 1, len, out); 182 } 183 else if (event_type & Process::eBroadcastBitStateChanged) 184 { 185 // Drain any stdout messages. 186 while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) 187 if (out != NULL) 188 ::fwrite (stdio_buffer, 1, len, out); 189 190 // Drain any stderr messages. 191 while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) 192 if (out != NULL) 193 ::fwrite (stdio_buffer, 1, len, out); 194 195 StateType event_state = SBProcess::GetStateFromEvent (event); 196 197 if (event_state == eStateInvalid) 198 return; 199 200 bool is_stopped = StateIsStoppedState (event_state); 201 if (!is_stopped) 202 process.ReportCurrentState (event, out); 203 } 204 } 205 206 void 207 SBDebugger::UpdateCurrentThread (SBProcess &process) 208 { 209 if (process.IsValid()) 210 { 211 SBThread curr_thread = process.GetCurrentThread (); 212 SBThread thread; 213 StopReason curr_thread_stop_reason = eStopReasonInvalid; 214 if (curr_thread.IsValid()) 215 { 216 if (curr_thread.GetStopReason() != eStopReasonInvalid) 217 curr_thread_stop_reason = curr_thread.GetStopReason (); 218 } 219 220 if (! curr_thread.IsValid() 221 || curr_thread_stop_reason == eStopReasonInvalid 222 || curr_thread_stop_reason == eStopReasonNone) 223 { 224 // Prefer a thread that has just completed its plan over another thread as current thread. 225 SBThread plan_thread; 226 SBThread other_thread; 227 const size_t num_threads = process.GetNumThreads (); 228 size_t i; 229 for (i = 0; i < num_threads; ++i) 230 { 231 thread = process.GetThreadAtIndex(i); 232 if (thread.GetStopReason () != eStopReasonInvalid) 233 { 234 switch (thread.GetStopReason ()) 235 { 236 default: 237 case eStopReasonInvalid: 238 case eStopReasonNone: 239 break; 240 241 case eStopReasonTrace: 242 case eStopReasonBreakpoint: 243 case eStopReasonWatchpoint: 244 case eStopReasonSignal: 245 case eStopReasonException: 246 if (! other_thread.IsValid()) 247 other_thread = thread; 248 break; 249 case eStopReasonPlanComplete: 250 if (! plan_thread.IsValid()) 251 plan_thread = thread; 252 break; 253 } 254 } 255 } 256 if (plan_thread.IsValid()) 257 process.SetCurrentThreadByID (plan_thread.GetThreadID()); 258 else if (other_thread.IsValid()) 259 process.SetCurrentThreadByID (other_thread.GetThreadID()); 260 else 261 { 262 if (curr_thread.IsValid()) 263 thread = curr_thread; 264 else 265 thread = process.GetThreadAtIndex(0); 266 267 if (thread.IsValid()) 268 process.SetCurrentThreadByID (thread.GetThreadID()); 269 } 270 } 271 } 272 } 273 274 void 275 SBDebugger::ReportCurrentLocation (FILE *out, FILE *err) 276 { 277 if ((out == NULL) || (err == NULL)) 278 return; 279 280 SBTarget sb_target (GetCurrentTarget()); 281 if (!sb_target.IsValid()) 282 { 283 fprintf (out, "no target\n"); 284 return; 285 } 286 287 SBProcess process = sb_target.GetProcess (); 288 if (process.IsValid()) 289 { 290 StateType state = process.GetState(); 291 292 if (StateIsStoppedState (state)) 293 { 294 if (state == eStateExited) 295 { 296 int exit_status = process.GetExitStatus(); 297 const char *exit_description = process.GetExitDescription(); 298 ::fprintf (out, "Process %d exited with status = %i (0x%8.8x) %s\n", 299 process.GetProcessID(), 300 exit_status, 301 exit_status, 302 exit_description ? exit_description : ""); 303 } 304 else 305 { 306 fprintf (out, "Process %d %s\n", process.GetProcessID(), StateAsCString (state)); 307 SBThread current_thread = process.GetThreadAtIndex (0); 308 if (current_thread.IsValid()) 309 { 310 process.DisplayThreadsInfo (out, err, true); 311 } 312 else 313 fprintf (out, "No valid thread found in current process\n"); 314 } 315 } 316 else 317 fprintf (out, "No current location or status available\n"); 318 } 319 } 320 321 SBSourceManager & 322 SBDebugger::GetSourceManager () 323 { 324 static SourceManager g_lldb_source_manager; 325 static SBSourceManager g_sb_source_manager (g_lldb_source_manager); 326 return g_sb_source_manager; 327 } 328 329 330 bool 331 SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len) 332 { 333 if (arch_name && arch_name_len) 334 { 335 ArchSpec &default_arch = lldb_private::GetDefaultArchitecture (); 336 if (default_arch.IsValid()) 337 { 338 ::snprintf (arch_name, arch_name_len, "%s", default_arch.AsCString()); 339 return true; 340 } 341 } 342 if (arch_name && arch_name_len) 343 arch_name[0] = '\0'; 344 return false; 345 } 346 347 348 bool 349 SBDebugger::SetDefaultArchitecture (const char *arch_name) 350 { 351 if (arch_name) 352 { 353 ArchSpec arch (arch_name); 354 if (arch.IsValid()) 355 { 356 lldb_private::GetDefaultArchitecture () = arch; 357 return true; 358 } 359 } 360 return false; 361 } 362 363 ScriptLanguage 364 SBDebugger::GetScriptingLanguage (const char *script_language_name) 365 { 366 return Args::StringToScriptLanguage (script_language_name, 367 eScriptLanguageDefault, 368 NULL); 369 } 370 //pid_t 371 /* 372 SBDebugger::AttachByName (const char *process_name, const char *filename) 373 { 374 SBTarget *temp_target = GetCurrentTarget(); 375 SBTarget sb_target; 376 pid_t return_pid = (pid_t) LLDB_INVALID_PROCESS_ID; 377 378 if (temp_target == NULL) 379 { 380 if (filename != NULL) 381 { 382 sb_target = CreateWithFile (filename); 383 sb_target.SetArch (LLDB_ARCH_DEFAULT); 384 } 385 } 386 else 387 { 388 sb_target = *temp_target; 389 } 390 391 if (sb_target.IsValid()) 392 { 393 SBProcess process = sb_target.GetProcess (); 394 if (process.IsValid()) 395 { 396 return_pid = process.AttachByName (process_name); 397 } 398 } 399 return return_pid; 400 } 401 */ 402 403 const char * 404 SBDebugger::GetVersionString () 405 { 406 return lldb_private::GetVersion(); 407 } 408 409 const char * 410 SBDebugger::StateAsCString (lldb::StateType state) 411 { 412 return lldb_private::StateAsCString (state); 413 } 414 415 bool 416 SBDebugger::StateIsRunningState (lldb::StateType state) 417 { 418 return lldb_private::StateIsRunningState (state); 419 } 420 421 bool 422 SBDebugger::StateIsStoppedState (lldb::StateType state) 423 { 424 return lldb_private::StateIsStoppedState (state); 425 } 426 427 428 SBTarget 429 SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename, 430 const char *target_triple) 431 { 432 ArchSpec arch; 433 FileSpec file_spec (filename); 434 arch.SetArchFromTargetTriple(target_triple); 435 TargetSP target_sp; 436 Error error (Debugger::GetSharedInstance().GetTargetList().CreateTarget (file_spec, arch, NULL, true, target_sp)); 437 SBTarget target(target_sp); 438 return target; 439 } 440 441 SBTarget 442 SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *archname) 443 { 444 FileSpec file (filename); 445 ArchSpec arch = lldb_private::GetDefaultArchitecture(); 446 TargetSP target_sp; 447 Error error; 448 449 if (archname != NULL) 450 { 451 ArchSpec arch2 (archname); 452 error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch2, NULL, true, target_sp); 453 } 454 else 455 { 456 if (!arch.IsValid()) 457 arch = LLDB_ARCH_DEFAULT; 458 459 error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch, NULL, true, target_sp); 460 461 if (error.Fail()) 462 { 463 if (arch == LLDB_ARCH_DEFAULT_32BIT) 464 arch = LLDB_ARCH_DEFAULT_64BIT; 465 else 466 arch = LLDB_ARCH_DEFAULT_32BIT; 467 468 error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch, NULL, true, target_sp); 469 } 470 } 471 472 if (error.Success()) 473 Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget (target_sp.get()); 474 else 475 target_sp.reset(); 476 477 SBTarget sb_target (target_sp); 478 return sb_target; 479 } 480 481 SBTarget 482 SBDebugger::CreateTarget (const char *filename) 483 { 484 FileSpec file (filename); 485 ArchSpec arch = lldb_private::GetDefaultArchitecture(); 486 TargetSP target_sp; 487 Error error; 488 489 if (!arch.IsValid()) 490 arch = LLDB_ARCH_DEFAULT; 491 492 error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch, NULL, true, target_sp); 493 494 if (error.Fail()) 495 { 496 if (arch == LLDB_ARCH_DEFAULT_32BIT) 497 arch = LLDB_ARCH_DEFAULT_64BIT; 498 else 499 arch = LLDB_ARCH_DEFAULT_32BIT; 500 501 error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file, arch, NULL, true, target_sp); 502 } 503 504 if (!error.Fail()) 505 Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget (target_sp.get()); 506 507 SBTarget sb_target (target_sp); 508 return sb_target; 509 } 510 511 SBTarget 512 SBDebugger::GetTargetAtIndex (uint32_t idx) 513 { 514 SBTarget sb_target (Debugger::GetSharedInstance().GetTargetList().GetTargetAtIndex (idx)); 515 return sb_target; 516 } 517 518 SBTarget 519 SBDebugger::FindTargetWithProcessID (pid_t pid) 520 { 521 SBTarget sb_target(Debugger::GetSharedInstance().GetTargetList().FindTargetWithProcessID (pid)); 522 return sb_target; 523 } 524 525 SBTarget 526 SBDebugger::FindTargetWithFileAndArch (const char *filename, const char *arch_name) 527 { 528 ArchSpec arch; 529 if (arch_name) 530 arch.SetArch(arch_name); 531 return SBTarget (Debugger::GetSharedInstance().GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename), 532 arch_name ? &arch : NULL)); 533 } 534 535 SBTarget 536 SBDebugger::FindTargetWithLLDBProcess (const lldb::ProcessSP &process_sp) 537 { 538 SBTarget sb_target(Debugger::GetSharedInstance().GetTargetList().FindTargetWithProcess (process_sp.get())); 539 return sb_target; 540 } 541 542 543 uint32_t 544 SBDebugger::GetNumTargets () 545 { 546 return Debugger::GetSharedInstance().GetTargetList().GetNumTargets ();} 547 548 SBTarget 549 SBDebugger::GetCurrentTarget () 550 { 551 SBTarget sb_target(Debugger::GetSharedInstance().GetTargetList().GetCurrentTarget ()); 552 return sb_target; 553 } 554 555 void 556 SBDebugger::DispatchInput (void *baton, const void *data, size_t data_len) 557 { 558 Debugger::GetSharedInstance().DispatchInput ((const char *) data, data_len); 559 } 560 561 void 562 SBDebugger::PushInputReader (SBInputReader &reader) 563 { 564 if (reader.IsValid()) 565 { 566 InputReaderSP reader_sp(*reader); 567 Debugger::GetSharedInstance().PushInputReader (reader_sp); 568 } 569 } 570