1 //===-- LineEntry.cpp -----------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Symbol/LineEntry.h"
10 #include "lldb/Symbol/CompileUnit.h"
11 #include "lldb/Target/Process.h"
12 #include "lldb/Target/Target.h"
14 using namespace lldb_private
;
16 LineEntry::LineEntry()
17 : range(), file(), is_start_of_statement(0), is_start_of_basic_block(0),
18 is_prologue_end(0), is_epilogue_begin(0), is_terminal_entry(0) {}
20 LineEntry::LineEntry(const lldb::SectionSP
§ion_sp
,
21 lldb::addr_t section_offset
, lldb::addr_t byte_size
,
22 const FileSpec
&_file
, uint32_t _line
, uint16_t _column
,
23 bool _is_start_of_statement
, bool _is_start_of_basic_block
,
24 bool _is_prologue_end
, bool _is_epilogue_begin
,
25 bool _is_terminal_entry
)
26 : range(section_sp
, section_offset
, byte_size
), file(_file
),
27 original_file(_file
), line(_line
), column(_column
),
28 is_start_of_statement(_is_start_of_statement
),
29 is_start_of_basic_block(_is_start_of_basic_block
),
30 is_prologue_end(_is_prologue_end
), is_epilogue_begin(_is_epilogue_begin
),
31 is_terminal_entry(_is_terminal_entry
) {}
33 void LineEntry::Clear() {
36 original_file
.Clear();
37 line
= LLDB_INVALID_LINE_NUMBER
;
39 is_start_of_statement
= 0;
40 is_start_of_basic_block
= 0;
42 is_epilogue_begin
= 0;
43 is_terminal_entry
= 0;
46 bool LineEntry::IsValid() const {
47 return range
.GetBaseAddress().IsValid() && line
!= LLDB_INVALID_LINE_NUMBER
;
50 bool LineEntry::DumpStopContext(Stream
*s
, bool show_fullpaths
) const {
53 file
.Dump(s
->AsRawOstream());
55 file
.GetFilename().Dump(s
);
61 s
->Printf("%u", line
);
64 s
->Printf("%u", column
);
70 bool LineEntry::Dump(Stream
*s
, Target
*target
, bool show_file
,
71 Address::DumpStyle style
,
72 Address::DumpStyle fallback_style
, bool show_range
) const {
75 if (!range
.Dump(s
, target
, style
, fallback_style
))
79 if (!range
.GetBaseAddress().Dump(s
, target
, style
, fallback_style
))
83 *s
<< ", file = " << file
;
85 s
->Printf(", line = %u", line
);
87 s
->Printf(", column = %u", column
);
88 if (is_start_of_statement
)
89 *s
<< ", is_start_of_statement = TRUE";
91 if (is_start_of_basic_block
)
92 *s
<< ", is_start_of_basic_block = TRUE";
95 *s
<< ", is_prologue_end = TRUE";
97 if (is_epilogue_begin
)
98 *s
<< ", is_epilogue_begin = TRUE";
100 if (is_terminal_entry
)
101 *s
<< ", is_terminal_entry = TRUE";
105 bool LineEntry::GetDescription(Stream
*s
, lldb::DescriptionLevel level
,
106 CompileUnit
*cu
, Target
*target
,
107 bool show_address_only
) const {
109 if (level
== lldb::eDescriptionLevelBrief
||
110 level
== lldb::eDescriptionLevelFull
) {
111 if (show_address_only
) {
112 range
.GetBaseAddress().Dump(s
, target
, Address::DumpStyleLoadAddress
,
113 Address::DumpStyleFileAddress
);
115 range
.Dump(s
, target
, Address::DumpStyleLoadAddress
,
116 Address::DumpStyleFileAddress
);
122 s
->Printf(":%u", line
);
124 s
->Printf(":%u", column
);
127 if (level
== lldb::eDescriptionLevelFull
) {
128 if (is_start_of_statement
)
129 *s
<< ", is_start_of_statement = TRUE";
131 if (is_start_of_basic_block
)
132 *s
<< ", is_start_of_basic_block = TRUE";
135 *s
<< ", is_prologue_end = TRUE";
137 if (is_epilogue_begin
)
138 *s
<< ", is_epilogue_begin = TRUE";
140 if (is_terminal_entry
)
141 *s
<< ", is_terminal_entry = TRUE";
143 if (is_terminal_entry
)
147 return Dump(s
, target
, true, Address::DumpStyleLoadAddress
,
148 Address::DumpStyleModuleWithFileAddress
, true);
153 bool lldb_private::operator<(const LineEntry
&a
, const LineEntry
&b
) {
154 return LineEntry::Compare(a
, b
) < 0;
157 int LineEntry::Compare(const LineEntry
&a
, const LineEntry
&b
) {
158 int result
= Address::CompareFileAddress(a
.range
.GetBaseAddress(),
159 b
.range
.GetBaseAddress());
163 const lldb::addr_t a_byte_size
= a
.range
.GetByteSize();
164 const lldb::addr_t b_byte_size
= b
.range
.GetByteSize();
166 if (a_byte_size
< b_byte_size
)
168 if (a_byte_size
> b_byte_size
)
171 // Check for an end sequence entry mismatch after we have determined that the
172 // address values are equal. If one of the items is an end sequence, we don't
173 // care about the line, file, or column info.
174 if (a
.is_terminal_entry
> b
.is_terminal_entry
)
176 if (a
.is_terminal_entry
< b
.is_terminal_entry
)
184 if (a
.column
< b
.column
)
186 if (a
.column
> b
.column
)
189 return FileSpec::Compare(a
.file
, b
.file
, true);
192 AddressRange
LineEntry::GetSameLineContiguousAddressRange(
193 bool include_inlined_functions
) const {
194 // Add each LineEntry's range to complete_line_range until we find a
195 // different file / line number.
196 AddressRange complete_line_range
= range
;
197 auto symbol_context_scope
= lldb::eSymbolContextLineEntry
;
198 Declaration
start_call_site(original_file
, line
);
199 if (include_inlined_functions
)
200 symbol_context_scope
|= lldb::eSymbolContextBlock
;
203 SymbolContext next_line_sc
;
204 Address
range_end(complete_line_range
.GetBaseAddress());
205 range_end
.Slide(complete_line_range
.GetByteSize());
206 range_end
.CalculateSymbolContext(&next_line_sc
, symbol_context_scope
);
208 if (!next_line_sc
.line_entry
.IsValid() ||
209 next_line_sc
.line_entry
.range
.GetByteSize() == 0)
212 if (original_file
== next_line_sc
.line_entry
.original_file
&&
213 (next_line_sc
.line_entry
.line
== 0 ||
214 line
== next_line_sc
.line_entry
.line
)) {
215 // Include any line 0 entries - they indicate that this is compiler-
216 // generated code that does not correspond to user source code.
217 // next_line_sc is the same file & line as this LineEntry, so extend
218 // our AddressRange by its size and continue to see if there are more
219 // LineEntries that we can combine. However, if there was nothing to
220 // extend we're done.
221 if (!complete_line_range
.Extend(next_line_sc
.line_entry
.range
))
226 if (include_inlined_functions
&& next_line_sc
.block
&&
227 next_line_sc
.block
->GetContainingInlinedBlock() != nullptr) {
228 // The next_line_sc might be in a different file if it's an inlined
229 // function. If this is the case then we still want to expand our line
230 // range to include them if the inlined function is at the same call site
231 // as this line entry. The current block could represent a nested inline
232 // function call so we need to need to check up the block tree to see if
234 auto inlined_parent_block
=
235 next_line_sc
.block
->GetContainingInlinedBlockWithCallSite(
237 if (!inlined_parent_block
)
238 // We didn't find any parent inlined block with a call site at this line
239 // entry so this inlined function is probably at another line.
241 // Extend our AddressRange by the size of the inlined block, but if there
242 // was nothing to add then we're done.
243 if (!complete_line_range
.Extend(next_line_sc
.line_entry
.range
))
250 return complete_line_range
;
253 void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp
) {
255 // Apply any file remappings to our file.
256 if (auto new_file_spec
=
257 target_sp
->GetSourcePathMap().FindFile(original_file
))
258 file
= *new_file_spec
;