blob: ff08689acd95d17ad9f7c412d6881734b7caa7b4 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
Eli Friedman7a62c8b2010-06-09 07:44:37 +000010#include "lldb/API/SBTarget.h"
Chris Lattner24943d22010-06-08 16:52:24 +000011
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"
Jim Ingham84cdc152010-06-15 19:49:27 +000023#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000024#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
Eli Friedman7a62c8b2010-06-09 07:44:37 +000038#include "lldb/API/SBDebugger.h"
39#include "lldb/API/SBProcess.h"
40#include "lldb/API/SBListener.h"
41#include "lldb/API/SBBreakpoint.h"
Chris Lattner24943d22010-06-08 16:52:24 +000042
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) :
Greg Clayton63094e02010-06-23 01:19:29 +000056 m_opaque_sp (rhs.m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000057{
58}
59
60SBTarget::SBTarget(const TargetSP& target_sp) :
Greg Clayton63094e02010-06-23 01:19:29 +000061 m_opaque_sp (target_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000062{
63}
64
65const SBTarget&
66SBTarget::Assign (const SBTarget& rhs)
67{
68 if (this != &rhs)
69 {
Greg Clayton63094e02010-06-23 01:19:29 +000070 m_opaque_sp = rhs.m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +000071 }
72 return *this;
73}
74
75
76//----------------------------------------------------------------------
77// Destructor
78//----------------------------------------------------------------------
79SBTarget::~SBTarget()
80{
81}
82
83bool
84SBTarget::IsValid () const
85{
Greg Clayton63094e02010-06-23 01:19:29 +000086 return m_opaque_sp.get() != NULL;
Chris Lattner24943d22010-06-08 16:52:24 +000087}
88
89SBProcess
90SBTarget::GetProcess ()
91{
92 SBProcess sb_process;
Greg Clayton63094e02010-06-23 01:19:29 +000093 if (m_opaque_sp)
94 sb_process.SetProcess (m_opaque_sp->GetProcessSP());
Chris Lattner24943d22010-06-08 16:52:24 +000095 return sb_process;
96}
97
Greg Clayton63094e02010-06-23 01:19:29 +000098SBDebugger
99SBTarget::GetDebugger () const
100{
101 SBDebugger debugger;
102 if (m_opaque_sp)
103 debugger.reset (m_opaque_sp->GetDebugger().GetSP());
104 return debugger;
105}
106
Chris Lattner24943d22010-06-08 16:52:24 +0000107SBProcess
108SBTarget::CreateProcess ()
109{
110 SBProcess sb_process;
111
Greg Clayton63094e02010-06-23 01:19:29 +0000112 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000113 {
Greg Clayton63094e02010-06-23 01:19:29 +0000114 SBListener sb_listener (m_opaque_sp->GetDebugger().GetListener());
Chris Lattner24943d22010-06-08 16:52:24 +0000115 if (sb_listener.IsValid())
Greg Clayton63094e02010-06-23 01:19:29 +0000116 sb_process.SetProcess (m_opaque_sp->CreateProcess (*sb_listener));
Chris Lattner24943d22010-06-08 16:52:24 +0000117 }
118 return sb_process;
119}
120
121SBProcess
122SBTarget::LaunchProcess
123(
124 char const **argv,
125 char const **envp,
126 const char *tty,
127 bool stop_at_entry
128)
129{
130 SBProcess process(GetProcess ());
131 if (!process.IsValid())
132 process = CreateProcess();
133 if (process.IsValid())
134 {
135 Error error (process->Launch (argv, envp, tty, tty, tty));
136 if (error.Success())
137 {
138 if (!stop_at_entry)
139 {
140 StateType state = process->WaitForProcessToStop (NULL);
141 if (state == eStateStopped)
142 process->Resume();
143 }
144 }
145 }
146 return process;
147}
148
149SBFileSpec
150SBTarget::GetExecutable ()
151{
152 SBFileSpec exe_file_spec;
Greg Clayton63094e02010-06-23 01:19:29 +0000153 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000154 {
Greg Clayton63094e02010-06-23 01:19:29 +0000155 ModuleSP exe_module_sp (m_opaque_sp->GetExecutableModule ());
Chris Lattner24943d22010-06-08 16:52:24 +0000156 if (exe_module_sp)
157 exe_file_spec.SetFileSpec (exe_module_sp->GetFileSpec());
158 }
159 return exe_file_spec;
160}
161
162
163bool
164SBTarget::DeleteTargetFromList (TargetList *list)
165{
Greg Clayton63094e02010-06-23 01:19:29 +0000166 if (m_opaque_sp)
167 return list->DeleteTarget (m_opaque_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000168 else
169 return false;
170}
171
172bool
173SBTarget::MakeCurrentTarget ()
174{
Greg Clayton63094e02010-06-23 01:19:29 +0000175 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000176 {
Greg Clayton63094e02010-06-23 01:19:29 +0000177 m_opaque_sp->GetDebugger().GetTargetList().SetCurrentTarget (m_opaque_sp.get());
Chris Lattner24943d22010-06-08 16:52:24 +0000178 return true;
179 }
180 return false;
181}
182
183bool
184SBTarget::operator == (const SBTarget &rhs) const
185{
Greg Clayton63094e02010-06-23 01:19:29 +0000186 return m_opaque_sp.get() == rhs.m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000187}
188
189bool
190SBTarget::operator != (const SBTarget &rhs) const
191{
Greg Clayton63094e02010-06-23 01:19:29 +0000192 return m_opaque_sp.get() != rhs.m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000193}
194
195lldb_private::Target *
Greg Clayton63094e02010-06-23 01:19:29 +0000196SBTarget::operator ->() const
Chris Lattner24943d22010-06-08 16:52:24 +0000197{
Greg Clayton63094e02010-06-23 01:19:29 +0000198 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000199}
Greg Clayton63094e02010-06-23 01:19:29 +0000200
201lldb_private::Target *
202SBTarget::get() const
Chris Lattner24943d22010-06-08 16:52:24 +0000203{
Greg Clayton63094e02010-06-23 01:19:29 +0000204 return m_opaque_sp.get();
205}
206
207void
208SBTarget::reset (const lldb::TargetSP& target_sp)
209{
210 m_opaque_sp = target_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000211}
212
213SBBreakpoint
214SBTarget::BreakpointCreateByLocation (const char *file, uint32_t line)
215{
216 SBBreakpoint sb_bp;
217 if (file != NULL && line != 0)
218 sb_bp = BreakpointCreateByLocation (SBFileSpec (file), line);
219 return sb_bp;
220}
221
222SBBreakpoint
223SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t line)
224{
225 SBBreakpoint sb_bp;
Greg Clayton63094e02010-06-23 01:19:29 +0000226 if (m_opaque_sp.get() && line != 0)
227 *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, *sb_file_spec, line, true, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000228 return sb_bp;
229}
230
231SBBreakpoint
232SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_name)
233{
234 SBBreakpoint sb_bp;
Greg Clayton63094e02010-06-23 01:19:29 +0000235 if (m_opaque_sp.get() && symbol_name && symbol_name[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000236 {
237 if (module_name && module_name[0])
238 {
239 FileSpec module_file_spec(module_name);
Greg Clayton63094e02010-06-23 01:19:29 +0000240 *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, symbol_name, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000241 }
242 else
243 {
Greg Clayton63094e02010-06-23 01:19:29 +0000244 *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, symbol_name, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000245 }
246 }
247 return sb_bp;
248}
249
250SBBreakpoint
251SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name)
252{
253 SBBreakpoint sb_bp;
Greg Clayton63094e02010-06-23 01:19:29 +0000254 if (m_opaque_sp.get() && symbol_name_regex && symbol_name_regex[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000255 {
256 RegularExpression regexp(symbol_name_regex);
257
258 if (module_name && module_name[0])
259 {
260 FileSpec module_file_spec(module_name);
261
Greg Clayton63094e02010-06-23 01:19:29 +0000262 *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, regexp, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000263 }
264 else
265 {
Greg Clayton63094e02010-06-23 01:19:29 +0000266 *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, regexp, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000267 }
268 }
269 return sb_bp;
270}
271
272
273
274SBBreakpoint
275SBTarget::BreakpointCreateByAddress (addr_t address)
276{
277 SBBreakpoint sb_bp;
Greg Clayton63094e02010-06-23 01:19:29 +0000278 if (m_opaque_sp.get())
279 *sb_bp = m_opaque_sp->CreateBreakpoint (address, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000280 return sb_bp;
281}
282
283void
284SBTarget::ListAllBreakpoints ()
285{
Greg Clayton63094e02010-06-23 01:19:29 +0000286 FILE *out_file = m_opaque_sp->GetDebugger().GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000287
288 if (out_file == NULL)
289 return;
290
Greg Clayton63094e02010-06-23 01:19:29 +0000291 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000292 {
Greg Clayton63094e02010-06-23 01:19:29 +0000293 const BreakpointList &bp_list = m_opaque_sp->GetBreakpointList();
Chris Lattner24943d22010-06-08 16:52:24 +0000294 size_t num_bps = bp_list.GetSize();
295 for (int i = 0; i < num_bps; ++i)
296 {
297 SBBreakpoint sb_breakpoint (bp_list.GetBreakpointByIndex (i));
298 sb_breakpoint.GetDescription (out_file, "full");
299 }
300 }
301}
302
303SBBreakpoint
304SBTarget::FindBreakpointByID (break_id_t bp_id)
305{
306 SBBreakpoint sb_breakpoint;
Greg Clayton63094e02010-06-23 01:19:29 +0000307 if (m_opaque_sp && bp_id != LLDB_INVALID_BREAK_ID)
308 *sb_breakpoint = m_opaque_sp->GetBreakpointByID (bp_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000309 return sb_breakpoint;
310}
311
312
313bool
314SBTarget::BreakpointDelete (break_id_t bp_id)
315{
Greg Clayton63094e02010-06-23 01:19:29 +0000316 if (m_opaque_sp)
317 return m_opaque_sp->RemoveBreakpointByID (bp_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000318 return false;
319}
320
321bool
322SBTarget::EnableAllBreakpoints ()
323{
Greg Clayton63094e02010-06-23 01:19:29 +0000324 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000325 {
Greg Clayton63094e02010-06-23 01:19:29 +0000326 m_opaque_sp->EnableAllBreakpoints ();
Chris Lattner24943d22010-06-08 16:52:24 +0000327 return true;
328 }
329 return false;
330}
331
332bool
333SBTarget::DisableAllBreakpoints ()
334{
Greg Clayton63094e02010-06-23 01:19:29 +0000335 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000336 {
Greg Clayton63094e02010-06-23 01:19:29 +0000337 m_opaque_sp->DisableAllBreakpoints ();
Chris Lattner24943d22010-06-08 16:52:24 +0000338 return true;
339 }
340 return false;
341}
342
343bool
344SBTarget::DeleteAllBreakpoints ()
345{
Greg Clayton63094e02010-06-23 01:19:29 +0000346 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000347 {
Greg Clayton63094e02010-06-23 01:19:29 +0000348 m_opaque_sp->RemoveAllBreakpoints ();
Chris Lattner24943d22010-06-08 16:52:24 +0000349 return true;
350 }
351 return false;
352}
353
354
355uint32_t
356SBTarget::GetNumModules () const
357{
Greg Clayton63094e02010-06-23 01:19:29 +0000358 if (m_opaque_sp)
359 return m_opaque_sp->GetImages().GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000360 return 0;
361}
362
363SBModule
364SBTarget::FindModule (const SBFileSpec &sb_file_spec)
365{
366 SBModule sb_module;
Greg Clayton63094e02010-06-23 01:19:29 +0000367 if (m_opaque_sp && sb_file_spec.IsValid())
368 sb_module.SetModule (m_opaque_sp->GetImages().FindFirstModuleForFileSpec (*sb_file_spec, NULL));
Chris Lattner24943d22010-06-08 16:52:24 +0000369 return sb_module;
370}
371
372SBModule
373SBTarget::GetModuleAtIndex (uint32_t idx)
374{
375 SBModule sb_module;
Greg Clayton63094e02010-06-23 01:19:29 +0000376 if (m_opaque_sp)
377 sb_module.SetModule(m_opaque_sp->GetImages().GetModuleAtIndex(idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000378 return sb_module;
379}
380
381
382SBBroadcaster
383SBTarget::GetBroadcaster () const
384{
Greg Clayton63094e02010-06-23 01:19:29 +0000385 SBBroadcaster broadcaster(m_opaque_sp.get(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000386 return broadcaster;
387}
388
389void
390SBTarget::Disassemble (lldb::addr_t file_address_start, lldb::addr_t file_address_end, const char *module_name)
391{
392 if (file_address_start == LLDB_INVALID_ADDRESS)
393 return;
394
Greg Clayton63094e02010-06-23 01:19:29 +0000395 FILE *out = m_opaque_sp->GetDebugger().GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000396 if (out == NULL)
397 return;
398
Greg Clayton63094e02010-06-23 01:19:29 +0000399 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000400 {
401 SBModule module;
402 if (module_name != NULL)
403 {
404 SBFileSpec file_spec (module_name);
405 module = FindModule (file_spec);
406 }
Greg Clayton63094e02010-06-23 01:19:29 +0000407 ArchSpec arch (m_opaque_sp->GetArchitecture());
Chris Lattner24943d22010-06-08 16:52:24 +0000408 if (!arch.IsValid())
409 return;
410 Disassembler *disassembler = Disassembler::FindPlugin (arch);
411 if (disassembler == NULL)
412 return;
413
414 // For now, we need a process; the disassembly functions insist. If we don't have one already,
415 // make one.
416
417 SBProcess process = GetProcess();
418 if (! process.IsValid())
419 process = CreateProcess();
420
421 ExecutionContext exe_context (process.get());
422
423 if (file_address_end == LLDB_INVALID_ADDRESS
424 || file_address_end < file_address_start)
425 file_address_end = file_address_start + DEFAULT_DISASM_BYTE_SIZE;
426
427 // TO BE FIXED: SOMEHOW WE NEED TO SPECIFY/USE THE MODULE, IF THE USER SPECIFIED ONE. I'M NOT
428 // SURE HOW TO DO THAT AT THE MOMENT. WE ALSO NEED TO FIGURE OUT WHAT TO DO IF THERE ARE MULTIPLE
429 // MODULES CONTAINING THE SPECIFIED ADDRESSES (E.G. THEY HAVEN'T ALL LOADED & BEEN GIVEN UNIQUE
430 // ADDRESSES YET).
431
432 DataExtractor data;
433 size_t bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeLoad,
434 file_address_start,
435 file_address_end - file_address_start, data);
436
437 if (bytes_disassembled > 0)
438 {
439 size_t num_instructions = disassembler->GetInstructionList().GetSize();
440 uint32_t offset = 0;
441 StreamFile out_stream (out);
442
443 for (size_t i = 0; i < num_instructions; ++i)
444 {
445 Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
446 if (inst)
447 {
448 lldb::addr_t cur_addr = file_address_start + offset;
449 size_t inst_byte_size = inst->GetByteSize();
450 inst->Dump (&out_stream, cur_addr, &data, offset, exe_context, false);
451 out_stream.EOL();
452 offset += inst_byte_size;
453 }
454 }
455 }
456 }
457}
458
459void
460SBTarget::Disassemble (const char *function_name, const char *module_name)
461{
462 if (function_name == NULL)
463 return;
464
Greg Clayton63094e02010-06-23 01:19:29 +0000465 FILE *out = m_opaque_sp->GetDebugger().GetOutputFileHandle();
Chris Lattner24943d22010-06-08 16:52:24 +0000466 if (out == NULL)
467 return;
468
Greg Clayton63094e02010-06-23 01:19:29 +0000469 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000470 {
471 SBModule module;
472
473 if (module_name != NULL)
474 {
475 SBFileSpec file_spec (module_name);
476 module = FindModule (file_spec);
477 }
478
Greg Clayton63094e02010-06-23 01:19:29 +0000479 ArchSpec arch (m_opaque_sp->GetArchitecture());
Chris Lattner24943d22010-06-08 16:52:24 +0000480 if (!arch.IsValid())
481 return;
482
483 Disassembler *disassembler = Disassembler::FindPlugin (arch);
484 if (disassembler == NULL)
485 return;
486
487 // For now, we need a process; the disassembly functions insist. If we don't have one already,
488 // make one.
489
490 SBProcess process = GetProcess();
491 if (! process.IsValid()
492 || process.GetProcessID() == 0)
493 {
494 fprintf (out, "Cannot disassemble functions until after process has launched.\n");
495 return;
496 }
497
498 ExecutionContext exe_context (process.get());
499
500 FileSpec *containing_module = NULL;
501
502 if (module_name != NULL)
503 containing_module = new FileSpec (module_name);
504
Greg Clayton63094e02010-06-23 01:19:29 +0000505 SearchFilterSP filter_sp (m_opaque_sp->GetSearchFilterForModule (containing_module));
Chris Lattner24943d22010-06-08 16:52:24 +0000506 AddressResolverSP resolver_sp (new AddressResolverName (function_name));
507
508 resolver_sp->ResolveAddress (*filter_sp);
509
510 size_t num_matches_found = resolver_sp->GetNumberOfAddresses();
511
512 if (num_matches_found == 1)
513 {
514 DataExtractor data;
515
516 AddressRange func_addresses = resolver_sp->GetAddressRangeAtIndex (0);
517 Address start_addr = func_addresses.GetBaseAddress();
518 lldb::addr_t num_bytes = func_addresses.GetByteSize();
519
520 lldb::addr_t addr = LLDB_INVALID_ADDRESS;
521 size_t bytes_disassembled = 0;
522
523
524 if (process.GetProcessID() == 0)
525 {
526 // Leave this branch in for now, but it should not be reached, since we exit above if the PID is 0.
527 addr = start_addr.GetFileAddress ();
528 bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeFile, addr,
529 num_bytes, data);
530
531 }
532 else
533 {
534 addr = start_addr.GetLoadAddress (process.get());
535 bytes_disassembled = disassembler->ParseInstructions (&exe_context, eAddressTypeLoad, addr,
536 num_bytes, data);
537
538 }
539
540 if (bytes_disassembled > 0)
541 {
542 size_t num_instructions = disassembler->GetInstructionList().GetSize();
543 uint32_t offset = 0;
544 StreamFile out_stream (out);
545
546 for (size_t i = 0; i < num_instructions; ++i)
547 {
548 Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
549 if (inst)
550 {
551 lldb::addr_t cur_addr = addr + offset;
552 size_t inst_byte_size = inst->GetByteSize();
553 inst->Dump (&out_stream, cur_addr, &data, offset, exe_context, false);
554 out_stream.EOL();
555 offset += inst_byte_size;
556 }
557 }
558 }
559 }
560 else if (num_matches_found > 1)
561 {
562 // TO BE FIXED: Eventually we want to list/disassemble all functions found.
563 fprintf (out, "Function '%s' was found in multiple modules; please specify the desired module name.\n",
564 function_name);
565 }
566 else
567 fprintf (out, "Function '%s' was not found.\n", function_name);
568 }
569}