SBTarget.cpp revision 84cdc15005983e5244d665fa779e33c2b6fac95f
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 43using namespace lldb; 44using namespace lldb_private; 45 46#define DEFAULT_DISASM_BYTE_SIZE 32 47 48//---------------------------------------------------------------------- 49// SBTarget constructor 50//---------------------------------------------------------------------- 51SBTarget::SBTarget () 52{ 53} 54 55SBTarget::SBTarget (const SBTarget& rhs) : 56 m_target_sp (rhs.m_target_sp) 57{ 58} 59 60SBTarget::SBTarget(const TargetSP& target_sp) : 61 m_target_sp (target_sp) 62{ 63} 64 65const SBTarget& 66SBTarget::Assign (const SBTarget& rhs) 67{ 68 if (this != &rhs) 69 { 70 m_target_sp = rhs.m_target_sp; 71 } 72 return *this; 73} 74 75 76//---------------------------------------------------------------------- 77// Destructor 78//---------------------------------------------------------------------- 79SBTarget::~SBTarget() 80{ 81} 82 83bool 84SBTarget::IsValid () const 85{ 86 return m_target_sp.get() != NULL; 87} 88 89SBProcess 90SBTarget::GetProcess () 91{ 92 SBProcess sb_process; 93 if (IsValid()) 94 sb_process.SetProcess (m_target_sp->GetProcessSP()); 95 return sb_process; 96} 97 98SBProcess 99SBTarget::CreateProcess () 100{ 101 SBProcess sb_process; 102 103 if (IsValid()) 104 { 105 SBListener sb_listener = SBDebugger::GetListener(); 106 if (sb_listener.IsValid()) 107 sb_process.SetProcess (m_target_sp->CreateProcess (*sb_listener)); 108 } 109 return sb_process; 110} 111 112SBProcess 113SBTarget::LaunchProcess 114( 115 char const **argv, 116 char const **envp, 117 const char *tty, 118 bool stop_at_entry 119) 120{ 121 SBProcess process(GetProcess ()); 122 if (!process.IsValid()) 123 process = CreateProcess(); 124 if (process.IsValid()) 125 { 126 Error error (process->Launch (argv, envp, tty, tty, tty)); 127 if (error.Success()) 128 { 129 if (!stop_at_entry) 130 { 131 StateType state = process->WaitForProcessToStop (NULL); 132 if (state == eStateStopped) 133 process->Resume(); 134 } 135 } 136 } 137 return process; 138} 139 140SBFileSpec 141SBTarget::GetExecutable () 142{ 143 SBFileSpec exe_file_spec; 144 if (IsValid()) 145 { 146 ModuleSP exe_module_sp (m_target_sp->GetExecutableModule ()); 147 if (exe_module_sp) 148 exe_file_spec.SetFileSpec (exe_module_sp->GetFileSpec()); 149 } 150 return exe_file_spec; 151} 152 153 154bool 155SBTarget::DeleteTargetFromList (TargetList *list) 156{ 157 if (IsValid()) 158 return list->DeleteTarget (m_target_sp); 159 else 160 return false; 161} 162 163bool 164SBTarget::MakeCurrentTarget () 165{ 166 if (IsValid()) 167 { 168 Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget (m_target_sp.get()); 169 return true; 170 } 171 return false; 172} 173 174bool 175SBTarget::operator == (const SBTarget &rhs) const 176{ 177 return m_target_sp.get() == rhs.m_target_sp.get(); 178} 179 180bool 181SBTarget::operator != (const SBTarget &rhs) const 182{ 183 return m_target_sp.get() != rhs.m_target_sp.get(); 184} 185 186lldb_private::Target * 187SBTarget::GetLLDBObjectPtr() 188{ 189 return m_target_sp.get(); 190} 191const lldb_private::Target * 192SBTarget::GetLLDBObjectPtr() const 193{ 194 return m_target_sp.get(); 195} 196 197SBBreakpoint 198SBTarget::BreakpointCreateByLocation (const char *file, uint32_t line) 199{ 200 SBBreakpoint sb_bp; 201 if (file != NULL && line != 0) 202 sb_bp = BreakpointCreateByLocation (SBFileSpec (file), line); 203 return sb_bp; 204} 205 206SBBreakpoint 207SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t line) 208{ 209 SBBreakpoint sb_bp; 210 if (m_target_sp.get() && line != 0) 211 *sb_bp = m_target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, true, false); 212 return sb_bp; 213} 214 215SBBreakpoint 216SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_name) 217{ 218 SBBreakpoint sb_bp; 219 if (m_target_sp.get() && symbol_name && symbol_name[0]) 220 { 221 if (module_name && module_name[0]) 222 { 223 FileSpec module_file_spec(module_name); 224 *sb_bp = m_target_sp->CreateBreakpoint (&module_file_spec, symbol_name, false); 225 } 226 else 227 { 228 *sb_bp = m_target_sp->CreateBreakpoint (NULL, symbol_name, false); 229 } 230 } 231 return sb_bp; 232} 233 234SBBreakpoint 235SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name) 236{ 237 SBBreakpoint sb_bp; 238 if (m_target_sp.get() && symbol_name_regex && symbol_name_regex[0]) 239 { 240 RegularExpression regexp(symbol_name_regex); 241 242 if (module_name && module_name[0]) 243 { 244 FileSpec module_file_spec(module_name); 245 246 *sb_bp = m_target_sp->CreateBreakpoint (&module_file_spec, regexp, false); 247 } 248 else 249 { 250 *sb_bp = m_target_sp->CreateBreakpoint (NULL, regexp, false); 251 } 252 } 253 return sb_bp; 254} 255 256 257 258SBBreakpoint 259SBTarget::BreakpointCreateByAddress (addr_t address) 260{ 261 SBBreakpoint sb_bp; 262 if (m_target_sp.get()) 263 *sb_bp = m_target_sp->CreateBreakpoint (address, false); 264 return sb_bp; 265} 266 267void 268SBTarget::ListAllBreakpoints () 269{ 270 FILE *out_file = SBDebugger::GetOutputFileHandle(); 271 272 if (out_file == NULL) 273 return; 274 275 if (IsValid()) 276 { 277 const BreakpointList &bp_list = m_target_sp->GetBreakpointList(); 278 size_t num_bps = bp_list.GetSize(); 279 for (int i = 0; i < num_bps; ++i) 280 { 281 SBBreakpoint sb_breakpoint (bp_list.GetBreakpointByIndex (i)); 282 sb_breakpoint.GetDescription (out_file, "full"); 283 } 284 } 285} 286 287SBBreakpoint 288SBTarget::FindBreakpointByID (break_id_t bp_id) 289{ 290 SBBreakpoint sb_breakpoint; 291 if (m_target_sp && bp_id != LLDB_INVALID_BREAK_ID) 292 *sb_breakpoint = m_target_sp->GetBreakpointByID (bp_id); 293 return sb_breakpoint; 294} 295 296 297bool 298SBTarget::BreakpointDelete (break_id_t bp_id) 299{ 300 if (m_target_sp) 301 return m_target_sp->RemoveBreakpointByID (bp_id); 302 return false; 303} 304 305bool 306SBTarget::EnableAllBreakpoints () 307{ 308 if (m_target_sp) 309 { 310 m_target_sp->EnableAllBreakpoints (); 311 return true; 312 } 313 return false; 314} 315 316bool 317SBTarget::DisableAllBreakpoints () 318{ 319 if (m_target_sp) 320 { 321 m_target_sp->DisableAllBreakpoints (); 322 return true; 323 } 324 return false; 325} 326 327bool 328SBTarget::DeleteAllBreakpoints () 329{ 330 if (m_target_sp) 331 { 332 m_target_sp->RemoveAllBreakpoints (); 333 return true; 334 } 335 return false; 336} 337 338 339uint32_t 340SBTarget::GetNumModules () const 341{ 342 if (m_target_sp) 343 return m_target_sp->GetImages().GetSize(); 344 return 0; 345} 346 347SBModule 348SBTarget::FindModule (const SBFileSpec &sb_file_spec) 349{ 350 SBModule sb_module; 351 if (m_target_sp && sb_file_spec.IsValid()) 352 sb_module.SetModule (m_target_sp->GetImages().FindFirstModuleForFileSpec (*sb_file_spec, NULL)); 353 return sb_module; 354} 355 356SBModule 357SBTarget::GetModuleAtIndex (uint32_t idx) 358{ 359 SBModule sb_module; 360 if (m_target_sp) 361 sb_module.SetModule(m_target_sp->GetImages().GetModuleAtIndex(idx)); 362 return sb_module; 363} 364 365 366SBBroadcaster 367SBTarget::GetBroadcaster () const 368{ 369 SBBroadcaster broadcaster(m_target_sp.get(), false); 370 return broadcaster; 371} 372 373void 374SBTarget::Disassemble (lldb::addr_t file_address_start, lldb::addr_t file_address_end, const char *module_name) 375{ 376 if (file_address_start == LLDB_INVALID_ADDRESS) 377 return; 378 379 FILE *out = SBDebugger::GetOutputFileHandle(); 380 if (out == NULL) 381 return; 382 383 if (IsValid()) 384 { 385 SBModule module; 386 if (module_name != NULL) 387 { 388 SBFileSpec file_spec (module_name); 389 module = FindModule (file_spec); 390 } 391 ArchSpec arch (m_target_sp->GetArchitecture()); 392 if (!arch.IsValid()) 393 return; 394 Disassembler *disassembler = Disassembler::FindPlugin (arch); 395 if (disassembler == NULL) 396 return; 397 398 // For now, we need a process; the disassembly functions insist. If we don't have one already, 399 // make one. 400 401 SBProcess process = GetProcess(); 402 if (! process.IsValid()) 403 process = CreateProcess(); 404 405 ExecutionContext exe_context (process.get()); 406 407 if (file_address_end == LLDB_INVALID_ADDRESS 408 || file_address_end < file_address_start) 409 file_address_end = file_address_start + DEFAULT_DISASM_BYTE_SIZE; 410 411 // TO BE FIXED: SOMEHOW WE NEED TO SPECIFY/USE THE MODULE, IF THE USER SPECIFIED ONE. I'M NOT 412 // SURE HOW TO DO THAT AT THE MOMENT. WE ALSO NEED TO FIGURE OUT WHAT TO DO IF THERE ARE MULTIPLE 413 // MODULES CONTAINING THE SPECIFIED ADDRESSES (E.G. THEY HAVEN'T ALL LOADED & BEEN GIVEN UNIQUE 414 // ADDRESSES YET). 415 416 DataExtractor data; 417 size_t bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeLoad, 418 file_address_start, 419 file_address_end - file_address_start, data); 420 421 if (bytes_disassembled > 0) 422 { 423 size_t num_instructions = disassembler->GetInstructionList().GetSize(); 424 uint32_t offset = 0; 425 StreamFile out_stream (out); 426 427 for (size_t i = 0; i < num_instructions; ++i) 428 { 429 Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i); 430 if (inst) 431 { 432 lldb::addr_t cur_addr = file_address_start + offset; 433 size_t inst_byte_size = inst->GetByteSize(); 434 inst->Dump (&out_stream, cur_addr, &data, offset, exe_context, false); 435 out_stream.EOL(); 436 offset += inst_byte_size; 437 } 438 } 439 } 440 } 441} 442 443void 444SBTarget::Disassemble (const char *function_name, const char *module_name) 445{ 446 if (function_name == NULL) 447 return; 448 449 FILE *out = SBDebugger::GetOutputFileHandle(); 450 if (out == NULL) 451 return; 452 453 if (IsValid()) 454 { 455 SBModule module; 456 457 if (module_name != NULL) 458 { 459 SBFileSpec file_spec (module_name); 460 module = FindModule (file_spec); 461 } 462 463 ArchSpec arch (m_target_sp->GetArchitecture()); 464 if (!arch.IsValid()) 465 return; 466 467 Disassembler *disassembler = Disassembler::FindPlugin (arch); 468 if (disassembler == NULL) 469 return; 470 471 // For now, we need a process; the disassembly functions insist. If we don't have one already, 472 // make one. 473 474 SBProcess process = GetProcess(); 475 if (! process.IsValid() 476 || process.GetProcessID() == 0) 477 { 478 fprintf (out, "Cannot disassemble functions until after process has launched.\n"); 479 return; 480 } 481 482 ExecutionContext exe_context (process.get()); 483 484 FileSpec *containing_module = NULL; 485 486 if (module_name != NULL) 487 containing_module = new FileSpec (module_name); 488 489 SearchFilterSP filter_sp (m_target_sp->GetSearchFilterForModule (containing_module)); 490 AddressResolverSP resolver_sp (new AddressResolverName (function_name)); 491 492 resolver_sp->ResolveAddress (*filter_sp); 493 494 size_t num_matches_found = resolver_sp->GetNumberOfAddresses(); 495 496 if (num_matches_found == 1) 497 { 498 DataExtractor data; 499 500 AddressRange func_addresses = resolver_sp->GetAddressRangeAtIndex (0); 501 Address start_addr = func_addresses.GetBaseAddress(); 502 lldb::addr_t num_bytes = func_addresses.GetByteSize(); 503 504 lldb::addr_t addr = LLDB_INVALID_ADDRESS; 505 size_t bytes_disassembled = 0; 506 507 508 if (process.GetProcessID() == 0) 509 { 510 // Leave this branch in for now, but it should not be reached, since we exit above if the PID is 0. 511 addr = start_addr.GetFileAddress (); 512 bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeFile, addr, 513 num_bytes, data); 514 515 } 516 else 517 { 518 addr = start_addr.GetLoadAddress (process.get()); 519 bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeLoad, addr, 520 num_bytes, data); 521 522 } 523 524 if (bytes_disassembled > 0) 525 { 526 size_t num_instructions = disassembler->GetInstructionList().GetSize(); 527 uint32_t offset = 0; 528 StreamFile out_stream (out); 529 530 for (size_t i = 0; i < num_instructions; ++i) 531 { 532 Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i); 533 if (inst) 534 { 535 lldb::addr_t cur_addr = addr + offset; 536 size_t inst_byte_size = inst->GetByteSize(); 537 inst->Dump (&out_stream, cur_addr, &data, offset, exe_context, false); 538 out_stream.EOL(); 539 offset += inst_byte_size; 540 } 541 } 542 } 543 } 544 else if (num_matches_found > 1) 545 { 546 // TO BE FIXED: Eventually we want to list/disassemble all functions found. 547 fprintf (out, "Function '%s' was found in multiple modules; please specify the desired module name.\n", 548 function_name); 549 } 550 else 551 fprintf (out, "Function '%s' was not found.\n", function_name); 552 } 553} 554