1 //===-- LineEntry.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/Symbol/LineEntry.h"
11 #include "lldb/Symbol/CompileUnit.h"
12 #include "lldb/Target/Process.h"
13 #include "lldb/Target/Target.h"
14 
15 using namespace lldb_private;
16 
17 LineEntry::LineEntry() :
18     range(),
19     file(),
20     line(LLDB_INVALID_LINE_NUMBER),
21     column(0),
22     is_start_of_statement(0),
23     is_start_of_basic_block(0),
24     is_prologue_end(0),
25     is_epilogue_begin(0),
26     is_terminal_entry(0)
27 {
28 }
29 
30 LineEntry::LineEntry
31 (
32     const lldb::SectionSP &section_sp,
33     lldb::addr_t section_offset,
34     lldb::addr_t byte_size,
35     const FileSpec &_file,
36     uint32_t _line,
37     uint16_t _column,
38     bool _is_start_of_statement,
39     bool _is_start_of_basic_block,
40     bool _is_prologue_end,
41     bool _is_epilogue_begin,
42     bool _is_terminal_entry
43 ) :
44     range(section_sp, section_offset, byte_size),
45     file(_file),
46     original_file(_file),
47     line(_line),
48     column(_column),
49     is_start_of_statement(_is_start_of_statement),
50     is_start_of_basic_block(_is_start_of_basic_block),
51     is_prologue_end(_is_prologue_end),
52     is_epilogue_begin(_is_epilogue_begin),
53     is_terminal_entry(_is_terminal_entry)
54 {
55 }
56 
57 void
58 LineEntry::Clear()
59 {
60     range.Clear();
61     file.Clear();
62     original_file.Clear();
63     line = LLDB_INVALID_LINE_NUMBER;
64     column = 0;
65     is_start_of_statement = 0;
66     is_start_of_basic_block = 0;
67     is_prologue_end = 0;
68     is_epilogue_begin = 0;
69     is_terminal_entry = 0;
70 }
71 
72 
73 bool
74 LineEntry::IsValid() const
75 {
76     return range.GetBaseAddress().IsValid() && line != LLDB_INVALID_LINE_NUMBER;
77 }
78 
79 bool
80 LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const
81 {
82     bool result = false;
83     if (file)
84     {
85         if (show_fullpaths)
86             file.Dump (s);
87         else
88             file.GetFilename().Dump (s);
89 
90         if (line)
91             s->PutChar(':');
92         result = true;
93     }
94     if (line)
95         s->Printf ("%u", line);
96     else
97         result = false;
98 
99     return result;
100 }
101 
102 bool
103 LineEntry::Dump
104 (
105     Stream *s,
106     Target *target,
107     bool show_file,
108     Address::DumpStyle style,
109     Address::DumpStyle fallback_style,
110     bool show_range
111 ) const
112 {
113     if (show_range)
114     {
115         // Show address range
116         if (!range.Dump(s, target, style, fallback_style))
117             return false;
118     }
119     else
120     {
121         // Show address only
122         if (!range.GetBaseAddress().Dump(s,
123                                          target,
124                                          style,
125                                          fallback_style))
126             return false;
127     }
128     if (show_file)
129         *s << ", file = " << file;
130     if (line)
131         s->Printf(", line = %u", line);
132     if (column)
133         s->Printf(", column = %u", column);
134     if (is_start_of_statement)
135         *s << ", is_start_of_statement = TRUE";
136 
137     if (is_start_of_basic_block)
138         *s << ", is_start_of_basic_block = TRUE";
139 
140     if (is_prologue_end)
141         *s << ", is_prologue_end = TRUE";
142 
143     if (is_epilogue_begin)
144         *s << ", is_epilogue_begin = TRUE";
145 
146     if (is_terminal_entry)
147         *s << ", is_terminal_entry = TRUE";
148     return true;
149 }
150 
151 bool
152 LineEntry::GetDescription (Stream *s, lldb::DescriptionLevel level, CompileUnit* cu, Target *target, bool show_address_only) const
153 {
154 
155     if (level == lldb::eDescriptionLevelBrief || level == lldb::eDescriptionLevelFull)
156     {
157         if (show_address_only)
158         {
159             range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
160         }
161         else
162         {
163             range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
164         }
165 
166         *s << ": " << file;
167 
168         if (line)
169         {
170             s->Printf(":%u", line);
171             if (column)
172                 s->Printf(":%u", column);
173         }
174 
175 
176         if (level == lldb::eDescriptionLevelFull)
177         {
178             if (is_start_of_statement)
179                 *s << ", is_start_of_statement = TRUE";
180 
181             if (is_start_of_basic_block)
182                 *s << ", is_start_of_basic_block = TRUE";
183 
184             if (is_prologue_end)
185                 *s << ", is_prologue_end = TRUE";
186 
187             if (is_epilogue_begin)
188                 *s << ", is_epilogue_begin = TRUE";
189 
190             if (is_terminal_entry)
191                 *s << ", is_terminal_entry = TRUE";
192         }
193         else
194         {
195             if (is_terminal_entry)
196                 s->EOL();
197         }
198     }
199     else
200     {
201         return Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
202     }
203     return true;
204 }
205 
206 
207 bool
208 lldb_private::operator< (const LineEntry& a, const LineEntry& b)
209 {
210     return LineEntry::Compare (a, b) < 0;
211 }
212 
213 int
214 LineEntry::Compare (const LineEntry& a, const LineEntry& b)
215 {
216     int result = Address::CompareFileAddress (a.range.GetBaseAddress(), b.range.GetBaseAddress());
217     if (result != 0)
218         return result;
219 
220     const lldb::addr_t a_byte_size = a.range.GetByteSize();
221     const lldb::addr_t b_byte_size = b.range.GetByteSize();
222 
223     if (a_byte_size < b_byte_size)
224         return -1;
225     if (a_byte_size > b_byte_size)
226         return +1;
227 
228     // Check for an end sequence entry mismatch after we have determined
229     // that the address values are equal. If one of the items is an end
230     // sequence, we don't care about the line, file, or column info.
231     if (a.is_terminal_entry > b.is_terminal_entry)
232         return -1;
233     if (a.is_terminal_entry < b.is_terminal_entry)
234         return +1;
235 
236     if (a.line < b.line)
237         return -1;
238     if (a.line > b.line)
239         return +1;
240 
241     if (a.column < b.column)
242         return -1;
243     if (a.column > b.column)
244         return +1;
245 
246     return FileSpec::Compare (a.file, b.file, true);
247 }
248 
249 AddressRange
250 LineEntry::GetSameLineContiguousAddressRange () const
251 {
252     // Add each LineEntry's range to complete_line_range until we find
253     // a different file / line number.
254     AddressRange complete_line_range = range;
255 
256     while (true)
257     {
258         SymbolContext next_line_sc;
259         Address range_end (complete_line_range.GetBaseAddress());
260         range_end.Slide (complete_line_range.GetByteSize());
261         range_end.CalculateSymbolContext (&next_line_sc, lldb::eSymbolContextLineEntry);
262 
263         if (next_line_sc.line_entry.IsValid()
264             && next_line_sc.line_entry.range.GetByteSize() > 0
265             && original_file == next_line_sc.line_entry.original_file)
266         {
267             // Include any line 0 entries - they indicate that this is compiler-generated code
268             // that does not correspond to user source code.
269             if (next_line_sc.line_entry.line == 0)
270             {
271                 complete_line_range.SetByteSize (complete_line_range.GetByteSize() + next_line_sc.line_entry.range.GetByteSize());
272                 continue;
273             }
274 
275             if (line == next_line_sc.line_entry.line)
276             {
277                 // next_line_sc is the same file & line as this LineEntry, so extend our
278                 // AddressRange by its size and continue to see if there are more LineEntries
279                 // that we can combine.
280                 complete_line_range.SetByteSize (complete_line_range.GetByteSize() + next_line_sc.line_entry.range.GetByteSize());
281                 continue;
282             }
283         }
284         break;
285     }
286     return complete_line_range;
287 }
288 
289 void
290 LineEntry::ApplyFileMappings(lldb::TargetSP target_sp)
291 {
292     if (target_sp)
293     {
294         // Apply any file remappings to our file
295         FileSpec new_file_spec;
296         if (target_sp->GetSourcePathMap().FindFile(original_file, new_file_spec))
297             file = new_file_spec;
298     }
299 }
300