1254721Semaste//===-- LineTable.cpp -------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Core/Address.h" 11254721Semaste#include "lldb/Core/Module.h" 12254721Semaste#include "lldb/Core/Section.h" 13254721Semaste#include "lldb/Core/Stream.h" 14254721Semaste#include "lldb/Symbol/CompileUnit.h" 15254721Semaste#include "lldb/Symbol/LineTable.h" 16254721Semaste#include <algorithm> 17254721Semaste 18254721Semasteusing namespace lldb; 19254721Semasteusing namespace lldb_private; 20254721Semaste 21254721Semaste//---------------------------------------------------------------------- 22254721Semaste// LineTable constructor 23254721Semaste//---------------------------------------------------------------------- 24254721SemasteLineTable::LineTable(CompileUnit* comp_unit) : 25254721Semaste m_comp_unit(comp_unit), 26254721Semaste m_entries() 27254721Semaste{ 28254721Semaste} 29254721Semaste 30254721Semaste//---------------------------------------------------------------------- 31254721Semaste// Destructor 32254721Semaste//---------------------------------------------------------------------- 33254721SemasteLineTable::~LineTable() 34254721Semaste{ 35254721Semaste} 36254721Semaste 37254721Semastevoid 38254721SemasteLineTable::InsertLineEntry 39254721Semaste( 40254721Semaste lldb::addr_t file_addr, 41254721Semaste uint32_t line, 42254721Semaste uint16_t column, 43254721Semaste uint16_t file_idx, 44254721Semaste bool is_start_of_statement, 45254721Semaste bool is_start_of_basic_block, 46254721Semaste bool is_prologue_end, 47254721Semaste bool is_epilogue_begin, 48254721Semaste bool is_terminal_entry 49254721Semaste) 50254721Semaste{ 51254721Semaste 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); 52254721Semaste 53254721Semaste entry_collection::iterator begin_pos = m_entries.begin(); 54254721Semaste entry_collection::iterator end_pos = m_entries.end(); 55254721Semaste LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); 56254721Semaste entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp); 57254721Semaste 58254721Semaste// Stream s(stdout); 59254721Semaste// s << "\n\nBefore:\n"; 60254721Semaste// Dump (&s, Address::DumpStyleFileAddress); 61254721Semaste m_entries.insert(pos, entry); 62254721Semaste// s << "After:\n"; 63254721Semaste// Dump (&s, Address::DumpStyleFileAddress); 64254721Semaste} 65254721Semaste 66254721SemasteLineSequence::LineSequence() 67254721Semaste{ 68254721Semaste} 69254721Semaste 70254721Semastevoid 71254721SemasteLineTable::LineSequenceImpl::Clear() 72254721Semaste{ 73254721Semaste m_entries.clear(); 74254721Semaste} 75254721Semaste 76254721SemasteLineSequence* LineTable::CreateLineSequenceContainer () 77254721Semaste{ 78254721Semaste return new LineTable::LineSequenceImpl(); 79254721Semaste} 80254721Semaste 81254721Semastevoid 82254721SemasteLineTable::AppendLineEntryToSequence 83254721Semaste( 84254721Semaste LineSequence* sequence, 85254721Semaste lldb::addr_t file_addr, 86254721Semaste uint32_t line, 87254721Semaste uint16_t column, 88254721Semaste uint16_t file_idx, 89254721Semaste bool is_start_of_statement, 90254721Semaste bool is_start_of_basic_block, 91254721Semaste bool is_prologue_end, 92254721Semaste bool is_epilogue_begin, 93254721Semaste bool is_terminal_entry 94254721Semaste) 95254721Semaste{ 96254721Semaste assert(sequence != NULL); 97254721Semaste LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); 98254721Semaste 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); 99254721Semaste seq->m_entries.push_back (entry); 100254721Semaste} 101254721Semaste 102254721Semastevoid 103254721SemasteLineTable::InsertSequence (LineSequence* sequence) 104254721Semaste{ 105254721Semaste assert(sequence != NULL); 106254721Semaste LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); 107254721Semaste if (seq->m_entries.empty()) 108254721Semaste return; 109254721Semaste Entry& entry = seq->m_entries.front(); 110254721Semaste 111254721Semaste // If the first entry address in this sequence is greater than or equal to 112254721Semaste // the address of the last item in our entry collection, just append. 113254721Semaste if (m_entries.empty() || !Entry::EntryAddressLessThan(entry, m_entries.back())) 114254721Semaste { 115254721Semaste m_entries.insert(m_entries.end(), 116254721Semaste seq->m_entries.begin(), 117254721Semaste seq->m_entries.end()); 118254721Semaste return; 119254721Semaste } 120254721Semaste 121254721Semaste // Otherwise, find where this belongs in the collection 122254721Semaste entry_collection::iterator begin_pos = m_entries.begin(); 123254721Semaste entry_collection::iterator end_pos = m_entries.end(); 124254721Semaste LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); 125254721Semaste entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp); 126254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG 127254721Semaste // If we aren't inserting at the beginning, the previous entry should 128254721Semaste // terminate a sequence. 129254721Semaste if (pos != begin_pos) 130254721Semaste { 131254721Semaste entry_collection::iterator prev_pos = pos - 1; 132254721Semaste assert(prev_pos->is_terminal_entry); 133254721Semaste } 134254721Semaste#endif 135254721Semaste m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end()); 136254721Semaste} 137254721Semaste 138254721Semaste//---------------------------------------------------------------------- 139254721SemasteLineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *line_table) : 140254721Semaste m_line_table (line_table) 141254721Semaste{ 142254721Semaste} 143254721Semaste 144254721Semastebool 145254721SemasteLineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const 146254721Semaste{ 147254721Semaste #define LT_COMPARE(a,b) if (a != b) return a < b 148254721Semaste LT_COMPARE (a.file_addr, b.file_addr); 149254721Semaste // b and a reversed on purpose below. 150254721Semaste LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry); 151254721Semaste LT_COMPARE (a.line, b.line); 152254721Semaste LT_COMPARE (a.column, b.column); 153254721Semaste LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement); 154254721Semaste LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block); 155254721Semaste // b and a reversed on purpose below. 156254721Semaste LT_COMPARE (b.is_prologue_end, a.is_prologue_end); 157254721Semaste LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin); 158254721Semaste LT_COMPARE (a.file_idx, b.file_idx); 159254721Semaste return false; 160254721Semaste #undef LT_COMPARE 161254721Semaste} 162254721Semaste 163254721Semaste 164254721Semaste 165254721Semasteuint32_t 166254721SemasteLineTable::GetSize() const 167254721Semaste{ 168254721Semaste return m_entries.size(); 169254721Semaste} 170254721Semaste 171254721Semastebool 172254721SemasteLineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry) 173254721Semaste{ 174254721Semaste if (idx < m_entries.size()) 175254721Semaste { 176254721Semaste ConvertEntryAtIndexToLineEntry (idx, line_entry); 177254721Semaste return true; 178254721Semaste } 179254721Semaste line_entry.Clear(); 180254721Semaste return false; 181254721Semaste} 182254721Semaste 183254721Semastebool 184254721SemasteLineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr) 185254721Semaste{ 186254721Semaste if (index_ptr != NULL ) 187254721Semaste *index_ptr = UINT32_MAX; 188254721Semaste 189254721Semaste bool success = false; 190254721Semaste 191254721Semaste if (so_addr.GetModule().get() == m_comp_unit->GetModule().get()) 192254721Semaste { 193254721Semaste Entry search_entry; 194254721Semaste search_entry.file_addr = so_addr.GetFileAddress(); 195254721Semaste if (search_entry.file_addr != LLDB_INVALID_ADDRESS) 196254721Semaste { 197254721Semaste entry_collection::const_iterator begin_pos = m_entries.begin(); 198254721Semaste entry_collection::const_iterator end_pos = m_entries.end(); 199254721Semaste entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan); 200254721Semaste if (pos != end_pos) 201254721Semaste { 202254721Semaste if (pos != begin_pos) 203254721Semaste { 204254721Semaste if (pos->file_addr != search_entry.file_addr) 205254721Semaste --pos; 206254721Semaste else if (pos->file_addr == search_entry.file_addr) 207254721Semaste { 208254721Semaste // If this is a termination entry, it should't match since 209254721Semaste // entries with the "is_terminal_entry" member set to true 210254721Semaste // are termination entries that define the range for the 211254721Semaste // previous entry. 212254721Semaste if (pos->is_terminal_entry) 213254721Semaste { 214254721Semaste // The matching entry is a terminal entry, so we skip 215254721Semaste // ahead to the next entry to see if there is another 216254721Semaste // entry following this one whose section/offset matches. 217254721Semaste ++pos; 218254721Semaste if (pos != end_pos) 219254721Semaste { 220254721Semaste if (pos->file_addr != search_entry.file_addr) 221254721Semaste pos = end_pos; 222254721Semaste } 223254721Semaste } 224254721Semaste 225254721Semaste if (pos != end_pos) 226254721Semaste { 227254721Semaste // While in the same section/offset backup to find the first 228254721Semaste // line entry that matches the address in case there are 229254721Semaste // multiple 230254721Semaste while (pos != begin_pos) 231254721Semaste { 232254721Semaste entry_collection::const_iterator prev_pos = pos - 1; 233254721Semaste if (prev_pos->file_addr == search_entry.file_addr && 234254721Semaste prev_pos->is_terminal_entry == false) 235254721Semaste --pos; 236254721Semaste else 237254721Semaste break; 238254721Semaste } 239254721Semaste } 240254721Semaste } 241254721Semaste 242254721Semaste } 243254721Semaste 244254721Semaste // Make sure we have a valid match and that the match isn't a terminating 245254721Semaste // entry for a previous line... 246254721Semaste if (pos != end_pos && pos->is_terminal_entry == false) 247254721Semaste { 248254721Semaste uint32_t match_idx = std::distance (begin_pos, pos); 249254721Semaste success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry); 250254721Semaste if (index_ptr != NULL && success) 251254721Semaste *index_ptr = match_idx; 252254721Semaste } 253254721Semaste } 254254721Semaste } 255254721Semaste } 256254721Semaste return success; 257254721Semaste} 258254721Semaste 259254721Semaste 260254721Semastebool 261254721SemasteLineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry) 262254721Semaste{ 263254721Semaste if (idx < m_entries.size()) 264254721Semaste { 265254721Semaste const Entry& entry = m_entries[idx]; 266254721Semaste ModuleSP module_sp (m_comp_unit->GetModule()); 267254721Semaste if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress())) 268254721Semaste { 269254721Semaste if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) 270254721Semaste line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr); 271254721Semaste else 272254721Semaste line_entry.range.SetByteSize(0); 273254721Semaste 274254721Semaste line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx); 275254721Semaste line_entry.line = entry.line; 276254721Semaste line_entry.column = entry.column; 277254721Semaste line_entry.is_start_of_statement = entry.is_start_of_statement; 278254721Semaste line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; 279254721Semaste line_entry.is_prologue_end = entry.is_prologue_end; 280254721Semaste line_entry.is_epilogue_begin = entry.is_epilogue_begin; 281254721Semaste line_entry.is_terminal_entry = entry.is_terminal_entry; 282254721Semaste return true; 283254721Semaste } 284254721Semaste } 285254721Semaste return false; 286254721Semaste} 287254721Semaste 288254721Semasteuint32_t 289254721SemasteLineTable::FindLineEntryIndexByFileIndex 290254721Semaste( 291254721Semaste uint32_t start_idx, 292254721Semaste const std::vector<uint32_t> &file_indexes, 293254721Semaste uint32_t line, 294254721Semaste bool exact, 295254721Semaste LineEntry* line_entry_ptr 296254721Semaste) 297254721Semaste{ 298254721Semaste 299254721Semaste const size_t count = m_entries.size(); 300254721Semaste std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin(); 301254721Semaste std::vector<uint32_t>::const_iterator end_pos = file_indexes.end(); 302254721Semaste size_t best_match = UINT32_MAX; 303254721Semaste 304254721Semaste for (size_t idx = start_idx; idx < count; ++idx) 305254721Semaste { 306254721Semaste // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) 307254721Semaste if (m_entries[idx].is_terminal_entry) 308254721Semaste continue; 309254721Semaste 310254721Semaste if (find (begin_pos, end_pos, m_entries[idx].file_idx) == end_pos) 311254721Semaste continue; 312254721Semaste 313254721Semaste // Exact match always wins. Otherwise try to find the closest line > the desired 314254721Semaste // line. 315254721Semaste // FIXME: Maybe want to find the line closest before and the line closest after and 316254721Semaste // if they're not in the same function, don't return a match. 317254721Semaste 318254721Semaste if (m_entries[idx].line < line) 319254721Semaste { 320254721Semaste continue; 321254721Semaste } 322254721Semaste else if (m_entries[idx].line == line) 323254721Semaste { 324254721Semaste if (line_entry_ptr) 325254721Semaste ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr); 326254721Semaste return idx; 327254721Semaste } 328254721Semaste else if (!exact) 329254721Semaste { 330254721Semaste if (best_match == UINT32_MAX) 331254721Semaste best_match = idx; 332254721Semaste else if (m_entries[idx].line < m_entries[best_match].line) 333254721Semaste best_match = idx; 334254721Semaste } 335254721Semaste } 336254721Semaste 337254721Semaste if (best_match != UINT32_MAX) 338254721Semaste { 339254721Semaste if (line_entry_ptr) 340254721Semaste ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr); 341254721Semaste return best_match; 342254721Semaste } 343254721Semaste return UINT32_MAX; 344254721Semaste} 345254721Semaste 346254721Semasteuint32_t 347254721SemasteLineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr) 348254721Semaste{ 349254721Semaste const size_t count = m_entries.size(); 350254721Semaste size_t best_match = UINT32_MAX; 351254721Semaste 352254721Semaste for (size_t idx = start_idx; idx < count; ++idx) 353254721Semaste { 354254721Semaste // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) 355254721Semaste if (m_entries[idx].is_terminal_entry) 356254721Semaste continue; 357254721Semaste 358254721Semaste if (m_entries[idx].file_idx != file_idx) 359254721Semaste continue; 360254721Semaste 361254721Semaste // Exact match always wins. Otherwise try to find the closest line > the desired 362254721Semaste // line. 363254721Semaste // FIXME: Maybe want to find the line closest before and the line closest after and 364254721Semaste // if they're not in the same function, don't return a match. 365254721Semaste 366254721Semaste if (m_entries[idx].line < line) 367254721Semaste { 368254721Semaste continue; 369254721Semaste } 370254721Semaste else if (m_entries[idx].line == line) 371254721Semaste { 372254721Semaste if (line_entry_ptr) 373254721Semaste ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr); 374254721Semaste return idx; 375254721Semaste } 376254721Semaste else if (!exact) 377254721Semaste { 378254721Semaste if (best_match == UINT32_MAX) 379254721Semaste best_match = idx; 380254721Semaste else if (m_entries[idx].line < m_entries[best_match].line) 381254721Semaste best_match = idx; 382254721Semaste } 383254721Semaste } 384254721Semaste 385254721Semaste if (best_match != UINT32_MAX) 386254721Semaste { 387254721Semaste if (line_entry_ptr) 388254721Semaste ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr); 389254721Semaste return best_match; 390254721Semaste } 391254721Semaste return UINT32_MAX; 392254721Semaste} 393254721Semaste 394254721Semastesize_t 395254721SemasteLineTable::FineLineEntriesForFileIndex (uint32_t file_idx, 396254721Semaste bool append, 397254721Semaste SymbolContextList &sc_list) 398254721Semaste{ 399254721Semaste 400254721Semaste if (!append) 401254721Semaste sc_list.Clear(); 402254721Semaste 403254721Semaste size_t num_added = 0; 404254721Semaste const size_t count = m_entries.size(); 405254721Semaste if (count > 0) 406254721Semaste { 407254721Semaste SymbolContext sc (m_comp_unit); 408254721Semaste 409254721Semaste for (size_t idx = 0; idx < count; ++idx) 410254721Semaste { 411254721Semaste // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) 412254721Semaste if (m_entries[idx].is_terminal_entry) 413254721Semaste continue; 414254721Semaste 415254721Semaste if (m_entries[idx].file_idx == file_idx) 416254721Semaste { 417254721Semaste if (ConvertEntryAtIndexToLineEntry (idx, sc.line_entry)) 418254721Semaste { 419254721Semaste ++num_added; 420254721Semaste sc_list.Append(sc); 421254721Semaste } 422254721Semaste } 423254721Semaste } 424254721Semaste } 425254721Semaste return num_added; 426254721Semaste} 427254721Semaste 428254721Semaste 429254721Semastevoid 430254721SemasteLineTable::Dump (Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges) 431254721Semaste{ 432254721Semaste const size_t count = m_entries.size(); 433254721Semaste LineEntry line_entry; 434254721Semaste FileSpec prev_file; 435254721Semaste for (size_t idx = 0; idx < count; ++idx) 436254721Semaste { 437254721Semaste ConvertEntryAtIndexToLineEntry (idx, line_entry); 438254721Semaste line_entry.Dump (s, target, prev_file != line_entry.file, style, fallback_style, show_line_ranges); 439254721Semaste s->EOL(); 440254721Semaste prev_file = line_entry.file; 441254721Semaste } 442254721Semaste} 443254721Semaste 444254721Semaste 445254721Semastevoid 446254721SemasteLineTable::GetDescription (Stream *s, Target *target, DescriptionLevel level) 447254721Semaste{ 448254721Semaste const size_t count = m_entries.size(); 449254721Semaste LineEntry line_entry; 450254721Semaste for (size_t idx = 0; idx < count; ++idx) 451254721Semaste { 452254721Semaste ConvertEntryAtIndexToLineEntry (idx, line_entry); 453254721Semaste line_entry.GetDescription (s, level, m_comp_unit, target, true); 454254721Semaste s->EOL(); 455254721Semaste } 456254721Semaste} 457254721Semaste 458254721Semastesize_t 459254721SemasteLineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append) 460254721Semaste{ 461254721Semaste if (!append) 462254721Semaste file_ranges.Clear(); 463254721Semaste const size_t initial_count = file_ranges.GetSize(); 464254721Semaste 465254721Semaste const size_t count = m_entries.size(); 466254721Semaste LineEntry line_entry; 467254721Semaste FileAddressRanges::Entry range (LLDB_INVALID_ADDRESS, 0); 468254721Semaste for (size_t idx = 0; idx < count; ++idx) 469254721Semaste { 470254721Semaste const Entry& entry = m_entries[idx]; 471254721Semaste 472254721Semaste if (entry.is_terminal_entry) 473254721Semaste { 474254721Semaste if (range.GetRangeBase() != LLDB_INVALID_ADDRESS) 475254721Semaste { 476254721Semaste range.SetRangeEnd(entry.file_addr); 477254721Semaste file_ranges.Append(range); 478254721Semaste range.Clear(LLDB_INVALID_ADDRESS); 479254721Semaste } 480254721Semaste } 481254721Semaste else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS) 482254721Semaste { 483254721Semaste range.SetRangeBase(entry.file_addr); 484254721Semaste } 485254721Semaste } 486254721Semaste return file_ranges.GetSize() - initial_count; 487254721Semaste} 488254721Semaste 489254721SemasteLineTable * 490254721SemasteLineTable::LinkLineTable (const FileRangeMap &file_range_map) 491254721Semaste{ 492254721Semaste std::unique_ptr<LineTable> line_table_ap (new LineTable (m_comp_unit)); 493254721Semaste LineSequenceImpl sequence; 494254721Semaste const size_t count = m_entries.size(); 495254721Semaste LineEntry line_entry; 496254721Semaste const FileRangeMap::Entry *file_range_entry = NULL; 497254721Semaste const FileRangeMap::Entry *prev_file_range_entry = NULL; 498254721Semaste lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS; 499254721Semaste bool prev_entry_was_linked = false; 500254721Semaste bool range_changed = false; 501254721Semaste for (size_t idx = 0; idx < count; ++idx) 502254721Semaste { 503254721Semaste const Entry& entry = m_entries[idx]; 504254721Semaste 505254721Semaste const bool end_sequence = entry.is_terminal_entry; 506254721Semaste const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0); 507254721Semaste if (file_range_entry == NULL || !file_range_entry->Contains(lookup_file_addr)) 508254721Semaste { 509254721Semaste prev_file_range_entry = file_range_entry; 510254721Semaste file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr); 511254721Semaste range_changed = true; 512254721Semaste } 513254721Semaste 514254721Semaste lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS; 515254721Semaste lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS; 516254721Semaste 517254721Semaste bool terminate_previous_entry = false; 518254721Semaste if (file_range_entry) 519254721Semaste { 520254721Semaste entry_linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data; 521254721Semaste // Determine if we need to terminate the previous entry when the previous 522254721Semaste // entry was not contguous with this one after being linked. 523254721Semaste if (range_changed && prev_file_range_entry) 524254721Semaste { 525254721Semaste 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; 526254721Semaste if (prev_end_entry_linked_file_addr != entry_linked_file_addr) 527254721Semaste terminate_previous_entry = prev_entry_was_linked; 528254721Semaste } 529254721Semaste } 530254721Semaste else if (prev_entry_was_linked) 531254721Semaste { 532254721Semaste // This entry doesn't have a remapping and it needs to be removed. 533254721Semaste // Watch out in case we need to terminate a previous entry needs to 534254721Semaste // be terminated now that one line entry in a sequence is not longer valid. 535254721Semaste if (!entry.is_terminal_entry && 536254721Semaste !sequence.m_entries.empty() && 537254721Semaste !sequence.m_entries.back().is_terminal_entry) 538254721Semaste { 539254721Semaste terminate_previous_entry = true; 540254721Semaste } 541254721Semaste } 542254721Semaste 543254721Semaste if (terminate_previous_entry && !sequence.m_entries.empty()) 544254721Semaste { 545254721Semaste assert (prev_file_addr != LLDB_INVALID_ADDRESS); 546254721Semaste sequence.m_entries.push_back(sequence.m_entries.back()); 547254721Semaste if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS) 548254721Semaste 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; 549254721Semaste sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr; 550254721Semaste sequence.m_entries.back().is_terminal_entry = true; 551254721Semaste 552254721Semaste // Append the sequence since we just terminated the previous one 553254721Semaste line_table_ap->InsertSequence (&sequence); 554254721Semaste sequence.Clear(); 555254721Semaste prev_entry_was_linked = false; 556254721Semaste } 557254721Semaste 558254721Semaste // Now link the current entry 559254721Semaste if (file_range_entry) 560254721Semaste { 561254721Semaste // This entry has an address remapping and it needs to have its address relinked 562254721Semaste sequence.m_entries.push_back(entry); 563254721Semaste sequence.m_entries.back().file_addr = entry_linked_file_addr; 564254721Semaste } 565254721Semaste 566254721Semaste // If we have items in the sequence and the last entry is a terminal entry, 567254721Semaste // insert this sequence into our new line table. 568254721Semaste if (!sequence.m_entries.empty() && sequence.m_entries.back().is_terminal_entry) 569254721Semaste { 570254721Semaste line_table_ap->InsertSequence (&sequence); 571254721Semaste sequence.Clear(); 572254721Semaste prev_entry_was_linked = false; 573254721Semaste } 574254721Semaste else 575254721Semaste { 576254721Semaste prev_entry_was_linked = file_range_entry != NULL; 577254721Semaste } 578254721Semaste prev_file_addr = entry.file_addr; 579254721Semaste range_changed = false; 580254721Semaste } 581254721Semaste if (line_table_ap->m_entries.empty()) 582254721Semaste return NULL; 583254721Semaste return line_table_ap.release(); 584254721Semaste} 585254721Semaste 586254721Semaste 587254721Semaste 588254721Semaste 589