Index: lib/DebugInfo/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARFContext.cpp +++ lib/DebugInfo/DWARFContext.cpp @@ -425,47 +425,6 @@ return getCompileUnitForOffset(CUOffset); } -static bool getFileNameForUnit(DWARFCompileUnit *U, - const DWARFLineTable *LineTable, - uint64_t FileIndex, FileLineInfoKind Kind, - std::string &FileName) { - if (!U || !LineTable || Kind == FileLineInfoKind::None || - !LineTable->getFileNameByIndex(FileIndex, Kind, FileName)) - return false; - if (Kind == FileLineInfoKind::AbsoluteFilePath && - sys::path::is_relative(FileName)) { - // We may still need to append compilation directory of compile unit. - SmallString<16> AbsolutePath; - if (const char *CompilationDir = U->getCompilationDir()) { - sys::path::append(AbsolutePath, CompilationDir); - } - sys::path::append(AbsolutePath, FileName); - FileName = AbsolutePath.str(); - } - return true; -} - -static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, - const DWARFLineTable *LineTable, - uint64_t Address, - FileLineInfoKind Kind, - DILineInfo &Result) { - if (!CU || !LineTable) - return false; - // Get the index of row we're looking for in the line table. - uint32_t RowIndex = LineTable->lookupAddress(Address); - if (RowIndex == -1U) - return false; - // Take file number and line/column from the row. - const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; - if (!getFileNameForUnit(CU, LineTable, Row.File, Kind, - Result.FileName)) - return false; - Result.Line = Row.Line; - Result.Column = Row.Column; - return true; -} - static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind, std::string &FunctionName) { @@ -497,7 +456,8 @@ getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName); if (Spec.FLIKind != FileLineInfoKind::None) { const DWARFLineTable *LineTable = getLineTableForUnit(CU); - getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, Result); + if (LineTable) + LineTable->getFileLineInfoForCompileUnit(CU, Address, Spec.FLIKind, Result); } return Result; } @@ -533,8 +493,9 @@ // Take file number and line/column from the row. const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; DILineInfo Result; - getFileNameForUnit(CU, LineTable, Row.File, Spec.FLIKind, - Result.FileName); + if (!LineTable->getFileNameByIndex(Row.File, Spec.FLIKind, + Result.FileName, CU)) + continue; Result.FunctionName = FunctionName; Result.Line = Row.Line; Result.Column = Row.Column; @@ -562,10 +523,10 @@ if (Spec.FLIKind != FileLineInfoKind::None) { DILineInfo Frame; LineTable = getLineTableForUnit(CU); - if (getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, - Frame)) { + if (LineTable && + LineTable->getFileLineInfoForCompileUnit(CU, Address, Spec.FLIKind, + Frame)) InliningInfo.addFrame(Frame); - } } return InliningInfo; } @@ -584,13 +545,15 @@ // compile unit and fetch file/line info from it. LineTable = getLineTableForUnit(CU); // For the topmost routine, get file/line info from line table. - getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, - Frame); + if (LineTable) + LineTable->getFileLineInfoForCompileUnit(CU, Address, Spec.FLIKind, + Frame); } else { // Otherwise, use call file, call line and call column from // previous DIE in inlined chain. - getFileNameForUnit(CU, LineTable, CallFile, Spec.FLIKind, - Frame.FileName); + if (LineTable) + LineTable->getFileNameByIndex(CallFile, Spec.FLIKind, + Frame.FileName, CU); Frame.Line = CallLine; Frame.Column = CallColumn; } Index: lib/DebugInfo/DWARFDebugInfoEntry.h =================================================================== --- lib/DebugInfo/DWARFDebugInfoEntry.h +++ lib/DebugInfo/DWARFDebugInfoEntry.h @@ -38,9 +38,9 @@ DWARFDebugInfoEntryMinimal() : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} - void dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth, + void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, unsigned indent = 0) const; - void dumpAttribute(raw_ostream &OS, const DWARFUnit *u, uint32_t *offset_ptr, + void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, uint16_t attr, uint16_t form, unsigned indent = 0) const; /// Extracts a debug info entry, which is a child of a given unit, Index: lib/DebugInfo/DWARFDebugInfoEntry.cpp =================================================================== --- lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -16,11 +16,14 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" + +#include + using namespace llvm; using namespace dwarf; typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; -void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u, +void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, unsigned indent) const { DataExtractor debug_info_data = u->getDebugInfoExtractor(); @@ -63,7 +66,7 @@ } void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, - const DWARFUnit *u, + DWARFUnit *u, uint32_t *offset_ptr, uint16_t attr, uint16_t form, unsigned indent) const { @@ -91,8 +94,24 @@ if (Optional Val = formValue.getAsUnsignedConstant()) Name = AttributeValueString(attr, *Val); + if (attr == DW_AT_decl_file || attr == DW_AT_call_file) { + typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; + const DWARFDebugLine::LineTable *LT; + std::string File; + + LT = u->getContext().getLineTableForUnit(u); + if (LT && + LT->getFileNameByIndex(formValue.getAsUnsignedConstant().getValue(), + FileLineInfoKind::AbsoluteFilePath, File, u)) { + File = '"' + File + '"'; + Name = File.c_str(); + } + } + if (Name) { OS << Name; + } else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) { + OS << *formValue.getAsUnsignedConstant(); } else { formValue.dump(OS, u); } Index: lib/DebugInfo/DWARFDebugLine.h =================================================================== --- lib/DebugInfo/DWARFDebugLine.h +++ lib/DebugInfo/DWARFDebugLine.h @@ -20,6 +20,8 @@ namespace llvm { class raw_ostream; +class DWARFUnit; +class DWARFCompileUnit; class DWARFDebugLine { public: @@ -181,7 +183,12 @@ // Returns true on success. bool getFileNameByIndex(uint64_t FileIndex, DILineInfoSpecifier::FileLineInfoKind Kind, - std::string &Result) const; + std::string &Result, DWARFUnit *U = nullptr) const; + + bool + getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, uint64_t Address, + DILineInfoSpecifier::FileLineInfoKind Kind, + DILineInfo &Result) const; void dump(raw_ostream &OS) const; void clear(); Index: lib/DebugInfo/DWARFDebugLine.cpp =================================================================== --- lib/DebugInfo/DWARFDebugLine.cpp +++ lib/DebugInfo/DWARFDebugLine.cpp @@ -8,11 +8,15 @@ //===----------------------------------------------------------------------===// #include "DWARFDebugLine.h" +#include "DWARFCompileUnit.h" +#include "DWARFUnit.h" +#include "llvm/Config/config.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include +#include using namespace llvm; using namespace dwarf; typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; @@ -645,7 +649,8 @@ bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, FileLineInfoKind Kind, - std::string &Result) const { + std::string &Result, + DWARFUnit *U) const { if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() || Kind == FileLineInfoKind::None) return false; @@ -665,6 +670,45 @@ sys::path::append(FilePath, IncludeDir); } sys::path::append(FilePath, FileName); + + if (U && Kind == FileLineInfoKind::AbsoluteFilePath && + sys::path::is_relative(FilePath.str())) { + // We may still need to append compilation directory of compile unit. + SmallString<16> AbsolutePath; + if (const char *CompilationDir = U->getCompilationDir()) { + sys::path::append(AbsolutePath, CompilationDir); + } + sys::path::append(AbsolutePath, FilePath.str()); + FilePath = AbsolutePath.str(); + } + +#ifdef HAVE_REALPATH + // Calling realpath will resolve any '..' in the path. + char ResolvedPath[PATH_MAX]; + if (realpath(FilePath.c_str(), ResolvedPath)) + Result = ResolvedPath; + else +#endif Result = FilePath.str(); return true; } + +bool +DWARFDebugLine::LineTable::getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, + uint64_t Address, + FileLineInfoKind Kind, + DILineInfo &Result) const { + if (!CU) + return false; + // Get the index of row we're looking for in the line table. + uint32_t RowIndex = lookupAddress(Address); + if (RowIndex == -1U) + return false; + // Take file number and line/column from the row. + const DWARFDebugLine::Row &Row = Rows[RowIndex]; + if (!getFileNameByIndex(Row.File, Kind, Result.FileName, CU)) + return false; + Result.Line = Row.Line; + Result.Column = Row.Column; + return true; +} Index: test/DebugInfo/X86/2011-09-26-GlobalVarContext.ll =================================================================== --- test/DebugInfo/X86/2011-09-26-GlobalVarContext.ll +++ test/DebugInfo/X86/2011-09-26-GlobalVarContext.ll @@ -40,16 +40,16 @@ ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]*}}] = "GLB") ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01) +; CHECK: DW_AT_decl_file [DW_FORM_data1] ("/work/llvm/vanilla/test/DebugInfo/test.c") ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_decl_line [DW_FORM_data1] (0x01) +; CHECK: DW_AT_decl_line [DW_FORM_data1] (1) ; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]*}}] = "LOC") ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01) +; CHECK: DW_AT_decl_file [DW_FORM_data1] ("/work/llvm/vanilla/test/DebugInfo/test.c") ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_decl_line [DW_FORM_data1] (0x04) +; CHECK: DW_AT_decl_line [DW_FORM_data1] (4) !21 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} Index: test/DebugInfo/X86/fission-cu.ll =================================================================== --- test/DebugInfo/X86/fission-cu.ll +++ test/DebugInfo/X86/fission-cu.ll @@ -76,7 +76,7 @@ ; CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[0-9a-f]*}} => {[[TYPE:0x[0-9a-f]*]]}) ; CHECK: DW_AT_external [DW_FORM_flag_present] (true) ; CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01) -; CHECK: DW_AT_decl_line [DW_FORM_data1] (0x01) +; CHECK: DW_AT_decl_line [DW_FORM_data1] (1) ; CHECK: DW_AT_location [DW_FORM_exprloc] (<0x2> fb 00 ) ; CHECK: [[TYPE]]: DW_TAG_base_type ; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000003) string = "int") Index: test/DebugInfo/namespace.ll =================================================================== --- test/DebugInfo/namespace.ll +++ test/DebugInfo/namespace.ll @@ -5,13 +5,21 @@ ; CHECK: debug_info contents ; CHECK: [[NS1:0x[0-9a-f]*]]:{{ *}}DW_TAG_namespace ; CHECK-NEXT: DW_AT_name{{.*}} = "A" +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F1:[0-9]]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x03) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F1:".*debug-info-namespace.cpp"]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(3) ; CHECK-NOT: NULL ; CHECK: [[NS2:0x[0-9a-f]*]]:{{ *}}DW_TAG_namespace ; CHECK-NEXT: DW_AT_name{{.*}} = "B" +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2:[0-9]]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x01) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2:".*foo.cpp"]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(1) ; CHECK-NOT: NULL ; CHECK: [[I:0x[0-9a-f]*]]:{{ *}}DW_TAG_variable ; CHECK-NEXT: DW_AT_name{{.*}}= "i" @@ -39,16 +47,24 @@ ; CHECK: DW_TAG_imported_module ; This is a bug, it should be in F2 but it inherits the file from its ; enclosing scope +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F1]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x08) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F1]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(8) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS2]]}) ; CHECK: NULL ; CHECK-NOT: NULL ; CHECK: DW_TAG_imported_module ; Same bug as above, this should be F2, not F1 +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F1]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x0b) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F1]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(11) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS1]]}) ; CHECK-NOT: NULL @@ -59,55 +75,84 @@ ; CHECK: DW_AT_name{{.*}}= "func" ; CHECK-NOT: NULL ; CHECK: DW_TAG_imported_module +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x12) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(18) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS1]]}) ; CHECK-NOT: NULL ; CHECK: DW_TAG_imported_declaration +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x13) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(19) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[FOO]]}) ; CHECK-NOT: NULL ; CHECK: DW_TAG_imported_declaration +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x14) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(20) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[BAR]]}) ; CHECK-NOT: NULL ; CHECK: DW_TAG_imported_declaration +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x15) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(21) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[FUNC1]]}) ; CHECK-NOT: NULL ; CHECK: DW_TAG_imported_declaration +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x16) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(22) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[I]]}) ; CHECK-NOT: NULL ; CHECK: [[X:0x[0-9a-f]*]]:{{ *}}DW_TAG_imported_declaration +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x18) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(24) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS1]]}) ; CHECK-NEXT: DW_AT_name{{.*}}"X" ; CHECK-NOT: NULL ; CHECK: DW_TAG_imported_declaration +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x19) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(25) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[X]]}) ; CHECK-NEXT: DW_AT_name{{.*}}"Y" ; CHECK-NOT: NULL ; CHECK: DW_TAG_lexical_block ; CHECK-NOT: NULL ; CHECK: DW_TAG_imported_module +<<<<<<< HEAD ; CHECK-NEXT: DW_AT_decl_file{{.*}}(0x0[[F2]]) -; CHECK-NEXT: DW_AT_decl_line{{.*}}(0x0f) +======= +; CHECK-NEXT: DW_AT_decl_file{{.*}}([[F2]]) +>>>>>>> a5684ab... [dwarfdump] Dump full filenames as DW_AT_(decl|call)_file attribute values +; CHECK-NEXT: DW_AT_decl_line{{.*}}(15) ; CHECK-NEXT: DW_AT_import{{.*}}=> {[[NS2]]}) ; CHECK: NULL ; CHECK: NULL ; CHECK: NULL -; CHECK: file_names[ [[F1]]]{{.*}}debug-info-namespace.cpp -; CHECK: file_names[ [[F2]]]{{.*}}foo.cpp - ; IR generated from clang/test/CodeGenCXX/debug-info-namespace.cpp, file paths ; changed to protect the guilty. The C++ source code is: ; namespace A { Index: test/MC/MachO/gen-dwarf.s =================================================================== --- test/MC/MachO/gen-dwarf.s +++ test/MC/MachO/gen-dwarf.s @@ -50,8 +50,8 @@ // CHECK: DW_TAG_label [2] * // CHECK: DW_AT_name [DW_FORM_string] ("bar") -// CHECK: DW_AT_decl_file [DW_FORM_data4] (0x00000001) -// CHECK: DW_AT_decl_line [DW_FORM_data4] (0x00000005) +// CHECK: DW_AT_decl_file [DW_FORM_data4] ([[FILE:".*gen-dwarf.s"]]) +// CHECK: DW_AT_decl_line [DW_FORM_data4] (5) // CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) // CHECK: DW_AT_prototyped [DW_FORM_flag] (0x00) @@ -61,8 +61,8 @@ // CHECK: DW_TAG_label [2] * // CHECK: DW_AT_name [DW_FORM_string] ("foo") -// CHECK: DW_AT_decl_file [DW_FORM_data4] (0x00000001) -// CHECK: DW_AT_decl_line [DW_FORM_data4] (0x00000009) +// CHECK: DW_AT_decl_file [DW_FORM_data4] ([[FILE]]) +// CHECK: DW_AT_decl_line [DW_FORM_data4] (9) // CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000007) // CHECK: DW_AT_prototyped [DW_FORM_flag] (0x00) @@ -72,8 +72,8 @@ // CHECK: DW_TAG_label [2] * // CHECK: DW_AT_name [DW_FORM_string] ("baz") -// CHECK: DW_AT_decl_file [DW_FORM_data4] (0x00000001) -// CHECK: DW_AT_decl_line [DW_FORM_data4] (0x0000000a) +// CHECK: DW_AT_decl_file [DW_FORM_data4] ([[FILE]]) +// CHECK: DW_AT_decl_line [DW_FORM_data4] (10) // CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000007) // CHECK: DW_AT_prototyped [DW_FORM_flag] (0x00)