static LineTable createLineTable(SourceLocTable& srcLoc, Offset bclen) { LineTable lines; for (size_t i = 0; i < srcLoc.size(); ++i) { Offset endOff = i < srcLoc.size() - 1 ? srcLoc[i + 1].first : bclen; lines.push_back(LineEntry(endOff, srcLoc[i].second.line1)); } return lines; }
const DWARFDebugLine::LineTable * DWARFDebugLine::getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint32_t Offset, const DWARFUnit *U) { std::pair<LineTableIter, bool> Pos = LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable())); LineTable *LT = &Pos.first->second; if (Pos.second) { if (!LT->parse(DebugLineData, &Offset, U)) return nullptr; } return LT; }
const DWARFDebugLine::LineTable * DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data, uint32_t offset) { std::pair<LineTableIter, bool> pos = LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable())); LineTable *LT = &pos.first->second; if (pos.second) { if (!LT->parse(debug_line_data, RelocMap, &offset)) return nullptr; } return LT; }
TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchSpecific)) { // Test that when calling ResolveSymbolContext with a specific line number, // only line entries // which match the requested line are returned. FileSpec fspec(m_pdb_test_exe.c_str(), false); ArchSpec aspec("i686-pc-windows"); lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); SymbolVendor *plugin = module->GetSymbolVendor(); SymbolFile *symfile = plugin->GetSymbolFile(); FileSpec source_file("test-pdb.cpp", false); FileSpec header1("test-pdb.h", false); FileSpec header2("test-pdb-nested.h", false); uint32_t cus = symfile->GetNumCompileUnits(); EXPECT_EQ(2u, cus); SymbolContextList sc_list; uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry; // First test with line 7, and verify that only line 7 entries are added. uint32_t count = symfile->ResolveSymbolContext(source_file, 7, true, scope, sc_list); EXPECT_EQ(1u, count); SymbolContext sc; EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); LineTable *lt = sc.comp_unit->GetLineTable(); EXPECT_NE(nullptr, lt); count = lt->GetSize(); // We expect one extra entry for termination EXPECT_EQ(3u, count); VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040); VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089); sc_list.Clear(); // Then test with line 9, and verify that only line 9 entries are added. count = symfile->ResolveSymbolContext(source_file, 9, true, scope, sc_list); EXPECT_EQ(1u, count); EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); lt = sc.comp_unit->GetLineTable(); EXPECT_NE(nullptr, lt); count = lt->GetSize(); // We expect one extra entry for termination EXPECT_EQ(3u, count); VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045); VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090); }
DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext( function_ref<void(Error)> RecoverableErrorCallback, function_ref<void(Error)> UnrecoverableErrorCallback, raw_ostream *OS) { assert(DebugLineData.isValidOffset(Offset) && "parsing should have terminated"); DWARFUnit *U = prepareToParse(Offset); uint32_t OldOffset = Offset; LineTable LT; if (Error Err = LT.parse(DebugLineData, &Offset, Context, U, RecoverableErrorCallback, OS)) UnrecoverableErrorCallback(std::move(Err)); moveToNextTable(OldOffset, LT.Prologue); return LT; }
TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchAll)) { // Test that when calling ResolveSymbolContext with a line number of 0, all // line entries from // the specified files are returned. FileSpec fspec(m_pdb_test_exe.c_str(), false); ArchSpec aspec("i686-pc-windows"); lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); SymbolVendor *plugin = module->GetSymbolVendor(); SymbolFile *symfile = plugin->GetSymbolFile(); FileSpec source_file("test-pdb.cpp", false); FileSpec header1("test-pdb.h", false); FileSpec header2("test-pdb-nested.h", false); uint32_t cus = symfile->GetNumCompileUnits(); EXPECT_EQ(2u, cus); SymbolContextList sc_list; uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry; uint32_t count = symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list); EXPECT_EQ(1u, count); SymbolContext sc; EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc)); LineTable *lt = sc.comp_unit->GetLineTable(); EXPECT_NE(nullptr, lt); count = lt->GetSize(); // We expect one extra entry for termination (per function) EXPECT_EQ(16u, count); VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040); VerifyLineEntry(module, sc, source_file, *lt, 8, 0x401043); VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045); VerifyLineEntry(module, sc, source_file, *lt, 13, 0x401050); VerifyLineEntry(module, sc, source_file, *lt, 14, 0x401054); VerifyLineEntry(module, sc, source_file, *lt, 15, 0x401070); VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090); VerifyLineEntry(module, sc, header1, *lt, 10, 0x401093); VerifyLineEntry(module, sc, header1, *lt, 11, 0x4010a2); VerifyLineEntry(module, sc, header2, *lt, 5, 0x401080); VerifyLineEntry(module, sc, header2, *lt, 6, 0x401083); VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089); }
Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable( DWARFDataExtractor &DebugLineData, uint32_t Offset, const DWARFContext &Ctx, const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) { if (!DebugLineData.isValidOffset(Offset)) return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx32 " is not a valid debug line section offset", Offset); std::pair<LineTableIter, bool> Pos = LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable())); LineTable *LT = &Pos.first->second; if (Pos.second) { if (Error Err = LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorCallback)) return std::move(Err); return LT; } return LT; }
void UnitEmitter::setLines(const LineTable& lines) { Offset prevPastOffset = 0; for (size_t i = 0; i < lines.size(); ++i) { const LineEntry* line = &lines[i]; Location sLoc; sLoc.line0 = sLoc.line1 = line->val(); Offset pastOffset = line->pastOffset(); recordSourceLocation(&sLoc, prevPastOffset); prevPastOffset = pastOffset; } }
void VerifyLineEntry(lldb::ModuleSP module, const SymbolContext &sc, const FileSpec &spec, LineTable <, uint32_t line, lldb::addr_t addr) { LineEntry entry; Address address; EXPECT_TRUE(module->ResolveFileAddress(addr, address)); EXPECT_TRUE(lt.FindLineEntryByAddress(address, entry)); EXPECT_EQ(line, entry.line); EXPECT_EQ(address, entry.range.GetBaseAddress()); EXPECT_TRUE(FileSpecMatchesAsBaseOrFull(spec, entry.file)); }