180814287SRaphael Isemann //===-- LineEntry.cpp -----------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "lldb/Symbol/LineEntry.h"
1030fdc8d8SChris Lattner #include "lldb/Symbol/CompileUnit.h"
1130fdc8d8SChris Lattner #include "lldb/Target/Process.h"
12f5e56de0SGreg Clayton #include "lldb/Target/Target.h"
1330fdc8d8SChris Lattner 
1430fdc8d8SChris Lattner using namespace lldb_private;
1530fdc8d8SChris Lattner 
LineEntry()16b9c1b51eSKate Stone LineEntry::LineEntry()
179494c510SJonas Devlieghere     : range(), file(), is_start_of_statement(0), is_start_of_basic_block(0),
189494c510SJonas Devlieghere       is_prologue_end(0), is_epilogue_begin(0), is_terminal_entry(0) {}
1930fdc8d8SChris Lattner 
LineEntry(const lldb::SectionSP & section_sp,lldb::addr_t section_offset,lldb::addr_t byte_size,const FileSpec & _file,uint32_t _line,uint16_t _column,bool _is_start_of_statement,bool _is_start_of_basic_block,bool _is_prologue_end,bool _is_epilogue_begin,bool _is_terminal_entry)20b9c1b51eSKate Stone LineEntry::LineEntry(const lldb::SectionSP &section_sp,
21b9c1b51eSKate Stone                      lldb::addr_t section_offset, lldb::addr_t byte_size,
22b9c1b51eSKate Stone                      const FileSpec &_file, uint32_t _line, uint16_t _column,
23b9c1b51eSKate Stone                      bool _is_start_of_statement, bool _is_start_of_basic_block,
24b9c1b51eSKate Stone                      bool _is_prologue_end, bool _is_epilogue_begin,
25b9c1b51eSKate Stone                      bool _is_terminal_entry)
26b9c1b51eSKate Stone     : range(section_sp, section_offset, byte_size), file(_file),
27b9c1b51eSKate Stone       original_file(_file), line(_line), column(_column),
2830fdc8d8SChris Lattner       is_start_of_statement(_is_start_of_statement),
2930fdc8d8SChris Lattner       is_start_of_basic_block(_is_start_of_basic_block),
30b9c1b51eSKate Stone       is_prologue_end(_is_prologue_end), is_epilogue_begin(_is_epilogue_begin),
31b9c1b51eSKate Stone       is_terminal_entry(_is_terminal_entry) {}
3230fdc8d8SChris Lattner 
Clear()33b9c1b51eSKate Stone void LineEntry::Clear() {
3430fdc8d8SChris Lattner   range.Clear();
3530fdc8d8SChris Lattner   file.Clear();
36911d5784STed Woodward   original_file.Clear();
372b89a531SJim Ingham   line = LLDB_INVALID_LINE_NUMBER;
3830fdc8d8SChris Lattner   column = 0;
3930fdc8d8SChris Lattner   is_start_of_statement = 0;
4030fdc8d8SChris Lattner   is_start_of_basic_block = 0;
4130fdc8d8SChris Lattner   is_prologue_end = 0;
4230fdc8d8SChris Lattner   is_epilogue_begin = 0;
4330fdc8d8SChris Lattner   is_terminal_entry = 0;
4430fdc8d8SChris Lattner }
4530fdc8d8SChris Lattner 
IsValid() const46b9c1b51eSKate Stone bool LineEntry::IsValid() const {
472b89a531SJim Ingham   return range.GetBaseAddress().IsValid() && line != LLDB_INVALID_LINE_NUMBER;
4830fdc8d8SChris Lattner }
4930fdc8d8SChris Lattner 
DumpStopContext(Stream * s,bool show_fullpaths) const50b9c1b51eSKate Stone bool LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const {
51b9c1b51eSKate Stone   if (file) {
526dadd508SGreg Clayton     if (show_fullpaths)
534dac97ebSRaphael Isemann       file.Dump(s->AsRawOstream());
546dadd508SGreg Clayton     else
556dadd508SGreg Clayton       file.GetFilename().Dump(s);
566dadd508SGreg Clayton 
5730fdc8d8SChris Lattner     if (line)
5830fdc8d8SChris Lattner       s->PutChar(':');
5930fdc8d8SChris Lattner   }
60431b1584SAdrian Prantl   if (line) {
6130fdc8d8SChris Lattner     s->Printf("%u", line);
62431b1584SAdrian Prantl     if (column) {
63431b1584SAdrian Prantl       s->PutChar(':');
64431b1584SAdrian Prantl       s->Printf("%u", column);
65431b1584SAdrian Prantl     }
66431b1584SAdrian Prantl   }
67431b1584SAdrian Prantl   return file || line;
6830fdc8d8SChris Lattner }
6930fdc8d8SChris Lattner 
Dump(Stream * s,Target * target,bool show_file,Address::DumpStyle style,Address::DumpStyle fallback_style,bool show_range) const70b9c1b51eSKate Stone bool LineEntry::Dump(Stream *s, Target *target, bool show_file,
7130fdc8d8SChris Lattner                      Address::DumpStyle style,
72b9c1b51eSKate Stone                      Address::DumpStyle fallback_style, bool show_range) const {
73b9c1b51eSKate Stone   if (show_range) {
7430fdc8d8SChris Lattner     // Show address range
75f5e56de0SGreg Clayton     if (!range.Dump(s, target, style, fallback_style))
7630fdc8d8SChris Lattner       return false;
77b9c1b51eSKate Stone   } else {
7830fdc8d8SChris Lattner     // Show address only
79b9c1b51eSKate Stone     if (!range.GetBaseAddress().Dump(s, target, style, fallback_style))
8030fdc8d8SChris Lattner       return false;
8130fdc8d8SChris Lattner   }
820c5cd90dSGreg Clayton   if (show_file)
830c5cd90dSGreg Clayton     *s << ", file = " << file;
8430fdc8d8SChris Lattner   if (line)
8530fdc8d8SChris Lattner     s->Printf(", line = %u", line);
8630fdc8d8SChris Lattner   if (column)
8730fdc8d8SChris Lattner     s->Printf(", column = %u", column);
8830fdc8d8SChris Lattner   if (is_start_of_statement)
8930fdc8d8SChris Lattner     *s << ", is_start_of_statement = TRUE";
9030fdc8d8SChris Lattner 
9130fdc8d8SChris Lattner   if (is_start_of_basic_block)
9230fdc8d8SChris Lattner     *s << ", is_start_of_basic_block = TRUE";
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner   if (is_prologue_end)
9530fdc8d8SChris Lattner     *s << ", is_prologue_end = TRUE";
9630fdc8d8SChris Lattner 
9730fdc8d8SChris Lattner   if (is_epilogue_begin)
9830fdc8d8SChris Lattner     *s << ", is_epilogue_begin = TRUE";
9930fdc8d8SChris Lattner 
10030fdc8d8SChris Lattner   if (is_terminal_entry)
10130fdc8d8SChris Lattner     *s << ", is_terminal_entry = TRUE";
10230fdc8d8SChris Lattner   return true;
10330fdc8d8SChris Lattner }
10430fdc8d8SChris Lattner 
GetDescription(Stream * s,lldb::DescriptionLevel level,CompileUnit * cu,Target * target,bool show_address_only) const105b9c1b51eSKate Stone bool LineEntry::GetDescription(Stream *s, lldb::DescriptionLevel level,
106b9c1b51eSKate Stone                                CompileUnit *cu, Target *target,
107b9c1b51eSKate Stone                                bool show_address_only) const {
10830fdc8d8SChris Lattner 
109b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelBrief ||
110b9c1b51eSKate Stone       level == lldb::eDescriptionLevelFull) {
111b9c1b51eSKate Stone     if (show_address_only) {
112b9c1b51eSKate Stone       range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress,
113b9c1b51eSKate Stone                                   Address::DumpStyleFileAddress);
114b9c1b51eSKate Stone     } else {
115b9c1b51eSKate Stone       range.Dump(s, target, Address::DumpStyleLoadAddress,
116b9c1b51eSKate Stone                  Address::DumpStyleFileAddress);
1170c5cd90dSGreg Clayton     }
11830fdc8d8SChris Lattner 
119c9800667SGreg Clayton     *s << ": " << file;
12030fdc8d8SChris Lattner 
121b9c1b51eSKate Stone     if (line) {
12230fdc8d8SChris Lattner       s->Printf(":%u", line);
12330fdc8d8SChris Lattner       if (column)
12430fdc8d8SChris Lattner         s->Printf(":%u", column);
12530fdc8d8SChris Lattner     }
12630fdc8d8SChris Lattner 
127b9c1b51eSKate Stone     if (level == lldb::eDescriptionLevelFull) {
12830fdc8d8SChris Lattner       if (is_start_of_statement)
12930fdc8d8SChris Lattner         *s << ", is_start_of_statement = TRUE";
13030fdc8d8SChris Lattner 
13130fdc8d8SChris Lattner       if (is_start_of_basic_block)
13230fdc8d8SChris Lattner         *s << ", is_start_of_basic_block = TRUE";
13330fdc8d8SChris Lattner 
13430fdc8d8SChris Lattner       if (is_prologue_end)
13530fdc8d8SChris Lattner         *s << ", is_prologue_end = TRUE";
13630fdc8d8SChris Lattner 
13730fdc8d8SChris Lattner       if (is_epilogue_begin)
13830fdc8d8SChris Lattner         *s << ", is_epilogue_begin = TRUE";
13930fdc8d8SChris Lattner 
14030fdc8d8SChris Lattner       if (is_terminal_entry)
14130fdc8d8SChris Lattner         *s << ", is_terminal_entry = TRUE";
142b9c1b51eSKate Stone     } else {
14330fdc8d8SChris Lattner       if (is_terminal_entry)
14430fdc8d8SChris Lattner         s->EOL();
14530fdc8d8SChris Lattner     }
146b9c1b51eSKate Stone   } else {
147b9c1b51eSKate Stone     return Dump(s, target, true, Address::DumpStyleLoadAddress,
148b9c1b51eSKate Stone                 Address::DumpStyleModuleWithFileAddress, true);
14930fdc8d8SChris Lattner   }
15030fdc8d8SChris Lattner   return true;
15130fdc8d8SChris Lattner }
15230fdc8d8SChris Lattner 
operator <(const LineEntry & a,const LineEntry & b)153b9c1b51eSKate Stone bool lldb_private::operator<(const LineEntry &a, const LineEntry &b) {
15430fdc8d8SChris Lattner   return LineEntry::Compare(a, b) < 0;
15530fdc8d8SChris Lattner }
15630fdc8d8SChris Lattner 
Compare(const LineEntry & a,const LineEntry & b)157b9c1b51eSKate Stone int LineEntry::Compare(const LineEntry &a, const LineEntry &b) {
158b9c1b51eSKate Stone   int result = Address::CompareFileAddress(a.range.GetBaseAddress(),
159b9c1b51eSKate Stone                                            b.range.GetBaseAddress());
16030fdc8d8SChris Lattner   if (result != 0)
16130fdc8d8SChris Lattner     return result;
16230fdc8d8SChris Lattner 
16330fdc8d8SChris Lattner   const lldb::addr_t a_byte_size = a.range.GetByteSize();
16430fdc8d8SChris Lattner   const lldb::addr_t b_byte_size = b.range.GetByteSize();
16530fdc8d8SChris Lattner 
16630fdc8d8SChris Lattner   if (a_byte_size < b_byte_size)
16730fdc8d8SChris Lattner     return -1;
16830fdc8d8SChris Lattner   if (a_byte_size > b_byte_size)
16930fdc8d8SChris Lattner     return +1;
17030fdc8d8SChris Lattner 
17105097246SAdrian Prantl   // Check for an end sequence entry mismatch after we have determined that the
17205097246SAdrian Prantl   // address values are equal. If one of the items is an end sequence, we don't
17305097246SAdrian Prantl   // care about the line, file, or column info.
17430fdc8d8SChris Lattner   if (a.is_terminal_entry > b.is_terminal_entry)
17530fdc8d8SChris Lattner     return -1;
17630fdc8d8SChris Lattner   if (a.is_terminal_entry < b.is_terminal_entry)
17730fdc8d8SChris Lattner     return +1;
17830fdc8d8SChris Lattner 
17930fdc8d8SChris Lattner   if (a.line < b.line)
18030fdc8d8SChris Lattner     return -1;
18130fdc8d8SChris Lattner   if (a.line > b.line)
18230fdc8d8SChris Lattner     return +1;
18330fdc8d8SChris Lattner 
18430fdc8d8SChris Lattner   if (a.column < b.column)
18530fdc8d8SChris Lattner     return -1;
18630fdc8d8SChris Lattner   if (a.column > b.column)
18730fdc8d8SChris Lattner     return +1;
18830fdc8d8SChris Lattner 
18930fdc8d8SChris Lattner   return FileSpec::Compare(a.file, b.file, true);
19030fdc8d8SChris Lattner }
19130fdc8d8SChris Lattner 
GetSameLineContiguousAddressRange(bool include_inlined_functions) const1928a777920SGreg Clayton AddressRange LineEntry::GetSameLineContiguousAddressRange(
1938a777920SGreg Clayton     bool include_inlined_functions) const {
19405097246SAdrian Prantl   // Add each LineEntry's range to complete_line_range until we find a
19505097246SAdrian Prantl   // different file / line number.
19625d5b10bSJason Molenda   AddressRange complete_line_range = range;
1978a777920SGreg Clayton   auto symbol_context_scope = lldb::eSymbolContextLineEntry;
1988a777920SGreg Clayton   Declaration start_call_site(original_file, line);
1998a777920SGreg Clayton   if (include_inlined_functions)
2008a777920SGreg Clayton     symbol_context_scope |= lldb::eSymbolContextBlock;
20125d5b10bSJason Molenda 
202b9c1b51eSKate Stone   while (true) {
20325d5b10bSJason Molenda     SymbolContext next_line_sc;
20425d5b10bSJason Molenda     Address range_end(complete_line_range.GetBaseAddress());
20525d5b10bSJason Molenda     range_end.Slide(complete_line_range.GetByteSize());
2068a777920SGreg Clayton     range_end.CalculateSymbolContext(&next_line_sc, symbol_context_scope);
20725d5b10bSJason Molenda 
2088a777920SGreg Clayton     if (!next_line_sc.line_entry.IsValid() ||
2098a777920SGreg Clayton         next_line_sc.line_entry.range.GetByteSize() == 0)
2108a777920SGreg Clayton       break;
2118a777920SGreg Clayton 
2128a777920SGreg Clayton     if (original_file == next_line_sc.line_entry.original_file &&
2138a777920SGreg Clayton         (next_line_sc.line_entry.line == 0 ||
2148a777920SGreg Clayton          line == next_line_sc.line_entry.line)) {
21505097246SAdrian Prantl       // Include any line 0 entries - they indicate that this is compiler-
21605097246SAdrian Prantl       // generated code that does not correspond to user source code.
2178a777920SGreg Clayton       // next_line_sc is the same file & line as this LineEntry, so extend
2188a777920SGreg Clayton       // our AddressRange by its size and continue to see if there are more
2198a777920SGreg Clayton       // LineEntries that we can combine. However, if there was nothing to
2208a777920SGreg Clayton       // extend we're done.
2218a777920SGreg Clayton       if (!complete_line_range.Extend(next_line_sc.line_entry.range))
2228a777920SGreg Clayton         break;
22325d5b10bSJason Molenda       continue;
22425d5b10bSJason Molenda     }
22525d5b10bSJason Molenda 
2268a777920SGreg Clayton     if (include_inlined_functions && next_line_sc.block &&
2278a777920SGreg Clayton         next_line_sc.block->GetContainingInlinedBlock() != nullptr) {
2288a777920SGreg Clayton       // The next_line_sc might be in a different file if it's an inlined
2298a777920SGreg Clayton       // function. If this is the case then we still want to expand our line
2308a777920SGreg Clayton       // range to include them if the inlined function is at the same call site
2318a777920SGreg Clayton       // as this line entry. The current block could represent a nested inline
2328a777920SGreg Clayton       // function call so we need to need to check up the block tree to see if
2338a777920SGreg Clayton       // we find one.
2348a777920SGreg Clayton       auto inlined_parent_block =
2358a777920SGreg Clayton           next_line_sc.block->GetContainingInlinedBlockWithCallSite(
2368a777920SGreg Clayton               start_call_site);
2378a777920SGreg Clayton       if (!inlined_parent_block)
2388a777920SGreg Clayton         // We didn't find any parent inlined block with a call site at this line
2398a777920SGreg Clayton         // entry so this inlined function is probably at another line.
2408a777920SGreg Clayton         break;
2418a777920SGreg Clayton       // Extend our AddressRange by the size of the inlined block, but if there
2428a777920SGreg Clayton       // was nothing to add then we're done.
2438a777920SGreg Clayton       if (!complete_line_range.Extend(next_line_sc.line_entry.range))
2448a777920SGreg Clayton         break;
24525d5b10bSJason Molenda       continue;
24625d5b10bSJason Molenda     }
2478a777920SGreg Clayton 
24825d5b10bSJason Molenda     break;
24925d5b10bSJason Molenda   }
25025d5b10bSJason Molenda   return complete_line_range;
25125d5b10bSJason Molenda }
252911d5784STed Woodward 
ApplyFileMappings(lldb::TargetSP target_sp)253b9c1b51eSKate Stone void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) {
254b9c1b51eSKate Stone   if (target_sp) {
255*a3463722SAdrian Prantl     // Apply any file remappings to our file.
256*a3463722SAdrian Prantl     if (auto new_file_spec =
257*a3463722SAdrian Prantl             target_sp->GetSourcePathMap().FindFile(original_file))
258*a3463722SAdrian Prantl       file = *new_file_spec;
259911d5784STed Woodward   }
260911d5784STed Woodward }
261