Index: lld/trunk/ELF/InputFiles.cpp =================================================================== --- lld/trunk/ELF/InputFiles.cpp +++ lld/trunk/ELF/InputFiles.cpp @@ -124,10 +124,8 @@ // The second parameter is offset in .debug_line section // for compilation unit (CU) of interest. We have only one // CU (object file), so offset is always 0. - // FIXME: Provide the associated DWARFUnit if there is one. DWARF v5 - // needs it in order to find indirect strings. const DWARFDebugLine::LineTable *LT = - DwarfLine->getOrParseLineTable(LineData, 0, nullptr); + DwarfLine->getOrParseLineTable(LineData, 0, Dwarf, nullptr); // Return if there is no debug information about CU available. if (!Dwarf.getNumCompileUnits()) Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -34,6 +34,7 @@ #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" #include "llvm/Support/Host.h" #include @@ -43,7 +44,6 @@ namespace llvm { -class DataExtractor; class MCRegisterInfo; class MemoryBuffer; class raw_ostream; @@ -261,6 +261,13 @@ /// Get a pointer to a parsed line table corresponding to a compile unit. const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); + DataExtractor getStringExtractor() const { + return DataExtractor(DObj->getStringSection(), false, 0); + } + DataExtractor getLineStringExtractor() const { + return DataExtractor(DObj->getLineStringSection(), false, 0); + } + /// Wraps the returned DIEs for a given address. struct DIEsForAddress { DWARFCompileUnit *CompileUnit = nullptr; Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -101,7 +101,7 @@ void clear(); void dump(raw_ostream &OS) const; bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, - const DWARFUnit *U = nullptr); + const DWARFContext &Ctx, const DWARFUnit *U = nullptr); }; /// Standard .debug_line state machine structure. @@ -224,7 +224,8 @@ /// Parse prologue and all rows. bool parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, - const DWARFUnit *U, raw_ostream *OS = nullptr); + const DWARFContext &Ctx, const DWARFUnit *U, + raw_ostream *OS = nullptr); using RowVector = std::vector; using RowIter = RowVector::const_iterator; @@ -242,7 +243,8 @@ const LineTable *getLineTable(uint32_t Offset) const; const LineTable *getOrParseLineTable(DWARFDataExtractor &DebugLineData, - uint32_t Offset, const DWARFUnit *U); + uint32_t Offset, const DWARFContext &C, + const DWARFUnit *U); private: struct ParsingState { Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFFormValue.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -20,6 +20,7 @@ namespace llvm { +class DWARFContext; class DWARFUnit; class raw_ostream; @@ -85,7 +86,7 @@ dwarf::Form Form; /// Form for this value. ValueType Value; /// Contains all data for the form. const DWARFUnit *U = nullptr; /// Remember the DWARFUnit at extract time. - + const DWARFContext *C = nullptr; /// Context for extract time. public: DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {} @@ -108,10 +109,17 @@ /// Extracts a value in \p Data at offset \p *OffsetPtr. The information /// in \p FormParams is needed to interpret some forms. The optional - /// \p Unit allows extracting information if the form refers to other - /// sections (e.g., .debug_str). + /// \p Context and \p Unit allows extracting information if the form refers + /// to other sections (e.g., .debug_str). + bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, + DWARFFormParams FormParams, + const DWARFContext *Context = nullptr, + const DWARFUnit *Unit = nullptr); + bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, - DWARFFormParams FormParams, const DWARFUnit *U = nullptr); + DWARFFormParams FormParams, const DWARFUnit *U) { + return extractValue(Data, OffsetPtr, FormParams, nullptr, U); + } bool isInlinedCStr() const { return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr; Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -387,7 +387,7 @@ if (DumpOffset && Offset != *DumpOffset) { // Find the size of this part of the line table section and skip it. unsigned OldOffset = Offset; - LineTable.Prologue.parse(LineData, &Offset, U); + LineTable.Prologue.parse(LineData, &Offset, *this, U); Offset = OldOffset + LineTable.Prologue.TotalLength + LineTable.Prologue.sizeofTotalLength(); continue; @@ -397,9 +397,9 @@ OS << "debug_line[" << format("0x%8.8x", Offset) << "]\n"; unsigned OldOffset = Offset; if (DumpOpts.Verbose) { - LineTable.parse(LineData, &Offset, U, &OS); + LineTable.parse(LineData, &Offset, *this, U, &OS); } else { - LineTable.parse(LineData, &Offset, U); + LineTable.parse(LineData, &Offset, *this, U); LineTable.dump(OS); } // Check for unparseable prologue, to avoid infinite loops. @@ -422,7 +422,7 @@ U = It->second; DWARFDebugLine::LineTable LineTable; unsigned OldOffset = Offset; - if (!LineTable.Prologue.parse(LineData, &Offset, U)) + if (!LineTable.Prologue.parse(LineData, &Offset, *this, U)) break; if (!DumpOffset || OldOffset == *DumpOffset) LineTable.dump(OS); @@ -781,7 +781,7 @@ // We have to parse it first. DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(), U->getAddressByteSize()); - return Line->getOrParseLineTable(lineData, stmtOffset, U); + return Line->getOrParseLineTable(lineData, stmtOffset, *this, U); } void DWARFContext::parseCompileUnits() { Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugLine.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -157,8 +157,9 @@ static bool parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, uint64_t EndPrologueOffset, - const DWARFFormParams &FormParams, const DWARFUnit *U, - bool &HasMD5, std::vector &IncludeDirectories, + const DWARFFormParams &FormParams, const DWARFContext &Ctx, + const DWARFUnit *U, bool &HasMD5, + std::vector &IncludeDirectories, std::vector &FileNames) { // Get the directory entry description. ContentDescriptors DirDescriptors = @@ -175,7 +176,7 @@ DWARFFormValue Value(Descriptor.Form); switch (Descriptor.Type) { case DW_LNCT_path: - if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, U)) + if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U)) return false; IncludeDirectories.push_back(Value.getAsCString().getValue()); break; @@ -200,7 +201,7 @@ DWARFDebugLine::FileNameEntry FileEntry; for (auto Descriptor : FileDescriptors) { DWARFFormValue Value(Descriptor.Form); - if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, U)) + if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U)) return false; switch (Descriptor.Type) { case DW_LNCT_path: @@ -230,7 +231,9 @@ } bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr, const DWARFUnit *U) { + uint32_t *OffsetPtr, + const DWARFContext &Ctx, + const DWARFUnit *U) { const uint64_t PrologueOffset = *OffsetPtr; clear(); @@ -271,7 +274,7 @@ if (getVersion() >= 5) { if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, - FormParams, U, HasMD5, IncludeDirectories, + FormParams, Ctx, U, HasMD5, IncludeDirectories, FileNames)) { fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64 @@ -401,25 +404,27 @@ const DWARFDebugLine::LineTable * DWARFDebugLine::getOrParseLineTable(DWARFDataExtractor &DebugLineData, - uint32_t Offset, const DWARFUnit *U) { + uint32_t Offset, const DWARFContext &Ctx, + const DWARFUnit *U) { std::pair Pos = LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable())); LineTable *LT = &Pos.first->second; if (Pos.second) { - if (!LT->parse(DebugLineData, &Offset, U)) + if (!LT->parse(DebugLineData, &Offset, Ctx, U)) return nullptr; } return LT; } bool DWARFDebugLine::LineTable::parse(DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr, const DWARFUnit *U, - raw_ostream *OS) { + uint32_t *OffsetPtr, + const DWARFContext &Ctx, + const DWARFUnit *U, raw_ostream *OS) { const uint32_t DebugLineOffset = *OffsetPtr; clear(); - if (!Prologue.parse(DebugLineData, OffsetPtr, U)) { + if (!Prologue.parse(DebugLineData, OffsetPtr, Ctx, U)) { // Restore our offset and return false to indicate failure! *OffsetPtr = DebugLineOffset; return false; Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFFormValue.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -293,7 +293,11 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, DWARFFormParams FP, + const DWARFContext *Ctx, const DWARFUnit *CU) { + if (!Ctx && CU) + Ctx = &CU->getContext(); + C = Ctx; U = CU; bool Indirect = false; bool IsBlock = false; @@ -591,11 +595,12 @@ if (Form == DW_FORM_string) return Value.cstr; // FIXME: Add support for DW_FORM_GNU_strp_alt - if (Form == DW_FORM_GNU_strp_alt || U == nullptr) + if (Form == DW_FORM_GNU_strp_alt || C == nullptr) return None; uint32_t Offset = Value.uval; if (Form == DW_FORM_line_strp) { - if (const char *Str = U->getLineStringExtractor().getCStr(&Offset)) + // .debug_line_str is tracked in the Context. + if (const char *Str = C->getLineStringExtractor().getCStr(&Offset)) return Str; return None; } @@ -603,13 +608,19 @@ Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 || Form == DW_FORM_strx4) { uint64_t StrOffset; - if (!U->getStringOffsetSectionItem(Offset, StrOffset)) + if (!U || !U->getStringOffsetSectionItem(Offset, StrOffset)) return None; Offset = StrOffset; } - if (const char *Str = U->getStringExtractor().getCStr(&Offset)) { - return Str; + // Prefer the Unit's string extractor, because for .dwo it will point to + // .debug_str.dwo, while the Context's extractor always uses .debug_str. + if (U) { + if (const char *Str = U->getStringExtractor().getCStr(&Offset)) + return Str; + return None; } + if (const char *Str = C->getStringExtractor().getCStr(&Offset)) + return Str; return None; } Index: llvm/trunk/test/DebugInfo/X86/dwarfdump-line-only.s =================================================================== --- llvm/trunk/test/DebugInfo/X86/dwarfdump-line-only.s +++ llvm/trunk/test/DebugInfo/X86/dwarfdump-line-only.s @@ -1,6 +1,5 @@ # Test object to verify dwarfdump handles dumping a DWARF v5 line table # without an associated unit. -# FIXME: Support FORM_strp in this situation. # # RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o - | \ # RUN: llvm-dwarfdump -v - | FileCheck %s @@ -42,17 +41,17 @@ # Directory table format .byte 1 # One element per directory entry .byte 1 # DW_LNCT_path - .byte 0x08 # DW_FORM_string + .byte 0x0e # DW_FORM_strp (-> .debug_str) # Directory table entries .byte 2 # Two directory entries - .asciz "Directory1" - .asciz "Directory2" + .long str_D1 + .long str_D2 # File table format .byte 4 # Four elements per file entry .byte 2 # DW_LNCT_directory_index .byte 0x0b # DW_FORM_data1 .byte 1 # DW_LNCT_path - .byte 0x08 # DW_FORM_string + .byte 0x1f # DW_FORM_line_strp (-> .debug_line_str) .byte 3 # DW_LNCT_timestamp .byte 0x0f # DW_FORM_udata .byte 4 # DW_LNCT_size @@ -60,11 +59,11 @@ # File table entries .byte 2 # Two file entries .byte 1 - .asciz "File1" + .long ls_F1 .byte 0x51 .byte 0x52 .byte 0 - .asciz "File2" + .long ls_F2 .byte 0x53 .byte 0x54 LH_5_header_end: @@ -79,6 +78,14 @@ .byte 1 # DW_LNE_end_sequence LH_5_end: + .section .debug_str,"MS",@progbits,1 +str_D1: .asciz "Directory1" +str_D2: .asciz "Directory2" + + .section .debug_line_str,"MS",@progbits,1 +ls_F1: .asciz "File1" +ls_F2: .asciz "File2" + # CHECK: Line table prologue: # CHECK: version: 5 # CHECK: address_size: 8 Index: llvm/trunk/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/trunk/tools/dsymutil/DwarfLinker.cpp +++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp @@ -3344,7 +3344,7 @@ DWARFDataExtractor LineExtractor( OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(), OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize()); - LineTable.parse(LineExtractor, &StmtOffset, &Unit.getOrigUnit()); + LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf, &Unit.getOrigUnit()); // This vector is the output line table. std::vector NewRows;