diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h --- a/llvm/include/llvm/DebugInfo/DIContext.h +++ b/llvm/include/llvm/DebugInfo/DIContext.h @@ -133,7 +133,12 @@ /// Controls which fields of DILineInfo container should be filled /// with data. struct DILineInfoSpecifier { - enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; + enum class FileLineInfoKind { + None, + Default, + RelativeFilePath, + AbsoluteFilePath + }; using FunctionNameKind = DINameKind; FileLineInfoKind FLIKind; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -1082,7 +1082,7 @@ if (!Name) return false; StringRef FileName = *Name; - if (Kind != FileLineInfoKind::AbsoluteFilePath || + if (Kind == FileLineInfoKind::Default || isPathAbsoluteOnWindowsOrPosix(FileName)) { Result = std::string(FileName); return true; @@ -1099,12 +1099,17 @@ IncludeDir = IncludeDirectories[Entry.DirIdx - 1].getAsCString().getValue(); } - // We may still need to append compilation directory of compile unit. - // We know that FileName is not absolute, the only way to have an - // absolute path at this point would be if IncludeDir is absolute. - if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) + // For absolute paths only, include the compilation directory of compile unit. + // We know that FileName is not absolute, the only way to have an absolute + // path at this point would be if IncludeDir is absolute. + if (Kind == FileLineInfoKind::AbsoluteFilePath && !CompDir.empty() && + !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) sys::path::append(FilePath, Style, CompDir); + assert((Kind == FileLineInfoKind::AbsoluteFilePath || + Kind == FileLineInfoKind::RelativeFilePath) && + "invalid FileLineInfo Kind"); + // sys::path::append skips empty strings. sys::path::append(FilePath, Style, IncludeDir, FileName); Result = std::string(FilePath.str()); diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -180,7 +180,7 @@ UnitLength = PrologueLength + 2; break; case 5: - PrologueLength = 39; + PrologueLength = 42; UnitLength = PrologueLength + 4; EXPECT_EQ(Prologue.getAddressSize(), 8u); EXPECT_EQ(Prologue.SegSelectorSize, 0u); @@ -901,4 +901,51 @@ EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output; } +TEST_F(DebugLineBasicFixture, PrintPathsProperly) { + if (!setupGenerator(5)) + return; + + LineTable < = Gen->addLineTable(); + DWARFDebugLine::Prologue P = LT.createBasicPrologue(); + P.IncludeDirectories.push_back( + DWARFFormValue::createFromPValue(DW_FORM_string, "b dir")); + P.FileNames.push_back(DWARFDebugLine::FileNameEntry()); + P.FileNames.back().Name = + DWARFFormValue::createFromPValue(DW_FORM_string, "b file"); + P.FileNames.back().DirIdx = 1; + P.PrologueLength += 14; + LT.setPrologue(P); + generate(); + + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, + nullptr, RecordRecoverable); + EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); + std::string Result; + // DWARF 5 stores the compilation directory in two places: the Compilation + // Unit and the directory table entry 0, and implementations are free to use + // one or the other. This copy serves as the one stored in the CU. + StringRef CompDir = "a dir"; + EXPECT_FALSE( + (*ExpectedLineTable) + ->Prologue.getFileNameByIndex( + 1, CompDir, DILineInfoSpecifier::FileLineInfoKind::None, Result)); + EXPECT_TRUE((*ExpectedLineTable) + ->Prologue.getFileNameByIndex( + 1, CompDir, + DILineInfoSpecifier::FileLineInfoKind::Default, Result)); + EXPECT_STREQ(Result.c_str(), "b file"); + EXPECT_TRUE((*ExpectedLineTable) + ->Prologue.getFileNameByIndex( + 1, CompDir, + DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, + Result)); + EXPECT_STREQ(Result.c_str(), "b dir/b file"); + EXPECT_TRUE((*ExpectedLineTable) + ->Prologue.getFileNameByIndex( + 1, CompDir, + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, + Result)); + EXPECT_STREQ(Result.c_str(), "a dir/b dir/b file"); +} + } // end anonymous namespace diff --git a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp --- a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp @@ -164,8 +164,8 @@ P.PrologueLength = 36; break; case 5: - P.TotalLength = 47; - P.PrologueLength = 39; + P.TotalLength = 50; + P.PrologueLength = 42; P.FormParams.AddrSize = AddrSize; break; default: @@ -343,13 +343,16 @@ writeCString(*Include.getAsCString(), Asm); } - Asm.emitInt8(1); // file_name_entry_format_count. + Asm.emitInt8(2); // file_name_entry_format_count. Asm.EmitULEB128(DW_LNCT_path); Asm.EmitULEB128(DW_FORM_string); + Asm.EmitULEB128(DW_LNCT_directory_index); + Asm.EmitULEB128(DW_FORM_data1); Asm.EmitULEB128(Prologue.FileNames.size()); for (auto File : Prologue.FileNames) { assert(File.Name.getAsCString() && "expected a string form for file name"); writeCString(*File.Name.getAsCString(), Asm); + Asm.emitInt8(File.DirIdx); } }