1 //===-- SBTarget.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 "lldb/API/SBTarget.h" 11 12 #include "lldb/lldb-include.h" 13 14 #include "lldb/API/SBFileSpec.h" 15 #include "lldb/API/SBModule.h" 16 #include "lldb/Breakpoint/BreakpointID.h" 17 #include "lldb/Breakpoint/BreakpointIDList.h" 18 #include "lldb/Breakpoint/BreakpointList.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Core/Address.h" 21 #include "lldb/Core/AddressResolver.h" 22 #include "lldb/Core/AddressResolverName.h" 23 #include "lldb/Interpreter/Args.h" 24 #include "lldb/Core/ArchSpec.h" 25 #include "lldb/Core/Debugger.h" 26 #include "lldb/Core/Disassembler.h" 27 #include "lldb/Core/FileSpec.h" 28 #include "lldb/Core/RegularExpression.h" 29 #include "lldb/Core/SearchFilter.h" 30 #include "lldb/Core/STLUtils.h" 31 #include "lldb/Target/Process.h" 32 #include "lldb/Target/Target.h" 33 #include "lldb/Target/TargetList.h" 34 35 #include "lldb/Interpreter/CommandReturnObject.h" 36 #include "../source/Commands/CommandObjectBreakpoint.h" 37 38 #include "lldb/API/SBDebugger.h" 39 #include "lldb/API/SBProcess.h" 40 #include "lldb/API/SBListener.h" 41 #include "lldb/API/SBBreakpoint.h" 42 43 using namespace lldb; 44 using namespace lldb_private; 45 46 #define DEFAULT_DISASM_BYTE_SIZE 32 47 48 //---------------------------------------------------------------------- 49 // SBTarget constructor 50 //---------------------------------------------------------------------- 51 SBTarget::SBTarget () 52 { 53 } 54 55 SBTarget::SBTarget (const SBTarget& rhs) : 56 m_opaque_sp (rhs.m_opaque_sp) 57 { 58 } 59 60 SBTarget::SBTarget(const TargetSP& target_sp) : 61 m_opaque_sp (target_sp) 62 { 63 } 64 65 const SBTarget& 66 SBTarget::Assign (const SBTarget& rhs) 67 { 68 if (this != &rhs) 69 { 70 m_opaque_sp = rhs.m_opaque_sp; 71 } 72 return *this; 73 } 74 75 76 //---------------------------------------------------------------------- 77 // Destructor 78 //---------------------------------------------------------------------- 79 SBTarget::~SBTarget() 80 { 81 } 82 83 bool 84 SBTarget::IsValid () const 85 { 86 return m_opaque_sp.get() != NULL; 87 } 88 89 SBProcess 90 SBTarget::GetProcess () 91 { 92 SBProcess sb_process; 93 if (m_opaque_sp) 94 sb_process.SetProcess (m_opaque_sp->GetProcessSP()); 95 return sb_process; 96 } 97 98 SBDebugger 99 SBTarget::GetDebugger () const 100 { 101 SBDebugger debugger; 102 if (m_opaque_sp) 103 debugger.reset (m_opaque_sp->GetDebugger().GetSP()); 104 return debugger; 105 } 106 107 SBProcess 108 SBTarget::CreateProcess () 109 { 110 SBProcess sb_process; 111 112 if (m_opaque_sp) 113 sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener())); 114 115 return sb_process; 116 } 117 118 SBProcess 119 SBTarget::LaunchProcess 120 ( 121 char const **argv, 122 char const **envp, 123 const char *tty, 124 bool stop_at_entry 125 ) 126 { 127 SBProcess process(GetProcess ()); 128 if (!process.IsValid()) 129 process = CreateProcess(); 130 if (process.IsValid()) 131 { 132 Error error (process->Launch (argv, envp, tty, tty, tty)); 133 if (error.Success()) 134 { 135 if (!stop_at_entry) 136 { 137 StateType state = process->WaitForProcessToStop (NULL); 138 if (state == eStateStopped) 139 process->Resume(); 140 } 141 } 142 } 143 return process; 144 } 145 146 SBFileSpec 147 SBTarget::GetExecutable () 148 { 149 SBFileSpec exe_file_spec; 150 if (m_opaque_sp) 151 { 152 ModuleSP exe_module_sp (m_opaque_sp->GetExecutableModule ()); 153 if (exe_module_sp) 154 exe_file_spec.SetFileSpec (exe_module_sp->GetFileSpec()); 155 } 156 return exe_file_spec; 157 } 158 159 160 bool 161 SBTarget::DeleteTargetFromList (TargetList *list) 162 { 163 if (m_opaque_sp) 164 return list->DeleteTarget (m_opaque_sp); 165 else 166 return false; 167 } 168 169 bool 170 SBTarget::MakeCurrentTarget () 171 { 172 if (m_opaque_sp) 173 { 174 m_opaque_sp->GetDebugger().GetTargetList().SetCurrentTarget (m_opaque_sp.get()); 175 return true; 176 } 177 return false; 178 } 179 180 bool 181 SBTarget::operator == (const SBTarget &rhs) const 182 { 183 return m_opaque_sp.get() == rhs.m_opaque_sp.get(); 184 } 185 186 bool 187 SBTarget::operator != (const SBTarget &rhs) const 188 { 189 return m_opaque_sp.get() != rhs.m_opaque_sp.get(); 190 } 191 192 lldb_private::Target * 193 SBTarget::operator ->() const 194 { 195 return m_opaque_sp.get(); 196 } 197 198 lldb_private::Target * 199 SBTarget::get() const 200 { 201 return m_opaque_sp.get(); 202 } 203 204 void 205 SBTarget::reset (const lldb::TargetSP& target_sp) 206 { 207 m_opaque_sp = target_sp; 208 } 209 210 SBBreakpoint 211 SBTarget::BreakpointCreateByLocation (const char *file, uint32_t line) 212 { 213 SBBreakpoint sb_bp; 214 if (file != NULL && line != 0) 215 sb_bp = BreakpointCreateByLocation (SBFileSpec (file), line); 216 return sb_bp; 217 } 218 219 SBBreakpoint 220 SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t line) 221 { 222 SBBreakpoint sb_bp; 223 if (m_opaque_sp.get() && line != 0) 224 *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, *sb_file_spec, line, true, false); 225 return sb_bp; 226 } 227 228 SBBreakpoint 229 SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_name) 230 { 231 SBBreakpoint sb_bp; 232 if (m_opaque_sp.get() && symbol_name && symbol_name[0]) 233 { 234 if (module_name && module_name[0]) 235 { 236 FileSpec module_file_spec(module_name); 237 *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, symbol_name, false); 238 } 239 else 240 { 241 *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, symbol_name, false); 242 } 243 } 244 return sb_bp; 245 } 246 247 SBBreakpoint 248 SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name) 249 { 250 SBBreakpoint sb_bp; 251 if (m_opaque_sp.get() && symbol_name_regex && symbol_name_regex[0]) 252 { 253 RegularExpression regexp(symbol_name_regex); 254 255 if (module_name && module_name[0]) 256 { 257 FileSpec module_file_spec(module_name); 258 259 *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, regexp, false); 260 } 261 else 262 { 263 *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, regexp, false); 264 } 265 } 266 return sb_bp; 267 } 268 269 270 271 SBBreakpoint 272 SBTarget::BreakpointCreateByAddress (addr_t address) 273 { 274 SBBreakpoint sb_bp; 275 if (m_opaque_sp.get()) 276 *sb_bp = m_opaque_sp->CreateBreakpoint (address, false); 277 return sb_bp; 278 } 279 280 void 281 SBTarget::ListAllBreakpoints () 282 { 283 FILE *out_file = m_opaque_sp->GetDebugger().GetOutputFileHandle(); 284 285 if (out_file == NULL) 286 return; 287 288 if (m_opaque_sp) 289 { 290 const BreakpointList &bp_list = m_opaque_sp->GetBreakpointList(); 291 size_t num_bps = bp_list.GetSize(); 292 for (int i = 0; i < num_bps; ++i) 293 { 294 SBBreakpoint sb_breakpoint (bp_list.GetBreakpointByIndex (i)); 295 sb_breakpoint.GetDescription (out_file, "full"); 296 } 297 } 298 } 299 300 SBBreakpoint 301 SBTarget::FindBreakpointByID (break_id_t bp_id) 302 { 303 SBBreakpoint sb_breakpoint; 304 if (m_opaque_sp && bp_id != LLDB_INVALID_BREAK_ID) 305 *sb_breakpoint = m_opaque_sp->GetBreakpointByID (bp_id); 306 return sb_breakpoint; 307 } 308 309 310 bool 311 SBTarget::BreakpointDelete (break_id_t bp_id) 312 { 313 if (m_opaque_sp) 314 return m_opaque_sp->RemoveBreakpointByID (bp_id); 315 return false; 316 } 317 318 bool 319 SBTarget::EnableAllBreakpoints () 320 { 321 if (m_opaque_sp) 322 { 323 m_opaque_sp->EnableAllBreakpoints (); 324 return true; 325 } 326 return false; 327 } 328 329 bool 330 SBTarget::DisableAllBreakpoints () 331 { 332 if (m_opaque_sp) 333 { 334 m_opaque_sp->DisableAllBreakpoints (); 335 return true; 336 } 337 return false; 338 } 339 340 bool 341 SBTarget::DeleteAllBreakpoints () 342 { 343 if (m_opaque_sp) 344 { 345 m_opaque_sp->RemoveAllBreakpoints (); 346 return true; 347 } 348 return false; 349 } 350 351 352 uint32_t 353 SBTarget::GetNumModules () const 354 { 355 if (m_opaque_sp) 356 return m_opaque_sp->GetImages().GetSize(); 357 return 0; 358 } 359 360 SBModule 361 SBTarget::FindModule (const SBFileSpec &sb_file_spec) 362 { 363 SBModule sb_module; 364 if (m_opaque_sp && sb_file_spec.IsValid()) 365 sb_module.SetModule (m_opaque_sp->GetImages().FindFirstModuleForFileSpec (*sb_file_spec, NULL)); 366 return sb_module; 367 } 368 369 SBModule 370 SBTarget::GetModuleAtIndex (uint32_t idx) 371 { 372 SBModule sb_module; 373 if (m_opaque_sp) 374 sb_module.SetModule(m_opaque_sp->GetImages().GetModuleAtIndex(idx)); 375 return sb_module; 376 } 377 378 379 SBBroadcaster 380 SBTarget::GetBroadcaster () const 381 { 382 SBBroadcaster broadcaster(m_opaque_sp.get(), false); 383 return broadcaster; 384 } 385 386 void 387 SBTarget::Disassemble (lldb::addr_t start_addr, lldb::addr_t end_addr, const char *module_name) 388 { 389 if (start_addr == LLDB_INVALID_ADDRESS) 390 return; 391 392 FILE *out = m_opaque_sp->GetDebugger().GetOutputFileHandle(); 393 if (out == NULL) 394 return; 395 396 if (m_opaque_sp) 397 { 398 ModuleSP module_sp; 399 if (module_name != NULL) 400 { 401 FileSpec module_file_spec (module_name); 402 module_sp = m_opaque_sp->GetImages().FindFirstModuleForFileSpec (module_file_spec, NULL); 403 } 404 405 AddressRange range; 406 407 // Make sure the process object is alive if we have one (it might be 408 // created but we might not be launched yet). 409 Process *process = m_opaque_sp->GetProcessSP().get(); 410 if (process && !process->IsAlive()) 411 process = NULL; 412 413 // If we are given a module, then "start_addr" is a file address in 414 // that module. 415 if (module_sp) 416 { 417 if (!module_sp->ResolveFileAddress (start_addr, range.GetBaseAddress())) 418 range.GetBaseAddress().SetOffset(start_addr); 419 } 420 else if (process) 421 { 422 // We don't have a module, se we need to figure out if "start_addr" 423 // resolves to anything in a running process. 424 if (!process->ResolveLoadAddress(start_addr, range.GetBaseAddress())) 425 range.GetBaseAddress().SetOffset(start_addr); 426 } 427 else 428 { 429 if (m_opaque_sp->GetImages().ResolveFileAddress (start_addr, range.GetBaseAddress())) 430 range.GetBaseAddress().SetOffset(start_addr); 431 } 432 433 // For now, we need a process; the disassembly functions insist. If we don't have one already, 434 // make one. 435 436 ExecutionContext exe_ctx; 437 438 if (process) 439 process->Calculate(exe_ctx); 440 else 441 m_opaque_sp->Calculate(exe_ctx); 442 443 if (end_addr == LLDB_INVALID_ADDRESS || end_addr < start_addr) 444 range.SetByteSize( DEFAULT_DISASM_BYTE_SIZE); 445 else 446 range.SetByteSize(end_addr - start_addr); 447 448 StreamFile out_stream (out); 449 450 Disassembler::Disassemble (m_opaque_sp->GetDebugger(), 451 m_opaque_sp->GetArchitecture(), 452 exe_ctx, 453 range, 454 3, 455 false, 456 out_stream); 457 } 458 } 459 460 void 461 SBTarget::Disassemble (const char *function_name, const char *module_name) 462 { 463 if (function_name == NULL) 464 return; 465 466 FILE *out = m_opaque_sp->GetDebugger().GetOutputFileHandle(); 467 if (out == NULL) 468 return; 469 470 if (m_opaque_sp) 471 { 472 Disassembler *disassembler = Disassembler::FindPlugin (m_opaque_sp->GetArchitecture()); 473 if (disassembler == NULL) 474 return; 475 476 ModuleSP module_sp; 477 if (module_name != NULL) 478 { 479 FileSpec module_file_spec (module_name); 480 module_sp = m_opaque_sp->GetImages().FindFirstModuleForFileSpec (module_file_spec, NULL); 481 } 482 483 ExecutionContext exe_ctx; 484 485 // Make sure the process object is alive if we have one (it might be 486 // created but we might not be launched yet). 487 Process *process = m_opaque_sp->GetProcessSP().get(); 488 if (process && !process->IsAlive()) 489 process = NULL; 490 491 if (process) 492 process->Calculate(exe_ctx); 493 else 494 m_opaque_sp->Calculate(exe_ctx); 495 496 497 StreamFile out_stream (out); 498 499 Disassembler::Disassemble (m_opaque_sp->GetDebugger(), 500 m_opaque_sp->GetArchitecture(), 501 exe_ctx, 502 ConstString (function_name), 503 module_sp.get(), 504 3, 505 false, 506 out_stream); 507 } 508 } 509