xref: /freebsd/contrib/llvm-project/lldb/source/Symbol/LineEntry.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- LineEntry.cpp -----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Symbol/LineEntry.h"
100b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
110b57cec5SDimitry Andric #include "lldb/Target/Process.h"
120b57cec5SDimitry Andric #include "lldb/Target/Target.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric using namespace lldb_private;
150b57cec5SDimitry Andric 
LineEntry()160b57cec5SDimitry Andric LineEntry::LineEntry()
17*0fca6ea1SDimitry Andric     : range(), file_sp(std::make_shared<SupportFile>()),
18*0fca6ea1SDimitry Andric       original_file_sp(std::make_shared<SupportFile>()),
19*0fca6ea1SDimitry Andric       is_start_of_statement(0), is_start_of_basic_block(0), is_prologue_end(0),
20*0fca6ea1SDimitry Andric       is_epilogue_begin(0), is_terminal_entry(0) {}
210b57cec5SDimitry Andric 
Clear()220b57cec5SDimitry Andric void LineEntry::Clear() {
230b57cec5SDimitry Andric   range.Clear();
24*0fca6ea1SDimitry Andric   file_sp = std::make_shared<SupportFile>();
257a6dacacSDimitry Andric   original_file_sp = std::make_shared<SupportFile>();
260b57cec5SDimitry Andric   line = LLDB_INVALID_LINE_NUMBER;
270b57cec5SDimitry Andric   column = 0;
280b57cec5SDimitry Andric   is_start_of_statement = 0;
290b57cec5SDimitry Andric   is_start_of_basic_block = 0;
300b57cec5SDimitry Andric   is_prologue_end = 0;
310b57cec5SDimitry Andric   is_epilogue_begin = 0;
320b57cec5SDimitry Andric   is_terminal_entry = 0;
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric 
IsValid() const350b57cec5SDimitry Andric bool LineEntry::IsValid() const {
360b57cec5SDimitry Andric   return range.GetBaseAddress().IsValid() && line != LLDB_INVALID_LINE_NUMBER;
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
DumpStopContext(Stream * s,bool show_fullpaths) const390b57cec5SDimitry Andric bool LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const {
40*0fca6ea1SDimitry Andric   const FileSpec &file = file_sp->GetSpecOnly();
410b57cec5SDimitry Andric   if (file) {
420b57cec5SDimitry Andric     if (show_fullpaths)
43480093f4SDimitry Andric       file.Dump(s->AsRawOstream());
440b57cec5SDimitry Andric     else
450b57cec5SDimitry Andric       file.GetFilename().Dump(s);
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric     if (line)
480b57cec5SDimitry Andric       s->PutChar(':');
490b57cec5SDimitry Andric   }
500b57cec5SDimitry Andric   if (line) {
510b57cec5SDimitry Andric     s->Printf("%u", line);
520b57cec5SDimitry Andric     if (column) {
530b57cec5SDimitry Andric       s->PutChar(':');
540b57cec5SDimitry Andric       s->Printf("%u", column);
550b57cec5SDimitry Andric     }
560b57cec5SDimitry Andric   }
570b57cec5SDimitry Andric   return file || line;
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
Dump(Stream * s,Target * target,bool show_file,Address::DumpStyle style,Address::DumpStyle fallback_style,bool show_range) const600b57cec5SDimitry Andric bool LineEntry::Dump(Stream *s, Target *target, bool show_file,
610b57cec5SDimitry Andric                      Address::DumpStyle style,
620b57cec5SDimitry Andric                      Address::DumpStyle fallback_style, bool show_range) const {
630b57cec5SDimitry Andric   if (show_range) {
640b57cec5SDimitry Andric     // Show address range
650b57cec5SDimitry Andric     if (!range.Dump(s, target, style, fallback_style))
660b57cec5SDimitry Andric       return false;
670b57cec5SDimitry Andric   } else {
680b57cec5SDimitry Andric     // Show address only
690b57cec5SDimitry Andric     if (!range.GetBaseAddress().Dump(s, target, style, fallback_style))
700b57cec5SDimitry Andric       return false;
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric   if (show_file)
73*0fca6ea1SDimitry Andric     *s << ", file = " << GetFile();
740b57cec5SDimitry Andric   if (line)
750b57cec5SDimitry Andric     s->Printf(", line = %u", line);
760b57cec5SDimitry Andric   if (column)
770b57cec5SDimitry Andric     s->Printf(", column = %u", column);
780b57cec5SDimitry Andric   if (is_start_of_statement)
790b57cec5SDimitry Andric     *s << ", is_start_of_statement = TRUE";
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   if (is_start_of_basic_block)
820b57cec5SDimitry Andric     *s << ", is_start_of_basic_block = TRUE";
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   if (is_prologue_end)
850b57cec5SDimitry Andric     *s << ", is_prologue_end = TRUE";
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   if (is_epilogue_begin)
880b57cec5SDimitry Andric     *s << ", is_epilogue_begin = TRUE";
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   if (is_terminal_entry)
910b57cec5SDimitry Andric     *s << ", is_terminal_entry = TRUE";
920b57cec5SDimitry Andric   return true;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
GetDescription(Stream * s,lldb::DescriptionLevel level,CompileUnit * cu,Target * target,bool show_address_only) const950b57cec5SDimitry Andric bool LineEntry::GetDescription(Stream *s, lldb::DescriptionLevel level,
960b57cec5SDimitry Andric                                CompileUnit *cu, Target *target,
970b57cec5SDimitry Andric                                bool show_address_only) const {
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   if (level == lldb::eDescriptionLevelBrief ||
1000b57cec5SDimitry Andric       level == lldb::eDescriptionLevelFull) {
1010b57cec5SDimitry Andric     if (show_address_only) {
1020b57cec5SDimitry Andric       range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress,
1030b57cec5SDimitry Andric                                   Address::DumpStyleFileAddress);
1040b57cec5SDimitry Andric     } else {
1050b57cec5SDimitry Andric       range.Dump(s, target, Address::DumpStyleLoadAddress,
1060b57cec5SDimitry Andric                  Address::DumpStyleFileAddress);
1070b57cec5SDimitry Andric     }
1080b57cec5SDimitry Andric 
109*0fca6ea1SDimitry Andric     *s << ": " << GetFile();
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     if (line) {
1120b57cec5SDimitry Andric       s->Printf(":%u", line);
1130b57cec5SDimitry Andric       if (column)
1140b57cec5SDimitry Andric         s->Printf(":%u", column);
1150b57cec5SDimitry Andric     }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric     if (level == lldb::eDescriptionLevelFull) {
1180b57cec5SDimitry Andric       if (is_start_of_statement)
1190b57cec5SDimitry Andric         *s << ", is_start_of_statement = TRUE";
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric       if (is_start_of_basic_block)
1220b57cec5SDimitry Andric         *s << ", is_start_of_basic_block = TRUE";
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric       if (is_prologue_end)
1250b57cec5SDimitry Andric         *s << ", is_prologue_end = TRUE";
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric       if (is_epilogue_begin)
1280b57cec5SDimitry Andric         *s << ", is_epilogue_begin = TRUE";
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric       if (is_terminal_entry)
1310b57cec5SDimitry Andric         *s << ", is_terminal_entry = TRUE";
1320b57cec5SDimitry Andric     } else {
1330b57cec5SDimitry Andric       if (is_terminal_entry)
1340b57cec5SDimitry Andric         s->EOL();
1350b57cec5SDimitry Andric     }
1360b57cec5SDimitry Andric   } else {
1370b57cec5SDimitry Andric     return Dump(s, target, true, Address::DumpStyleLoadAddress,
1380b57cec5SDimitry Andric                 Address::DumpStyleModuleWithFileAddress, true);
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric   return true;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
operator <(const LineEntry & a,const LineEntry & b)1430b57cec5SDimitry Andric bool lldb_private::operator<(const LineEntry &a, const LineEntry &b) {
1440b57cec5SDimitry Andric   return LineEntry::Compare(a, b) < 0;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
Compare(const LineEntry & a,const LineEntry & b)1470b57cec5SDimitry Andric int LineEntry::Compare(const LineEntry &a, const LineEntry &b) {
1480b57cec5SDimitry Andric   int result = Address::CompareFileAddress(a.range.GetBaseAddress(),
1490b57cec5SDimitry Andric                                            b.range.GetBaseAddress());
1500b57cec5SDimitry Andric   if (result != 0)
1510b57cec5SDimitry Andric     return result;
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   const lldb::addr_t a_byte_size = a.range.GetByteSize();
1540b57cec5SDimitry Andric   const lldb::addr_t b_byte_size = b.range.GetByteSize();
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   if (a_byte_size < b_byte_size)
1570b57cec5SDimitry Andric     return -1;
1580b57cec5SDimitry Andric   if (a_byte_size > b_byte_size)
1590b57cec5SDimitry Andric     return +1;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   // Check for an end sequence entry mismatch after we have determined that the
1620b57cec5SDimitry Andric   // address values are equal. If one of the items is an end sequence, we don't
1630b57cec5SDimitry Andric   // care about the line, file, or column info.
1640b57cec5SDimitry Andric   if (a.is_terminal_entry > b.is_terminal_entry)
1650b57cec5SDimitry Andric     return -1;
1660b57cec5SDimitry Andric   if (a.is_terminal_entry < b.is_terminal_entry)
1670b57cec5SDimitry Andric     return +1;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   if (a.line < b.line)
1700b57cec5SDimitry Andric     return -1;
1710b57cec5SDimitry Andric   if (a.line > b.line)
1720b57cec5SDimitry Andric     return +1;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   if (a.column < b.column)
1750b57cec5SDimitry Andric     return -1;
1760b57cec5SDimitry Andric   if (a.column > b.column)
1770b57cec5SDimitry Andric     return +1;
1780b57cec5SDimitry Andric 
179*0fca6ea1SDimitry Andric   return FileSpec::Compare(a.GetFile(), b.GetFile(), true);
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
GetSameLineContiguousAddressRange(bool include_inlined_functions) const1820b57cec5SDimitry Andric AddressRange LineEntry::GetSameLineContiguousAddressRange(
1830b57cec5SDimitry Andric     bool include_inlined_functions) const {
1840b57cec5SDimitry Andric   // Add each LineEntry's range to complete_line_range until we find a
1850b57cec5SDimitry Andric   // different file / line number.
1860b57cec5SDimitry Andric   AddressRange complete_line_range = range;
1870b57cec5SDimitry Andric   auto symbol_context_scope = lldb::eSymbolContextLineEntry;
1887a6dacacSDimitry Andric   Declaration start_call_site(original_file_sp->GetSpecOnly(), line);
1890b57cec5SDimitry Andric   if (include_inlined_functions)
1900b57cec5SDimitry Andric     symbol_context_scope |= lldb::eSymbolContextBlock;
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   while (true) {
1930b57cec5SDimitry Andric     SymbolContext next_line_sc;
1940b57cec5SDimitry Andric     Address range_end(complete_line_range.GetBaseAddress());
1950b57cec5SDimitry Andric     range_end.Slide(complete_line_range.GetByteSize());
1960b57cec5SDimitry Andric     range_end.CalculateSymbolContext(&next_line_sc, symbol_context_scope);
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric     if (!next_line_sc.line_entry.IsValid() ||
1990b57cec5SDimitry Andric         next_line_sc.line_entry.range.GetByteSize() == 0)
2000b57cec5SDimitry Andric       break;
2010b57cec5SDimitry Andric 
202*0fca6ea1SDimitry Andric     if (original_file_sp->Equal(*next_line_sc.line_entry.original_file_sp,
203*0fca6ea1SDimitry Andric                                 SupportFile::eEqualFileSpecAndChecksumIfSet) &&
2040b57cec5SDimitry Andric         (next_line_sc.line_entry.line == 0 ||
2050b57cec5SDimitry Andric          line == next_line_sc.line_entry.line)) {
2060b57cec5SDimitry Andric       // Include any line 0 entries - they indicate that this is compiler-
2070b57cec5SDimitry Andric       // generated code that does not correspond to user source code.
2080b57cec5SDimitry Andric       // next_line_sc is the same file & line as this LineEntry, so extend
2090b57cec5SDimitry Andric       // our AddressRange by its size and continue to see if there are more
2100b57cec5SDimitry Andric       // LineEntries that we can combine. However, if there was nothing to
2110b57cec5SDimitry Andric       // extend we're done.
2120b57cec5SDimitry Andric       if (!complete_line_range.Extend(next_line_sc.line_entry.range))
2130b57cec5SDimitry Andric         break;
2140b57cec5SDimitry Andric       continue;
2150b57cec5SDimitry Andric     }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric     if (include_inlined_functions && next_line_sc.block &&
2180b57cec5SDimitry Andric         next_line_sc.block->GetContainingInlinedBlock() != nullptr) {
2190b57cec5SDimitry Andric       // The next_line_sc might be in a different file if it's an inlined
2200b57cec5SDimitry Andric       // function. If this is the case then we still want to expand our line
2210b57cec5SDimitry Andric       // range to include them if the inlined function is at the same call site
2220b57cec5SDimitry Andric       // as this line entry. The current block could represent a nested inline
2230b57cec5SDimitry Andric       // function call so we need to need to check up the block tree to see if
2240b57cec5SDimitry Andric       // we find one.
2250b57cec5SDimitry Andric       auto inlined_parent_block =
2260b57cec5SDimitry Andric           next_line_sc.block->GetContainingInlinedBlockWithCallSite(
2270b57cec5SDimitry Andric               start_call_site);
2280b57cec5SDimitry Andric       if (!inlined_parent_block)
2290b57cec5SDimitry Andric         // We didn't find any parent inlined block with a call site at this line
2300b57cec5SDimitry Andric         // entry so this inlined function is probably at another line.
2310b57cec5SDimitry Andric         break;
2320b57cec5SDimitry Andric       // Extend our AddressRange by the size of the inlined block, but if there
2330b57cec5SDimitry Andric       // was nothing to add then we're done.
2340b57cec5SDimitry Andric       if (!complete_line_range.Extend(next_line_sc.line_entry.range))
2350b57cec5SDimitry Andric         break;
2360b57cec5SDimitry Andric       continue;
2370b57cec5SDimitry Andric     }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric     break;
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric   return complete_line_range;
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
ApplyFileMappings(lldb::TargetSP target_sp)2440b57cec5SDimitry Andric void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) {
2450b57cec5SDimitry Andric   if (target_sp) {
246fe6060f1SDimitry Andric     // Apply any file remappings to our file.
2477a6dacacSDimitry Andric     if (auto new_file_spec = target_sp->GetSourcePathMap().FindFile(
248*0fca6ea1SDimitry Andric             original_file_sp->GetSpecOnly())) {
249*0fca6ea1SDimitry Andric       file_sp = std::make_shared<SupportFile>(*new_file_spec,
250*0fca6ea1SDimitry Andric                                               original_file_sp->GetChecksum());
251*0fca6ea1SDimitry Andric     }
2520b57cec5SDimitry Andric   }
2530b57cec5SDimitry Andric }
254