1 //===-- BreakpointResolverFileLine.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/Breakpoint/BreakpointResolverFileLine.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/StreamString.h"
20 #include "lldb/Symbol/CompileUnit.h"
21 #include "lldb/Symbol/Function.h"
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 
26 //----------------------------------------------------------------------
27 // BreakpointResolverFileLine:
28 //----------------------------------------------------------------------
29 BreakpointResolverFileLine::BreakpointResolverFileLine
30 (
31     Breakpoint *bkpt,
32     const FileSpec &file_spec,
33     uint32_t line_no,
34     lldb::addr_t offset,
35     bool check_inlines,
36     bool skip_prologue,
37     bool exact_match
38 ) :
39     BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver, offset),
40     m_file_spec (file_spec),
41     m_line_number (line_no),
42     m_inlines (check_inlines),
43     m_skip_prologue(skip_prologue),
44     m_exact_match(exact_match)
45 {
46 }
47 
48 BreakpointResolverFileLine::~BreakpointResolverFileLine ()
49 {
50 }
51 
52 Searcher::CallbackReturn
53 BreakpointResolverFileLine::SearchCallback
54 (
55     SearchFilter &filter,
56     SymbolContext &context,
57     Address *addr,
58     bool containing
59 )
60 {
61     SymbolContextList sc_list;
62 
63     assert (m_breakpoint != NULL);
64 
65     // There is a tricky bit here.  You can have two compilation units that #include the same file, and
66     // in one of them the function at m_line_number is used (and so code and a line entry for it is generated) but in the
67     // other it isn't.  If we considered the CU's independently, then in the second inclusion, we'd move the breakpoint
68     // to the next function that actually generated code in the header file.  That would end up being confusing.
69     // So instead, we do the CU iterations by hand here, then scan through the complete list of matches, and figure out
70     // the closest line number match, and only set breakpoints on that match.
71 
72     // Note also that if file_spec only had a file name and not a directory, there may be many different file spec's in
73     // the resultant list.  The closest line match for one will not be right for some totally different file.
74     // So we go through the match list and pull out the sets that have the same file spec in their line_entry
75     // and treat each set separately.
76 
77     const size_t num_comp_units = context.module_sp->GetNumCompileUnits();
78     for (size_t i = 0; i < num_comp_units; i++)
79     {
80         CompUnitSP cu_sp (context.module_sp->GetCompileUnitAtIndex (i));
81         if (cu_sp)
82         {
83             if (filter.CompUnitPasses(*cu_sp))
84                 cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, m_exact_match, eSymbolContextEverything, sc_list);
85         }
86     }
87     StreamString s;
88     s.Printf ("for %s:%d ",
89                         m_file_spec.GetFilename().AsCString("<Unknown>"),
90                         m_line_number);
91 
92     SetSCMatchesByLine (filter, sc_list, m_skip_prologue, s.GetData());
93 
94     return Searcher::eCallbackReturnContinue;
95 }
96 
97 Searcher::Depth
98 BreakpointResolverFileLine::GetDepth()
99 {
100     return Searcher::eDepthModule;
101 }
102 
103 void
104 BreakpointResolverFileLine::GetDescription (Stream *s)
105 {
106     s->Printf ("file = '%s', line = %u, exact_match = %d", m_file_spec.GetPath().c_str(), m_line_number, m_exact_match);
107 }
108 
109 void
110 BreakpointResolverFileLine::Dump (Stream *s) const
111 {
112 
113 }
114 
115 lldb::BreakpointResolverSP
116 BreakpointResolverFileLine::CopyForBreakpoint (Breakpoint &breakpoint)
117 {
118     lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine(&breakpoint,
119                                                                      m_file_spec,
120                                                                      m_line_number,
121                                                                      m_offset,
122                                                                      m_inlines,
123                                                                      m_skip_prologue,
124                                                                      m_exact_match));
125 
126     return ret_sp;
127 }
128