diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/DebugInfo/DWARF | |
parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) |
Notes
Diffstat (limited to 'lib/DebugInfo/DWARF')
27 files changed, 850 insertions, 544 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index f49ab40fad9a..f4dd79937608 100644 --- a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -1,9 +1,8 @@ //===- DWARFAbbreviationDeclaration.cpp -----------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -164,11 +163,11 @@ Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue( for (const auto &Spec : AttributeSpecs) { if (*MatchAttrIndex == AttrIndex) { // We have arrived at the attribute to extract, extract if from Offset. + if (Spec.isImplicitConst()) + return DWARFFormValue::createFromSValue(Spec.Form, + Spec.getImplicitConstValue()); + DWARFFormValue FormValue(Spec.Form); - if (Spec.isImplicitConst()) { - FormValue.setSValue(Spec.getImplicitConstValue()); - return FormValue; - } if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U)) return FormValue; } diff --git a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index 54daf34ff253..0721efb40f6a 100644 --- a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -1,9 +1,8 @@ //===- DWARFAcceleratorTable.cpp ------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -42,7 +41,7 @@ static Atom formatAtom(unsigned Atom) { return {Atom}; } DWARFAcceleratorTable::~DWARFAcceleratorTable() = default; -llvm::Error AppleAcceleratorTable::extract() { +Error AppleAcceleratorTable::extract() { uint32_t Offset = 0; // Check that we can at least read the header. @@ -377,7 +376,7 @@ void DWARFDebugNames::Header::dump(ScopedPrinter &W) const { W.startLine() << "Augmentation: '" << AugmentationString << "'\n"; } -llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, +Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, uint32_t *Offset) { // Check that we can read the fixed-size part. if (!AS.isValidOffset(*Offset + sizeof(HeaderPOD) - 1)) @@ -519,6 +518,7 @@ Error DWARFDebugNames::NameIndex::extract() { "Duplicate abbreviation code."); } } + DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr) : NameIdx(&NameIdx), Abbr(&Abbr) { // This merely creates form values. It is up to the caller @@ -585,13 +585,14 @@ uint32_t DWARFDebugNames::NameIndex::getCUOffset(uint32_t CU) const { uint32_t DWARFDebugNames::NameIndex::getLocalTUOffset(uint32_t TU) const { assert(TU < Hdr.LocalTypeUnitCount); - uint32_t Offset = CUsBase + Hdr.CompUnitCount * 4; + uint32_t Offset = CUsBase + 4 * (Hdr.CompUnitCount + TU); return Section.AccelSection.getRelocatedValue(4, &Offset); } uint64_t DWARFDebugNames::NameIndex::getForeignTUSignature(uint32_t TU) const { assert(TU < Hdr.ForeignTypeUnitCount); - uint32_t Offset = CUsBase + (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) * 4; + uint32_t Offset = + CUsBase + 4 * (Hdr.CompUnitCount + Hdr.LocalTypeUnitCount) + 8 * TU; return Section.AccelSection.getU64(&Offset); } @@ -754,11 +755,11 @@ LLVM_DUMP_METHOD void DWARFDebugNames::NameIndex::dump(ScopedPrinter &W) const { dumpName(W, NTE, None); } -llvm::Error DWARFDebugNames::extract() { +Error DWARFDebugNames::extract() { uint32_t Offset = 0; while (AccelSection.isValidOffset(Offset)) { NameIndex Next(*this, Offset); - if (llvm::Error E = Next.extract()) + if (Error E = Next.extract()) return E; Offset = Next.getNextUnitOffset(); NameIndices.push_back(std::move(Next)); diff --git a/lib/DebugInfo/DWARF/DWARFAddressRange.cpp b/lib/DebugInfo/DWARF/DWARFAddressRange.cpp index 86c8d19c02f4..ef6da08d34aa 100644 --- a/lib/DebugInfo/DWARF/DWARFAddressRange.cpp +++ b/lib/DebugInfo/DWARF/DWARFAddressRange.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugAranges.cpp ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index 00a23b3898fa..74cce42466dd 100644 --- a/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -1,9 +1,8 @@ //===-- DWARFCompileUnit.cpp ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index e6620ee3dd1d..5ede9bf59619 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1,9 +1,8 @@ //===- DWARFContext.cpp ---------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -37,11 +36,12 @@ #include "llvm/Object/Decompressor.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Object/RelocVisitor.h" +#include "llvm/Object/RelocationResolver.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/TargetRegistry.h" @@ -102,7 +102,8 @@ static ContributionCollection collectContributionData(DWARFContext::unit_iterator_range Units) { ContributionCollection Contributions; for (const auto &U : Units) - Contributions.push_back(U->getStringOffsetsTableContribution()); + if (const auto &C = U->getStringOffsetsTableContribution()) + Contributions.push_back(C); // Sort the contributions so that any invalid ones are placed at // the start of the contributions vector. This way they are reported // first. @@ -158,9 +159,9 @@ static void dumpDWARFv5StringOffsetsSection( // Detect overlapping contributions. if (Offset > ContributionHeader) { - OS << "error: overlapping contributions to string offsets table in " - "section ." - << SectionName << ".\n"; + WithColor::error() + << "overlapping contributions to string offsets table in section ." + << SectionName << ".\n"; return; } // Report a gap in the table. @@ -269,11 +270,11 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, } // Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). -static void -dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData, - llvm::function_ref<Optional<SectionedAddress>(uint32_t)> - LookupPooledAddress, - DIDumpOptions DumpOpts) { +static void dumpRnglistsSection( + raw_ostream &OS, DWARFDataExtractor &rnglistData, + llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts) { uint32_t Offset = 0; while (rnglistData.isValidOffset(Offset)) { llvm::DWARFDebugRnglistTable Rnglists; @@ -926,6 +927,9 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { DWARFDie DIE = Worklist.back(); Worklist.pop_back(); + if (!DIE.isValid()) + continue; + if (DIE.getTag() == DW_TAG_lexical_block && DIE.addressRangeContainsAddress(Address)) { Result.BlockDIE = DIE; @@ -939,6 +943,8 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { return Result; } +/// TODO: change input parameter from "uint64_t Address" +/// into "SectionedAddress Address" static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind, @@ -967,36 +973,155 @@ static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, return FoundResult; } -DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, +static Optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) { + if (auto SizeAttr = Type.find(DW_AT_byte_size)) + if (Optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant()) + return Size; + + switch (Type.getTag()) { + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + return PointerSize; + case DW_TAG_ptr_to_member_type: { + if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) + if (BaseType.getTag() == DW_TAG_subroutine_type) + return 2 * PointerSize; + return PointerSize; + } + case DW_TAG_const_type: + case DW_TAG_volatile_type: + case DW_TAG_restrict_type: + case DW_TAG_typedef: { + if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) + return getTypeSize(BaseType, PointerSize); + break; + } + case DW_TAG_array_type: { + DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type); + if (!BaseType) + return Optional<uint64_t>(); + Optional<uint64_t> BaseSize = getTypeSize(BaseType, PointerSize); + if (!BaseSize) + return Optional<uint64_t>(); + uint64_t Size = *BaseSize; + for (DWARFDie Child : Type) { + if (Child.getTag() != DW_TAG_subrange_type) + continue; + + if (auto ElemCountAttr = Child.find(DW_AT_count)) + if (Optional<uint64_t> ElemCount = + ElemCountAttr->getAsUnsignedConstant()) + Size *= *ElemCount; + if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound)) + if (Optional<int64_t> UpperBound = + UpperBoundAttr->getAsSignedConstant()) { + int64_t LowerBound = 0; + if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound)) + LowerBound = LowerBoundAttr->getAsSignedConstant().getValueOr(0); + Size *= *UpperBound - LowerBound + 1; + } + } + return Size; + } + default: + break; + } + return Optional<uint64_t>(); +} + +void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, + DWARFDie Die, std::vector<DILocal> &Result) { + if (Die.getTag() == DW_TAG_variable || + Die.getTag() == DW_TAG_formal_parameter) { + DILocal Local; + if (auto NameAttr = Subprogram.find(DW_AT_name)) + if (Optional<const char *> Name = NameAttr->getAsCString()) + Local.FunctionName = *Name; + if (auto LocationAttr = Die.find(DW_AT_location)) + if (Optional<ArrayRef<uint8_t>> Location = LocationAttr->getAsBlock()) + if (!Location->empty() && (*Location)[0] == DW_OP_fbreg) + Local.FrameOffset = + decodeSLEB128(Location->data() + 1, nullptr, Location->end()); + if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset)) + Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant(); + + if (auto Origin = + Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) + Die = Origin; + if (auto NameAttr = Die.find(DW_AT_name)) + if (Optional<const char *> Name = NameAttr->getAsCString()) + Local.Name = *Name; + if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type)) + Local.Size = getTypeSize(Type, getCUAddrSize()); + if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) { + if (const auto *LT = CU->getContext().getLineTableForUnit(CU)) + LT->getFileNameByIndex( + DeclFileAttr->getAsUnsignedConstant().getValue(), + CU->getCompilationDir(), + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, + Local.DeclFile); + } + if (auto DeclLineAttr = Die.find(DW_AT_decl_line)) + Local.DeclLine = DeclLineAttr->getAsUnsignedConstant().getValue(); + + Result.push_back(Local); + return; + } + + if (Die.getTag() == DW_TAG_inlined_subroutine) + if (auto Origin = + Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) + Subprogram = Origin; + + for (auto Child : Die) + addLocalsForDie(CU, Subprogram, Child, Result); +} + +std::vector<DILocal> +DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { + std::vector<DILocal> Result; + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + + DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address); + if (Subprogram.isValid()) + addLocalsForDie(CU, Subprogram, Subprogram, Result); + return Result; +} + +DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Spec) { DILineInfo Result; - DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); if (!CU) return Result; - getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, - Result.FunctionName, - Result.StartLine); + + getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, + Result.FunctionName, Result.StartLine); if (Spec.FLIKind != FileLineInfoKind::None) { - if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), - Spec.FLIKind, Result); + if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) { + LineTable->getFileLineInfoForAddress( + {Address.Address, Address.SectionIndex}, CU->getCompilationDir(), + Spec.FLIKind, Result); + } } return Result; } -DILineInfoTable -DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, - DILineInfoSpecifier Spec) { +DILineInfoTable DWARFContext::getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) { DILineInfoTable Lines; - DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); if (!CU) return Lines; std::string FunctionName = "<invalid>"; uint32_t StartLine = 0; - getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, FunctionName, - StartLine); + getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, + FunctionName, StartLine); // If the Specifier says we don't need FileLineInfo, just // return the top-most function at the starting address. @@ -1004,7 +1129,7 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, DILineInfo Result; Result.FunctionName = FunctionName; Result.StartLine = StartLine; - Lines.push_back(std::make_pair(Address, Result)); + Lines.push_back(std::make_pair(Address.Address, Result)); return Lines; } @@ -1012,8 +1137,10 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, // Get the index of row we're looking for in the line table. std::vector<uint32_t> RowVector; - if (!LineTable->lookupAddressRange(Address, Size, RowVector)) + if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex}, + Size, RowVector)) { return Lines; + } for (uint32_t RowIndex : RowVector) { // Take file number and line/column from the row. @@ -1025,33 +1152,33 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, Result.Line = Row.Line; Result.Column = Row.Column; Result.StartLine = StartLine; - Lines.push_back(std::make_pair(Row.Address, Result)); + Lines.push_back(std::make_pair(Row.Address.Address, Result)); } return Lines; } DIInliningInfo -DWARFContext::getInliningInfoForAddress(uint64_t Address, +DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Spec) { DIInliningInfo InliningInfo; - DWARFCompileUnit *CU = getCompileUnitForAddress(Address); + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); if (!CU) return InliningInfo; const DWARFLineTable *LineTable = nullptr; SmallVector<DWARFDie, 4> InlinedChain; - CU->getInlinedChainForAddress(Address, InlinedChain); + CU->getInlinedChainForAddress(Address.Address, InlinedChain); if (InlinedChain.size() == 0) { // If there is no DIE for address (e.g. it is in unavailable .dwo file), // try to at least get file/line info from symbol table. if (Spec.FLIKind != FileLineInfoKind::None) { DILineInfo Frame; LineTable = getLineTableForUnit(CU); - if (LineTable && - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), - Spec.FLIKind, Frame)) + if (LineTable && LineTable->getFileLineInfoForAddress( + {Address.Address, Address.SectionIndex}, + CU->getCompilationDir(), Spec.FLIKind, Frame)) InliningInfo.addFrame(Frame); } return InliningInfo; @@ -1073,8 +1200,9 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address, LineTable = getLineTableForUnit(CU); // For the topmost routine, get file/line info from line table. if (LineTable) - LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(), - Spec.FLIKind, Frame); + LineTable->getFileLineInfoForAddress( + {Address.Address, Address.SectionIndex}, CU->getCompilationDir(), + Spec.FLIKind, Frame); } else { // Otherwise, use call file, call line and call column from // previous DIE in inlined chain. @@ -1402,8 +1530,14 @@ public: // Try to obtain an already relocated version of this section. // Else use the unrelocated section from the object file. We'll have to // apply relocations ourselves later. - if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) - Section.getContents(Data); + if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) { + Expected<StringRef> E = Section.getContents(); + if (E) + Data = *E; + else + // maybeDecompress below will error. + consumeError(E.takeError()); + } if (auto Err = maybeDecompress(Section, Name, Data)) { ErrorPolicy EP = HandleError(createError( @@ -1495,6 +1629,9 @@ public: // Symbol to [address, section index] cache mapping. std::map<SymbolRef, SymInfo> AddrCache; + bool (*Supports)(uint64_t); + RelocationResolver Resolver; + std::tie(Supports, Resolver) = getRelocationResolver(Obj); for (const RelocationRef &Reloc : Section.relocations()) { // FIXME: it's not clear how to correctly handle scattered // relocations. @@ -1509,9 +1646,31 @@ public: continue; } - object::RelocVisitor V(Obj); - uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); - if (V.error()) { + // Check if Resolver can handle this relocation type early so as not to + // handle invalid cases in DWARFDataExtractor. + // + // TODO Don't store Resolver in every RelocAddrEntry. + if (Supports && Supports(Reloc.getType())) { + auto I = Map->try_emplace( + Reloc.getOffset(), + RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc, + SymInfoOrErr->Address, + Optional<object::RelocationRef>(), 0, Resolver}); + // If we didn't successfully insert that's because we already had a + // relocation for that offset. Store it as a second relocation in the + // same RelocAddrEntry instead. + if (!I.second) { + RelocAddrEntry &entry = I.first->getSecond(); + if (entry.Reloc2) { + ErrorPolicy EP = HandleError(createError( + "At most two relocations per offset are supported")); + if (EP == ErrorPolicy::Halt) + return; + } + entry.Reloc2 = Reloc; + entry.SymbolValue2 = SymInfoOrErr->Address; + } + } else { SmallString<32> Type; Reloc.getTypeName(Type); ErrorPolicy EP = HandleError( @@ -1519,10 +1678,7 @@ public: errorCodeToError(object_error::parse_failed))); if (EP == ErrorPolicy::Halt) return; - continue; } - RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; - Map->insert({Reloc.getOffset(), Rel}); } } diff --git a/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp index 03e317461396..b9adf8cb1d99 100644 --- a/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -1,9 +1,8 @@ //===- DWARFDataExtractor.cpp ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -16,15 +15,19 @@ using namespace llvm; uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, uint64_t *SecNdx) const { if (SecNdx) - *SecNdx = -1ULL; + *SecNdx = object::SectionedAddress::UndefSection; if (!Section) return getUnsigned(Off, Size); - Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off); - if (!Rel) - return getUnsigned(Off, Size); + Optional<RelocAddrEntry> E = Obj->find(*Section, *Off); + uint64_t A = getUnsigned(Off, Size); + if (!E) + return A; if (SecNdx) - *SecNdx = Rel->SectionIndex; - return getUnsigned(Off, Size) + Rel->Value; + *SecNdx = E->SectionIndex; + uint64_t R = E->Resolver(E->Reloc, E->SymbolValue, A); + if (E->Reloc2) + R = E->Resolver(*E->Reloc2, E->SymbolValue2, R); + return R; } Optional<uint64_t> diff --git a/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp index 4830c36a8ee7..31b324e5eb27 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugAbbrev.cpp -----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -84,12 +83,12 @@ void DWARFDebugAbbrev::parse() const { if (!Data) return; uint32_t Offset = 0; - DWARFAbbreviationDeclarationSet AbbrDecls; auto I = AbbrDeclSets.begin(); while (Data->isValidOffset(Offset)) { while (I != AbbrDeclSets.end() && I->first < Offset) ++I; uint32_t CUAbbrOffset = Offset; + DWARFAbbreviationDeclarationSet AbbrDecls; if (!AbbrDecls.extract(*Data, &Offset)) break; AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls))); diff --git a/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp b/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp index 22759bfac26c..58626539bba4 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugAddr.cpp -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -148,28 +147,13 @@ void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { HeaderData.Length, HeaderData.Version, HeaderData.AddrSize, HeaderData.SegSize); - static const char *Fmt32 = "0x%8.8" PRIx64; - static const char *Fmt64 = "0x%16.16" PRIx64; - std::string AddrFmt = "\n"; - std::string AddrFmtVerbose = " => "; - if (HeaderData.AddrSize == 4) { - AddrFmt.append(Fmt32); - AddrFmtVerbose.append(Fmt32); - } - else { - AddrFmt.append(Fmt64); - AddrFmtVerbose.append(Fmt64); - } - if (Addrs.size() > 0) { - OS << "Addrs: ["; - for (uint64_t Addr : Addrs) { - OS << format(AddrFmt.c_str(), Addr); - if (DumpOpts.Verbose) - OS << format(AddrFmtVerbose.c_str(), - Addr + HeaderOffset + sizeof(HeaderData)); - } - OS << "\n]\n"; + const char *AddrFmt = (HeaderData.AddrSize == 4) ? "0x%8.8" PRIx64 "\n" + : "0x%16.16" PRIx64 "\n"; + OS << "Addrs: [\n"; + for (uint64_t Addr : Addrs) + OS << format(AddrFmt, Addr); + OS << "]\n"; } } diff --git a/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp index b9ef6905912a..6551b61accb8 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugArangeSet.cpp --------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp index e8c5dec821b4..6460c9feeab8 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugAranges.cpp ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -115,20 +114,9 @@ void DWARFDebugAranges::construct() { } uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const { - if (!Aranges.empty()) { - Range range(Address); - RangeCollIterator begin = Aranges.begin(); - RangeCollIterator end = Aranges.end(); - RangeCollIterator pos = - std::lower_bound(begin, end, range); - - if (pos != end && pos->containsAddress(Address)) { - return pos->CUOffset; - } else if (pos != begin) { - --pos; - if (pos->containsAddress(Address)) - return pos->CUOffset; - } - } + RangeCollIterator It = + partition_point(Aranges, [=](Range R) { return R.HighPC() <= Address; }); + if (It != Aranges.end() && It->LowPC <= Address) + return It->CUOffset; return -1U; } diff --git a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index ba55ffc28174..b3f23366f2a2 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -267,7 +266,7 @@ void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, case OT_Expression: assert(Instr.Expression && "missing DWARFExpression object"); OS << " "; - Instr.Expression->print(OS, MRI, IsEH); + Instr.Expression->print(OS, MRI, nullptr, IsEH); break; } } @@ -301,7 +300,7 @@ void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor); OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister); if (Personality) - OS << format(" Personality Address: %08x\n", *Personality); + OS << format(" Personality Address: %016" PRIx64 "\n", *Personality); if (!AugmentationData.empty()) { OS << " Augmentation data: "; for (uint8_t Byte : AugmentationData) @@ -320,7 +319,7 @@ void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { (uint32_t)InitialLocation, (uint32_t)InitialLocation + (uint32_t)AddressRange); if (LSDAAddress) - OS << format(" LSDA Address: %08x\n", *LSDAAddress); + OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); CFIs.dump(OS, MRI, IsEH); OS << "\n"; } @@ -533,10 +532,9 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { } FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { - auto It = - std::lower_bound(Entries.begin(), Entries.end(), Offset, - [](const std::unique_ptr<FrameEntry> &E, - uint64_t Offset) { return E->getOffset() < Offset; }); + auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) { + return E->getOffset() < Offset; + }); if (It != Entries.end() && (*It)->getOffset() == Offset) return It->get(); return nullptr; diff --git a/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index 976bc4651ae6..d8a755e90df4 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugInfoEntry.cpp --------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 1d621ff244f3..a1cb1e8582ed 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugLine.cpp -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -67,6 +66,26 @@ void DWARFDebugLine::ContentTypeTracker::trackContentType( DWARFDebugLine::Prologue::Prologue() { clear(); } +bool DWARFDebugLine::Prologue::hasFileAtIndex(uint64_t FileIndex) const { + uint16_t DwarfVersion = getVersion(); + assert(DwarfVersion != 0 && + "line table prologue has no dwarf version information"); + if (DwarfVersion >= 5) + return FileIndex < FileNames.size(); + return FileIndex != 0 && FileIndex <= FileNames.size(); +} + +const llvm::DWARFDebugLine::FileNameEntry & +DWARFDebugLine::Prologue::getFileNameEntry(uint64_t Index) const { + uint16_t DwarfVersion = getVersion(); + assert(DwarfVersion != 0 && + "line table prologue has no dwarf version information"); + // In DWARF v5 the file names are 0-indexed. + if (DwarfVersion >= 5) + return FileNames[Index]; + return FileNames[Index - 1]; +} + void DWARFDebugLine::Prologue::clear() { TotalLength = PrologueLength = 0; SegSelectorSize = 0; @@ -145,8 +164,8 @@ parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, StringRef S = DebugLineData.getCStrRef(OffsetPtr); if (S.empty()) break; - DWARFFormValue Dir(dwarf::DW_FORM_string); - Dir.setPValue(S.data()); + DWARFFormValue Dir = + DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, S.data()); IncludeDirectories.push_back(Dir); } @@ -155,8 +174,8 @@ parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, if (Name.empty()) break; DWARFDebugLine::FileNameEntry FileEntry; - FileEntry.Name.setForm(dwarf::DW_FORM_string); - FileEntry.Name.setPValue(Name.data()); + FileEntry.Name = + DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name.data()); FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr); FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr); FileEntry.Length = DebugLineData.getULEB128(OffsetPtr); @@ -281,11 +300,11 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, const uint64_t PrologueOffset = *OffsetPtr; clear(); - TotalLength = DebugLineData.getU32(OffsetPtr); + TotalLength = DebugLineData.getRelocatedValue(4, OffsetPtr); if (TotalLength == UINT32_MAX) { FormParams.Format = dwarf::DWARF64; TotalLength = DebugLineData.getU64(OffsetPtr); - } else if (TotalLength >= 0xffffff00) { + } else if (TotalLength >= 0xfffffff0) { return createStringError(errc::invalid_argument, "parsing line table prologue at offset 0x%8.8" PRIx64 " unsupported reserved unit length found of value 0x%8.8" PRIx64, @@ -306,7 +325,8 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, SegSelectorSize = DebugLineData.getU8(OffsetPtr); } - PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength()); + PrologueLength = + DebugLineData.getRelocatedValue(sizeofPrologueLength(), OffsetPtr); const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr; MinInstLength = DebugLineData.getU8(OffsetPtr); if (getVersion() >= 4) @@ -348,13 +368,15 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); } void DWARFDebugLine::Row::postAppend() { + Discriminator = 0; BasicBlock = false; PrologueEnd = false; EpilogueBegin = false; } void DWARFDebugLine::Row::reset(bool DefaultIsStmt) { - Address = 0; + Address.Address = 0; + Address.SectionIndex = object::SectionedAddress::UndefSection; Line = 1; Column = 0; File = 1; @@ -374,7 +396,7 @@ void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) { } void DWARFDebugLine::Row::dump(raw_ostream &OS) const { - OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column) + OS << format("0x%16.16" PRIx64 " %6u %6u", Address.Address, Line, Column) << format(" %6u %3u %13u ", File, Isa, Discriminator) << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "") << (PrologueEnd ? " prologue_end" : "") @@ -387,6 +409,7 @@ DWARFDebugLine::Sequence::Sequence() { reset(); } void DWARFDebugLine::Sequence::reset() { LowPC = 0; HighPC = 0; + SectionIndex = object::SectionedAddress::UndefSection; FirstRowIndex = 0; LastRowIndex = 0; Empty = true; @@ -423,19 +446,20 @@ void DWARFDebugLine::ParsingState::resetRowAndSequence() { Sequence.reset(); } -void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t Offset) { +void DWARFDebugLine::ParsingState::appendRowToMatrix() { + unsigned RowNumber = LineTable->Rows.size(); if (Sequence.Empty) { // Record the beginning of instruction sequence. Sequence.Empty = false; - Sequence.LowPC = Row.Address; + Sequence.LowPC = Row.Address.Address; Sequence.FirstRowIndex = RowNumber; } - ++RowNumber; LineTable->appendRow(Row); if (Row.EndSequence) { // Record the end of instruction sequence. - Sequence.HighPC = Row.Address; - Sequence.LastRowIndex = RowNumber; + Sequence.HighPC = Row.Address.Address; + Sequence.LastRowIndex = RowNumber + 1; + Sequence.SectionIndex = Row.Address.SectionIndex; if (Sequence.isValid()) LineTable->appendSequence(Sequence); Sequence.reset(); @@ -538,7 +562,7 @@ Error DWARFDebugLine::LineTable::parse( // address is that of the byte after the last target machine instruction // of the sequence. State.Row.EndSequence = true; - State.appendRowToMatrix(*OffsetPtr); + State.appendRowToMatrix(); if (OS) { *OS << "\n"; OS->indent(12); @@ -566,9 +590,10 @@ Error DWARFDebugLine::LineTable::parse( ExtOffset, DebugLineData.getAddressSize(), Len - 1); } - State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr); + State.Row.Address.Address = DebugLineData.getRelocatedAddress( + OffsetPtr, &State.Row.Address.SectionIndex); if (OS) - *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address); + *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address.Address); break; case DW_LNE_define_file: @@ -595,8 +620,8 @@ Error DWARFDebugLine::LineTable::parse( { FileNameEntry FileEntry; const char *Name = DebugLineData.getCStr(OffsetPtr); - FileEntry.Name.setForm(dwarf::DW_FORM_string); - FileEntry.Name.setPValue(Name); + FileEntry.Name = + DWARFFormValue::createFromPValue(dwarf::DW_FORM_string, Name); FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr); FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr); FileEntry.Length = DebugLineData.getULEB128(OffsetPtr); @@ -637,15 +662,14 @@ Error DWARFDebugLine::LineTable::parse( // Standard Opcodes case DW_LNS_copy: // Takes no arguments. Append a row to the matrix using the - // current values of the state-machine registers. Then set - // the basic_block register to false. - State.appendRowToMatrix(*OffsetPtr); + // current values of the state-machine registers. if (OS) { *OS << "\n"; OS->indent(12); State.Row.dump(*OS); *OS << "\n"; } + State.appendRowToMatrix(); break; case DW_LNS_advance_pc: @@ -655,7 +679,7 @@ Error DWARFDebugLine::LineTable::parse( { uint64_t AddrOffset = DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength; - State.Row.Address += AddrOffset; + State.Row.Address.Address += AddrOffset; if (OS) *OS << " (" << AddrOffset << ")"; } @@ -713,7 +737,7 @@ Error DWARFDebugLine::LineTable::parse( uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase; uint64_t AddrOffset = (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength; - State.Row.Address += AddrOffset; + State.Row.Address.Address += AddrOffset; if (OS) *OS << format(" (0x%16.16" PRIx64 ")", AddrOffset); @@ -731,11 +755,11 @@ Error DWARFDebugLine::LineTable::parse( // requires the use of DW_LNS_advance_pc. Such assemblers, however, // can use DW_LNS_fixed_advance_pc instead, sacrificing compression. { - uint16_t PCOffset = DebugLineData.getU16(OffsetPtr); - State.Row.Address += PCOffset; + uint16_t PCOffset = DebugLineData.getRelocatedValue(2, OffsetPtr); + State.Row.Address.Address += PCOffset; if (OS) *OS - << format(" (0x%16.16" PRIx64 ")", PCOffset); + << format(" (0x%4.4" PRIx16 ")", PCOffset); } break; @@ -815,18 +839,16 @@ Error DWARFDebugLine::LineTable::parse( int32_t LineOffset = Prologue.LineBase + (AdjustOpcode % Prologue.LineRange); State.Row.Line += LineOffset; - State.Row.Address += AddrOffset; + State.Row.Address.Address += AddrOffset; if (OS) { - *OS << "address += " << ((uint32_t)AdjustOpcode) - << ", line += " << LineOffset << "\n"; + *OS << "address += " << AddrOffset << ", line += " << LineOffset + << "\n"; OS->indent(12); State.Row.dump(*OS); } - State.appendRowToMatrix(*OffsetPtr); - // Reset discriminator to 0. - State.Row.Discriminator = 0; + State.appendRowToMatrix(); } if(OS) *OS << "\n"; @@ -839,7 +861,7 @@ Error DWARFDebugLine::LineTable::parse( // Sort all sequences so that address lookup will work faster. if (!Sequences.empty()) { - llvm::sort(Sequences, Sequence::orderByLowPC); + llvm::sort(Sequences, Sequence::orderByHighPC); // Note: actually, instruction address ranges of sequences should not // overlap (in shared objects and executables). If they do, the address // lookup would still work, though, but result would be ambiguous. @@ -851,74 +873,88 @@ Error DWARFDebugLine::LineTable::parse( return Error::success(); } -uint32_t -DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq, - uint64_t Address) const { +uint32_t DWARFDebugLine::LineTable::findRowInSeq( + const DWARFDebugLine::Sequence &Seq, + object::SectionedAddress Address) const { if (!Seq.containsPC(Address)) return UnknownRowIndex; - // Search for instruction address in the rows describing the sequence. - // Rows are stored in a vector, so we may use arithmetical operations with - // iterators. + assert(Seq.SectionIndex == Address.SectionIndex); + // In some cases, e.g. first instruction in a function, the compiler generates + // two entries, both with the same address. We want the last one. + // + // In general we want a non-empty range: the last row whose address is less + // than or equal to Address. This can be computed as upper_bound - 1. DWARFDebugLine::Row Row; Row.Address = Address; RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex; RowIter LastRow = Rows.begin() + Seq.LastRowIndex; - LineTable::RowIter RowPos = std::lower_bound( - FirstRow, LastRow, Row, DWARFDebugLine::Row::orderByAddress); - if (RowPos == LastRow) { - return Seq.LastRowIndex - 1; - } - uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow); - if (RowPos->Address > Address) { - if (RowPos == FirstRow) - return UnknownRowIndex; - else - Index--; - } - return Index; + assert(FirstRow->Address.Address <= Row.Address.Address && + Row.Address.Address < LastRow[-1].Address.Address); + RowIter RowPos = std::upper_bound(FirstRow + 1, LastRow - 1, Row, + DWARFDebugLine::Row::orderByAddress) - + 1; + assert(Seq.SectionIndex == RowPos->Address.SectionIndex); + return RowPos - Rows.begin(); } -uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const { - if (Sequences.empty()) - return UnknownRowIndex; +uint32_t DWARFDebugLine::LineTable::lookupAddress( + object::SectionedAddress Address) const { + + // Search for relocatable addresses + uint32_t Result = lookupAddressImpl(Address); + + if (Result != UnknownRowIndex || + Address.SectionIndex == object::SectionedAddress::UndefSection) + return Result; + + // Search for absolute addresses + Address.SectionIndex = object::SectionedAddress::UndefSection; + return lookupAddressImpl(Address); +} + +uint32_t DWARFDebugLine::LineTable::lookupAddressImpl( + object::SectionedAddress Address) const { // First, find an instruction sequence containing the given address. DWARFDebugLine::Sequence Sequence; - Sequence.LowPC = Address; - SequenceIter FirstSeq = Sequences.begin(); - SequenceIter LastSeq = Sequences.end(); - SequenceIter SeqPos = std::lower_bound( - FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC); - DWARFDebugLine::Sequence FoundSeq; - if (SeqPos == LastSeq) { - FoundSeq = Sequences.back(); - } else if (SeqPos->LowPC == Address) { - FoundSeq = *SeqPos; - } else { - if (SeqPos == FirstSeq) - return UnknownRowIndex; - FoundSeq = *(SeqPos - 1); - } - return findRowInSeq(FoundSeq, Address); + Sequence.SectionIndex = Address.SectionIndex; + Sequence.HighPC = Address.Address; + SequenceIter It = llvm::upper_bound(Sequences, Sequence, + DWARFDebugLine::Sequence::orderByHighPC); + if (It == Sequences.end() || It->SectionIndex != Address.SectionIndex) + return UnknownRowIndex; + return findRowInSeq(*It, Address); } bool DWARFDebugLine::LineTable::lookupAddressRange( - uint64_t Address, uint64_t Size, std::vector<uint32_t> &Result) const { + object::SectionedAddress Address, uint64_t Size, + std::vector<uint32_t> &Result) const { + + // Search for relocatable addresses + if (lookupAddressRangeImpl(Address, Size, Result)) + return true; + + if (Address.SectionIndex == object::SectionedAddress::UndefSection) + return false; + + // Search for absolute addresses + Address.SectionIndex = object::SectionedAddress::UndefSection; + return lookupAddressRangeImpl(Address, Size, Result); +} + +bool DWARFDebugLine::LineTable::lookupAddressRangeImpl( + object::SectionedAddress Address, uint64_t Size, + std::vector<uint32_t> &Result) const { if (Sequences.empty()) return false; - uint64_t EndAddr = Address + Size; + uint64_t EndAddr = Address.Address + Size; // First, find an instruction sequence containing the given address. DWARFDebugLine::Sequence Sequence; - Sequence.LowPC = Address; - SequenceIter FirstSeq = Sequences.begin(); + Sequence.SectionIndex = Address.SectionIndex; + Sequence.HighPC = Address.Address; SequenceIter LastSeq = Sequences.end(); - SequenceIter SeqPos = std::lower_bound( - FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC); - if (SeqPos == LastSeq || SeqPos->LowPC != Address) { - if (SeqPos == FirstSeq) - return false; - SeqPos--; - } - if (!SeqPos->containsPC(Address)) + SequenceIter SeqPos = llvm::upper_bound( + Sequences, Sequence, DWARFDebugLine::Sequence::orderByHighPC); + if (SeqPos == LastSeq || !SeqPos->containsPC(Address)) return false; SequenceIter StartPos = SeqPos; @@ -935,7 +971,8 @@ bool DWARFDebugLine::LineTable::lookupAddressRange( FirstRowIndex = findRowInSeq(CurSeq, Address); // Figure out the last row in the range. - uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1); + uint32_t LastRowIndex = + findRowInSeq(CurSeq, {EndAddr - 1, Address.SectionIndex}); if (LastRowIndex == UnknownRowIndex) LastRowIndex = CurSeq.LastRowIndex - 1; @@ -952,15 +989,11 @@ bool DWARFDebugLine::LineTable::lookupAddressRange( return true; } -bool DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const { - return FileIndex != 0 && FileIndex <= Prologue.FileNames.size(); -} - Optional<StringRef> DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex, FileLineInfoKind Kind) const { - if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex)) + if (Kind == FileLineInfoKind::None || !Prologue.hasFileAtIndex(FileIndex)) return None; - const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; + const FileNameEntry &Entry = Prologue.getFileNameEntry(FileIndex); if (Optional<const char *> source = Entry.Source.getAsCString()) return StringRef(*source); return None; @@ -974,13 +1007,13 @@ static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) { sys::path::is_absolute(Path, sys::path::Style::windows); } -bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, - const char *CompDir, - FileLineInfoKind Kind, - std::string &Result) const { +bool DWARFDebugLine::Prologue::getFileNameByIndex(uint64_t FileIndex, + StringRef CompDir, + FileLineInfoKind Kind, + std::string &Result) const { if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex)) return false; - const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; + const FileNameEntry &Entry = getFileNameEntry(FileIndex); StringRef FileName = Entry.Name.getAsCString().getValue(); if (Kind != FileLineInfoKind::AbsoluteFilePath || isPathAbsoluteOnWindowsOrPosix(FileName)) { @@ -989,21 +1022,22 @@ bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, } SmallString<16> FilePath; - uint64_t IncludeDirIndex = Entry.DirIdx; StringRef IncludeDir; // Be defensive about the contents of Entry. - if (IncludeDirIndex > 0 && - IncludeDirIndex <= Prologue.IncludeDirectories.size()) - IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 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 && Kind == FileLineInfoKind::AbsoluteFilePath && - !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) - sys::path::append(FilePath, CompDir); + if (getVersion() >= 5) { + if (Entry.DirIdx < IncludeDirectories.size()) + IncludeDir = IncludeDirectories[Entry.DirIdx].getAsCString().getValue(); + } else { + if (0 < Entry.DirIdx && Entry.DirIdx <= IncludeDirectories.size()) + 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)) + sys::path::append(FilePath, CompDir); + } // sys::path::append skips empty strings. sys::path::append(FilePath, IncludeDir, FileName); @@ -1012,8 +1046,8 @@ bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, } bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( - uint64_t Address, const char *CompDir, FileLineInfoKind Kind, - DILineInfo &Result) const { + object::SectionedAddress Address, const char *CompDir, + FileLineInfoKind Kind, DILineInfo &Result) const { // Get the index of row we're looking for in the line table. uint32_t RowIndex = lookupAddress(Address); if (RowIndex == -1U) @@ -1058,7 +1092,7 @@ DWARFDebugLine::SectionParser::SectionParser(DWARFDataExtractor &Data, } bool DWARFDebugLine::Prologue::totalLengthIsValid() const { - return TotalLength == 0xffffffff || TotalLength < 0xffffff00; + return TotalLength == 0xffffffff || TotalLength < 0xfffffff0; } DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext( diff --git a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index f8b5ff6ec8fb..6d8f4bee77c4 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugLoc.cpp --------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -31,15 +30,16 @@ using namespace llvm; // non-LLVM tools. static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data, bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *MRI) { + const MCRegisterInfo *MRI, DWARFUnit *U) { DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()), IsLittleEndian, AddressSize); - DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI); + DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U); } void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, + DWARFUnit *U, uint64_t BaseAddress, unsigned Indent) const { for (const Entry &E : Entries) { @@ -51,15 +51,14 @@ void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, BaseAddress + E.End); OS << ": "; - dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI); + dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U); } } DWARFDebugLoc::LocationList const * DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { - auto It = std::lower_bound( - Locations.begin(), Locations.end(), Offset, - [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; }); + auto It = partition_point( + Locations, [=](const LocationList &L) { return L.Offset < Offset; }); if (It != Locations.end() && It->Offset == Offset) return &(*It); return nullptr; @@ -69,7 +68,7 @@ void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, Optional<uint64_t> Offset) const { auto DumpLocationList = [&](const LocationList &L) { OS << format("0x%8.8x: ", L.Offset); - L.dump(OS, IsLittleEndian, AddressSize, MRI, 0, 12); + L.dump(OS, IsLittleEndian, AddressSize, MRI, nullptr, 0, 12); OS << "\n\n"; }; @@ -184,7 +183,8 @@ DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset, } if (Kind != dwarf::DW_LLE_base_address) { - unsigned Bytes = Data.getU16(Offset); + unsigned Bytes = + Version >= 5 ? Data.getULEB128(Offset) : Data.getU16(Offset); // A single location description describing the location of the object... StringRef str = Data.getData().substr(*Offset, Bytes); *Offset += Bytes; @@ -212,9 +212,8 @@ void DWARFDebugLoclists::parse(DataExtractor data, unsigned Version) { DWARFDebugLoclists::LocationList const * DWARFDebugLoclists::getLocationListAtOffset(uint64_t Offset) const { - auto It = std::lower_bound( - Locations.begin(), Locations.end(), Offset, - [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; }); + auto It = partition_point( + Locations, [=](const LocationList &L) { return L.Offset < Offset; }); if (It != Locations.end() && It->Offset == Offset) return &(*It); return nullptr; @@ -224,6 +223,7 @@ void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, + DWARFUnit *U, unsigned Indent) const { for (const Entry &E : Entries) { switch (E.Kind) { @@ -253,7 +253,7 @@ void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr, llvm_unreachable("unreachable locations list kind"); } - dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI); + dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U); } } @@ -262,7 +262,7 @@ void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr, Optional<uint64_t> Offset) const { auto DumpLocationList = [&](const LocationList &L) { OS << format("0x%8.8x: ", L.Offset); - L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, /*Indent=*/12); + L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, nullptr, /*Indent=*/12); OS << "\n\n"; }; diff --git a/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp b/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp index 6d789c3027a5..3317a778cc70 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugMacro.cpp ------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp b/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp index abd1ad59a9c1..963ec64f5e91 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugPubTable.cpp ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp index dfb913000a46..d8df81a0aa0b 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugRangesList.cpp -------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -69,7 +68,7 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const { } DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( - llvm::Optional<SectionedAddress> BaseAddr) const { + llvm::Optional<object::SectionedAddress> BaseAddr) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.isBaseAddressSelectionEntry(AddressSize)) { diff --git a/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp index 60c6eb30857f..5ac3326f6681 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -1,9 +1,8 @@ //===- DWARFDebugRnglists.cpp ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -113,9 +112,8 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, return Error::success(); } -DWARFAddressRangesVector -DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, - DWARFUnit &U) const { +DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( + llvm::Optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) @@ -175,7 +173,7 @@ DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, void RangeListEntry::dump( raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, - llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> LookupPooledAddress) const { auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, uint8_t AddrSize, DIDumpOptions DumpOpts) { @@ -203,7 +201,6 @@ void RangeListEntry::dump( case dwarf::DW_RLE_end_of_list: OS << (DumpOpts.Verbose ? "" : "<End of list>"); break; - // case dwarf::DW_RLE_base_addressx: case dwarf::DW_RLE_base_addressx: { if (auto SA = LookupPooledAddress(Value0)) CurrentBase = SA->Address; @@ -240,7 +237,7 @@ void RangeListEntry::dump( Start = SA->Address; DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); break; - } break; + } default: llvm_unreachable("Unsupported range list encoding"); } diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp index 81ef0c8c7aec..d638dc4239f4 100644 --- a/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -1,9 +1,8 @@ //===- DWARFDie.cpp -------------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -87,7 +86,7 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), Ctx.isLittleEndian(), 0); DWARFExpression(Data, U->getVersion(), U->getAddressByteSize()) - .print(OS, MRI); + .print(OS, MRI, U); return; } @@ -101,10 +100,10 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, auto LL = DebugLoc.parseOneLocationList(Data, &Offset); if (LL) { uint64_t BaseAddr = 0; - if (Optional<SectionedAddress> BA = U->getBaseAddress()) + if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) BaseAddr = BA->Address; - LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, BaseAddr, - Indent); + LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, + BaseAddr, Indent); } else OS << "error extracting location list."; return; @@ -126,12 +125,12 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, Data, &Offset, UseLocLists ? U->getVersion() : 4); uint64_t BaseAddr = 0; - if (Optional<SectionedAddress> BA = U->getBaseAddress()) + if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) BaseAddr = BA->Address; if (LL) LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, - Indent); + U, Indent); else OS << "error extracting location list."; } @@ -279,11 +278,7 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, OS << formatv(" [{0}]", Form); DWARFUnit *U = Die.getDwarfUnit(); - DWARFFormValue formValue(Form); - - if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, - U->getFormParams(), U)) - return; + DWARFFormValue FormValue = DWARFFormValue::createFromUnit(Form, U, OffsetPtr); OS << "\t("; @@ -294,35 +289,33 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, Color = HighlightColor::String; if (const auto *LT = U->getContext().getLineTableForUnit(U)) if (LT->getFileNameByIndex( - formValue.getAsUnsignedConstant().getValue(), + FormValue.getAsUnsignedConstant().getValue(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { File = '"' + File + '"'; Name = File; } - } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant()) + } else if (Optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) Name = AttributeValueString(Attr, *Val); if (!Name.empty()) WithColor(OS, Color) << Name; else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) - OS << *formValue.getAsUnsignedConstant(); + OS << *FormValue.getAsUnsignedConstant(); else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose && - formValue.getAsUnsignedConstant()) { + FormValue.getAsUnsignedConstant()) { if (DumpOpts.ShowAddresses) { // Print the actual address rather than the offset. uint64_t LowPC, HighPC, Index; if (Die.getLowAndHighPC(LowPC, HighPC, Index)) OS << format("0x%016" PRIx64, HighPC); else - formValue.dump(OS, DumpOpts); + FormValue.dump(OS, DumpOpts); } - } else if (Attr == DW_AT_location || Attr == DW_AT_frame_base || - Attr == DW_AT_data_member_location || - Attr == DW_AT_GNU_call_site_value) - dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); + } else if (DWARFAttribute::mayHaveLocationDescription(Attr)) + dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); else - formValue.dump(OS, DumpOpts); + FormValue.dump(OS, DumpOpts); std::string Space = DumpOpts.ShowAddresses ? " " : ""; @@ -331,25 +324,25 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, // interesting. These attributes are handled below. if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { if (const char *Name = - Die.getAttributeValueAsReferencedDie(formValue).getName( + Die.getAttributeValueAsReferencedDie(FormValue).getName( DINameKind::LinkageName)) OS << Space << "\"" << Name << '\"'; } else if (Attr == DW_AT_type) { OS << Space << "\""; - dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(formValue)); + dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(FormValue)); OS << '"'; } else if (Attr == DW_AT_APPLE_property_attribute) { - if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) + if (Optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant()) dumpApplePropertyAttribute(OS, *OptVal); } else if (Attr == DW_AT_ranges) { const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); // For DW_FORM_rnglistx we need to dump the offset separately, since // we have only dumped the index so far. - if (formValue.getForm() == DW_FORM_rnglistx) + if (FormValue.getForm() == DW_FORM_rnglistx) if (auto RangeListOffset = - U->getRnglistOffset(*formValue.getAsSectionOffset())) { - DWARFFormValue FV(dwarf::DW_FORM_sec_offset); - FV.setUValue(*RangeListOffset); + U->getRnglistOffset(*FormValue.getAsSectionOffset())) { + DWARFFormValue FV = DWARFFormValue::createFromUValue( + dwarf::DW_FORM_sec_offset, *RangeListOffset); FV.dump(OS, DumpOpts); } if (auto RangesOrError = Die.getAddressRanges()) @@ -403,6 +396,7 @@ DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { // DWARF. This corresponds to following the DW_AT_abstract_origin and // DW_AT_specification just once. SmallSet<DWARFDie, 3> Seen; + Seen.insert(*this); while (!Worklist.empty()) { DWARFDie Die = Worklist.back(); @@ -411,19 +405,16 @@ DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { if (!Die.isValid()) continue; - if (Seen.count(Die)) - continue; - - Seen.insert(Die); - if (auto Value = Die.find(Attrs)) return Value; if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) - Worklist.push_back(D); + if (Seen.insert(D).second) + Worklist.push_back(D); if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) - Worklist.push_back(D); + if (Seen.insert(D).second) + Worklist.push_back(D); } return None; @@ -438,9 +429,11 @@ DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { DWARFDie DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const { - if (auto SpecRef = toReference(V)) { - if (auto SpecUnit = U->getUnitVector().getUnitForOffset(*SpecRef)) - return SpecUnit->getDIEForOffset(*SpecRef); + if (auto SpecRef = V.getAsRelativeReference()) { + if (SpecRef->Unit) + return SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + SpecRef->Offset); + if (auto SpecUnit = U->getUnitVector().getUnitForOffset(SpecRef->Offset)) + return SpecUnit->getDIEForOffset(SpecRef->Offset); } return DWARFDie(); } @@ -560,10 +553,12 @@ void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, /// Helper to dump a DIE with all of its parents, but no siblings. static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, - DIDumpOptions DumpOpts) { + DIDumpOptions DumpOpts, unsigned Depth = 0) { if (!Die) return Indent; - Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts); + if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth) + return Indent; + Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1); Die.dump(OS, Indent, DumpOpts); return Indent + 2; } @@ -611,8 +606,8 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent, } DWARFDie child = getFirstChild(); - if (DumpOpts.ShowChildren && DumpOpts.RecurseDepth > 0 && child) { - DumpOpts.RecurseDepth--; + if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0 && child) { + DumpOpts.ChildRecurseDepth--; DIDumpOptions ChildDumpOpts = DumpOpts; ChildDumpOpts.ShowParents = false; while (child) { @@ -668,7 +663,7 @@ iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const { } DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) - : Die(D), AttrValue(0), Index(0) { + : Die(D), Index(0) { auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); assert(AbbrDecl && "Must have abbreviation declaration"); if (End) { @@ -690,18 +685,15 @@ void DWARFDie::attribute_iterator::updateForIndex( AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); // Add the previous byte size of any previous attribute value. AttrValue.Offset += AttrValue.ByteSize; - AttrValue.Value.setForm(AbbrDecl.getFormByIndex(Index)); uint32_t ParseOffset = AttrValue.Offset; auto U = Die.getDwarfUnit(); assert(U && "Die must have valid DWARF unit"); - bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(), - &ParseOffset, U->getFormParams(), U); - (void)b; - assert(b && "extractValue cannot fail on fully parsed DWARF"); + AttrValue.Value = DWARFFormValue::createFromUnit( + AbbrDecl.getFormByIndex(Index), U, &ParseOffset); AttrValue.ByteSize = ParseOffset - AttrValue.Offset; } else { assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); - AttrValue.clear(); + AttrValue = {}; } } @@ -710,3 +702,39 @@ DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { updateForIndex(*AbbrDecl, Index + 1); return *this; } + +bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { + switch (Attr) { + // From the DWARF v5 specification. + case DW_AT_location: + case DW_AT_byte_size: + case DW_AT_bit_size: + case DW_AT_string_length: + case DW_AT_lower_bound: + case DW_AT_return_addr: + case DW_AT_bit_stride: + case DW_AT_upper_bound: + case DW_AT_count: + case DW_AT_data_member_location: + case DW_AT_frame_base: + case DW_AT_segment: + case DW_AT_static_link: + case DW_AT_use_location: + case DW_AT_vtable_elem_location: + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_byte_stride: + case DW_AT_rank: + case DW_AT_call_value: + case DW_AT_call_origin: + case DW_AT_call_target: + case DW_AT_call_target_clobbered: + case DW_AT_call_data_location: + case DW_AT_call_data_value: + // Extensions. + case DW_AT_GNU_call_site_value: + return true; + default: + return false; + } +} diff --git a/lib/DebugInfo/DWARF/DWARFExpression.cpp b/lib/DebugInfo/DWARF/DWARFExpression.cpp index 2df4456053fb..470d4b5364b4 100644 --- a/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -1,13 +1,13 @@ //===-- DWARFExpression.cpp -----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/Format.h" @@ -97,6 +97,11 @@ static DescVector getDescriptions() { Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB); Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB); Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB); + + Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef); + Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB); + return Descriptions; } @@ -152,17 +157,21 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version, case Operation::SizeAddr: if (AddressSize == 8) { Operands[Operand] = Data.getU64(&Offset); - } else { - assert(AddressSize == 4); + } else if (AddressSize == 4) { Operands[Operand] = Data.getU32(&Offset); + } else { + assert(AddressSize == 2); + Operands[Operand] = Data.getU16(&Offset); } break; case Operation::SizeRefAddr: if (getRefAddrSize(AddressSize, Version) == 8) { Operands[Operand] = Data.getU64(&Offset); - } else { - assert(getRefAddrSize(AddressSize, Version) == 4); + } else if (getRefAddrSize(AddressSize, Version) == 4) { Operands[Operand] = Data.getU32(&Offset); + } else { + assert(getRefAddrSize(AddressSize, Version) == 2); + Operands[Operand] = Data.getU16(&Offset); } break; case Operation::SizeLEB: @@ -171,6 +180,9 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version, else Operands[Operand] = Data.getULEB128(&Offset); break; + case Operation::BaseTypeRef: + Operands[Operand] = Data.getULEB128(&Offset); + break; case Operation::SizeBlock: // We need a size, so this cannot be the first operand if (Operand == 0) @@ -182,6 +194,8 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version, default: llvm_unreachable("Unknown DWARFExpression Op size"); } + + OperandEndOffsets[Operand] = Offset; } EndOffset = Offset; @@ -222,6 +236,7 @@ static bool prettyPrintRegisterOp(raw_ostream &OS, uint8_t Opcode, bool DWARFExpression::Operation::print(raw_ostream &OS, const DWARFExpression *Expr, const MCRegisterInfo *RegInfo, + DWARFUnit *U, bool isEH) { if (Error) { OS << "<decoding error>"; @@ -245,14 +260,25 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, if (Size == Operation::SizeNA) break; - if (Size == Operation::SizeBlock) { + if (Size == Operation::BaseTypeRef && U) { + auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); + if (Die && Die.getTag() == dwarf::DW_TAG_base_type) { + OS << format(" (0x%08x)", U->getOffset() + Operands[Operand]); + if (auto Name = Die.find(dwarf::DW_AT_name)) + OS << " \"" << Name->getAsCString() << "\""; + } else { + OS << format(" <invalid base_type ref: 0x%" PRIx64 ">", + Operands[Operand]); + } + } else if (Size == Operation::SizeBlock) { uint32_t Offset = Operands[Operand]; for (unsigned i = 0; i < Operands[Operand - 1]; ++i) OS << format(" 0x%02x", Expr->Data.getU8(&Offset)); } else { if (Signed) OS << format(" %+" PRId64, (int64_t)Operands[Operand]); - else + else if (Opcode != DW_OP_entry_value && + Opcode != DW_OP_GNU_entry_value) OS << format(" 0x%" PRIx64, Operands[Operand]); } } @@ -260,17 +286,60 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, } void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo, - bool IsEH) const { + DWARFUnit *U, bool IsEH) const { + uint32_t EntryValExprSize = 0; for (auto &Op : *this) { - if (!Op.print(OS, this, RegInfo, IsEH)) { + if (!Op.print(OS, this, RegInfo, U, IsEH)) { uint32_t FailOffset = Op.getEndOffset(); while (FailOffset < Data.getData().size()) OS << format(" %02x", Data.getU8(&FailOffset)); return; } + + if (Op.getCode() == DW_OP_entry_value || + Op.getCode() == DW_OP_GNU_entry_value) { + OS << "("; + EntryValExprSize = Op.getRawOperand(0); + continue; + } + + if (EntryValExprSize) { + EntryValExprSize--; + if (EntryValExprSize == 0) + OS << ")"; + } + if (Op.getEndOffset() < Data.getData().size()) OS << ", "; } } +bool DWARFExpression::Operation::verify(DWARFUnit *U) { + + for (unsigned Operand = 0; Operand < 2; ++Operand) { + unsigned Size = Desc.Op[Operand]; + + if (Size == Operation::SizeNA) + break; + + if (Size == Operation::BaseTypeRef) { + auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); + if (!Die || Die.getTag() != dwarf::DW_TAG_base_type) { + Error = true; + return false; + } + } + } + + return true; +} + +bool DWARFExpression::verify(DWARFUnit *U) { + for (auto &Op : *this) + if (!Op.verify(U)) + return false; + + return true; +} + } // namespace llvm diff --git a/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 7719fea63120..290d35511cdb 100644 --- a/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -1,9 +1,8 @@ //===- DWARFFormValue.cpp -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -78,6 +77,34 @@ static const DWARFFormValue::FormClass DWARF5FormClasses[] = { }; +DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) { + return DWARFFormValue(F, ValueType(V)); +} + +DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) { + return DWARFFormValue(F, ValueType(V)); +} + +DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) { + return DWARFFormValue(F, ValueType(V)); +} + +DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F, + ArrayRef<uint8_t> D) { + ValueType V; + V.uval = D.size(); + V.data = D.data(); + return DWARFFormValue(F, V); +} + +DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U, + uint32_t *OffsetPtr) { + DWARFFormValue FormValue(F); + FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, + U->getFormParams(), U); + return FormValue; +} + bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, uint32_t *OffsetPtr, const dwarf::FormParams Params) { @@ -193,13 +220,17 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { default: break; } - // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset. - // Don't check for DWARF version here, as some producers may still do this - // by mistake. Also accept DW_FORM_[line_]strp since these are - // .debug_[line_]str section offsets. - return (Form == DW_FORM_data4 || Form == DW_FORM_data8 || - Form == DW_FORM_strp || Form == DW_FORM_line_strp) && - FC == FC_SectionOffset; + + if (FC == FC_SectionOffset) { + if (Form == DW_FORM_strp || Form == DW_FORM_line_strp) + return true; + // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section + // offset. If we don't have a DWARFUnit, default to the old behavior. + if (Form == DW_FORM_data4 || Form == DW_FORM_data8) + return !U || U->getVersion() <= 3; + } + + return false; } bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, @@ -268,7 +299,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, case DW_FORM_data8: case DW_FORM_ref8: case DW_FORM_ref_sup8: - Value.uval = Data.getU64(OffsetPtr); + Value.uval = Data.getRelocatedValue(8, OffsetPtr); break; case DW_FORM_data16: // Treat this like a 16-byte block. @@ -323,7 +354,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, StringRef Str = Data.getData().substr(*OffsetPtr, Value.uval); Value.data = nullptr; if (!Str.empty()) { - Value.data = reinterpret_cast<const uint8_t *>(Str.data()); + Value.data = Str.bytes_begin(); *OffsetPtr += Value.uval; } } @@ -333,7 +364,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, - SectionedAddress SA) const { + object::SectionedAddress SA) const { OS << format("0x%016" PRIx64, SA.Address); dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, SA.SectionIndex); @@ -370,12 +401,14 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { case DW_FORM_addrx3: case DW_FORM_addrx4: case DW_FORM_GNU_addr_index: { - Optional<SectionedAddress> A = U->getAddrOffsetSectionItem(UValue); + if (U == nullptr) { + OS << "<invalid dwarf unit>"; + break; + } + Optional<object::SectionedAddress> A = U->getAddrOffsetSectionItem(UValue); if (!A || DumpOpts.Verbose) AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue); - if (U == nullptr) - OS << "<invalid dwarf unit>"; - else if (A) + if (A) dumpSectionedAddress(AddrOS, DumpOpts, *A); else OS << "<no .debug_addr section>"; @@ -591,14 +624,15 @@ Optional<uint64_t> DWARFFormValue::getAsAddress() const { return SA->Address; return None; } -Optional<SectionedAddress> DWARFFormValue::getAsSectionedAddress() const { +Optional<object::SectionedAddress> +DWARFFormValue::getAsSectionedAddress() const { if (!isFormClass(FC_Address)) return None; if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx) { uint32_t Index = Value.uval; if (!U) return None; - Optional<SectionedAddress> SA = U->getAddrOffsetSectionItem(Index); + Optional<object::SectionedAddress> SA = U->getAddrOffsetSectionItem(Index); if (!SA) return None; return SA; @@ -607,6 +641,12 @@ Optional<SectionedAddress> DWARFFormValue::getAsSectionedAddress() const { } Optional<uint64_t> DWARFFormValue::getAsReference() const { + if (auto R = getAsRelativeReference()) + return R->Unit ? R->Unit->getOffset() + R->Offset : R->Offset; + return None; +} + +Optional<DWARFFormValue::UnitOffset> DWARFFormValue::getAsRelativeReference() const { if (!isFormClass(FC_Reference)) return None; switch (Form) { @@ -617,11 +657,11 @@ Optional<uint64_t> DWARFFormValue::getAsReference() const { case DW_FORM_ref_udata: if (!U) return None; - return Value.uval + U->getOffset(); + return UnitOffset{const_cast<DWARFUnit*>(U), Value.uval}; case DW_FORM_ref_addr: case DW_FORM_ref_sig8: case DW_FORM_GNU_ref_alt: - return Value.uval; + return UnitOffset{nullptr, Value.uval}; default: return None; } diff --git a/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp index 1abd931e3b8b..f5f975578082 100644 --- a/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp +++ b/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp @@ -1,9 +1,8 @@ //===- DWARFGdbIndex.cpp --------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -121,7 +120,7 @@ bool DWARFGdbIndex::parseImpl(DataExtractor Data) { return false; CuListOffset = Data.getU32(&Offset); - uint32_t CuTypesOffset = Data.getU32(&Offset); + TuListOffset = Data.getU32(&Offset); AddressAreaOffset = Data.getU32(&Offset); SymbolTableOffset = Data.getU32(&Offset); ConstantPoolOffset = Data.getU32(&Offset); @@ -129,7 +128,7 @@ bool DWARFGdbIndex::parseImpl(DataExtractor Data) { if (Offset != CuListOffset) return false; - uint32_t CuListSize = (CuTypesOffset - CuListOffset) / 16; + uint32_t CuListSize = (TuListOffset - CuListOffset) / 16; CuList.reserve(CuListSize); for (uint32_t i = 0; i < CuListSize; ++i) { uint64_t CuOffset = Data.getU64(&Offset); @@ -139,7 +138,7 @@ bool DWARFGdbIndex::parseImpl(DataExtractor Data) { // CU Types are no longer needed as DWARF skeleton type units never made it // into the standard. - uint32_t TuListSize = (AddressAreaOffset - CuTypesOffset) / 24; + uint32_t TuListSize = (AddressAreaOffset - TuListOffset) / 24; TuList.resize(TuListSize); for (uint32_t I = 0; I < TuListSize; ++I) { uint64_t CuOffset = Data.getU64(&Offset); diff --git a/lib/DebugInfo/DWARF/DWARFListTable.cpp b/lib/DebugInfo/DWARF/DWARFListTable.cpp index 462c036d73ad..e38e706227da 100644 --- a/lib/DebugInfo/DWARF/DWARFListTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -1,9 +1,8 @@ //===- DWARFListTable.cpp ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -26,7 +25,7 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, "%s table length at offset 0x%" PRIx32, SectionName.data(), *OffsetPtr); // TODO: Add support for DWARF64. - HeaderData.Length = Data.getU32(OffsetPtr); + HeaderData.Length = Data.getRelocatedValue(4, OffsetPtr); if (HeaderData.Length == 0xffffffffu) return createStringError(errc::not_supported, "DWARF64 is not supported in %s at offset 0x%" PRIx32, @@ -74,7 +73,7 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount); Data.setAddressSize(HeaderData.AddrSize); for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I) - Offsets.push_back(Data.getU32(OffsetPtr)); + Offsets.push_back(Data.getRelocatedValue(4, OffsetPtr)); return Error::success(); } diff --git a/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp index 00be75e1a94d..844920ba5b11 100644 --- a/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -1,9 +1,8 @@ //===- DWARFTypeUnit.cpp --------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index 80234665bdeb..b74acf60c747 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -1,9 +1,8 @@ //===- DWARFUnit.cpp ------------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -198,7 +197,7 @@ DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { getAddressByteSize()); } -Optional<SectionedAddress> +Optional<object::SectionedAddress> DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { if (IsDWO) { auto R = Context.info_section_units(); @@ -242,17 +241,21 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, IndexEntry = Entry; if (!IndexEntry && Index) IndexEntry = Index->getFromOffset(*offset_ptr); - Length = debug_info.getU32(offset_ptr); - // FIXME: Support DWARF64. - unsigned SizeOfLength = 4; + Length = debug_info.getRelocatedValue(4, offset_ptr); FormParams.Format = DWARF32; + unsigned SizeOfLength = 4; + if (Length == 0xffffffff) { + Length = debug_info.getU64(offset_ptr); + FormParams.Format = DWARF64; + SizeOfLength = 8; + } FormParams.Version = debug_info.getU16(offset_ptr); if (FormParams.Version >= 5) { UnitType = debug_info.getU8(offset_ptr); FormParams.AddrSize = debug_info.getU8(offset_ptr); - AbbrOffset = debug_info.getU32(offset_ptr); + AbbrOffset = debug_info.getRelocatedValue(FormParams.getDwarfOffsetByteSize(), offset_ptr); } else { - AbbrOffset = debug_info.getRelocatedValue(4, offset_ptr); + AbbrOffset = debug_info.getRelocatedValue(FormParams.getDwarfOffsetByteSize(), offset_ptr); FormParams.AddrSize = debug_info.getU8(offset_ptr); // Fake a unit type based on the section type. This isn't perfect, // but distinguishing compile and type units is generally enough. @@ -432,12 +435,17 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { // which may differ from the unit's format. DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, isLittleEndian, 0); - if (IsDWO) - StringOffsetsTableContribution = - determineStringOffsetsTableContributionDWO(DA); - else if (getVersion() >= 5) - StringOffsetsTableContribution = - determineStringOffsetsTableContribution(DA); + if (IsDWO || getVersion() >= 5) { + auto StringOffsetOrError = + IsDWO ? determineStringOffsetsTableContributionDWO(DA) + : determineStringOffsetsTableContribution(DA); + if (!StringOffsetOrError) { + WithColor::error() << "invalid contribution to string offsets table in section .debug_str_offsets[.dwo]: " + << toString(StringOffsetOrError.takeError()) << '\n'; + } else { + StringOffsetsTableContribution = *StringOffsetOrError; + } + } // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to // describe address ranges. @@ -634,7 +642,7 @@ DWARFUnit::getInlinedChainForAddress(uint64_t Address, // First, find the subroutine that contains the given address (the leaf // of inlined chain). DWARFDie SubroutineDIE = - (DWO ? DWO.get() : this)->getSubroutineForAddress(Address); + (DWO ? *DWO : *this).getSubroutineForAddress(Address); if (!SubroutineDIE) return; @@ -745,7 +753,7 @@ const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { return Abbrevs; } -llvm::Optional<SectionedAddress> DWARFUnit::getBaseAddress() { +llvm::Optional<object::SectionedAddress> DWARFUnit::getBaseAddress() { if (BaseAddr) return BaseAddr; @@ -755,7 +763,7 @@ llvm::Optional<SectionedAddress> DWARFUnit::getBaseAddress() { return BaseAddr; } -Optional<StrOffsetsContributionDescriptor> +Expected<StrOffsetsContributionDescriptor> StrOffsetsContributionDescriptor::validateContributionSize( DWARFDataExtractor &DA) { uint8_t EntrySize = getDwarfOffsetByteSize(); @@ -766,58 +774,94 @@ StrOffsetsContributionDescriptor::validateContributionSize( if (ValidationSize >= Size) if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize)) return *this; - return None; + return createStringError(errc::invalid_argument, "length exceeds section size"); } // Look for a DWARF64-formatted contribution to the string offsets table // starting at a given offset and record it in a descriptor. -static Optional<StrOffsetsContributionDescriptor> +static Expected<StrOffsetsContributionDescriptor> parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { if (!DA.isValidOffsetForDataOfSize(Offset, 16)) - return None; + return createStringError(errc::invalid_argument, "section offset exceeds section size"); if (DA.getU32(&Offset) != 0xffffffff) - return None; + return createStringError(errc::invalid_argument, "32 bit contribution referenced from a 64 bit unit"); uint64_t Size = DA.getU64(&Offset); uint8_t Version = DA.getU16(&Offset); (void)DA.getU16(&Offset); // padding // The encoded length includes the 2-byte version field and the 2-byte // padding, so we need to subtract them out when we populate the descriptor. - return {{Offset, Size - 4, Version, DWARF64}}; + return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64); } // Look for a DWARF32-formatted contribution to the string offsets table // starting at a given offset and record it in a descriptor. -static Optional<StrOffsetsContributionDescriptor> +static Expected<StrOffsetsContributionDescriptor> parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { if (!DA.isValidOffsetForDataOfSize(Offset, 8)) - return None; + return createStringError(errc::invalid_argument, "section offset exceeds section size"); + uint32_t ContributionSize = DA.getU32(&Offset); if (ContributionSize >= 0xfffffff0) - return None; + return createStringError(errc::invalid_argument, "invalid length"); + uint8_t Version = DA.getU16(&Offset); (void)DA.getU16(&Offset); // padding // The encoded length includes the 2-byte version field and the 2-byte // padding, so we need to subtract them out when we populate the descriptor. - return {{Offset, ContributionSize - 4, Version, DWARF32}}; + return StrOffsetsContributionDescriptor(Offset, ContributionSize - 4, Version, + DWARF32); +} + +static Expected<StrOffsetsContributionDescriptor> +parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, + llvm::dwarf::DwarfFormat Format, + uint64_t Offset) { + StrOffsetsContributionDescriptor Desc; + switch (Format) { + case dwarf::DwarfFormat::DWARF64: { + if (Offset < 16) + return createStringError(errc::invalid_argument, "insufficient space for 64 bit header prefix"); + auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16); + if (!DescOrError) + return DescOrError.takeError(); + Desc = *DescOrError; + break; + } + case dwarf::DwarfFormat::DWARF32: { + if (Offset < 8) + return createStringError(errc::invalid_argument, "insufficient space for 32 bit header prefix"); + auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8); + if (!DescOrError) + return DescOrError.takeError(); + Desc = *DescOrError; + break; + } + } + return Desc.validateContributionSize(DA); } -Optional<StrOffsetsContributionDescriptor> +Expected<Optional<StrOffsetsContributionDescriptor>> DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) { - auto Offset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base), 0); - Optional<StrOffsetsContributionDescriptor> Descriptor; - // Attempt to find a DWARF64 contribution 16 bytes before the base. - if (Offset >= 16) - Descriptor = - parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16); - // Try to find a DWARF32 contribution 8 bytes before the base. - if (!Descriptor && Offset >= 8) - Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8); - return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor; -} - -Optional<StrOffsetsContributionDescriptor> + uint64_t Offset; + if (IsDWO) { + Offset = 0; + if (DA.getData().data() == nullptr) + return None; + } else { + auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base)); + if (!OptOffset) + return None; + Offset = *OptOffset; + } + auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset); + if (!DescOrError) + return DescOrError.takeError(); + return *DescOrError; +} + +Expected<Optional<StrOffsetsContributionDescriptor>> DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { uint64_t Offset = 0; auto IndexEntry = Header.getIndexEntry(); @@ -826,19 +870,24 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { if (C) Offset = C->Offset; if (getVersion() >= 5) { + if (DA.getData().data() == nullptr) + return None; + Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16; // Look for a valid contribution at the given offset. - auto Descriptor = - parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset); - if (!Descriptor) - Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset); - return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor; + auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset); + if (!DescOrError) + return DescOrError.takeError(); + return *DescOrError; } // Prior to DWARF v5, we derive the contribution size from the // index table (in a package file). In a .dwo file it is simply // the length of the string offsets section. if (!IndexEntry) - return {{0, StringOffsetSection.Data.size(), 4, DWARF32}}; + return { + Optional<StrOffsetsContributionDescriptor>( + {0, StringOffsetSection.Data.size(), 4, DWARF32})}; if (C) - return {{C->Offset, C->Length, 4, DWARF32}}; + return {Optional<StrOffsetsContributionDescriptor>( + {C->Offset, C->Length, 4, DWARF32})}; return None; } diff --git a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp index 84b6c4b81817..047c63461ccf 100644 --- a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -1,9 +1,8 @@ //===- DWARFUnitIndex.cpp -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -173,10 +172,9 @@ DWARFUnitIndex::getFromOffset(uint32_t Offset) const { E2->Contributions[InfoColumn].Offset; }); } - auto I = - llvm::upper_bound(OffsetLookup, Offset, [&](uint32_t Offset, Entry *E2) { - return Offset < E2->Contributions[InfoColumn].Offset; - }); + auto I = partition_point(OffsetLookup, [&](Entry *E2) { + return E2->Contributions[InfoColumn].Offset <= Offset; + }); if (I == OffsetLookup.begin()) return nullptr; --I; diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp index f8370178b627..c2b3189514a8 100644 --- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -1,9 +1,8 @@ //===- DWARFVerifier.cpp --------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" @@ -61,55 +60,47 @@ DWARFVerifier::DieRangeInfo::insert(const DieRangeInfo &RI) { } bool DWARFVerifier::DieRangeInfo::contains(const DieRangeInfo &RHS) const { - // Both list of ranges are sorted so we can make this fast. - - if (Ranges.empty() || RHS.Ranges.empty()) - return false; - - // Since the ranges are sorted we can advance where we start searching with - // this object's ranges as we traverse RHS.Ranges. - auto End = Ranges.end(); - auto Iter = findRange(RHS.Ranges.front()); + auto I1 = Ranges.begin(), E1 = Ranges.end(); + auto I2 = RHS.Ranges.begin(), E2 = RHS.Ranges.end(); + if (I2 == E2) + return true; - // Now linearly walk the ranges in this object and see if they contain each - // ranges from RHS.Ranges. - for (const auto &R : RHS.Ranges) { - while (Iter != End) { - if (Iter->contains(R)) - break; - ++Iter; + DWARFAddressRange R = *I2; + while (I1 != E1) { + bool Covered = I1->LowPC <= R.LowPC; + if (R.LowPC == R.HighPC || (Covered && R.HighPC <= I1->HighPC)) { + if (++I2 == E2) + return true; + R = *I2; + continue; } - if (Iter == End) + if (!Covered) return false; + if (R.LowPC < I1->HighPC) + R.LowPC = I1->HighPC; + ++I1; } - return true; + return false; } bool DWARFVerifier::DieRangeInfo::intersects(const DieRangeInfo &RHS) const { - if (Ranges.empty() || RHS.Ranges.empty()) - return false; - - auto End = Ranges.end(); - auto Iter = findRange(RHS.Ranges.front()); - for (const auto &R : RHS.Ranges) { - if (Iter == End) - return false; - if (R.HighPC <= Iter->LowPC) - continue; - while (Iter != End) { - if (Iter->intersects(R)) - return true; - ++Iter; - } + auto I1 = Ranges.begin(), E1 = Ranges.end(); + auto I2 = RHS.Ranges.begin(), E2 = RHS.Ranges.end(); + while (I1 != E1 && I2 != E2) { + if (I1->intersects(*I2)) + return true; + if (I1->LowPC < I2->LowPC) + ++I1; + else + ++I2; } - return false; } bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType, bool &isUnitDWARF64) { - uint32_t AbbrOffset, Length; + uint64_t AbbrOffset, Length; uint8_t AddrSize = 0; uint16_t Version; bool Success = true; @@ -123,22 +114,19 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, uint32_t OffsetStart = *Offset; Length = DebugInfoData.getU32(Offset); if (Length == UINT32_MAX) { + Length = DebugInfoData.getU64(Offset); isUnitDWARF64 = true; - OS << format( - "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n", - UnitIndex); - return false; } Version = DebugInfoData.getU16(Offset); if (Version >= 5) { UnitType = DebugInfoData.getU8(Offset); AddrSize = DebugInfoData.getU8(Offset); - AbbrOffset = DebugInfoData.getU32(Offset); + AbbrOffset = isUnitDWARF64 ? DebugInfoData.getU64(Offset) : DebugInfoData.getU32(Offset); ValidType = dwarf::isUnitType(UnitType); } else { UnitType = 0; - AbbrOffset = DebugInfoData.getU32(Offset); + AbbrOffset = isUnitDWARF64 ? DebugInfoData.getU64(Offset) : DebugInfoData.getU32(Offset); AddrSize = DebugInfoData.getU8(Offset); } @@ -166,7 +154,7 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, if (!ValidAddrSize) note() << "The address size is unsupported.\n"; } - *Offset = OffsetStart + Length + 4; + *Offset = OffsetStart + Length + (isUnitDWARF64 ? 12 : 4); return Success; } @@ -179,21 +167,11 @@ unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit) { if (Die.getTag() == DW_TAG_null) continue; - bool HasTypeAttr = false; for (auto AttrValue : Die.attributes()) { NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue); NumUnitErrors += verifyDebugInfoForm(Die, AttrValue); - HasTypeAttr |= (AttrValue.Attr == DW_AT_type); } - if (!HasTypeAttr && (Die.getTag() == DW_TAG_formal_parameter || - Die.getTag() == DW_TAG_variable || - Die.getTag() == DW_TAG_array_type)) { - error() << "DIE with tag " << TagString(Die.getTag()) - << " is missing type attribute:\n"; - dump(Die) << '\n'; - NumUnitErrors++; - } NumUnitErrors += verifyDebugInfoCallSite(Die); } @@ -281,19 +259,12 @@ bool DWARFVerifier::handleDebugAbbrev() { OS << "Verifying .debug_abbrev...\n"; const DWARFObject &DObj = DCtx.getDWARFObj(); - bool noDebugAbbrev = DObj.getAbbrevSection().empty(); - bool noDebugAbbrevDWO = DObj.getAbbrevDWOSection().empty(); - - if (noDebugAbbrev && noDebugAbbrevDWO) { - return true; - } - unsigned NumErrors = 0; - if (!noDebugAbbrev) + if (!DObj.getAbbrevSection().empty()) NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrev()); - - if (!noDebugAbbrevDWO) + if (!DObj.getAbbrevDWOSection().empty()) NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrevDWO()); + return NumErrors == 0; } @@ -503,7 +474,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) { return Op.isError(); }); - if (Error) + if (Error || !Expression.verify(U)) ReportError("DIE contains invalid DWARF expression:"); }; if (Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock()) { @@ -629,7 +600,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, dump(Die) << '\n'; break; } - // Check that the index is within the bounds of the section. + // Check that the index is within the bounds of the section. unsigned ItemSize = DieCU->getDwarfStringOffsetsByteSize(); // Use a 64-bit type to calculate the offset to guard against overflow. uint64_t Offset = @@ -664,9 +635,9 @@ unsigned DWARFVerifier::verifyDebugInfoReferences() { // getting the DIE by offset and emitting an error OS << "Verifying .debug_info references...\n"; unsigned NumErrors = 0; - for (auto Pair : ReferenceToDIEOffsets) { - auto Die = DCtx.getDIEForOffset(Pair.first); - if (Die) + for (const std::pair<uint64_t, std::set<uint32_t>> &Pair : + ReferenceToDIEOffsets) { + if (DCtx.getDIEForOffset(Pair.first)) continue; ++NumErrors; error() << "invalid DIE reference " << format("0x%08" PRIx64, Pair.first) @@ -731,7 +702,6 @@ void DWARFVerifier::verifyDebugLineRows() { continue; // Verify prologue. - uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size(); uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size(); uint32_t FileIndex = 1; StringMap<uint16_t> FullPathMap; @@ -773,7 +743,7 @@ void DWARFVerifier::verifyDebugLineRows() { uint32_t RowIndex = 0; for (const auto &Row : LineTable->Rows) { // Verify row address. - if (Row.Address < PrevAddress) { + if (Row.Address.Address < PrevAddress) { ++NumDebugLineErrors; error() << ".debug_line[" << format("0x%08" PRIx64, @@ -789,13 +759,16 @@ void DWARFVerifier::verifyDebugLineRows() { } // Verify file index. - if (Row.File > MaxFileIndex) { + if (!LineTable->hasFileAtIndex(Row.File)) { ++NumDebugLineErrors; + bool isDWARF5 = LineTable->Prologue.getVersion() >= 5; error() << ".debug_line[" << format("0x%08" PRIx64, *toSectionOffset(Die.find(DW_AT_stmt_list))) << "][" << RowIndex << "] has invalid file index " << Row.File - << " (valid values are [1," << MaxFileIndex << "]):\n"; + << " (valid values are [" << (isDWARF5 ? "0," : "1,") + << LineTable->Prologue.FileNames.size() + << (isDWARF5 ? ")" : "]") << "):\n"; DWARFDebugLine::Row::dumpTableHeader(OS); Row.dump(OS); OS << '\n'; @@ -803,7 +776,7 @@ void DWARFVerifier::verifyDebugLineRows() { if (Row.EndSequence) PrevAddress = 0; else - PrevAddress = Row.Address; + PrevAddress = Row.Address.Address; ++RowIndex; } } |