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