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 "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/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 
38 #include "SBDebugger.h"
39 #include "SBProcess.h"
40 #include "SBListener.h"
41 #include "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_target_sp (rhs.m_target_sp)
57 {
58 }
59 
60 SBTarget::SBTarget(const TargetSP& target_sp) :
61     m_target_sp (target_sp)
62 {
63 }
64 
65 const SBTarget&
66 SBTarget::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 //----------------------------------------------------------------------
79 SBTarget::~SBTarget()
80 {
81 }
82 
83 bool
84 SBTarget::IsValid () const
85 {
86     return m_target_sp.get() != NULL;
87 }
88 
89 SBProcess
90 SBTarget::GetProcess ()
91 {
92     SBProcess sb_process;
93     if (IsValid())
94         sb_process.SetProcess (m_target_sp->GetProcessSP());
95     return sb_process;
96 }
97 
98 SBProcess
99 SBTarget::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 
112 SBProcess
113 SBTarget::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 
140 SBFileSpec
141 SBTarget::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 
154 bool
155 SBTarget::DeleteTargetFromList (TargetList *list)
156 {
157     if (IsValid())
158         return list->DeleteTarget (m_target_sp);
159     else
160         return false;
161 }
162 
163 bool
164 SBTarget::MakeCurrentTarget ()
165 {
166     if (IsValid())
167     {
168         Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget (m_target_sp.get());
169         return true;
170     }
171     return false;
172 }
173 
174 bool
175 SBTarget::operator == (const SBTarget &rhs) const
176 {
177     return m_target_sp.get() == rhs.m_target_sp.get();
178 }
179 
180 bool
181 SBTarget::operator != (const SBTarget &rhs) const
182 {
183     return m_target_sp.get() != rhs.m_target_sp.get();
184 }
185 
186 lldb_private::Target *
187 SBTarget::GetLLDBObjectPtr()
188 {
189     return m_target_sp.get();
190 }
191 const lldb_private::Target *
192 SBTarget::GetLLDBObjectPtr() const
193 {
194     return m_target_sp.get();
195 }
196 
197 SBBreakpoint
198 SBTarget::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 
206 SBBreakpoint
207 SBTarget::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 
215 SBBreakpoint
216 SBTarget::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 
234 SBBreakpoint
235 SBTarget::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 
258 SBBreakpoint
259 SBTarget::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 
267 void
268 SBTarget::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 
287 SBBreakpoint
288 SBTarget::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 
297 bool
298 SBTarget::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 
305 bool
306 SBTarget::EnableAllBreakpoints ()
307 {
308     if (m_target_sp)
309     {
310         m_target_sp->EnableAllBreakpoints ();
311         return true;
312     }
313     return false;
314 }
315 
316 bool
317 SBTarget::DisableAllBreakpoints ()
318 {
319     if (m_target_sp)
320     {
321         m_target_sp->DisableAllBreakpoints ();
322         return true;
323     }
324     return false;
325 }
326 
327 bool
328 SBTarget::DeleteAllBreakpoints ()
329 {
330     if (m_target_sp)
331     {
332         m_target_sp->RemoveAllBreakpoints ();
333         return true;
334     }
335     return false;
336 }
337 
338 
339 uint32_t
340 SBTarget::GetNumModules () const
341 {
342     if (m_target_sp)
343         return m_target_sp->GetImages().GetSize();
344     return 0;
345 }
346 
347 SBModule
348 SBTarget::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 
356 SBModule
357 SBTarget::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 
366 SBBroadcaster
367 SBTarget::GetBroadcaster () const
368 {
369     SBBroadcaster broadcaster(m_target_sp.get(), false);
370     return broadcaster;
371 }
372 
373 void
374 SBTarget::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 
443 void
444 SBTarget::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