blob: f1b8ac55cc1a4606d8be22ab4a7dce5148e8f658 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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/StreamString.h"
Jim Ingham2cf5ccb2012-05-22 00:12:20 +000019#include "lldb/Target/Target.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/lldb-private-log.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25//----------------------------------------------------------------------
26// BreakpointResolverFileLine:
27//----------------------------------------------------------------------
28BreakpointResolverFileLine::BreakpointResolverFileLine
29(
30 Breakpoint *bkpt,
31 const FileSpec &file_spec,
32 uint32_t line_no,
Jim Ingham2cf5ccb2012-05-22 00:12:20 +000033 bool check_inlines,
34 bool skip_prologue
Chris Lattner24943d22010-06-08 16:52:24 +000035) :
Johnny Chena62ad7c2010-10-28 17:27:46 +000036 BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver),
Chris Lattner24943d22010-06-08 16:52:24 +000037 m_file_spec (file_spec),
38 m_line_number (line_no),
Jim Ingham2cf5ccb2012-05-22 00:12:20 +000039 m_inlines (check_inlines),
40 m_skip_prologue(skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +000041{
42}
43
44BreakpointResolverFileLine::~BreakpointResolverFileLine ()
45{
46}
47
48Searcher::CallbackReturn
49BreakpointResolverFileLine::SearchCallback
50(
51 SearchFilter &filter,
52 SymbolContext &context,
53 Address *addr,
54 bool containing
55)
56{
57 SymbolContextList sc_list;
Chris Lattner24943d22010-06-08 16:52:24 +000058
59 assert (m_breakpoint != NULL);
Greg Claytone005f2c2010-11-06 01:53:30 +000060 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Jim Inghama44297a2012-01-13 02:04:05 +000061
62 // There is a tricky bit here. You can have two compilation units that #include the same file, and
63 // 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
64 // other it isn't. If we considered the CU's independently, then in the second inclusion, we'd move the breakpoint
65 // to the next function that actually generated code in the header file. That would end up being confusing.
66 // So instead, we do the CU iterations by hand here, then scan through the complete list of matches, and figure out
67 // the closest line number match, and only set breakpoints on that match.
68
69 // Note also that if file_spec only had a file name and not a directory, there may be many different file spec's in
70 // the resultant list. The closest line match for one will not be right for some totally different file.
71 // So we go through the match list and pull out the sets that have the same file spec in their line_entry
72 // and treat each set separately.
73
74 uint32_t num_comp_units = context.module_sp->GetNumCompileUnits();
75 for (uint32_t i = 0; i < num_comp_units; i++)
Chris Lattner24943d22010-06-08 16:52:24 +000076 {
Jim Inghama44297a2012-01-13 02:04:05 +000077 CompUnitSP cu_sp (context.module_sp->GetCompileUnitAtIndex (i));
Greg Claytonc7057302012-04-23 22:00:21 +000078 if (cu_sp)
79 {
80 if (filter.CompUnitPasses(*cu_sp))
81 cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list);
82 }
Jim Inghama44297a2012-01-13 02:04:05 +000083 }
84
85 while (sc_list.GetSize() > 0)
86 {
87 SymbolContextList tmp_sc_list;
88 int current_idx = 0;
Chris Lattner24943d22010-06-08 16:52:24 +000089 SymbolContext sc;
Jim Inghama44297a2012-01-13 02:04:05 +000090 bool first_entry = true;
91
92 FileSpec match_file_spec;
93 uint32_t closest_line_number = UINT32_MAX;
94
95 // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
96 while (current_idx < sc_list.GetSize())
Chris Lattner24943d22010-06-08 16:52:24 +000097 {
Jim Inghama44297a2012-01-13 02:04:05 +000098 bool matches;
99
100 sc_list.GetContextAtIndex (current_idx, sc);
101 if (first_entry)
Chris Lattner24943d22010-06-08 16:52:24 +0000102 {
Jim Inghama44297a2012-01-13 02:04:05 +0000103 match_file_spec = sc.line_entry.file;
104 matches = true;
105 first_entry = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000106 }
107 else
Jim Inghama44297a2012-01-13 02:04:05 +0000108 matches = (sc.line_entry.file == match_file_spec);
109
110 if (matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000111 {
Jim Inghama44297a2012-01-13 02:04:05 +0000112 tmp_sc_list.Append (sc);
113 sc_list.RemoveContextAtIndex(current_idx);
114
115 // ResolveSymbolContext will always return a number that is >= the line number you pass in.
116 // So the smaller line number is always better.
117 if (sc.line_entry.line < closest_line_number)
118 closest_line_number = sc.line_entry.line;
119 }
120 else
121 current_idx++;
122 }
123
124 // Okay, we've found the closest line number match, now throw away all the others,
125 // and make breakpoints out of the closest line number match.
126
127 uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
128
129 for (uint32_t i = 0; i < tmp_sc_list_size; i++)
130 {
131 SymbolContext sc;
132 if (tmp_sc_list.GetContextAtIndex(i, sc))
133 {
134 if (sc.line_entry.line == closest_line_number)
135 {
136 Address line_start = sc.line_entry.range.GetBaseAddress();
137 if (line_start.IsValid())
138 {
139 if (filter.AddressPasses(line_start))
140 {
Jim Ingham2cf5ccb2012-05-22 00:12:20 +0000141 // If the line number is before the prologue end, move it there...
142 bool skipped_prologue = false;
143 if (m_skip_prologue)
144 {
145 if (sc.function)
146 {
147 Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
148 if (prologue_addr.IsValid() && (line_start == prologue_addr))
149 {
150 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
151 if (prologue_byte_size)
152 {
153 prologue_addr.Slide(prologue_byte_size);
154
155 if (filter.AddressPasses(prologue_addr))
156 {
157 skipped_prologue = true;
158 line_start = prologue_addr;
159 }
160 }
161 }
162 }
163 }
164
Jim Inghama44297a2012-01-13 02:04:05 +0000165 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
166 if (log && bp_loc_sp && !m_breakpoint->IsInternal())
167 {
168 StreamString s;
169 bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
Jim Ingham2cf5ccb2012-05-22 00:12:20 +0000170 log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData());
Jim Inghama44297a2012-01-13 02:04:05 +0000171 }
172 }
173 else if (log)
174 {
175 log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass the filter.\n",
176 line_start.GetFileAddress(),
177 m_file_spec.GetFilename().AsCString("<Unknown>"),
178 m_line_number);
179 }
180 }
181 else
182 {
183 if (log)
184 log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
185 line_start.GetFileAddress(),
186 m_file_spec.GetFilename().AsCString("<Unknown>"),
187 m_line_number);
188 }
189 }
190 else
191 {
192 #if 0
193 s << "error: Breakpoint at '" << pos->c_str() << "' isn't resolved yet: \n";
194 if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionNameOffset))
195 s.EOL();
196 if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionPointerOffset))
197 s.EOL();
198 if (sc.line_entry.address.Dump(&s, Address::DumpStyleFileAddress))
199 s.EOL();
200 if (sc.line_entry.address.Dump(&s, Address::DumpStyleLoadAddress))
201 s.EOL();
202 #endif
203 }
Chris Lattner24943d22010-06-08 16:52:24 +0000204 }
205 }
Chris Lattner24943d22010-06-08 16:52:24 +0000206 }
Jim Inghama44297a2012-01-13 02:04:05 +0000207
Chris Lattner24943d22010-06-08 16:52:24 +0000208 return Searcher::eCallbackReturnContinue;
209}
210
211Searcher::Depth
212BreakpointResolverFileLine::GetDepth()
213{
Jim Inghama44297a2012-01-13 02:04:05 +0000214 return Searcher::eDepthModule;
Chris Lattner24943d22010-06-08 16:52:24 +0000215}
216
217void
218BreakpointResolverFileLine::GetDescription (Stream *s)
219{
Greg Clayton12bec712010-06-28 21:30:43 +0000220 s->Printf ("file ='%s', line = %u", m_file_spec.GetFilename().AsCString(), m_line_number);
Chris Lattner24943d22010-06-08 16:52:24 +0000221}
222
223void
224BreakpointResolverFileLine::Dump (Stream *s) const
225{
226
227}
228