1 //===-- LineTable.cpp -------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Core/Address.h" 11 #include "lldb/Core/Module.h" 12 #include "lldb/Core/Section.h" 13 #include "lldb/Core/Stream.h" 14 #include "lldb/Symbol/CompileUnit.h" 15 #include "lldb/Symbol/LineTable.h" 16 #include <algorithm> 17 18 using namespace lldb; 19 using namespace lldb_private; 20 21 //---------------------------------------------------------------------- 22 // LineTable constructor 23 //---------------------------------------------------------------------- 24 LineTable::LineTable(CompileUnit* comp_unit) : 25 m_comp_unit(comp_unit), 26 m_entries() 27 { 28 } 29 30 //---------------------------------------------------------------------- 31 // Destructor 32 //---------------------------------------------------------------------- 33 LineTable::~LineTable() 34 { 35 } 36 37 void 38 LineTable::InsertLineEntry 39 ( 40 lldb::addr_t file_addr, 41 uint32_t line, 42 uint16_t column, 43 uint16_t file_idx, 44 bool is_start_of_statement, 45 bool is_start_of_basic_block, 46 bool is_prologue_end, 47 bool is_epilogue_begin, 48 bool is_terminal_entry 49 ) 50 { 51 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); 52 53 entry_collection::iterator begin_pos = m_entries.begin(); 54 entry_collection::iterator end_pos = m_entries.end(); 55 LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); 56 entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp); 57 58 // Stream s(stdout); 59 // s << "\n\nBefore:\n"; 60 // Dump (&s, Address::DumpStyleFileAddress); 61 m_entries.insert(pos, entry); 62 // s << "After:\n"; 63 // Dump (&s, Address::DumpStyleFileAddress); 64 } 65 66 LineSequence::LineSequence() 67 { 68 } 69 70 void 71 LineTable::LineSequenceImpl::Clear() 72 { 73 m_entries.clear(); 74 } 75 76 LineSequence* LineTable::CreateLineSequenceContainer () 77 { 78 return new LineTable::LineSequenceImpl(); 79 } 80 81 void 82 LineTable::AppendLineEntryToSequence 83 ( 84 LineSequence* sequence, 85 lldb::addr_t file_addr, 86 uint32_t line, 87 uint16_t column, 88 uint16_t file_idx, 89 bool is_start_of_statement, 90 bool is_start_of_basic_block, 91 bool is_prologue_end, 92 bool is_epilogue_begin, 93 bool is_terminal_entry 94 ) 95 { 96 assert(sequence != nullptr); 97 LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); 98 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); 99 entry_collection &entries = seq->m_entries; 100 // Replace the last entry if the address is the same, otherwise append it. If we have multiple 101 // line entries at the same address, this indicates illegal DWARF so this "fixes" the line table 102 // to be correct. If not fixed this can cause a line entry's address that when resolved back to 103 // a symbol context, could resolve to a different line entry. We really want a 1 to 1 mapping 104 // here to avoid these kinds of inconsistencies. We will need tor revisit this if the DWARF line 105 // tables are updated to allow multiple entries at the same address legally. 106 if (!entries.empty() && entries.back().file_addr == file_addr) 107 { 108 // GCC don't use the is_prologue_end flag to mark the first instruction after the prologue. 109 // Instead of it it is issueing a line table entry for the first instruction of the prologue 110 // and one for the first instruction after the prologue. If the size of the prologue is 0 111 // instruction then the 2 line entry will have the same file address. Removing it will remove 112 // our ability to properly detect the location of the end of prologe so we set the prologue_end 113 // flag to preserve this information (setting the prologue_end flag for an entry what is after 114 // the prologue end don't have any effect) 115 entry.is_prologue_end = entry.file_idx == entries.back().file_idx; 116 entries.back() = entry; 117 } 118 else 119 entries.push_back (entry); 120 } 121 122 void 123 LineTable::InsertSequence (LineSequence* sequence) 124 { 125 assert(sequence != nullptr); 126 LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); 127 if (seq->m_entries.empty()) 128 return; 129 Entry& entry = seq->m_entries.front(); 130 131 // If the first entry address in this sequence is greater than or equal to 132 // the address of the last item in our entry collection, just append. 133 if (m_entries.empty() || !Entry::EntryAddressLessThan(entry, m_entries.back())) 134 { 135 m_entries.insert(m_entries.end(), 136 seq->m_entries.begin(), 137 seq->m_entries.end()); 138 return; 139 } 140 141 // Otherwise, find where this belongs in the collection 142 entry_collection::iterator begin_pos = m_entries.begin(); 143 entry_collection::iterator end_pos = m_entries.end(); 144 LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); 145 entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp); 146 147 // We should never insert a sequence in the middle of another sequence 148 if (pos != begin_pos) { 149 while (pos < end_pos && !((pos - 1)->is_terminal_entry)) 150 pos++; 151 } 152 153 #ifdef LLDB_CONFIGURATION_DEBUG 154 // If we aren't inserting at the beginning, the previous entry should 155 // terminate a sequence. 156 if (pos != begin_pos) 157 { 158 entry_collection::iterator prev_pos = pos - 1; 159 assert(prev_pos->is_terminal_entry); 160 } 161 #endif 162 m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end()); 163 } 164 165 //---------------------------------------------------------------------- 166 LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *line_table) : 167 m_line_table (line_table) 168 { 169 } 170 171 bool 172 LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const 173 { 174 #define LT_COMPARE(a,b) if (a != b) return a < b 175 LT_COMPARE (a.file_addr, b.file_addr); 176 // b and a reversed on purpose below. 177 LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry); 178 LT_COMPARE (a.line, b.line); 179 LT_COMPARE (a.column, b.column); 180 LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement); 181 LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block); 182 // b and a reversed on purpose below. 183 LT_COMPARE (b.is_prologue_end, a.is_prologue_end); 184 LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin); 185 LT_COMPARE (a.file_idx, b.file_idx); 186 return false; 187 #undef LT_COMPARE 188 } 189 190 191 192 uint32_t 193 LineTable::GetSize() const 194 { 195 return m_entries.size(); 196 } 197 198 bool 199 LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry) 200 { 201 if (idx < m_entries.size()) 202 { 203 ConvertEntryAtIndexToLineEntry (idx, line_entry); 204 return true; 205 } 206 line_entry.Clear(); 207 return false; 208 } 209 210 bool 211 LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr) 212 { 213 if (index_ptr != nullptr ) 214 *index_ptr = UINT32_MAX; 215 216 bool success = false; 217 218 if (so_addr.GetModule().get() == m_comp_unit->GetModule().get()) 219 { 220 Entry search_entry; 221 search_entry.file_addr = so_addr.GetFileAddress(); 222 if (search_entry.file_addr != LLDB_INVALID_ADDRESS) 223 { 224 entry_collection::const_iterator begin_pos = m_entries.begin(); 225 entry_collection::const_iterator end_pos = m_entries.end(); 226 entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan); 227 if (pos != end_pos) 228 { 229 if (pos != begin_pos) 230 { 231 if (pos->file_addr != search_entry.file_addr) 232 --pos; 233 else if (pos->file_addr == search_entry.file_addr) 234 { 235 // If this is a termination entry, it shouldn't match since 236 // entries with the "is_terminal_entry" member set to true 237 // are termination entries that define the range for the 238 // previous entry. 239 if (pos->is_terminal_entry) 240 { 241 // The matching entry is a terminal entry, so we skip 242 // ahead to the next entry to see if there is another 243 // entry following this one whose section/offset matches. 244 ++pos; 245 if (pos != end_pos) 246 { 247 if (pos->file_addr != search_entry.file_addr) 248 pos = end_pos; 249 } 250 } 251 252 if (pos != end_pos) 253 { 254 // While in the same section/offset backup to find the first 255 // line entry that matches the address in case there are 256 // multiple 257 while (pos != begin_pos) 258 { 259 entry_collection::const_iterator prev_pos = pos - 1; 260 if (prev_pos->file_addr == search_entry.file_addr && 261 prev_pos->is_terminal_entry == false) 262 --pos; 263 else 264 break; 265 } 266 } 267 } 268 269 } 270 271 // Make sure we have a valid match and that the match isn't a terminating 272 // entry for a previous line... 273 if (pos != end_pos && pos->is_terminal_entry == false) 274 { 275 uint32_t match_idx = std::distance (begin_pos, pos); 276 success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry); 277 if (index_ptr != nullptr && success) 278 *index_ptr = match_idx; 279 } 280 } 281 } 282 } 283 return success; 284 } 285 286 287 bool 288 LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry) 289 { 290 if (idx < m_entries.size()) 291 { 292 const Entry& entry = m_entries[idx]; 293 ModuleSP module_sp (m_comp_unit->GetModule()); 294 if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress())) 295 { 296 if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) 297 line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr); 298 else 299 line_entry.range.SetByteSize(0); 300 301 line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx); 302 line_entry.original_file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); 303 line_entry.line = entry.line; 304 line_entry.column = entry.column; 305 line_entry.is_start_of_statement = entry.is_start_of_statement; 306 line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; 307 line_entry.is_prologue_end = entry.is_prologue_end; 308 line_entry.is_epilogue_begin = entry.is_epilogue_begin; 309 line_entry.is_terminal_entry = entry.is_terminal_entry; 310 return true; 311 } 312 } 313 return false; 314 } 315 316 uint32_t 317 LineTable::FindLineEntryIndexByFileIndex 318 ( 319 uint32_t start_idx, 320 const std::vector<uint32_t> &file_indexes, 321 uint32_t line, 322 bool exact, 323 LineEntry* line_entry_ptr 324 ) 325 { 326 327 const size_t count = m_entries.size(); 328 std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin(); 329 std::vector<uint32_t>::const_iterator end_pos = file_indexes.end(); 330 size_t best_match = UINT32_MAX; 331 332 for (size_t idx = start_idx; idx < count; ++idx) 333 { 334 // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) 335 if (m_entries[idx].is_terminal_entry) 336 continue; 337 338 if (find (begin_pos, end_pos, m_entries[idx].file_idx) == end_pos) 339 continue; 340 341 // Exact match always wins. Otherwise try to find the closest line > the desired 342 // line. 343 // FIXME: Maybe want to find the line closest before and the line closest after and 344 // if they're not in the same function, don't return a match. 345 346 if (m_entries[idx].line < line) 347 { 348 continue; 349 } 350 else if (m_entries[idx].line == line) 351 { 352 if (line_entry_ptr) 353 ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr); 354 return idx; 355 } 356 else if (!exact) 357 { 358 if (best_match == UINT32_MAX) 359 best_match = idx; 360 else if (m_entries[idx].line < m_entries[best_match].line) 361 best_match = idx; 362 } 363 } 364 365 if (best_match != UINT32_MAX) 366 { 367 if (line_entry_ptr) 368 ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr); 369 return best_match; 370 } 371 return UINT32_MAX; 372 } 373 374 uint32_t 375 LineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr) 376 { 377 const size_t count = m_entries.size(); 378 size_t best_match = UINT32_MAX; 379 380 for (size_t idx = start_idx; idx < count; ++idx) 381 { 382 // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) 383 if (m_entries[idx].is_terminal_entry) 384 continue; 385 386 if (m_entries[idx].file_idx != file_idx) 387 continue; 388 389 // Exact match always wins. Otherwise try to find the closest line > the desired 390 // line. 391 // FIXME: Maybe want to find the line closest before and the line closest after and 392 // if they're not in the same function, don't return a match. 393 394 if (m_entries[idx].line < line) 395 { 396 continue; 397 } 398 else if (m_entries[idx].line == line) 399 { 400 if (line_entry_ptr) 401 ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr); 402 return idx; 403 } 404 else if (!exact) 405 { 406 if (best_match == UINT32_MAX) 407 best_match = idx; 408 else if (m_entries[idx].line < m_entries[best_match].line) 409 best_match = idx; 410 } 411 } 412 413 if (best_match != UINT32_MAX) 414 { 415 if (line_entry_ptr) 416 ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr); 417 return best_match; 418 } 419 return UINT32_MAX; 420 } 421 422 size_t 423 LineTable::FineLineEntriesForFileIndex (uint32_t file_idx, 424 bool append, 425 SymbolContextList &sc_list) 426 { 427 428 if (!append) 429 sc_list.Clear(); 430 431 size_t num_added = 0; 432 const size_t count = m_entries.size(); 433 if (count > 0) 434 { 435 SymbolContext sc (m_comp_unit); 436 437 for (size_t idx = 0; idx < count; ++idx) 438 { 439 // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) 440 if (m_entries[idx].is_terminal_entry) 441 continue; 442 443 if (m_entries[idx].file_idx == file_idx) 444 { 445 if (ConvertEntryAtIndexToLineEntry (idx, sc.line_entry)) 446 { 447 ++num_added; 448 sc_list.Append(sc); 449 } 450 } 451 } 452 } 453 return num_added; 454 } 455 456 457 void 458 LineTable::Dump (Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges) 459 { 460 const size_t count = m_entries.size(); 461 LineEntry line_entry; 462 FileSpec prev_file; 463 for (size_t idx = 0; idx < count; ++idx) 464 { 465 ConvertEntryAtIndexToLineEntry (idx, line_entry); 466 line_entry.Dump (s, target, prev_file != line_entry.original_file, style, fallback_style, show_line_ranges); 467 s->EOL(); 468 prev_file = line_entry.original_file; 469 } 470 } 471 472 473 void 474 LineTable::GetDescription (Stream *s, Target *target, DescriptionLevel level) 475 { 476 const size_t count = m_entries.size(); 477 LineEntry line_entry; 478 for (size_t idx = 0; idx < count; ++idx) 479 { 480 ConvertEntryAtIndexToLineEntry (idx, line_entry); 481 line_entry.GetDescription (s, level, m_comp_unit, target, true); 482 s->EOL(); 483 } 484 } 485 486 size_t 487 LineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append) 488 { 489 if (!append) 490 file_ranges.Clear(); 491 const size_t initial_count = file_ranges.GetSize(); 492 493 const size_t count = m_entries.size(); 494 LineEntry line_entry; 495 FileAddressRanges::Entry range (LLDB_INVALID_ADDRESS, 0); 496 for (size_t idx = 0; idx < count; ++idx) 497 { 498 const Entry& entry = m_entries[idx]; 499 500 if (entry.is_terminal_entry) 501 { 502 if (range.GetRangeBase() != LLDB_INVALID_ADDRESS) 503 { 504 range.SetRangeEnd(entry.file_addr); 505 file_ranges.Append(range); 506 range.Clear(LLDB_INVALID_ADDRESS); 507 } 508 } 509 else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS) 510 { 511 range.SetRangeBase(entry.file_addr); 512 } 513 } 514 return file_ranges.GetSize() - initial_count; 515 } 516 517 LineTable * 518 LineTable::LinkLineTable (const FileRangeMap &file_range_map) 519 { 520 std::unique_ptr<LineTable> line_table_ap (new LineTable (m_comp_unit)); 521 LineSequenceImpl sequence; 522 const size_t count = m_entries.size(); 523 LineEntry line_entry; 524 const FileRangeMap::Entry *file_range_entry = nullptr; 525 const FileRangeMap::Entry *prev_file_range_entry = nullptr; 526 lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS; 527 bool prev_entry_was_linked = false; 528 bool range_changed = false; 529 for (size_t idx = 0; idx < count; ++idx) 530 { 531 const Entry& entry = m_entries[idx]; 532 533 const bool end_sequence = entry.is_terminal_entry; 534 const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0); 535 if (file_range_entry == nullptr || !file_range_entry->Contains(lookup_file_addr)) 536 { 537 prev_file_range_entry = file_range_entry; 538 file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr); 539 range_changed = true; 540 } 541 542 lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS; 543 lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS; 544 545 bool terminate_previous_entry = false; 546 if (file_range_entry) 547 { 548 entry_linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data; 549 // Determine if we need to terminate the previous entry when the previous 550 // entry was not contiguous with this one after being linked. 551 if (range_changed && prev_file_range_entry) 552 { 553 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; 554 if (prev_end_entry_linked_file_addr != entry_linked_file_addr) 555 terminate_previous_entry = prev_entry_was_linked; 556 } 557 } 558 else if (prev_entry_was_linked) 559 { 560 // This entry doesn't have a remapping and it needs to be removed. 561 // Watch out in case we need to terminate a previous entry needs to 562 // be terminated now that one line entry in a sequence is not longer valid. 563 if (!sequence.m_entries.empty() && 564 !sequence.m_entries.back().is_terminal_entry) 565 { 566 terminate_previous_entry = true; 567 } 568 } 569 570 if (terminate_previous_entry && !sequence.m_entries.empty()) 571 { 572 assert (prev_file_addr != LLDB_INVALID_ADDRESS); 573 sequence.m_entries.push_back(sequence.m_entries.back()); 574 if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS) 575 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; 576 sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr; 577 sequence.m_entries.back().is_terminal_entry = true; 578 579 // Append the sequence since we just terminated the previous one 580 line_table_ap->InsertSequence (&sequence); 581 sequence.Clear(); 582 } 583 584 // Now link the current entry 585 if (file_range_entry) 586 { 587 // This entry has an address remapping and it needs to have its address relinked 588 sequence.m_entries.push_back(entry); 589 sequence.m_entries.back().file_addr = entry_linked_file_addr; 590 } 591 592 // If we have items in the sequence and the last entry is a terminal entry, 593 // insert this sequence into our new line table. 594 if (!sequence.m_entries.empty() && sequence.m_entries.back().is_terminal_entry) 595 { 596 line_table_ap->InsertSequence (&sequence); 597 sequence.Clear(); 598 prev_entry_was_linked = false; 599 } 600 else 601 { 602 prev_entry_was_linked = file_range_entry != nullptr; 603 } 604 prev_file_addr = entry.file_addr; 605 range_changed = false; 606 } 607 if (line_table_ap->m_entries.empty()) 608 return nullptr; 609 return line_table_ap.release(); 610 } 611 612 613 614 615