diff options
Diffstat (limited to 'lldb/source/Symbol/LineTable.cpp')
-rw-r--r-- | lldb/source/Symbol/LineTable.cpp | 1000 |
1 files changed, 464 insertions, 536 deletions
diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index 6b4dea773d1..02ab0c12611 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Symbol/LineTable.h" #include "lldb/Core/Address.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/CompileUnit.h" -#include "lldb/Symbol/LineTable.h" #include <algorithm> using namespace lldb; @@ -21,594 +21,522 @@ using namespace lldb_private; //---------------------------------------------------------------------- // LineTable constructor //---------------------------------------------------------------------- -LineTable::LineTable(CompileUnit* comp_unit) : - m_comp_unit(comp_unit), - m_entries() -{ -} +LineTable::LineTable(CompileUnit *comp_unit) + : m_comp_unit(comp_unit), m_entries() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -LineTable::~LineTable() -{ +LineTable::~LineTable() {} + +void LineTable::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) { + Entry entry(file_addr, line, column, file_idx, is_start_of_statement, + is_start_of_basic_block, is_prologue_end, is_epilogue_begin, + is_terminal_entry); + + entry_collection::iterator begin_pos = m_entries.begin(); + entry_collection::iterator end_pos = m_entries.end(); + LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); + entry_collection::iterator pos = + upper_bound(begin_pos, end_pos, entry, less_than_bp); + + // Stream s(stdout); + // s << "\n\nBefore:\n"; + // Dump (&s, Address::DumpStyleFileAddress); + m_entries.insert(pos, entry); + // s << "After:\n"; + // Dump (&s, Address::DumpStyleFileAddress); } -void -LineTable::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 -) -{ - Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); - - entry_collection::iterator begin_pos = m_entries.begin(); - entry_collection::iterator end_pos = m_entries.end(); - LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); - entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp); - -// Stream s(stdout); -// s << "\n\nBefore:\n"; -// Dump (&s, Address::DumpStyleFileAddress); - m_entries.insert(pos, entry); -// s << "After:\n"; -// Dump (&s, Address::DumpStyleFileAddress); -} +LineSequence::LineSequence() {} -LineSequence::LineSequence() -{ -} +void LineTable::LineSequenceImpl::Clear() { m_entries.clear(); } -void -LineTable::LineSequenceImpl::Clear() -{ - m_entries.clear(); +LineSequence *LineTable::CreateLineSequenceContainer() { + return new LineTable::LineSequenceImpl(); } -LineSequence* LineTable::CreateLineSequenceContainer () -{ - return new LineTable::LineSequenceImpl(); +void LineTable::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) { + assert(sequence != nullptr); + LineSequenceImpl *seq = reinterpret_cast<LineSequenceImpl *>(sequence); + Entry entry(file_addr, line, column, file_idx, is_start_of_statement, + is_start_of_basic_block, is_prologue_end, is_epilogue_begin, + is_terminal_entry); + entry_collection &entries = seq->m_entries; + // Replace the last entry if the address is the same, otherwise append it. If + // we have multiple + // line entries at the same address, this indicates illegal DWARF so this + // "fixes" the line table + // to be correct. If not fixed this can cause a line entry's address that when + // resolved back to + // a symbol context, could resolve to a different line entry. We really want a + // 1 to 1 mapping + // here to avoid these kinds of inconsistencies. We will need tor revisit this + // if the DWARF line + // tables are updated to allow multiple entries at the same address legally. + if (!entries.empty() && entries.back().file_addr == file_addr) { + // GCC don't use the is_prologue_end flag to mark the first instruction + // after the prologue. + // Instead of it it is issuing a line table entry for the first instruction + // of the prologue + // and one for the first instruction after the prologue. If the size of the + // prologue is 0 + // instruction then the 2 line entry will have the same file address. + // Removing it will remove + // our ability to properly detect the location of the end of prologe so we + // set the prologue_end + // flag to preserve this information (setting the prologue_end flag for an + // entry what is after + // the prologue end don't have any effect) + entry.is_prologue_end = entry.file_idx == entries.back().file_idx; + entries.back() = entry; + } else + entries.push_back(entry); } -void -LineTable::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 -) -{ - assert(sequence != nullptr); - LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); - Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); - entry_collection &entries = seq->m_entries; - // Replace the last entry if the address is the same, otherwise append it. If we have multiple - // line entries at the same address, this indicates illegal DWARF so this "fixes" the line table - // to be correct. If not fixed this can cause a line entry's address that when resolved back to - // a symbol context, could resolve to a different line entry. We really want a 1 to 1 mapping - // here to avoid these kinds of inconsistencies. We will need tor revisit this if the DWARF line - // tables are updated to allow multiple entries at the same address legally. - if (!entries.empty() && entries.back().file_addr == file_addr) - { - // GCC don't use the is_prologue_end flag to mark the first instruction after the prologue. - // Instead of it it is issuing a line table entry for the first instruction of the prologue - // and one for the first instruction after the prologue. If the size of the prologue is 0 - // instruction then the 2 line entry will have the same file address. Removing it will remove - // our ability to properly detect the location of the end of prologe so we set the prologue_end - // flag to preserve this information (setting the prologue_end flag for an entry what is after - // the prologue end don't have any effect) - entry.is_prologue_end = entry.file_idx == entries.back().file_idx; - entries.back() = entry; - } - else - entries.push_back (entry); -} - -void -LineTable::InsertSequence (LineSequence* sequence) -{ - assert(sequence != nullptr); - LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); - if (seq->m_entries.empty()) - return; - Entry& entry = seq->m_entries.front(); - - // If the first entry address in this sequence is greater than or equal to - // the address of the last item in our entry collection, just append. - if (m_entries.empty() || !Entry::EntryAddressLessThan(entry, m_entries.back())) - { - m_entries.insert(m_entries.end(), - seq->m_entries.begin(), - seq->m_entries.end()); - return; - } - - // Otherwise, find where this belongs in the collection - entry_collection::iterator begin_pos = m_entries.begin(); - entry_collection::iterator end_pos = m_entries.end(); - LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); - entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp); - - // We should never insert a sequence in the middle of another sequence - if (pos != begin_pos) { - while (pos < end_pos && !((pos - 1)->is_terminal_entry)) - pos++; - } +void LineTable::InsertSequence(LineSequence *sequence) { + assert(sequence != nullptr); + LineSequenceImpl *seq = reinterpret_cast<LineSequenceImpl *>(sequence); + if (seq->m_entries.empty()) + return; + Entry &entry = seq->m_entries.front(); + + // If the first entry address in this sequence is greater than or equal to + // the address of the last item in our entry collection, just append. + if (m_entries.empty() || + !Entry::EntryAddressLessThan(entry, m_entries.back())) { + m_entries.insert(m_entries.end(), seq->m_entries.begin(), + seq->m_entries.end()); + return; + } + + // Otherwise, find where this belongs in the collection + entry_collection::iterator begin_pos = m_entries.begin(); + entry_collection::iterator end_pos = m_entries.end(); + LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); + entry_collection::iterator pos = + upper_bound(begin_pos, end_pos, entry, less_than_bp); + + // We should never insert a sequence in the middle of another sequence + if (pos != begin_pos) { + while (pos < end_pos && !((pos - 1)->is_terminal_entry)) + pos++; + } #ifdef LLDB_CONFIGURATION_DEBUG - // If we aren't inserting at the beginning, the previous entry should - // terminate a sequence. - if (pos != begin_pos) - { - entry_collection::iterator prev_pos = pos - 1; - assert(prev_pos->is_terminal_entry); - } + // If we aren't inserting at the beginning, the previous entry should + // terminate a sequence. + if (pos != begin_pos) { + entry_collection::iterator prev_pos = pos - 1; + assert(prev_pos->is_terminal_entry); + } #endif - m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end()); + m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end()); } //---------------------------------------------------------------------- -LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *line_table) : - m_line_table (line_table) -{ -} - -bool -LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const -{ - #define LT_COMPARE(a,b) if (a != b) return a < b - LT_COMPARE (a.file_addr, b.file_addr); - // b and a reversed on purpose below. - LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry); - LT_COMPARE (a.line, b.line); - LT_COMPARE (a.column, b.column); - LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement); - LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block); - // b and a reversed on purpose below. - LT_COMPARE (b.is_prologue_end, a.is_prologue_end); - LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin); - LT_COMPARE (a.file_idx, b.file_idx); - return false; - #undef LT_COMPARE +LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate( + LineTable *line_table) + : m_line_table(line_table) {} + +bool LineTable::Entry::LessThanBinaryPredicate:: +operator()(const LineTable::Entry &a, const LineTable::Entry &b) const { +#define LT_COMPARE(a, b) \ + if (a != b) \ + return a < b + LT_COMPARE(a.file_addr, b.file_addr); + // b and a reversed on purpose below. + LT_COMPARE(b.is_terminal_entry, a.is_terminal_entry); + LT_COMPARE(a.line, b.line); + LT_COMPARE(a.column, b.column); + LT_COMPARE(a.is_start_of_statement, b.is_start_of_statement); + LT_COMPARE(a.is_start_of_basic_block, b.is_start_of_basic_block); + // b and a reversed on purpose below. + LT_COMPARE(b.is_prologue_end, a.is_prologue_end); + LT_COMPARE(a.is_epilogue_begin, b.is_epilogue_begin); + LT_COMPARE(a.file_idx, b.file_idx); + return false; +#undef LT_COMPARE } +uint32_t LineTable::GetSize() const { return m_entries.size(); } - -uint32_t -LineTable::GetSize() const -{ - return m_entries.size(); +bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) { + if (idx < m_entries.size()) { + ConvertEntryAtIndexToLineEntry(idx, line_entry); + return true; + } + line_entry.Clear(); + return false; } -bool -LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry) -{ - if (idx < m_entries.size()) - { - ConvertEntryAtIndexToLineEntry (idx, line_entry); - return true; - } - line_entry.Clear(); - return false; -} +bool LineTable::FindLineEntryByAddress(const Address &so_addr, + LineEntry &line_entry, + uint32_t *index_ptr) { + if (index_ptr != nullptr) + *index_ptr = UINT32_MAX; + + bool success = false; + + if (so_addr.GetModule().get() == m_comp_unit->GetModule().get()) { + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr != LLDB_INVALID_ADDRESS) { + entry_collection::const_iterator begin_pos = m_entries.begin(); + entry_collection::const_iterator end_pos = m_entries.end(); + entry_collection::const_iterator pos = lower_bound( + begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan); + if (pos != end_pos) { + if (pos != begin_pos) { + if (pos->file_addr != search_entry.file_addr) + --pos; + else if (pos->file_addr == search_entry.file_addr) { + // If this is a termination entry, it shouldn't match since + // entries with the "is_terminal_entry" member set to true + // are termination entries that define the range for the + // previous entry. + if (pos->is_terminal_entry) { + // The matching entry is a terminal entry, so we skip + // ahead to the next entry to see if there is another + // entry following this one whose section/offset matches. + ++pos; + if (pos != end_pos) { + if (pos->file_addr != search_entry.file_addr) + pos = end_pos; + } + } -bool -LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr) -{ - if (index_ptr != nullptr ) - *index_ptr = UINT32_MAX; - - bool success = false; - - if (so_addr.GetModule().get() == m_comp_unit->GetModule().get()) - { - Entry search_entry; - search_entry.file_addr = so_addr.GetFileAddress(); - if (search_entry.file_addr != LLDB_INVALID_ADDRESS) - { - entry_collection::const_iterator begin_pos = m_entries.begin(); - entry_collection::const_iterator end_pos = m_entries.end(); - entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan); - if (pos != end_pos) - { - if (pos != begin_pos) - { - if (pos->file_addr != search_entry.file_addr) - --pos; - else if (pos->file_addr == search_entry.file_addr) - { - // If this is a termination entry, it shouldn't match since - // entries with the "is_terminal_entry" member set to true - // are termination entries that define the range for the - // previous entry. - if (pos->is_terminal_entry) - { - // The matching entry is a terminal entry, so we skip - // ahead to the next entry to see if there is another - // entry following this one whose section/offset matches. - ++pos; - if (pos != end_pos) - { - if (pos->file_addr != search_entry.file_addr) - pos = end_pos; - } - } - - if (pos != end_pos) - { - // While in the same section/offset backup to find the first - // line entry that matches the address in case there are - // multiple - while (pos != begin_pos) - { - entry_collection::const_iterator prev_pos = pos - 1; - if (prev_pos->file_addr == search_entry.file_addr && - prev_pos->is_terminal_entry == false) - --pos; - else - break; - } - } - } - - } - - // Make sure we have a valid match and that the match isn't a terminating - // entry for a previous line... - if (pos != end_pos && pos->is_terminal_entry == false) - { - uint32_t match_idx = std::distance (begin_pos, pos); - success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry); - if (index_ptr != nullptr && success) - *index_ptr = match_idx; - } + if (pos != end_pos) { + // While in the same section/offset backup to find the first + // line entry that matches the address in case there are + // multiple + while (pos != begin_pos) { + entry_collection::const_iterator prev_pos = pos - 1; + if (prev_pos->file_addr == search_entry.file_addr && + prev_pos->is_terminal_entry == false) + --pos; + else + break; + } } + } } - } - return success; -} - -bool -LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry) -{ - if (idx < m_entries.size()) - { - const Entry& entry = m_entries[idx]; - ModuleSP module_sp (m_comp_unit->GetModule()); - if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress())) - { - if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) - line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr); - else - line_entry.range.SetByteSize(0); - - line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx); - line_entry.original_file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); - line_entry.line = entry.line; - line_entry.column = entry.column; - line_entry.is_start_of_statement = entry.is_start_of_statement; - line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; - line_entry.is_prologue_end = entry.is_prologue_end; - line_entry.is_epilogue_begin = entry.is_epilogue_begin; - line_entry.is_terminal_entry = entry.is_terminal_entry; - return true; + // Make sure we have a valid match and that the match isn't a + // terminating + // entry for a previous line... + if (pos != end_pos && pos->is_terminal_entry == false) { + uint32_t match_idx = std::distance(begin_pos, pos); + success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry); + if (index_ptr != nullptr && success) + *index_ptr = match_idx; } + } } - return false; + } + return success; } -uint32_t -LineTable::FindLineEntryIndexByFileIndex -( - uint32_t start_idx, - const std::vector<uint32_t> &file_indexes, - uint32_t line, - bool exact, - LineEntry* line_entry_ptr -) -{ - - const size_t count = m_entries.size(); - std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin(); - std::vector<uint32_t>::const_iterator end_pos = file_indexes.end(); - size_t best_match = UINT32_MAX; - - for (size_t idx = start_idx; idx < count; ++idx) - { - // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) - if (m_entries[idx].is_terminal_entry) - continue; - - if (find (begin_pos, end_pos, m_entries[idx].file_idx) == end_pos) - continue; - - // Exact match always wins. Otherwise try to find the closest line > the desired - // line. - // FIXME: Maybe want to find the line closest before and the line closest after and - // if they're not in the same function, don't return a match. - - if (m_entries[idx].line < line) - { - continue; - } - else if (m_entries[idx].line == line) - { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr); - return idx; - } - else if (!exact) - { - if (best_match == UINT32_MAX) - best_match = idx; - else if (m_entries[idx].line < m_entries[best_match].line) - best_match = idx; - } +bool LineTable::ConvertEntryAtIndexToLineEntry(uint32_t idx, + LineEntry &line_entry) { + if (idx < m_entries.size()) { + const Entry &entry = m_entries[idx]; + ModuleSP module_sp(m_comp_unit->GetModule()); + if (module_sp && + module_sp->ResolveFileAddress(entry.file_addr, + line_entry.range.GetBaseAddress())) { + if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) + line_entry.range.SetByteSize(m_entries[idx + 1].file_addr - + entry.file_addr); + else + line_entry.range.SetByteSize(0); + + line_entry.file = + m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); + line_entry.original_file = + m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); + line_entry.line = entry.line; + line_entry.column = entry.column; + line_entry.is_start_of_statement = entry.is_start_of_statement; + line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; + line_entry.is_prologue_end = entry.is_prologue_end; + line_entry.is_epilogue_begin = entry.is_epilogue_begin; + line_entry.is_terminal_entry = entry.is_terminal_entry; + return true; } - - if (best_match != UINT32_MAX) - { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr); - return best_match; - } - return UINT32_MAX; + } + return false; } -uint32_t -LineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr) -{ - const size_t count = m_entries.size(); - size_t best_match = UINT32_MAX; - - for (size_t idx = start_idx; idx < count; ++idx) - { - // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) - if (m_entries[idx].is_terminal_entry) - continue; - - if (m_entries[idx].file_idx != file_idx) - continue; - - // Exact match always wins. Otherwise try to find the closest line > the desired - // line. - // FIXME: Maybe want to find the line closest before and the line closest after and - // if they're not in the same function, don't return a match. - - if (m_entries[idx].line < line) - { - continue; - } - else if (m_entries[idx].line == line) - { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr); - return idx; - } - else if (!exact) - { - if (best_match == UINT32_MAX) - best_match = idx; - else if (m_entries[idx].line < m_entries[best_match].line) - best_match = idx; - } - } - - if (best_match != UINT32_MAX) - { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr); - return best_match; +uint32_t LineTable::FindLineEntryIndexByFileIndex( + uint32_t start_idx, const std::vector<uint32_t> &file_indexes, + uint32_t line, bool exact, LineEntry *line_entry_ptr) { + + const size_t count = m_entries.size(); + std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin(); + std::vector<uint32_t>::const_iterator end_pos = file_indexes.end(); + size_t best_match = UINT32_MAX; + + for (size_t idx = start_idx; idx < count; ++idx) { + // Skip line table rows that terminate the previous row (is_terminal_entry + // is non-zero) + if (m_entries[idx].is_terminal_entry) + continue; + + if (find(begin_pos, end_pos, m_entries[idx].file_idx) == end_pos) + continue; + + // Exact match always wins. Otherwise try to find the closest line > the + // desired + // line. + // FIXME: Maybe want to find the line closest before and the line closest + // after and + // if they're not in the same function, don't return a match. + + if (m_entries[idx].line < line) { + continue; + } else if (m_entries[idx].line == line) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); + return idx; + } else if (!exact) { + if (best_match == UINT32_MAX) + best_match = idx; + else if (m_entries[idx].line < m_entries[best_match].line) + best_match = idx; } - return UINT32_MAX; + } + + if (best_match != UINT32_MAX) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr); + return best_match; + } + return UINT32_MAX; } -size_t -LineTable::FineLineEntriesForFileIndex (uint32_t file_idx, - bool append, - SymbolContextList &sc_list) -{ - - if (!append) - sc_list.Clear(); - - size_t num_added = 0; - const size_t count = m_entries.size(); - if (count > 0) - { - SymbolContext sc (m_comp_unit); - - for (size_t idx = 0; idx < count; ++idx) - { - // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) - if (m_entries[idx].is_terminal_entry) - continue; - - if (m_entries[idx].file_idx == file_idx) - { - if (ConvertEntryAtIndexToLineEntry (idx, sc.line_entry)) - { - ++num_added; - sc_list.Append(sc); - } - } - } +uint32_t LineTable::FindLineEntryIndexByFileIndex(uint32_t start_idx, + uint32_t file_idx, + uint32_t line, bool exact, + LineEntry *line_entry_ptr) { + const size_t count = m_entries.size(); + size_t best_match = UINT32_MAX; + + for (size_t idx = start_idx; idx < count; ++idx) { + // Skip line table rows that terminate the previous row (is_terminal_entry + // is non-zero) + if (m_entries[idx].is_terminal_entry) + continue; + + if (m_entries[idx].file_idx != file_idx) + continue; + + // Exact match always wins. Otherwise try to find the closest line > the + // desired + // line. + // FIXME: Maybe want to find the line closest before and the line closest + // after and + // if they're not in the same function, don't return a match. + + if (m_entries[idx].line < line) { + continue; + } else if (m_entries[idx].line == line) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); + return idx; + } else if (!exact) { + if (best_match == UINT32_MAX) + best_match = idx; + else if (m_entries[idx].line < m_entries[best_match].line) + best_match = idx; } - return num_added; + } + + if (best_match != UINT32_MAX) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr); + return best_match; + } + return UINT32_MAX; } +size_t LineTable::FineLineEntriesForFileIndex(uint32_t file_idx, bool append, + SymbolContextList &sc_list) { -void -LineTable::Dump (Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges) -{ - const size_t count = m_entries.size(); - LineEntry line_entry; - FileSpec prev_file; - for (size_t idx = 0; idx < count; ++idx) - { - ConvertEntryAtIndexToLineEntry (idx, line_entry); - line_entry.Dump (s, target, prev_file != line_entry.original_file, style, fallback_style, show_line_ranges); - s->EOL(); - prev_file = line_entry.original_file; - } -} + if (!append) + sc_list.Clear(); + size_t num_added = 0; + const size_t count = m_entries.size(); + if (count > 0) { + SymbolContext sc(m_comp_unit); -void -LineTable::GetDescription (Stream *s, Target *target, DescriptionLevel level) -{ - const size_t count = m_entries.size(); - LineEntry line_entry; - for (size_t idx = 0; idx < count; ++idx) - { - ConvertEntryAtIndexToLineEntry (idx, line_entry); - line_entry.GetDescription (s, level, m_comp_unit, target, true); - s->EOL(); - } -} + for (size_t idx = 0; idx < count; ++idx) { + // Skip line table rows that terminate the previous row (is_terminal_entry + // is non-zero) + if (m_entries[idx].is_terminal_entry) + continue; -size_t -LineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append) -{ - if (!append) - file_ranges.Clear(); - const size_t initial_count = file_ranges.GetSize(); - - const size_t count = m_entries.size(); - LineEntry line_entry; - FileAddressRanges::Entry range (LLDB_INVALID_ADDRESS, 0); - for (size_t idx = 0; idx < count; ++idx) - { - const Entry& entry = m_entries[idx]; - - if (entry.is_terminal_entry) - { - if (range.GetRangeBase() != LLDB_INVALID_ADDRESS) - { - range.SetRangeEnd(entry.file_addr); - file_ranges.Append(range); - range.Clear(LLDB_INVALID_ADDRESS); - } - } - else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS) - { - range.SetRangeBase(entry.file_addr); + if (m_entries[idx].file_idx == file_idx) { + if (ConvertEntryAtIndexToLineEntry(idx, sc.line_entry)) { + ++num_added; + sc_list.Append(sc); } + } } - return file_ranges.GetSize() - initial_count; + } + return num_added; } -LineTable * -LineTable::LinkLineTable (const FileRangeMap &file_range_map) -{ - std::unique_ptr<LineTable> line_table_ap (new LineTable (m_comp_unit)); - LineSequenceImpl sequence; - const size_t count = m_entries.size(); - LineEntry line_entry; - const FileRangeMap::Entry *file_range_entry = nullptr; - const FileRangeMap::Entry *prev_file_range_entry = nullptr; - lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS; - bool prev_entry_was_linked = false; - bool range_changed = false; - for (size_t idx = 0; idx < count; ++idx) - { - const Entry& entry = m_entries[idx]; - - const bool end_sequence = entry.is_terminal_entry; - const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0); - if (file_range_entry == nullptr || !file_range_entry->Contains(lookup_file_addr)) - { - prev_file_range_entry = file_range_entry; - file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr); - range_changed = true; - } +void LineTable::Dump(Stream *s, Target *target, Address::DumpStyle style, + Address::DumpStyle fallback_style, bool show_line_ranges) { + const size_t count = m_entries.size(); + LineEntry line_entry; + FileSpec prev_file; + for (size_t idx = 0; idx < count; ++idx) { + ConvertEntryAtIndexToLineEntry(idx, line_entry); + line_entry.Dump(s, target, prev_file != line_entry.original_file, style, + fallback_style, show_line_ranges); + s->EOL(); + prev_file = line_entry.original_file; + } +} - lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS; - lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS; - - bool terminate_previous_entry = false; - if (file_range_entry) - { - entry_linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data; - // Determine if we need to terminate the previous entry when the previous - // entry was not contiguous with this one after being linked. - if (range_changed && prev_file_range_entry) - { - prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr, prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; - if (prev_end_entry_linked_file_addr != entry_linked_file_addr) - terminate_previous_entry = prev_entry_was_linked; - } - } - else if (prev_entry_was_linked) - { - // This entry doesn't have a remapping and it needs to be removed. - // Watch out in case we need to terminate a previous entry needs to - // be terminated now that one line entry in a sequence is not longer valid. - if (!sequence.m_entries.empty() && - !sequence.m_entries.back().is_terminal_entry) - { - terminate_previous_entry = true; - } - } - - if (terminate_previous_entry && !sequence.m_entries.empty()) - { - assert (prev_file_addr != LLDB_INVALID_ADDRESS); - sequence.m_entries.push_back(sequence.m_entries.back()); - if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS) - prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr,prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; - sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr; - sequence.m_entries.back().is_terminal_entry = true; - - // Append the sequence since we just terminated the previous one - line_table_ap->InsertSequence (&sequence); - sequence.Clear(); - } - - // Now link the current entry - if (file_range_entry) - { - // This entry has an address remapping and it needs to have its address relinked - sequence.m_entries.push_back(entry); - sequence.m_entries.back().file_addr = entry_linked_file_addr; - } +void LineTable::GetDescription(Stream *s, Target *target, + DescriptionLevel level) { + const size_t count = m_entries.size(); + LineEntry line_entry; + for (size_t idx = 0; idx < count; ++idx) { + ConvertEntryAtIndexToLineEntry(idx, line_entry); + line_entry.GetDescription(s, level, m_comp_unit, target, true); + s->EOL(); + } +} - // If we have items in the sequence and the last entry is a terminal entry, - // insert this sequence into our new line table. - if (!sequence.m_entries.empty() && sequence.m_entries.back().is_terminal_entry) - { - line_table_ap->InsertSequence (&sequence); - sequence.Clear(); - prev_entry_was_linked = false; - } - else - { - prev_entry_was_linked = file_range_entry != nullptr; - } - prev_file_addr = entry.file_addr; - range_changed = false; +size_t LineTable::GetContiguousFileAddressRanges(FileAddressRanges &file_ranges, + bool append) { + if (!append) + file_ranges.Clear(); + const size_t initial_count = file_ranges.GetSize(); + + const size_t count = m_entries.size(); + LineEntry line_entry; + FileAddressRanges::Entry range(LLDB_INVALID_ADDRESS, 0); + for (size_t idx = 0; idx < count; ++idx) { + const Entry &entry = m_entries[idx]; + + if (entry.is_terminal_entry) { + if (range.GetRangeBase() != LLDB_INVALID_ADDRESS) { + range.SetRangeEnd(entry.file_addr); + file_ranges.Append(range); + range.Clear(LLDB_INVALID_ADDRESS); + } + } else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS) { + range.SetRangeBase(entry.file_addr); } - if (line_table_ap->m_entries.empty()) - return nullptr; - return line_table_ap.release(); + } + return file_ranges.GetSize() - initial_count; } +LineTable *LineTable::LinkLineTable(const FileRangeMap &file_range_map) { + std::unique_ptr<LineTable> line_table_ap(new LineTable(m_comp_unit)); + LineSequenceImpl sequence; + const size_t count = m_entries.size(); + LineEntry line_entry; + const FileRangeMap::Entry *file_range_entry = nullptr; + const FileRangeMap::Entry *prev_file_range_entry = nullptr; + lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS; + bool prev_entry_was_linked = false; + bool range_changed = false; + for (size_t idx = 0; idx < count; ++idx) { + const Entry &entry = m_entries[idx]; + + const bool end_sequence = entry.is_terminal_entry; + const lldb::addr_t lookup_file_addr = + entry.file_addr - (end_sequence ? 1 : 0); + if (file_range_entry == nullptr || + !file_range_entry->Contains(lookup_file_addr)) { + prev_file_range_entry = file_range_entry; + file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr); + range_changed = true; + } + lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS; + + bool terminate_previous_entry = false; + if (file_range_entry) { + entry_linked_file_addr = entry.file_addr - + file_range_entry->GetRangeBase() + + file_range_entry->data; + // Determine if we need to terminate the previous entry when the previous + // entry was not contiguous with this one after being linked. + if (range_changed && prev_file_range_entry) { + prev_end_entry_linked_file_addr = + std::min<lldb::addr_t>(entry.file_addr, + prev_file_range_entry->GetRangeEnd()) - + prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; + if (prev_end_entry_linked_file_addr != entry_linked_file_addr) + terminate_previous_entry = prev_entry_was_linked; + } + } else if (prev_entry_was_linked) { + // This entry doesn't have a remapping and it needs to be removed. + // Watch out in case we need to terminate a previous entry needs to + // be terminated now that one line entry in a sequence is not longer + // valid. + if (!sequence.m_entries.empty() && + !sequence.m_entries.back().is_terminal_entry) { + terminate_previous_entry = true; + } + } + if (terminate_previous_entry && !sequence.m_entries.empty()) { + assert(prev_file_addr != LLDB_INVALID_ADDRESS); + sequence.m_entries.push_back(sequence.m_entries.back()); + if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS) + prev_end_entry_linked_file_addr = + std::min<lldb::addr_t>(entry.file_addr, + prev_file_range_entry->GetRangeEnd()) - + prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; + sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr; + sequence.m_entries.back().is_terminal_entry = true; + + // Append the sequence since we just terminated the previous one + line_table_ap->InsertSequence(&sequence); + sequence.Clear(); + } + // Now link the current entry + if (file_range_entry) { + // This entry has an address remapping and it needs to have its address + // relinked + sequence.m_entries.push_back(entry); + sequence.m_entries.back().file_addr = entry_linked_file_addr; + } + + // If we have items in the sequence and the last entry is a terminal entry, + // insert this sequence into our new line table. + if (!sequence.m_entries.empty() && + sequence.m_entries.back().is_terminal_entry) { + line_table_ap->InsertSequence(&sequence); + sequence.Clear(); + prev_entry_was_linked = false; + } else { + prev_entry_was_linked = file_range_entry != nullptr; + } + prev_file_addr = entry.file_addr; + range_changed = false; + } + if (line_table_ap->m_entries.empty()) + return nullptr; + return line_table_ap.release(); +} |