diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 688c8025277a..e2717c206fbd 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -77,8 +77,10 @@ template void ObjFile::initializeDwarf() { // 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); + DwarfLine->getOrParseLineTable(LineData, 0, nullptr); // Return if there is no debug information about CU available. if (!Dwarf.getNumCompileUnits()) diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index a4d8c0dd716d..f89bcf82fee6 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -22,6 +22,7 @@ namespace llvm { +class DWARFUnit; class raw_ostream; class DWARFDebugLine { @@ -95,7 +96,8 @@ public: void clear(); void dump(raw_ostream &OS) const; - bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr); + bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + const DWARFUnit *U = nullptr); }; /// Standard .debug_line state machine structure. @@ -218,7 +220,7 @@ public: /// Parse prologue and all rows. bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, - raw_ostream *OS = nullptr); + const DWARFUnit *U, raw_ostream *OS = nullptr); using RowVector = std::vector; using RowIter = RowVector::const_iterator; @@ -236,7 +238,7 @@ public: const LineTable *getLineTable(uint32_t Offset) const; const LineTable *getOrParseLineTable(const DWARFDataExtractor &DebugLineData, - uint32_t Offset); + uint32_t Offset, const DWARFUnit *U); private: struct ParsingState { diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 497fe591c967..d32053519ec4 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -104,16 +104,12 @@ public: const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; - /// Extracts a value in \p Data at offset \p *OffsetPtr. - /// - /// The passed DWARFUnit is allowed to be nullptr, in which case some - /// kind of forms that depend on Unit information are disallowed. - /// \param Data The DWARFDataExtractor to use. - /// \param OffsetPtr The offset within \p Data where the data starts. - /// \param U The optional DWARFUnit supplying information for some forms. - /// \returns whether the extraction succeeded. + /// 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). bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, - const DWARFUnit *U); + DWARFFormParams FormParams, const DWARFUnit *U = nullptr); bool isInlinedCStr() const { return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index a88dcfcf5423..f593953c62ff 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -184,7 +184,7 @@ Optional DWARFAbbreviationDeclaration::getAttributeValue( FormValue.setSValue(Spec.getImplicitConstValue()); return FormValue; } - if (FormValue.extractValue(DebugInfoData, &Offset, &U)) + if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U)) return FormValue; } // March Offset along until we get to the attribute we want. diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index dbe6fe52407d..f04ec7706cd8 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -90,10 +90,11 @@ std::pair DWARFAcceleratorTable::readAtoms(uint32_t &HashDataOffset) { uint32_t DieOffset = dwarf::DW_INVALID_OFFSET; dwarf::Tag DieTag = dwarf::DW_TAG_null; + DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; for (auto Atom : getAtomsDesc()) { DWARFFormValue FormValue(Atom.second); - FormValue.extractValue(AccelSection, &HashDataOffset, NULL); + FormValue.extractValue(AccelSection, &HashDataOffset, FormParams); switch (Atom.first) { case dwarf::DW_ATOM_die_offset: DieOffset = *FormValue.getAsUnsignedConstant(); @@ -145,6 +146,7 @@ LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const { uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength; unsigned HashesBase = Offset + Hdr.NumBuckets * 4; unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4; + DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) { unsigned Index = AccelSection.getU32(&Offset); @@ -181,7 +183,7 @@ LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const { unsigned i = 0; for (auto &Atom : AtomForms) { OS << format("{Atom[%d]: ", i++); - if (Atom.extractValue(AccelSection, &DataOffset, nullptr)) + if (Atom.extractValue(AccelSection, &DataOffset, FormParams)) Atom.dump(OS); else OS << "Error extracting the value"; @@ -216,8 +218,10 @@ void DWARFAcceleratorTable::ValueIterator::Next() { NumData = 0; return; } + DWARFFormParams FormParams = {AccelTable->Hdr.Version, 0, + dwarf::DwarfFormat::DWARF32}; for (auto &Atom : AtomForms) - Atom.extractValue(AccelSection, &DataOffset, nullptr); + Atom.extractValue(AccelSection, &DataOffset, FormParams); ++Data; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index 24aa666fb81f..881cd1dfd110 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -329,9 +329,9 @@ void DWARFContext::dump( // representation. OS << "debug_line[" << format("0x%8.8x", Offset) << "]\n"; if (DumpOpts.Verbose) { - LineTable.parse(lineData, &Offset, &OS); + LineTable.parse(lineData, &Offset, &*CU, &OS); } else { - LineTable.parse(lineData, &Offset); + LineTable.parse(lineData, &Offset, &*CU); LineTable.dump(OS); } } @@ -349,7 +349,7 @@ void DWARFContext::dump( DWARFDataExtractor lineData(*DObj, DObj->getLineDWOSection(), isLittleEndian(), savedAddressByteSize); DWARFDebugLine::LineTable LineTable; - while (LineTable.Prologue.parse(lineData, &stmtOffset)) { + while (LineTable.Prologue.parse(lineData, &stmtOffset, nullptr)) { LineTable.dump(OS); LineTable.clear(); } @@ -681,7 +681,7 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) { // We have to parse it first. DWARFDataExtractor lineData(*DObj, U->getLineSection(), isLittleEndian(), U->getAddressByteSize()); - return Line->getOrParseLineTable(lineData, stmtOffset); + return Line->getOrParseLineTable(lineData, stmtOffset, U); } void DWARFContext::parseCompileUnits() { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index bd8dd0d0ede5..c99c7a9277ef 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -144,7 +144,7 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, static bool parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, uint64_t EndPrologueOffset, - const DWARFFormParams &FormParams, + const DWARFFormParams &FormParams, const DWARFUnit *U, std::vector &IncludeDirectories, std::vector &FileNames) { // Get the directory entry description. @@ -162,7 +162,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, DWARFFormValue Value(Descriptor.Form); switch (Descriptor.Type) { case DW_LNCT_path: - if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, U)) return false; IncludeDirectories.push_back(Value.getAsCString().getValue()); break; @@ -187,7 +187,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, DWARFDebugLine::FileNameEntry FileEntry; for (auto Descriptor : FileDescriptors) { DWARFFormValue Value(Descriptor.Form); - if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, U)) return false; switch (Descriptor.Type) { case DW_LNCT_path: @@ -213,7 +213,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, } bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr) { + uint32_t *OffsetPtr, const DWARFUnit *U) { const uint64_t PrologueOffset = *OffsetPtr; clear(); @@ -253,7 +253,8 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, if (getVersion() >= 5) { if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, - getFormParams(), IncludeDirectories, FileNames)) { + getFormParams(), U, IncludeDirectories, + FileNames)) { fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64 " found an invalid directory or file table description at" @@ -382,24 +383,25 @@ DWARFDebugLine::getLineTable(uint32_t Offset) const { const DWARFDebugLine::LineTable * DWARFDebugLine::getOrParseLineTable(const DWARFDataExtractor &DebugLineData, - uint32_t Offset) { + uint32_t Offset, 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)) + if (!LT->parse(DebugLineData, &Offset, U)) return nullptr; } return LT; } bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr, raw_ostream *OS) { + uint32_t *OffsetPtr, const DWARFUnit *U, + raw_ostream *OS) { const uint32_t DebugLineOffset = *OffsetPtr; clear(); - if (!Prologue.parse(DebugLineData, OffsetPtr)) { + if (!Prologue.parse(DebugLineData, OffsetPtr, U)) { // Restore our offset and return false to indicate failure! *OffsetPtr = DebugLineOffset; return false; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index d20eabff7f04..a579c06d02e7 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -208,7 +208,8 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, DWARFUnit *U = Die.getDwarfUnit(); DWARFFormValue formValue(Form); - if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U)) + if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, + U->getFormParams(), U)) return; OS << "\t("; @@ -550,7 +551,7 @@ void DWARFDie::attribute_iterator::updateForIndex( auto U = Die.getDwarfUnit(); assert(U && "Die must have valid DWARF unit"); bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(), - &ParseOffset, U); + &ParseOffset, U->getFormParams(), U); (void)b; assert(b && "extractValue cannot fail on fully parsed DWARF"); AttrValue.ByteSize = ParseOffset - AttrValue.Offset; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index d63e84ef4e7d..c4abd49797b1 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -276,7 +276,8 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { } bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, - uint32_t *OffsetPtr, const DWARFUnit *CU) { + uint32_t *OffsetPtr, DWARFFormParams FP, + const DWARFUnit *CU) { U = CU; bool Indirect = false; bool IsBlock = false; @@ -288,10 +289,8 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, switch (Form) { case DW_FORM_addr: case DW_FORM_ref_addr: { - if (!U) - return false; - uint16_t Size = (Form == DW_FORM_addr) ? U->getAddressByteSize() - : U->getRefAddrByteSize(); + uint16_t Size = + (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize(); Value.uval = Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex); break; } @@ -360,10 +359,8 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, case DW_FORM_GNU_strp_alt: case DW_FORM_line_strp: case DW_FORM_strp_sup: { - if (!U) - return false; Value.uval = - Data.getRelocatedValue(U->getDwarfOffsetByteSize(), OffsetPtr); + Data.getRelocatedValue(FP.getDwarfOffsetByteSize(), OffsetPtr); break; } case DW_FORM_flag_present: diff --git a/llvm/test/DebugInfo/Inputs/dwarfdump-header.elf-x86-64 b/llvm/test/DebugInfo/Inputs/dwarfdump-header.elf-x86-64 index 21c1eacd0714..e65f34f2a216 100644 Binary files a/llvm/test/DebugInfo/Inputs/dwarfdump-header.elf-x86-64 and b/llvm/test/DebugInfo/Inputs/dwarfdump-header.elf-x86-64 differ diff --git a/llvm/test/DebugInfo/Inputs/dwarfdump-header.s b/llvm/test/DebugInfo/Inputs/dwarfdump-header.s index c5cf48597765..e068cb4d7b17 100644 --- a/llvm/test/DebugInfo/Inputs/dwarfdump-header.s +++ b/llvm/test/DebugInfo/Inputs/dwarfdump-header.s @@ -15,6 +15,10 @@ str_CU_5: .asciz "V5_compile_unit" str_TU_4: .asciz "V4_type_unit" +str_LT_5a: + .asciz "Directory5a" +str_LT_5b: + .asciz "Directory5b" .section .debug_str.dwo,"MS",@progbits,1 dwo_TU_5: @@ -227,11 +231,11 @@ LH_5_params: # 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 directories - .asciz "Directory5a" - .asciz "Directory5b" + .long str_LT_5a + .long str_LT_5b # File table format .byte 4 # Four elements per file entry .byte 1 # DW_LNCT_path diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp index 9fb968cb5d25..0fdc690dab4d 100644 --- a/llvm/tools/dsymutil/DwarfLinker.cpp +++ b/llvm/tools/dsymutil/DwarfLinker.cpp @@ -2366,7 +2366,7 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr, continue; } - Val.extractValue(Data, &Offset, &Unit); + Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit); CompileUnit *ReferencedCU; if (auto RefDie = resolveDIEReference(*this, Units, Val, Unit, Die, ReferencedCU)) { @@ -2965,7 +2965,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE( DWARFFormValue Val(AttrSpec.Form); uint32_t AttrSize = Offset; - Val.extractValue(Data, &Offset, &U); + Val.extractValue(Data, &Offset, U.getFormParams(), &U); AttrSize = Offset - AttrSize; OutOffset += @@ -3158,7 +3158,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, DWARFDataExtractor LineExtractor( OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(), OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize()); - LineTable.parse(LineExtractor, &StmtOffset); + LineTable.parse(LineExtractor, &StmtOffset, &Unit.getOrigUnit()); // This vector is the output line table. std::vector NewRows; diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp index f283ac0961cc..14550b9082b4 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp @@ -99,7 +99,7 @@ DWARFFormValue createDataXFormValue(dwarf::Form Form, RawTypeT Value) { DWARFFormValue Result(Form); DWARFDataExtractor Data(StringRef(Raw, sizeof(RawTypeT)), sys::IsLittleEndianHost, sizeof(void *)); - Result.extractValue(Data, &Offset, nullptr); + Result.extractValue(Data, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32}); return Result; } @@ -110,7 +110,7 @@ DWARFFormValue createULEBFormValue(uint64_t Value) { uint32_t Offset = 0; DWARFFormValue Result(DW_FORM_udata); DWARFDataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void *)); - Result.extractValue(Data, &Offset, nullptr); + Result.extractValue(Data, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32}); return Result; } @@ -121,7 +121,7 @@ DWARFFormValue createSLEBFormValue(int64_t Value) { uint32_t Offset = 0; DWARFFormValue Result(DW_FORM_sdata); DWARFDataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void *)); - Result.extractValue(Data, &Offset, nullptr); + Result.extractValue(Data, &Offset, {0, 0, dwarf::DwarfFormat::DWARF32}); return Result; }