180814287SRaphael Isemann //===-- LineTable.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
9b9c1b51eSKate Stone #include "lldb/Symbol/LineTable.h"
1030fdc8d8SChris Lattner #include "lldb/Core/Address.h"
119422dd64SGreg Clayton #include "lldb/Core/Module.h"
1230fdc8d8SChris Lattner #include "lldb/Core/Section.h"
1330fdc8d8SChris Lattner #include "lldb/Symbol/CompileUnit.h"
14bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
1548862d45SEli Friedman #include <algorithm>
1630fdc8d8SChris Lattner
1730fdc8d8SChris Lattner using namespace lldb;
1830fdc8d8SChris Lattner using namespace lldb_private;
1930fdc8d8SChris Lattner
2030fdc8d8SChris Lattner // LineTable constructor
LineTable(CompileUnit * comp_unit)21b9c1b51eSKate Stone LineTable::LineTable(CompileUnit *comp_unit)
22b9c1b51eSKate Stone : m_comp_unit(comp_unit), m_entries() {}
2330fdc8d8SChris Lattner
LineTable(CompileUnit * comp_unit,std::vector<std::unique_ptr<LineSequence>> && sequences)2418a96fd5SPavel Labath LineTable::LineTable(CompileUnit *comp_unit,
2518a96fd5SPavel Labath std::vector<std::unique_ptr<LineSequence>> &&sequences)
2639f13354SUnnar Freyr Erlendsson : m_comp_unit(comp_unit), m_entries() {
2739f13354SUnnar Freyr Erlendsson LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
283f9b6b27SPavel Labath llvm::stable_sort(sequences, less_than_bp);
2918a96fd5SPavel Labath for (const auto &sequence : sequences) {
3018a96fd5SPavel Labath LineSequenceImpl *seq = static_cast<LineSequenceImpl *>(sequence.get());
3139f13354SUnnar Freyr Erlendsson m_entries.insert(m_entries.end(), seq->m_entries.begin(),
3239f13354SUnnar Freyr Erlendsson seq->m_entries.end());
3339f13354SUnnar Freyr Erlendsson }
3439f13354SUnnar Freyr Erlendsson }
3539f13354SUnnar Freyr Erlendsson
3630fdc8d8SChris Lattner // Destructor
37*fd2433e1SJonas Devlieghere LineTable::~LineTable() = default;
3830fdc8d8SChris Lattner
InsertLineEntry(lldb::addr_t file_addr,uint32_t line,uint16_t column,uint16_t file_idx,bool is_start_of_statement,bool is_start_of_basic_block,bool is_prologue_end,bool is_epilogue_begin,bool is_terminal_entry)39b9c1b51eSKate Stone void LineTable::InsertLineEntry(lldb::addr_t file_addr, uint32_t line,
40b9c1b51eSKate Stone uint16_t column, uint16_t file_idx,
4130fdc8d8SChris Lattner bool is_start_of_statement,
4230fdc8d8SChris Lattner bool is_start_of_basic_block,
43b9c1b51eSKate Stone bool is_prologue_end, bool is_epilogue_begin,
44b9c1b51eSKate Stone bool is_terminal_entry) {
45b9c1b51eSKate Stone Entry entry(file_addr, line, column, file_idx, is_start_of_statement,
46b9c1b51eSKate Stone is_start_of_basic_block, is_prologue_end, is_epilogue_begin,
47b9c1b51eSKate Stone is_terminal_entry);
4830fdc8d8SChris Lattner
4930fdc8d8SChris Lattner LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
50b9c1b51eSKate Stone entry_collection::iterator pos =
51159641d7SPavel Labath llvm::upper_bound(m_entries, entry, less_than_bp);
5230fdc8d8SChris Lattner
5330fdc8d8SChris Lattner // Stream s(stdout);
5430fdc8d8SChris Lattner // s << "\n\nBefore:\n";
5530fdc8d8SChris Lattner // Dump (&s, Address::DumpStyleFileAddress);
5630fdc8d8SChris Lattner m_entries.insert(pos, entry);
5730fdc8d8SChris Lattner // s << "After:\n";
5830fdc8d8SChris Lattner // Dump (&s, Address::DumpStyleFileAddress);
5930fdc8d8SChris Lattner }
6030fdc8d8SChris Lattner
61*fd2433e1SJonas Devlieghere LineSequence::LineSequence() = default;
62c740150fSAndrew Kaylor
Clear()63b9c1b51eSKate Stone void LineTable::LineSequenceImpl::Clear() { m_entries.clear(); }
64c740150fSAndrew Kaylor
CreateLineSequenceContainer()6518a96fd5SPavel Labath std::unique_ptr<LineSequence> LineTable::CreateLineSequenceContainer() {
6618a96fd5SPavel Labath return std::make_unique<LineTable::LineSequenceImpl>();
67c740150fSAndrew Kaylor }
68c740150fSAndrew Kaylor
AppendLineEntryToSequence(LineSequence * sequence,lldb::addr_t file_addr,uint32_t line,uint16_t column,uint16_t file_idx,bool is_start_of_statement,bool is_start_of_basic_block,bool is_prologue_end,bool is_epilogue_begin,bool is_terminal_entry)69b9c1b51eSKate Stone void LineTable::AppendLineEntryToSequence(
70b9c1b51eSKate Stone LineSequence *sequence, lldb::addr_t file_addr, uint32_t line,
71b9c1b51eSKate Stone uint16_t column, uint16_t file_idx, bool is_start_of_statement,
72b9c1b51eSKate Stone bool is_start_of_basic_block, bool is_prologue_end, bool is_epilogue_begin,
73b9c1b51eSKate Stone bool is_terminal_entry) {
74d4612ad0SEd Maste assert(sequence != nullptr);
75c740150fSAndrew Kaylor LineSequenceImpl *seq = reinterpret_cast<LineSequenceImpl *>(sequence);
76b9c1b51eSKate Stone Entry entry(file_addr, line, column, file_idx, is_start_of_statement,
77b9c1b51eSKate Stone is_start_of_basic_block, is_prologue_end, is_epilogue_begin,
78b9c1b51eSKate Stone is_terminal_entry);
799e42e92eSGreg Clayton entry_collection &entries = seq->m_entries;
80b9c1b51eSKate Stone // Replace the last entry if the address is the same, otherwise append it. If
8105097246SAdrian Prantl // we have multiple line entries at the same address, this indicates illegal
8205097246SAdrian Prantl // DWARF so this "fixes" the line table to be correct. If not fixed this can
8305097246SAdrian Prantl // cause a line entry's address that when resolved back to a symbol context,
8405097246SAdrian Prantl // could resolve to a different line entry. We really want a
85b9c1b51eSKate Stone // 1 to 1 mapping
8605097246SAdrian Prantl // here to avoid these kinds of inconsistencies. We will need tor revisit
8705097246SAdrian Prantl // this if the DWARF line tables are updated to allow multiple entries at the
8805097246SAdrian Prantl // same address legally.
89b9c1b51eSKate Stone if (!entries.empty() && entries.back().file_addr == file_addr) {
90b9c1b51eSKate Stone // GCC don't use the is_prologue_end flag to mark the first instruction
91b9c1b51eSKate Stone // after the prologue.
92b9c1b51eSKate Stone // Instead of it it is issuing a line table entry for the first instruction
9305097246SAdrian Prantl // of the prologue and one for the first instruction after the prologue. If
9405097246SAdrian Prantl // the size of the prologue is 0 instruction then the 2 line entry will
9505097246SAdrian Prantl // have the same file address. Removing it will remove our ability to
9605097246SAdrian Prantl // properly detect the location of the end of prologe so we set the
9705097246SAdrian Prantl // prologue_end flag to preserve this information (setting the prologue_end
9805097246SAdrian Prantl // flag for an entry what is after the prologue end don't have any effect)
996127f033STamas Berghammer entry.is_prologue_end = entry.file_idx == entries.back().file_idx;
1009e42e92eSGreg Clayton entries.back() = entry;
101b9c1b51eSKate Stone } else
1029e42e92eSGreg Clayton entries.push_back(entry);
103c740150fSAndrew Kaylor }
104c740150fSAndrew Kaylor
InsertSequence(LineSequence * sequence)105b9c1b51eSKate Stone void LineTable::InsertSequence(LineSequence *sequence) {
106d4612ad0SEd Maste assert(sequence != nullptr);
107c740150fSAndrew Kaylor LineSequenceImpl *seq = reinterpret_cast<LineSequenceImpl *>(sequence);
1089422dd64SGreg Clayton if (seq->m_entries.empty())
109c740150fSAndrew Kaylor return;
1109422dd64SGreg Clayton Entry &entry = seq->m_entries.front();
111c740150fSAndrew Kaylor
112c740150fSAndrew Kaylor // If the first entry address in this sequence is greater than or equal to
113c740150fSAndrew Kaylor // the address of the last item in our entry collection, just append.
114b9c1b51eSKate Stone if (m_entries.empty() ||
115b9c1b51eSKate Stone !Entry::EntryAddressLessThan(entry, m_entries.back())) {
116b9c1b51eSKate Stone m_entries.insert(m_entries.end(), seq->m_entries.begin(),
1179422dd64SGreg Clayton seq->m_entries.end());
118c740150fSAndrew Kaylor return;
119c740150fSAndrew Kaylor }
120c740150fSAndrew Kaylor
121c740150fSAndrew Kaylor // Otherwise, find where this belongs in the collection
122c740150fSAndrew Kaylor entry_collection::iterator begin_pos = m_entries.begin();
123c740150fSAndrew Kaylor entry_collection::iterator end_pos = m_entries.end();
124c740150fSAndrew Kaylor LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
125b9c1b51eSKate Stone entry_collection::iterator pos =
126b9c1b51eSKate Stone upper_bound(begin_pos, end_pos, entry, less_than_bp);
127506ecac0SStephane Sezer
128506ecac0SStephane Sezer // We should never insert a sequence in the middle of another sequence
129506ecac0SStephane Sezer if (pos != begin_pos) {
130506ecac0SStephane Sezer while (pos < end_pos && !((pos - 1)->is_terminal_entry))
131506ecac0SStephane Sezer pos++;
132506ecac0SStephane Sezer }
133506ecac0SStephane Sezer
13428f7466fSAdrian Prantl #ifndef NDEBUG
135c740150fSAndrew Kaylor // If we aren't inserting at the beginning, the previous entry should
136c740150fSAndrew Kaylor // terminate a sequence.
137b9c1b51eSKate Stone if (pos != begin_pos) {
138c740150fSAndrew Kaylor entry_collection::iterator prev_pos = pos - 1;
139c740150fSAndrew Kaylor assert(prev_pos->is_terminal_entry);
140c740150fSAndrew Kaylor }
141c740150fSAndrew Kaylor #endif
1429422dd64SGreg Clayton m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end());
143c740150fSAndrew Kaylor }
144c740150fSAndrew Kaylor
LessThanBinaryPredicate(LineTable * line_table)145b9c1b51eSKate Stone LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(
146b9c1b51eSKate Stone LineTable *line_table)
147b9c1b51eSKate Stone : m_line_table(line_table) {}
14830fdc8d8SChris Lattner
149b9c1b51eSKate Stone bool LineTable::Entry::LessThanBinaryPredicate::
operator ()(const LineTable::Entry & a,const LineTable::Entry & b) const150b9c1b51eSKate Stone operator()(const LineTable::Entry &a, const LineTable::Entry &b) const {
151b9c1b51eSKate Stone #define LT_COMPARE(a, b) \
152b9c1b51eSKate Stone if (a != b) \
153b9c1b51eSKate Stone return a < b
1549422dd64SGreg Clayton LT_COMPARE(a.file_addr, b.file_addr);
155322654a7SGreg Clayton // b and a reversed on purpose below.
156322654a7SGreg Clayton LT_COMPARE(b.is_terminal_entry, a.is_terminal_entry);
15730fdc8d8SChris Lattner LT_COMPARE(a.line, b.line);
15830fdc8d8SChris Lattner LT_COMPARE(a.column, b.column);
15930fdc8d8SChris Lattner LT_COMPARE(a.is_start_of_statement, b.is_start_of_statement);
16030fdc8d8SChris Lattner LT_COMPARE(a.is_start_of_basic_block, b.is_start_of_basic_block);
16130fdc8d8SChris Lattner // b and a reversed on purpose below.
16230fdc8d8SChris Lattner LT_COMPARE(b.is_prologue_end, a.is_prologue_end);
16330fdc8d8SChris Lattner LT_COMPARE(a.is_epilogue_begin, b.is_epilogue_begin);
16430fdc8d8SChris Lattner LT_COMPARE(a.file_idx, b.file_idx);
16530fdc8d8SChris Lattner return false;
16648862d45SEli Friedman #undef LT_COMPARE
16730fdc8d8SChris Lattner }
16830fdc8d8SChris Lattner
16939f13354SUnnar Freyr Erlendsson bool LineTable::Entry::LessThanBinaryPredicate::
operator ()(const std::unique_ptr<LineSequence> & sequence_a,const std::unique_ptr<LineSequence> & sequence_b) const17018a96fd5SPavel Labath operator()(const std::unique_ptr<LineSequence> &sequence_a,
17118a96fd5SPavel Labath const std::unique_ptr<LineSequence> &sequence_b) const {
17218a96fd5SPavel Labath auto *seq_a = static_cast<const LineSequenceImpl *>(sequence_a.get());
17318a96fd5SPavel Labath auto *seq_b = static_cast<const LineSequenceImpl *>(sequence_b.get());
17439f13354SUnnar Freyr Erlendsson return (*this)(seq_a->m_entries.front(), seq_b->m_entries.front());
17539f13354SUnnar Freyr Erlendsson }
17639f13354SUnnar Freyr Erlendsson
GetSize() const177b9c1b51eSKate Stone uint32_t LineTable::GetSize() const { return m_entries.size(); }
17830fdc8d8SChris Lattner
GetLineEntryAtIndex(uint32_t idx,LineEntry & line_entry)179b9c1b51eSKate Stone bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) {
180b9c1b51eSKate Stone if (idx < m_entries.size()) {
18130fdc8d8SChris Lattner ConvertEntryAtIndexToLineEntry(idx, line_entry);
18230fdc8d8SChris Lattner return true;
18330fdc8d8SChris Lattner }
18430fdc8d8SChris Lattner line_entry.Clear();
18530fdc8d8SChris Lattner return false;
18630fdc8d8SChris Lattner }
18730fdc8d8SChris Lattner
FindLineEntryByAddress(const Address & so_addr,LineEntry & line_entry,uint32_t * index_ptr)188b9c1b51eSKate Stone bool LineTable::FindLineEntryByAddress(const Address &so_addr,
189b9c1b51eSKate Stone LineEntry &line_entry,
190b9c1b51eSKate Stone uint32_t *index_ptr) {
191d4612ad0SEd Maste if (index_ptr != nullptr)
19230fdc8d8SChris Lattner *index_ptr = UINT32_MAX;
19330fdc8d8SChris Lattner
19430fdc8d8SChris Lattner bool success = false;
1959422dd64SGreg Clayton
196b9c1b51eSKate Stone if (so_addr.GetModule().get() == m_comp_unit->GetModule().get()) {
19730fdc8d8SChris Lattner Entry search_entry;
1989422dd64SGreg Clayton search_entry.file_addr = so_addr.GetFileAddress();
199b9c1b51eSKate Stone if (search_entry.file_addr != LLDB_INVALID_ADDRESS) {
20030fdc8d8SChris Lattner entry_collection::const_iterator begin_pos = m_entries.begin();
20130fdc8d8SChris Lattner entry_collection::const_iterator end_pos = m_entries.end();
202b9c1b51eSKate Stone entry_collection::const_iterator pos = lower_bound(
203b9c1b51eSKate Stone begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan);
204b9c1b51eSKate Stone if (pos != end_pos) {
205b9c1b51eSKate Stone if (pos != begin_pos) {
2069422dd64SGreg Clayton if (pos->file_addr != search_entry.file_addr)
20730fdc8d8SChris Lattner --pos;
208b9c1b51eSKate Stone else if (pos->file_addr == search_entry.file_addr) {
20905097246SAdrian Prantl // If this is a termination entry, it shouldn't match since entries
21005097246SAdrian Prantl // with the "is_terminal_entry" member set to true are termination
21105097246SAdrian Prantl // entries that define the range for the previous entry.
212b9c1b51eSKate Stone if (pos->is_terminal_entry) {
21305097246SAdrian Prantl // The matching entry is a terminal entry, so we skip ahead to
21405097246SAdrian Prantl // the next entry to see if there is another entry following this
21505097246SAdrian Prantl // one whose section/offset matches.
216364f1167SGreg Clayton ++pos;
217b9c1b51eSKate Stone if (pos != end_pos) {
2189422dd64SGreg Clayton if (pos->file_addr != search_entry.file_addr)
219364f1167SGreg Clayton pos = end_pos;
220364f1167SGreg Clayton }
221364f1167SGreg Clayton }
222364f1167SGreg Clayton
223b9c1b51eSKate Stone if (pos != end_pos) {
22405097246SAdrian Prantl // While in the same section/offset backup to find the first line
22505097246SAdrian Prantl // entry that matches the address in case there are multiple
226b9c1b51eSKate Stone while (pos != begin_pos) {
22730fdc8d8SChris Lattner entry_collection::const_iterator prev_pos = pos - 1;
2289422dd64SGreg Clayton if (prev_pos->file_addr == search_entry.file_addr &&
229364f1167SGreg Clayton prev_pos->is_terminal_entry == false)
23030fdc8d8SChris Lattner --pos;
23130fdc8d8SChris Lattner else
23230fdc8d8SChris Lattner break;
23330fdc8d8SChris Lattner }
23430fdc8d8SChris Lattner }
235364f1167SGreg Clayton }
23630fdc8d8SChris Lattner }
2372dc4a3e9SJim Ingham else
2382dc4a3e9SJim Ingham {
23905097246SAdrian Prantl // There might be code in the containing objfile before the first
24005097246SAdrian Prantl // line table entry. Make sure that does not get considered part of
24105097246SAdrian Prantl // the first line table entry.
2422dc4a3e9SJim Ingham if (pos->file_addr > so_addr.GetFileAddress())
2432dc4a3e9SJim Ingham return false;
2442dc4a3e9SJim Ingham }
245364f1167SGreg Clayton
246b9c1b51eSKate Stone // Make sure we have a valid match and that the match isn't a
24705097246SAdrian Prantl // terminating entry for a previous line...
248b9c1b51eSKate Stone if (pos != end_pos && pos->is_terminal_entry == false) {
24930fdc8d8SChris Lattner uint32_t match_idx = std::distance(begin_pos, pos);
25030fdc8d8SChris Lattner success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
251d4612ad0SEd Maste if (index_ptr != nullptr && success)
25230fdc8d8SChris Lattner *index_ptr = match_idx;
25330fdc8d8SChris Lattner }
25430fdc8d8SChris Lattner }
255364f1167SGreg Clayton }
2569422dd64SGreg Clayton }
25730fdc8d8SChris Lattner return success;
25830fdc8d8SChris Lattner }
25930fdc8d8SChris Lattner
ConvertEntryAtIndexToLineEntry(uint32_t idx,LineEntry & line_entry)260b9c1b51eSKate Stone bool LineTable::ConvertEntryAtIndexToLineEntry(uint32_t idx,
261b9c1b51eSKate Stone LineEntry &line_entry) {
262a3bdcdf7SPavel Labath if (idx >= m_entries.size())
263a3bdcdf7SPavel Labath return false;
264a3bdcdf7SPavel Labath
26530fdc8d8SChris Lattner const Entry &entry = m_entries[idx];
2669422dd64SGreg Clayton ModuleSP module_sp(m_comp_unit->GetModule());
267a3bdcdf7SPavel Labath if (!module_sp)
268a3bdcdf7SPavel Labath return false;
269a3bdcdf7SPavel Labath
270a3bdcdf7SPavel Labath addr_t file_addr = entry.file_addr;
271a3bdcdf7SPavel Labath
272a3bdcdf7SPavel Labath // A terminal entry can point outside of a module or a section. Decrement the
273a3bdcdf7SPavel Labath // address to ensure it resolves correctly.
274a3bdcdf7SPavel Labath if (entry.is_terminal_entry)
275a3bdcdf7SPavel Labath --file_addr;
276a3bdcdf7SPavel Labath
277a3bdcdf7SPavel Labath if (!module_sp->ResolveFileAddress(file_addr,
278a3bdcdf7SPavel Labath line_entry.range.GetBaseAddress()))
279a3bdcdf7SPavel Labath return false;
280a3bdcdf7SPavel Labath
281a3bdcdf7SPavel Labath // Now undo the decrement above.
282a3bdcdf7SPavel Labath if (entry.is_terminal_entry)
283a3bdcdf7SPavel Labath line_entry.range.GetBaseAddress().Slide(1);
284a3bdcdf7SPavel Labath
28530fdc8d8SChris Lattner if (!entry.is_terminal_entry && idx + 1 < m_entries.size())
286b9c1b51eSKate Stone line_entry.range.SetByteSize(m_entries[idx + 1].file_addr -
287b9c1b51eSKate Stone entry.file_addr);
28830fdc8d8SChris Lattner else
28930fdc8d8SChris Lattner line_entry.range.SetByteSize(0);
2909422dd64SGreg Clayton
291b9c1b51eSKate Stone line_entry.file =
292b9c1b51eSKate Stone m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx);
293b9c1b51eSKate Stone line_entry.original_file =
294b9c1b51eSKate Stone m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx);
29530fdc8d8SChris Lattner line_entry.line = entry.line;
29630fdc8d8SChris Lattner line_entry.column = entry.column;
29730fdc8d8SChris Lattner line_entry.is_start_of_statement = entry.is_start_of_statement;
29830fdc8d8SChris Lattner line_entry.is_start_of_basic_block = entry.is_start_of_basic_block;
29930fdc8d8SChris Lattner line_entry.is_prologue_end = entry.is_prologue_end;
30030fdc8d8SChris Lattner line_entry.is_epilogue_begin = entry.is_epilogue_begin;
30130fdc8d8SChris Lattner line_entry.is_terminal_entry = entry.is_terminal_entry;
30230fdc8d8SChris Lattner return true;
30330fdc8d8SChris Lattner }
30430fdc8d8SChris Lattner
FindLineEntryIndexByFileIndex(uint32_t start_idx,uint32_t file_idx,const SourceLocationSpec & src_location_spec,LineEntry * line_entry_ptr)305b9c1b51eSKate Stone uint32_t LineTable::FindLineEntryIndexByFileIndex(
30635ecfda0SMed Ismail Bennani uint32_t start_idx, uint32_t file_idx,
3073e2ed744SMed Ismail Bennani const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr) {
30835ecfda0SMed Ismail Bennani auto file_idx_matcher = [](uint32_t file_index, uint16_t entry_file_idx) {
30935ecfda0SMed Ismail Bennani return file_index == entry_file_idx;
31035ecfda0SMed Ismail Bennani };
31135ecfda0SMed Ismail Bennani return FindLineEntryIndexByFileIndexImpl<uint32_t>(
312fd269157SGreg Clayton
31335ecfda0SMed Ismail Bennani start_idx, file_idx, src_location_spec, line_entry_ptr, file_idx_matcher);
314fd269157SGreg Clayton }
315fd269157SGreg Clayton
FindLineEntryIndexByFileIndex(uint32_t start_idx,const std::vector<uint32_t> & file_idx,const SourceLocationSpec & src_location_spec,LineEntry * line_entry_ptr)3163e2ed744SMed Ismail Bennani uint32_t LineTable::FindLineEntryIndexByFileIndex(
31735ecfda0SMed Ismail Bennani uint32_t start_idx, const std::vector<uint32_t> &file_idx,
3183e2ed744SMed Ismail Bennani const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr) {
31935ecfda0SMed Ismail Bennani auto file_idx_matcher = [](const std::vector<uint32_t> &file_indexes,
32035ecfda0SMed Ismail Bennani uint16_t entry_file_idx) {
32135ecfda0SMed Ismail Bennani return llvm::is_contained(file_indexes, entry_file_idx);
32235ecfda0SMed Ismail Bennani };
32330fdc8d8SChris Lattner
32435ecfda0SMed Ismail Bennani return FindLineEntryIndexByFileIndexImpl<std::vector<uint32_t>>(
32535ecfda0SMed Ismail Bennani start_idx, file_idx, src_location_spec, line_entry_ptr, file_idx_matcher);
32630fdc8d8SChris Lattner }
32730fdc8d8SChris Lattner
FineLineEntriesForFileIndex(uint32_t file_idx,bool append,SymbolContextList & sc_list)328b9c1b51eSKate Stone size_t LineTable::FineLineEntriesForFileIndex(uint32_t file_idx, bool append,
329b9c1b51eSKate Stone SymbolContextList &sc_list) {
330176761e5SGreg Clayton
331176761e5SGreg Clayton if (!append)
332176761e5SGreg Clayton sc_list.Clear();
333176761e5SGreg Clayton
334176761e5SGreg Clayton size_t num_added = 0;
335176761e5SGreg Clayton const size_t count = m_entries.size();
336b9c1b51eSKate Stone if (count > 0) {
337176761e5SGreg Clayton SymbolContext sc(m_comp_unit);
338176761e5SGreg Clayton
339b9c1b51eSKate Stone for (size_t idx = 0; idx < count; ++idx) {
34005097246SAdrian Prantl // Skip line table rows that terminate the previous row
34105097246SAdrian Prantl // (is_terminal_entry is non-zero)
342176761e5SGreg Clayton if (m_entries[idx].is_terminal_entry)
343176761e5SGreg Clayton continue;
344176761e5SGreg Clayton
345b9c1b51eSKate Stone if (m_entries[idx].file_idx == file_idx) {
346b9c1b51eSKate Stone if (ConvertEntryAtIndexToLineEntry(idx, sc.line_entry)) {
347176761e5SGreg Clayton ++num_added;
348176761e5SGreg Clayton sc_list.Append(sc);
349176761e5SGreg Clayton }
350176761e5SGreg Clayton }
351176761e5SGreg Clayton }
352176761e5SGreg Clayton }
353176761e5SGreg Clayton return num_added;
354176761e5SGreg Clayton }
355176761e5SGreg Clayton
Dump(Stream * s,Target * target,Address::DumpStyle style,Address::DumpStyle fallback_style,bool show_line_ranges)356b9c1b51eSKate Stone void LineTable::Dump(Stream *s, Target *target, Address::DumpStyle style,
357b9c1b51eSKate Stone Address::DumpStyle fallback_style, bool show_line_ranges) {
35830fdc8d8SChris Lattner const size_t count = m_entries.size();
35930fdc8d8SChris Lattner LineEntry line_entry;
36030fdc8d8SChris Lattner FileSpec prev_file;
361b9c1b51eSKate Stone for (size_t idx = 0; idx < count; ++idx) {
36230fdc8d8SChris Lattner ConvertEntryAtIndexToLineEntry(idx, line_entry);
363b9c1b51eSKate Stone line_entry.Dump(s, target, prev_file != line_entry.original_file, style,
364b9c1b51eSKate Stone fallback_style, show_line_ranges);
36530fdc8d8SChris Lattner s->EOL();
366911d5784STed Woodward prev_file = line_entry.original_file;
36730fdc8d8SChris Lattner }
36830fdc8d8SChris Lattner }
36930fdc8d8SChris Lattner
GetDescription(Stream * s,Target * target,DescriptionLevel level)370b9c1b51eSKate Stone void LineTable::GetDescription(Stream *s, Target *target,
371b9c1b51eSKate Stone DescriptionLevel level) {
37230fdc8d8SChris Lattner const size_t count = m_entries.size();
37330fdc8d8SChris Lattner LineEntry line_entry;
374b9c1b51eSKate Stone for (size_t idx = 0; idx < count; ++idx) {
37530fdc8d8SChris Lattner ConvertEntryAtIndexToLineEntry(idx, line_entry);
376f5e56de0SGreg Clayton line_entry.GetDescription(s, level, m_comp_unit, target, true);
37730fdc8d8SChris Lattner s->EOL();
37830fdc8d8SChris Lattner }
37930fdc8d8SChris Lattner }
38030fdc8d8SChris Lattner
GetContiguousFileAddressRanges(FileAddressRanges & file_ranges,bool append)381b9c1b51eSKate Stone size_t LineTable::GetContiguousFileAddressRanges(FileAddressRanges &file_ranges,
382b9c1b51eSKate Stone bool append) {
3836ab80139SGreg Clayton if (!append)
3846ab80139SGreg Clayton file_ranges.Clear();
3856ab80139SGreg Clayton const size_t initial_count = file_ranges.GetSize();
3866ab80139SGreg Clayton
3876ab80139SGreg Clayton const size_t count = m_entries.size();
3886ab80139SGreg Clayton LineEntry line_entry;
3896ab80139SGreg Clayton FileAddressRanges::Entry range(LLDB_INVALID_ADDRESS, 0);
390b9c1b51eSKate Stone for (size_t idx = 0; idx < count; ++idx) {
3916ab80139SGreg Clayton const Entry &entry = m_entries[idx];
3926ab80139SGreg Clayton
393b9c1b51eSKate Stone if (entry.is_terminal_entry) {
394b9c1b51eSKate Stone if (range.GetRangeBase() != LLDB_INVALID_ADDRESS) {
3959422dd64SGreg Clayton range.SetRangeEnd(entry.file_addr);
3966ab80139SGreg Clayton file_ranges.Append(range);
3976ab80139SGreg Clayton range.Clear(LLDB_INVALID_ADDRESS);
3986ab80139SGreg Clayton }
399b9c1b51eSKate Stone } else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS) {
4009422dd64SGreg Clayton range.SetRangeBase(entry.file_addr);
4016ab80139SGreg Clayton }
4026ab80139SGreg Clayton }
4036ab80139SGreg Clayton return file_ranges.GetSize() - initial_count;
4046ab80139SGreg Clayton }
4056ab80139SGreg Clayton
LinkLineTable(const FileRangeMap & file_range_map)406b9c1b51eSKate Stone LineTable *LineTable::LinkLineTable(const FileRangeMap &file_range_map) {
407d5b44036SJonas Devlieghere std::unique_ptr<LineTable> line_table_up(new LineTable(m_comp_unit));
4089422dd64SGreg Clayton LineSequenceImpl sequence;
4099422dd64SGreg Clayton const size_t count = m_entries.size();
4109422dd64SGreg Clayton LineEntry line_entry;
411d4612ad0SEd Maste const FileRangeMap::Entry *file_range_entry = nullptr;
412d4612ad0SEd Maste const FileRangeMap::Entry *prev_file_range_entry = nullptr;
4139422dd64SGreg Clayton lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS;
4149422dd64SGreg Clayton bool prev_entry_was_linked = false;
415084fad6aSGreg Clayton bool range_changed = false;
416b9c1b51eSKate Stone for (size_t idx = 0; idx < count; ++idx) {
4179422dd64SGreg Clayton const Entry &entry = m_entries[idx];
4189422dd64SGreg Clayton
4199422dd64SGreg Clayton const bool end_sequence = entry.is_terminal_entry;
420b9c1b51eSKate Stone const lldb::addr_t lookup_file_addr =
421b9c1b51eSKate Stone entry.file_addr - (end_sequence ? 1 : 0);
422b9c1b51eSKate Stone if (file_range_entry == nullptr ||
423b9c1b51eSKate Stone !file_range_entry->Contains(lookup_file_addr)) {
4249422dd64SGreg Clayton prev_file_range_entry = file_range_entry;
4259422dd64SGreg Clayton file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr);
426084fad6aSGreg Clayton range_changed = true;
4279422dd64SGreg Clayton }
4289422dd64SGreg Clayton
429084fad6aSGreg Clayton lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS;
430084fad6aSGreg Clayton lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS;
431084fad6aSGreg Clayton
432084fad6aSGreg Clayton bool terminate_previous_entry = false;
433b9c1b51eSKate Stone if (file_range_entry) {
434b9c1b51eSKate Stone entry_linked_file_addr = entry.file_addr -
435b9c1b51eSKate Stone file_range_entry->GetRangeBase() +
436b9c1b51eSKate Stone file_range_entry->data;
437084fad6aSGreg Clayton // Determine if we need to terminate the previous entry when the previous
438e171da5cSBruce Mitchener // entry was not contiguous with this one after being linked.
439b9c1b51eSKate Stone if (range_changed && prev_file_range_entry) {
440b9c1b51eSKate Stone prev_end_entry_linked_file_addr =
441b9c1b51eSKate Stone std::min<lldb::addr_t>(entry.file_addr,
442b9c1b51eSKate Stone prev_file_range_entry->GetRangeEnd()) -
443b9c1b51eSKate Stone prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data;
444084fad6aSGreg Clayton if (prev_end_entry_linked_file_addr != entry_linked_file_addr)
445617995c0SGreg Clayton terminate_previous_entry = prev_entry_was_linked;
446084fad6aSGreg Clayton }
447b9c1b51eSKate Stone } else if (prev_entry_was_linked) {
44805097246SAdrian Prantl // This entry doesn't have a remapping and it needs to be removed. Watch
44905097246SAdrian Prantl // out in case we need to terminate a previous entry needs to be
45005097246SAdrian Prantl // terminated now that one line entry in a sequence is not longer valid.
451cc8913ccSGreg Clayton if (!sequence.m_entries.empty() &&
452b9c1b51eSKate Stone !sequence.m_entries.back().is_terminal_entry) {
453084fad6aSGreg Clayton terminate_previous_entry = true;
454084fad6aSGreg Clayton }
455084fad6aSGreg Clayton }
456084fad6aSGreg Clayton
457b9c1b51eSKate Stone if (terminate_previous_entry && !sequence.m_entries.empty()) {
4589422dd64SGreg Clayton assert(prev_file_addr != LLDB_INVALID_ADDRESS);
459b1554311SHafiz Abid Qadeer UNUSED_IF_ASSERT_DISABLED(prev_file_addr);
4609422dd64SGreg Clayton sequence.m_entries.push_back(sequence.m_entries.back());
461084fad6aSGreg Clayton if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS)
462b9c1b51eSKate Stone prev_end_entry_linked_file_addr =
463b9c1b51eSKate Stone std::min<lldb::addr_t>(entry.file_addr,
464b9c1b51eSKate Stone prev_file_range_entry->GetRangeEnd()) -
465b9c1b51eSKate Stone prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data;
466084fad6aSGreg Clayton sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr;
4679422dd64SGreg Clayton sequence.m_entries.back().is_terminal_entry = true;
468084fad6aSGreg Clayton
469084fad6aSGreg Clayton // Append the sequence since we just terminated the previous one
470d5b44036SJonas Devlieghere line_table_up->InsertSequence(&sequence);
471084fad6aSGreg Clayton sequence.Clear();
4729422dd64SGreg Clayton }
473084fad6aSGreg Clayton
474084fad6aSGreg Clayton // Now link the current entry
475b9c1b51eSKate Stone if (file_range_entry) {
476b9c1b51eSKate Stone // This entry has an address remapping and it needs to have its address
477b9c1b51eSKate Stone // relinked
478084fad6aSGreg Clayton sequence.m_entries.push_back(entry);
479084fad6aSGreg Clayton sequence.m_entries.back().file_addr = entry_linked_file_addr;
4809422dd64SGreg Clayton }
4819422dd64SGreg Clayton
4829422dd64SGreg Clayton // If we have items in the sequence and the last entry is a terminal entry,
4839422dd64SGreg Clayton // insert this sequence into our new line table.
484b9c1b51eSKate Stone if (!sequence.m_entries.empty() &&
485b9c1b51eSKate Stone sequence.m_entries.back().is_terminal_entry) {
486d5b44036SJonas Devlieghere line_table_up->InsertSequence(&sequence);
4879422dd64SGreg Clayton sequence.Clear();
4889422dd64SGreg Clayton prev_entry_was_linked = false;
489b9c1b51eSKate Stone } else {
490d4612ad0SEd Maste prev_entry_was_linked = file_range_entry != nullptr;
4919422dd64SGreg Clayton }
492084fad6aSGreg Clayton prev_file_addr = entry.file_addr;
493084fad6aSGreg Clayton range_changed = false;
4949422dd64SGreg Clayton }
495d5b44036SJonas Devlieghere if (line_table_up->m_entries.empty())
496d4612ad0SEd Maste return nullptr;
497d5b44036SJonas Devlieghere return line_table_up.release();
4989422dd64SGreg Clayton }
499