diff options
author | Zachary Turner <zturner@google.com> | 2016-03-10 00:06:26 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2016-03-10 00:06:26 +0000 |
commit | 7e8c7bea796a72e9cf8cd05d39a5df9e84505a0c (patch) | |
tree | bf8a9b4f11c15e26199e7af02c691fb6c367ec80 | |
parent | c1424fc7c883c4bd184c4a715749a587c6b96fb2 (diff) | |
download | bcm5719-llvm-7e8c7bea796a72e9cf8cd05d39a5df9e84505a0c.tar.gz bcm5719-llvm-7e8c7bea796a72e9cf8cd05d39a5df9e84505a0c.zip |
Fix SymbolFilePDB for discontiguous functions.
Previously line table parsing code assumed that the only gaps would
occur at the end of functions. In practice this isn't true, so this
patch makes the line table parsing more robust in the face of
functions with non-contiguous byte arrangements.
llvm-svn: 263078
-rw-r--r-- | lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp | 82 |
1 files changed, 53 insertions, 29 deletions
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index a626a806151..a6357408551 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -43,6 +43,12 @@ namespace return lldb::LanguageType::eLanguageTypeUnknown; } } + + bool + ShouldAddLine(uint32_t requested_line, uint32_t actual_line, uint32_t addr_length) + { + return ((requested_line == 0 || actual_line == requested_line) && addr_length > 0); + } } void @@ -480,49 +486,67 @@ SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc, auto lines = m_session_up->findLineNumbers(*cu, *file); int entry_count = lines->getChildCount(); + uint64_t prev_addr; + uint32_t prev_length; + uint32_t prev_line; + uint32_t prev_source_idx; + for (int i = 0; i < entry_count; ++i) { auto line = lines->getChildAtIndex(i); - uint32_t lno = line->getLineNumber(); - // If `match_line` == 0 we add any line no matter what. Otherwise, we only add - // lines that match the requested line number. - if (match_line != 0 && lno != match_line) - continue; - - uint64_t va = line->getVirtualAddress(); - uint32_t cno = line->getColumnNumber(); + uint64_t lno = line->getLineNumber(); + uint64_t addr = line->getVirtualAddress(); + uint32_t length = line->getLength(); uint32_t source_id = line->getSourceFileId(); + uint32_t col = line->getColumnNumber(); uint32_t source_idx = index_map[source_id]; - bool is_basic_block = false; // PDB doesn't even have this concept, but LLDB doesn't use it anyway. - bool is_prologue = false; - bool is_epilogue = false; - bool is_statement = line->isStatement(); - auto func = m_session_up->findSymbolByAddress(va, llvm::PDB_SymType::Function); - if (func) - { - auto prologue = func->findOneChild<llvm::PDBSymbolFuncDebugStart>(); - is_prologue = (va == prologue->getVirtualAddress()); + // There was a gap between the current entry and the previous entry if the addresses don't perfectly line + // up. + bool is_gap = (i > 0) && (prev_addr + prev_length < addr); - auto epilogue = func->findOneChild<llvm::PDBSymbolFuncDebugEnd>(); - is_epilogue = (va == epilogue->getVirtualAddress()); + // Before inserting the current entry, insert a terminal entry at the end of the previous entry's address + // range if the current entry resulted in a gap from the previous entry. + if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) + { + line_table->AppendLineEntryToSequence(sequence.get(), prev_addr + prev_length, prev_line, 0, + prev_source_idx, false, false, false, false, true); + } - if (is_epilogue) + if (ShouldAddLine(match_line, lno, length)) + { + bool is_statement = line->isStatement(); + bool is_prologue = false; + bool is_epilogue = false; + auto func = m_session_up->findSymbolByAddress(addr, llvm::PDB_SymType::Function); + if (func) { - // Once per function, add a termination entry after the last byte of the function. - // TODO: This makes the assumption that all functions are laid out contiguously in - // memory and have no gaps. This is a wrong assumption in the general case, but is - // good enough to allow simple scenarios to work. This needs to be revisited. - auto concrete_func = llvm::dyn_cast<llvm::PDBSymbolFunc>(func.get()); - lldb::addr_t end_addr = concrete_func->getVirtualAddress() + concrete_func->getLength(); - line_table->InsertLineEntry(end_addr, lno, 0, source_idx, false, false, false, false, true); + auto prologue = func->findOneChild<llvm::PDBSymbolFuncDebugStart>(); + is_prologue = (addr == prologue->getVirtualAddress()); + + auto epilogue = func->findOneChild<llvm::PDBSymbolFuncDebugEnd>(); + is_epilogue = (addr == epilogue->getVirtualAddress()); } + + line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col, source_idx, is_statement, false, + is_prologue, is_epilogue, false); } - line_table->InsertLineEntry(va, lno, cno, source_idx, is_statement, is_basic_block, is_prologue, - is_epilogue, false); + prev_addr = addr; + prev_length = length; + prev_line = lno; + prev_source_idx = source_idx; } + + if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) + { + // The end is always a terminal entry, so insert it regardless. + line_table->AppendLineEntryToSequence(sequence.get(), prev_addr + prev_length, prev_line, 0, + prev_source_idx, false, false, false, false, true); + } + + line_table->InsertSequence(sequence.release()); } sc.comp_unit->SetLineTable(line_table.release()); |