blob: 6231bce658932032f0dbecc9ea81fc8933a7f189 [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"
Greg Clayton49ce8962012-08-29 21:13:06 +000018#include "lldb/Core/Module.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000020#include "lldb/Symbol/CompileUnit.h"
21#include "lldb/Symbol/Function.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/lldb-private-log.h"
23
24using namespace lldb;
25using namespace lldb_private;
26
27//----------------------------------------------------------------------
28// BreakpointResolverFileLine:
29//----------------------------------------------------------------------
30BreakpointResolverFileLine::BreakpointResolverFileLine
31(
32 Breakpoint *bkpt,
33 const FileSpec &file_spec,
34 uint32_t line_no,
Jim Ingham2cf5ccb2012-05-22 00:12:20 +000035 bool check_inlines,
36 bool skip_prologue
Chris Lattner24943d22010-06-08 16:52:24 +000037) :
Johnny Chena62ad7c2010-10-28 17:27:46 +000038 BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver),
Chris Lattner24943d22010-06-08 16:52:24 +000039 m_file_spec (file_spec),
40 m_line_number (line_no),
Jim Ingham2cf5ccb2012-05-22 00:12:20 +000041 m_inlines (check_inlines),
42 m_skip_prologue(skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +000043{
44}
45
46BreakpointResolverFileLine::~BreakpointResolverFileLine ()
47{
48}
49
50Searcher::CallbackReturn
51BreakpointResolverFileLine::SearchCallback
52(
53 SearchFilter &filter,
54 SymbolContext &context,
55 Address *addr,
56 bool containing
57)
58{
59 SymbolContextList sc_list;
Chris Lattner24943d22010-06-08 16:52:24 +000060
61 assert (m_breakpoint != NULL);
Greg Claytone005f2c2010-11-06 01:53:30 +000062 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Jim Inghama44297a2012-01-13 02:04:05 +000063
64 // There is a tricky bit here. You can have two compilation units that #include the same file, and
65 // 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
66 // other it isn't. If we considered the CU's independently, then in the second inclusion, we'd move the breakpoint
67 // to the next function that actually generated code in the header file. That would end up being confusing.
68 // So instead, we do the CU iterations by hand here, then scan through the complete list of matches, and figure out
69 // the closest line number match, and only set breakpoints on that match.
70
71 // Note also that if file_spec only had a file name and not a directory, there may be many different file spec's in
72 // the resultant list. The closest line match for one will not be right for some totally different file.
73 // So we go through the match list and pull out the sets that have the same file spec in their line_entry
74 // and treat each set separately.
75
76 uint32_t num_comp_units = context.module_sp->GetNumCompileUnits();
77 for (uint32_t i = 0; i < num_comp_units; i++)
Chris Lattner24943d22010-06-08 16:52:24 +000078 {
Jim Inghama44297a2012-01-13 02:04:05 +000079 CompUnitSP cu_sp (context.module_sp->GetCompileUnitAtIndex (i));
Greg Claytonc7057302012-04-23 22:00:21 +000080 if (cu_sp)
81 {
82 if (filter.CompUnitPasses(*cu_sp))
83 cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list);
84 }
Jim Inghama44297a2012-01-13 02:04:05 +000085 }
86
87 while (sc_list.GetSize() > 0)
88 {
89 SymbolContextList tmp_sc_list;
90 int current_idx = 0;
Chris Lattner24943d22010-06-08 16:52:24 +000091 SymbolContext sc;
Jim Inghama44297a2012-01-13 02:04:05 +000092 bool first_entry = true;
93
94 FileSpec match_file_spec;
95 uint32_t closest_line_number = UINT32_MAX;
96
97 // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
98 while (current_idx < sc_list.GetSize())
Chris Lattner24943d22010-06-08 16:52:24 +000099 {
Jim Inghama44297a2012-01-13 02:04:05 +0000100 bool matches;
101
102 sc_list.GetContextAtIndex (current_idx, sc);
103 if (first_entry)
Chris Lattner24943d22010-06-08 16:52:24 +0000104 {
Jim Inghama44297a2012-01-13 02:04:05 +0000105 match_file_spec = sc.line_entry.file;
106 matches = true;
107 first_entry = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000108 }
109 else
Jim Inghama44297a2012-01-13 02:04:05 +0000110 matches = (sc.line_entry.file == match_file_spec);
111
112 if (matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000113 {
Jim Inghama44297a2012-01-13 02:04:05 +0000114 tmp_sc_list.Append (sc);
115 sc_list.RemoveContextAtIndex(current_idx);
116
117 // ResolveSymbolContext will always return a number that is >= the line number you pass in.
118 // So the smaller line number is always better.
119 if (sc.line_entry.line < closest_line_number)
120 closest_line_number = sc.line_entry.line;
121 }
122 else
123 current_idx++;
124 }
125
126 // Okay, we've found the closest line number match, now throw away all the others,
127 // and make breakpoints out of the closest line number match.
128
129 uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
130
131 for (uint32_t i = 0; i < tmp_sc_list_size; i++)
132 {
133 SymbolContext sc;
134 if (tmp_sc_list.GetContextAtIndex(i, sc))
135 {
136 if (sc.line_entry.line == closest_line_number)
137 {
138 Address line_start = sc.line_entry.range.GetBaseAddress();
139 if (line_start.IsValid())
140 {
141 if (filter.AddressPasses(line_start))
142 {
Jim Ingham2cf5ccb2012-05-22 00:12:20 +0000143 // If the line number is before the prologue end, move it there...
144 bool skipped_prologue = false;
145 if (m_skip_prologue)
146 {
147 if (sc.function)
148 {
149 Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress());
150 if (prologue_addr.IsValid() && (line_start == prologue_addr))
151 {
152 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
153 if (prologue_byte_size)
154 {
155 prologue_addr.Slide(prologue_byte_size);
156
157 if (filter.AddressPasses(prologue_addr))
158 {
159 skipped_prologue = true;
160 line_start = prologue_addr;
161 }
162 }
163 }
164 }
165 }
166
Jim Inghama44297a2012-01-13 02:04:05 +0000167 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
168 if (log && bp_loc_sp && !m_breakpoint->IsInternal())
169 {
170 StreamString s;
171 bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
Jim Ingham2cf5ccb2012-05-22 00:12:20 +0000172 log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData());
Jim Inghama44297a2012-01-13 02:04:05 +0000173 }
174 }
175 else if (log)
176 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000177 log->Printf ("Breakpoint at file address 0x%" PRIx64 " for %s:%d didn't pass the filter.\n",
Jim Inghama44297a2012-01-13 02:04:05 +0000178 line_start.GetFileAddress(),
179 m_file_spec.GetFilename().AsCString("<Unknown>"),
180 m_line_number);
181 }
182 }
183 else
184 {
185 if (log)
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000186 log->Printf ("error: Unable to set breakpoint at file address 0x%" PRIx64 " for %s:%d\n",
Jim Inghama44297a2012-01-13 02:04:05 +0000187 line_start.GetFileAddress(),
188 m_file_spec.GetFilename().AsCString("<Unknown>"),
189 m_line_number);
190 }
191 }
192 else
193 {
194 #if 0
195 s << "error: Breakpoint at '" << pos->c_str() << "' isn't resolved yet: \n";
196 if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionNameOffset))
197 s.EOL();
198 if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionPointerOffset))
199 s.EOL();
200 if (sc.line_entry.address.Dump(&s, Address::DumpStyleFileAddress))
201 s.EOL();
202 if (sc.line_entry.address.Dump(&s, Address::DumpStyleLoadAddress))
203 s.EOL();
204 #endif
205 }
Chris Lattner24943d22010-06-08 16:52:24 +0000206 }
207 }
Chris Lattner24943d22010-06-08 16:52:24 +0000208 }
Jim Inghama44297a2012-01-13 02:04:05 +0000209
Chris Lattner24943d22010-06-08 16:52:24 +0000210 return Searcher::eCallbackReturnContinue;
211}
212
213Searcher::Depth
214BreakpointResolverFileLine::GetDepth()
215{
Jim Inghama44297a2012-01-13 02:04:05 +0000216 return Searcher::eDepthModule;
Chris Lattner24943d22010-06-08 16:52:24 +0000217}
218
219void
220BreakpointResolverFileLine::GetDescription (Stream *s)
221{
Greg Clayton12bec712010-06-28 21:30:43 +0000222 s->Printf ("file ='%s', line = %u", m_file_spec.GetFilename().AsCString(), m_line_number);
Chris Lattner24943d22010-06-08 16:52:24 +0000223}
224
225void
226BreakpointResolverFileLine::Dump (Stream *s) const
227{
228
229}
230