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