blob: 14405b4563802df24e925eea93ee10ac1cb8f11e [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"
23#include "lldb/Core/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
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) :
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}