diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
| commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
| tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/DebugInfo/DWARF | |
| parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF')
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 63 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp | 29 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 683 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp | 39 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 147 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp | 23 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 43 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 110 |
10 files changed, 988 insertions, 153 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index 2b08120ef4dc..6e30309ae94a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -26,7 +26,8 @@ void DWARFCompileUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) { if (!getAbbreviations()) OS << " (invalid)"; OS << ", addr_size = " << format("0x%02x", getAddressByteSize()); - if (getVersion() >= 5 && getUnitType() != dwarf::DW_UT_compile) + if (getVersion() >= 5 && (getUnitType() == dwarf::DW_UT_skeleton || + getUnitType() == dwarf::DW_UT_split_compile)) OS << ", DWO_id = " << format("0x%016" PRIx64, *getDWOId()); OS << " (next unit at " << format("0x%08" PRIx64, getNextUnitOffset()) << ")\n"; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index 749d738af9c1..4e1cafeb2126 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -823,6 +823,8 @@ Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() { if (DebugFrame) return DebugFrame.get(); + const DWARFSection &DS = DObj->getFrameSection(); + // There's a "bug" in the DWARFv3 standard with respect to the target address // size within debug frame sections. While DWARF is supposed to be independent // of its container, FDEs have fields with size being "target address size", @@ -832,10 +834,11 @@ Expected<const DWARFDebugFrame *> DWARFContext::getDebugFrame() { // provides this information). This problem is fixed in DWARFv4 // See this dwarf-discuss discussion for more details: // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html - DWARFDataExtractor debugFrameData(*DObj, DObj->getFrameSection(), - isLittleEndian(), DObj->getAddressSize()); - auto DF = std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/false); - if (Error E = DF->parse(debugFrameData)) + DWARFDataExtractor DebugFrameData(*DObj, DS, isLittleEndian(), + DObj->getAddressSize()); + auto DF = + std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/false, DS.Address); + if (Error E = DF->parse(DebugFrameData)) return std::move(E); DebugFrame.swap(DF); @@ -846,11 +849,13 @@ Expected<const DWARFDebugFrame *> DWARFContext::getEHFrame() { if (EHFrame) return EHFrame.get(); - DWARFDataExtractor debugFrameData(*DObj, DObj->getEHFrameSection(), - isLittleEndian(), DObj->getAddressSize()); + const DWARFSection &DS = DObj->getEHFrameSection(); + DWARFDataExtractor DebugFrameData(*DObj, DS, isLittleEndian(), + DObj->getAddressSize()); - auto DF = std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/true); - if (Error E = DF->parse(debugFrameData)) + auto DF = + std::make_unique<DWARFDebugFrame>(getArch(), /*IsEH=*/true, DS.Address); + if (Error E = DF->parse(DebugFrameData)) return std::move(E); DebugFrame.swap(DF); return DebugFrame.get(); @@ -1022,8 +1027,7 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { break; } - for (auto Child : DIE) - Worklist.push_back(Child); + append_range(Worklist, DIE); } return Result; @@ -1031,13 +1035,11 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { /// TODO: change input parameter from "uint64_t Address" /// into "SectionedAddress Address" -static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, - uint64_t Address, - FunctionNameKind Kind, - DILineInfoSpecifier::FileLineInfoKind FileNameKind, - std::string &FunctionName, - std::string &StartFile, - uint32_t &StartLine) { +static bool getFunctionNameAndStartLineForAddress( + DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind, + DILineInfoSpecifier::FileLineInfoKind FileNameKind, + std::string &FunctionName, std::string &StartFile, uint32_t &StartLine, + Optional<uint64_t> &StartAddress) { // The address may correspond to instruction in some inlined function, // so we have to build the chain of inlined functions and take the // name of the topmost function in it. @@ -1062,7 +1064,8 @@ static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, StartLine = DeclLineResult; FoundResult = true; } - + if (auto LowPcAddr = toSectionedAddress(DIE.find(DW_AT_low_pc))) + StartAddress = LowPcAddr->Address; return FoundResult; } @@ -1229,9 +1232,9 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, if (!CU) return Result; - getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, Spec.FLIKind, - Result.FunctionName, - Result.StartFileName, Result.StartLine); + getFunctionNameAndStartLineForAddress( + CU, Address.Address, Spec.FNKind, Spec.FLIKind, Result.FunctionName, + Result.StartFileName, Result.StartLine, Result.StartAddress); if (Spec.FLIKind != FileLineInfoKind::None) { if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) { LineTable->getFileLineInfoForAddress( @@ -1244,7 +1247,7 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, DILineInfoTable DWARFContext::getLineInfoForAddressRange( object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) { - DILineInfoTable Lines; + DILineInfoTable Lines; DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); if (!CU) return Lines; @@ -1252,8 +1255,10 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange( uint32_t StartLine = 0; std::string StartFileName; std::string FunctionName(DILineInfo::BadString); - getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, Spec.FLIKind, - FunctionName, StartFileName, StartLine); + Optional<uint64_t> StartAddress; + getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, + Spec.FLIKind, FunctionName, + StartFileName, StartLine, StartAddress); // If the Specifier says we don't need FileLineInfo, just // return the top-most function at the starting address. @@ -1262,6 +1267,7 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange( Result.FunctionName = FunctionName; Result.StartFileName = StartFileName; Result.StartLine = StartLine; + Result.StartAddress = StartAddress; Lines.push_back(std::make_pair(Address.Address, Result)); return Lines; } @@ -1286,6 +1292,7 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange( Result.Column = Row.Column; Result.StartFileName = StartFileName; Result.StartLine = StartLine; + Result.StartAddress = StartAddress; Lines.push_back(std::make_pair(Row.Address.Address, Result)); } @@ -1328,6 +1335,8 @@ DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address, if (auto DeclLineResult = FunctionDIE.getDeclLine()) Frame.StartLine = DeclLineResult; Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind); + if (auto LowPcAddr = toSectionedAddress(FunctionDIE.find(DW_AT_low_pc))) + Frame.StartAddress = LowPcAddr->Address; if (Spec.FLIKind != FileLineInfoKind::None) { if (i == 0) { // For the topmost frame, initialize the line table of this @@ -1678,7 +1687,8 @@ 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. - section_iterator RelocatedSection = *SecOrErr; + section_iterator RelocatedSection = + Obj.isRelocatableObject() ? *SecOrErr : Obj.section_end(); if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) { Expected<StringRef> E = Section.getContents(); if (E) @@ -1708,6 +1718,9 @@ public: if (Name == "debug_ranges") { // FIXME: Use the other dwo range section when we emit it. RangesDWOSection.Data = Data; + } else if (Name == "debug_frame" || Name == "eh_frame") { + if (DWARFSection *S = mapNameToDWARFSection(Name)) + S->Address = Section.getAddress(); } } else if (InfoSectionMap *Sections = StringSwitch<InfoSectionMap *>(Name) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp index 4afac2f99503..d91a630256d6 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp @@ -67,6 +67,35 @@ DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration( return &Decls[AbbrCode - FirstAbbrCode]; } +std::string DWARFAbbreviationDeclarationSet::getCodeRange() const { + // Create a sorted list of all abbrev codes. + std::vector<uint32_t> Codes; + Codes.reserve(Decls.size()); + for (const auto &Decl : Decls) + Codes.push_back(Decl.getCode()); + + std::string Buffer = ""; + raw_string_ostream Stream(Buffer); + // Each iteration through this loop represents a single contiguous range in + // the set of codes. + for (auto Current = Codes.begin(), End = Codes.end(); Current != End;) { + uint32_t RangeStart = *Current; + // Add the current range start. + Stream << *Current; + uint32_t RangeEnd = RangeStart; + // Find the end of the current range. + while (++Current != End && *Current == RangeEnd + 1) + ++RangeEnd; + // If there is more than one value in the range, add the range end too. + if (RangeStart != RangeEnd) + Stream << "-" << RangeEnd; + // If there is at least one more range, add a separator. + if (Current != End) + Stream << ", "; + } + return Buffer; +} + DWARFDebugAbbrev::DWARFDebugAbbrev() { clear(); } void DWARFDebugAbbrev::clear() { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp index e0db469752cd..1a1b8ea0976f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -15,7 +15,6 @@ #include <cassert> #include <cstdint> #include <set> -#include <vector> using namespace llvm; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index b74ecac681f3..92a461dbd941 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -24,8 +24,6 @@ #include <cassert> #include <cinttypes> #include <cstdint> -#include <string> -#include <vector> using namespace llvm; using namespace dwarf; @@ -43,6 +41,211 @@ static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, OS << "reg" << RegNum; } +UnwindLocation UnwindLocation::createUnspecified() { return {Unspecified}; } + +UnwindLocation UnwindLocation::createUndefined() { return {Undefined}; } + +UnwindLocation UnwindLocation::createSame() { return {Same}; } + +UnwindLocation UnwindLocation::createIsConstant(int32_t Value) { + return {Constant, InvalidRegisterNumber, Value, None, false}; +} + +UnwindLocation UnwindLocation::createIsCFAPlusOffset(int32_t Offset) { + return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, false}; +} + +UnwindLocation UnwindLocation::createAtCFAPlusOffset(int32_t Offset) { + return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, true}; +} + +UnwindLocation +UnwindLocation::createIsRegisterPlusOffset(uint32_t RegNum, int32_t Offset, + Optional<uint32_t> AddrSpace) { + return {RegPlusOffset, RegNum, Offset, AddrSpace, false}; +} + +UnwindLocation +UnwindLocation::createAtRegisterPlusOffset(uint32_t RegNum, int32_t Offset, + Optional<uint32_t> AddrSpace) { + return {RegPlusOffset, RegNum, Offset, AddrSpace, true}; +} + +UnwindLocation UnwindLocation::createIsDWARFExpression(DWARFExpression Expr) { + return {Expr, false}; +} + +UnwindLocation UnwindLocation::createAtDWARFExpression(DWARFExpression Expr) { + return {Expr, true}; +} + +void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI, + bool IsEH) const { + if (Dereference) + OS << '['; + switch (Kind) { + case Unspecified: + OS << "unspecified"; + break; + case Undefined: + OS << "undefined"; + break; + case Same: + OS << "same"; + break; + case CFAPlusOffset: + OS << "CFA"; + if (Offset == 0) + break; + if (Offset > 0) + OS << "+"; + OS << Offset; + break; + case RegPlusOffset: + printRegister(OS, MRI, IsEH, RegNum); + if (Offset == 0 && !AddrSpace) + break; + if (Offset >= 0) + OS << "+"; + OS << Offset; + if (AddrSpace) + OS << " in addrspace" << *AddrSpace; + break; + case DWARFExpr: + Expr->print(OS, DIDumpOptions(), MRI, nullptr, IsEH); + break; + case Constant: + OS << Offset; + break; + } + if (Dereference) + OS << ']'; +} + +raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, + const UnwindLocation &UL) { + UL.dump(OS, nullptr, false); + return OS; +} + +bool UnwindLocation::operator==(const UnwindLocation &RHS) const { + if (Kind != RHS.Kind) + return false; + switch (Kind) { + case Unspecified: + case Undefined: + case Same: + return true; + case CFAPlusOffset: + return Offset == RHS.Offset && Dereference == RHS.Dereference; + case RegPlusOffset: + return RegNum == RHS.RegNum && Offset == RHS.Offset && + Dereference == RHS.Dereference; + case DWARFExpr: + return *Expr == *RHS.Expr && Dereference == RHS.Dereference; + case Constant: + return Offset == RHS.Offset; + } + return false; +} + +void RegisterLocations::dump(raw_ostream &OS, const MCRegisterInfo *MRI, + bool IsEH) const { + bool First = true; + for (const auto &RegLocPair : Locations) { + if (First) + First = false; + else + OS << ", "; + printRegister(OS, MRI, IsEH, RegLocPair.first); + OS << '='; + RegLocPair.second.dump(OS, MRI, IsEH); + } +} + +raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, + const RegisterLocations &RL) { + RL.dump(OS, nullptr, false); + return OS; +} + +void UnwindRow::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, + unsigned IndentLevel) const { + OS.indent(2 * IndentLevel); + if (hasAddress()) + OS << format("0x%" PRIx64 ": ", *Address); + OS << "CFA="; + CFAValue.dump(OS, MRI, IsEH); + if (RegLocs.hasLocations()) { + OS << ": "; + RegLocs.dump(OS, MRI, IsEH); + } + OS << "\n"; +} + +raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) { + Row.dump(OS, nullptr, false, 0); + return OS; +} + +void UnwindTable::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, + unsigned IndentLevel) const { + for (const UnwindRow &Row : Rows) + Row.dump(OS, MRI, IsEH, IndentLevel); +} + +raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) { + Rows.dump(OS, nullptr, false, 0); + return OS; +} + +Expected<UnwindTable> UnwindTable::create(const FDE *Fde) { + const CIE *Cie = Fde->getLinkedCIE(); + if (Cie == nullptr) + return createStringError(errc::invalid_argument, + "unable to get CIE for FDE at offset 0x%" PRIx64, + Fde->getOffset()); + + // Rows will be empty if there are no CFI instructions. + if (Cie->cfis().empty() && Fde->cfis().empty()) + return UnwindTable(); + + UnwindTable UT; + UnwindRow Row; + Row.setAddress(Fde->getInitialLocation()); + UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange(); + if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr)) + return std::move(CieError); + // We need to save the initial locations of registers from the CIE parsing + // in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes. + const RegisterLocations InitialLocs = Row.getRegisterLocations(); + if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs)) + return std::move(FdeError); + // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty. + // Do not add that to the unwind table. + if (Row.getRegisterLocations().hasLocations() || + Row.getCFAValue().getLocation() != UnwindLocation::Unspecified) + UT.Rows.push_back(Row); + return UT; +} + +Expected<UnwindTable> UnwindTable::create(const CIE *Cie) { + // Rows will be empty if there are no CFI instructions. + if (Cie->cfis().empty()) + return UnwindTable(); + + UnwindTable UT; + UnwindRow Row; + if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr)) + return std::move(CieError); + // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty. + // Do not add that to the unwind table. + if (Row.getRegisterLocations().hasLocations() || + Row.getCFAValue().getLocation() != UnwindLocation::Unspecified) + UT.Rows.push_back(Row); + return UT; +} + // See DWARF standard v3, section 7.23 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; @@ -115,6 +318,16 @@ Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, // Operands: SLEB128 addInstruction(Opcode, Data.getSLEB128(C)); break; + case DW_CFA_LLVM_def_aspace_cfa: + case DW_CFA_LLVM_def_aspace_cfa_sf: { + auto RegNum = Data.getULEB128(C); + auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa + ? Data.getULEB128(C) + : Data.getSLEB128(C); + auto AddressSpace = Data.getULEB128(C); + addInstruction(Opcode, RegNum, CfaOffset, AddressSpace); + break; + } case DW_CFA_offset_extended: case DW_CFA_register: case DW_CFA_def_cfa: @@ -175,24 +388,424 @@ Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, return C.takeError(); } -namespace { +StringRef CFIProgram::callFrameString(unsigned Opcode) const { + return dwarf::CallFrameString(Opcode, Arch); +} + +const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT) { +#define ENUM_TO_CSTR(e) \ + case e: \ + return #e; + switch (OT) { + ENUM_TO_CSTR(OT_Unset); + ENUM_TO_CSTR(OT_None); + ENUM_TO_CSTR(OT_Address); + ENUM_TO_CSTR(OT_Offset); + ENUM_TO_CSTR(OT_FactoredCodeOffset); + ENUM_TO_CSTR(OT_SignedFactDataOffset); + ENUM_TO_CSTR(OT_UnsignedFactDataOffset); + ENUM_TO_CSTR(OT_Register); + ENUM_TO_CSTR(OT_AddressSpace); + ENUM_TO_CSTR(OT_Expression); + } + return "<unknown CFIProgram::OperandType>"; +} + +llvm::Expected<uint64_t> +CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram &CFIP, + uint32_t OperandIdx) const { + if (OperandIdx >= MaxOperands) + return createStringError(errc::invalid_argument, + "operand index %" PRIu32 " is not valid", + OperandIdx); + OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx]; + uint64_t Operand = Ops[OperandIdx]; + switch (Type) { + case OT_Unset: + case OT_None: + case OT_Expression: + return createStringError(errc::invalid_argument, + "op[%" PRIu32 "] has type %s which has no value", + OperandIdx, CFIProgram::operandTypeString(Type)); + + case OT_Offset: + case OT_SignedFactDataOffset: + case OT_UnsignedFactDataOffset: + return createStringError( + errc::invalid_argument, + "op[%" PRIu32 "] has OperandType OT_Offset which produces a signed " + "result, call getOperandAsSigned instead", + OperandIdx); + + case OT_Address: + case OT_Register: + case OT_AddressSpace: + return Operand; + + case OT_FactoredCodeOffset: { + const uint64_t CodeAlignmentFactor = CFIP.codeAlign(); + if (CodeAlignmentFactor == 0) + return createStringError( + errc::invalid_argument, + "op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment " + "is zero", + OperandIdx); + return Operand * CodeAlignmentFactor; + } + } + llvm_unreachable("invalid operand type"); +} + +llvm::Expected<int64_t> +CFIProgram::Instruction::getOperandAsSigned(const CFIProgram &CFIP, + uint32_t OperandIdx) const { + if (OperandIdx >= MaxOperands) + return createStringError(errc::invalid_argument, + "operand index %" PRIu32 " is not valid", + OperandIdx); + OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx]; + uint64_t Operand = Ops[OperandIdx]; + switch (Type) { + case OT_Unset: + case OT_None: + case OT_Expression: + return createStringError(errc::invalid_argument, + "op[%" PRIu32 "] has type %s which has no value", + OperandIdx, CFIProgram::operandTypeString(Type)); + + case OT_Address: + case OT_Register: + case OT_AddressSpace: + return createStringError( + errc::invalid_argument, + "op[%" PRIu32 "] has OperandType %s which produces an unsigned result, " + "call getOperandAsUnsigned instead", + OperandIdx, CFIProgram::operandTypeString(Type)); + + case OT_Offset: + return (int64_t)Operand; + + case OT_FactoredCodeOffset: + case OT_SignedFactDataOffset: { + const int64_t DataAlignmentFactor = CFIP.dataAlign(); + if (DataAlignmentFactor == 0) + return createStringError(errc::invalid_argument, + "op[%" PRIu32 "] has type %s but data " + "alignment is zero", + OperandIdx, CFIProgram::operandTypeString(Type)); + return int64_t(Operand) * DataAlignmentFactor; + } + + case OT_UnsignedFactDataOffset: { + const int64_t DataAlignmentFactor = CFIP.dataAlign(); + if (DataAlignmentFactor == 0) + return createStringError(errc::invalid_argument, + "op[%" PRIu32 + "] has type OT_UnsignedFactDataOffset but data " + "alignment is zero", + OperandIdx); + return Operand * DataAlignmentFactor; + } + } + llvm_unreachable("invalid operand type"); +} + +Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row, + const RegisterLocations *InitialLocs) { + std::vector<RegisterLocations> RegisterStates; + for (const CFIProgram::Instruction &Inst : CFIP) { + switch (Inst.Opcode) { + case dwarf::DW_CFA_set_loc: { + // The DW_CFA_set_loc instruction takes a single operand that + // represents a target address. The required action is to create a new + // table row using the specified address as the location. All other + // values in the new row are initially identical to the current row. + // The new location value is always greater than the current one. If + // the segment_size field of this FDE's CIE is non- zero, the initial + // location is preceded by a segment selector of the given length + llvm::Expected<uint64_t> NewAddress = Inst.getOperandAsUnsigned(CFIP, 0); + if (!NewAddress) + return NewAddress.takeError(); + if (*NewAddress <= Row.getAddress()) + return createStringError( + errc::invalid_argument, + "%s with adrress 0x%" PRIx64 " which must be greater than the " + "current row address 0x%" PRIx64, + CFIP.callFrameString(Inst.Opcode).str().c_str(), *NewAddress, + Row.getAddress()); + Rows.push_back(Row); + Row.setAddress(*NewAddress); + break; + } + + case dwarf::DW_CFA_advance_loc: + case dwarf::DW_CFA_advance_loc1: + case dwarf::DW_CFA_advance_loc2: + case dwarf::DW_CFA_advance_loc4: { + // The DW_CFA_advance instruction takes a single operand that + // represents a constant delta. The required action is to create a new + // table row with a location value that is computed by taking the + // current entry’s location value and adding the value of delta * + // code_alignment_factor. All other values in the new row are initially + // identical to the current row. + Rows.push_back(Row); + llvm::Expected<uint64_t> Offset = Inst.getOperandAsUnsigned(CFIP, 0); + if (!Offset) + return Offset.takeError(); + Row.slideAddress(*Offset); + break; + } + + case dwarf::DW_CFA_restore: + case dwarf::DW_CFA_restore_extended: { + // The DW_CFA_restore instruction takes a single operand (encoded with + // the opcode) that represents a register number. The required action + // is to change the rule for the indicated register to the rule + // assigned it by the initial_instructions in the CIE. + if (InitialLocs == nullptr) + return createStringError( + errc::invalid_argument, "%s encountered while parsing a CIE", + CFIP.callFrameString(Inst.Opcode).str().c_str()); + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + if (Optional<UnwindLocation> O = + InitialLocs->getRegisterLocation(*RegNum)) + Row.getRegisterLocations().setRegisterLocation(*RegNum, *O); + else + Row.getRegisterLocations().removeRegisterLocation(*RegNum); + break; + } + + case dwarf::DW_CFA_offset: + case dwarf::DW_CFA_offset_extended: + case dwarf::DW_CFA_offset_extended_sf: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1); + if (!Offset) + return Offset.takeError(); + Row.getRegisterLocations().setRegisterLocation( + *RegNum, UnwindLocation::createAtCFAPlusOffset(*Offset)); + break; + } + + case dwarf::DW_CFA_nop: + break; + + case dwarf::DW_CFA_remember_state: + RegisterStates.push_back(Row.getRegisterLocations()); + break; + + case dwarf::DW_CFA_restore_state: + if (RegisterStates.empty()) + return createStringError(errc::invalid_argument, + "DW_CFA_restore_state without a matching " + "previous DW_CFA_remember_state"); + Row.getRegisterLocations() = RegisterStates.back(); + RegisterStates.pop_back(); + break; + + case dwarf::DW_CFA_GNU_window_save: + switch (CFIP.triple()) { + case Triple::aarch64: + case Triple::aarch64_be: + case Triple::aarch64_32: { + // DW_CFA_GNU_window_save is used for different things on different + // architectures. For aarch64 it is known as + // DW_CFA_AARCH64_negate_ra_state. The action is to toggle the + // value of the return address state between 1 and 0. If there is + // no rule for the AARCH64_DWARF_PAUTH_RA_STATE register, then it + // should be initially set to 1. + constexpr uint32_t AArch64DWARFPAuthRaState = 34; + auto LRLoc = Row.getRegisterLocations().getRegisterLocation( + AArch64DWARFPAuthRaState); + if (LRLoc) { + if (LRLoc->getLocation() == UnwindLocation::Constant) { + // Toggle the constant value from 0 to 1 or 1 to 0. + LRLoc->setConstant(LRLoc->getConstant() ^ 1); + } else { + return createStringError( + errc::invalid_argument, + "%s encountered when existing rule for this register is not " + "a constant", + CFIP.callFrameString(Inst.Opcode).str().c_str()); + } + } else { + Row.getRegisterLocations().setRegisterLocation( + AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(1)); + } + break; + } + + case Triple::sparc: + case Triple::sparcv9: + case Triple::sparcel: + for (uint32_t RegNum = 16; RegNum < 32; ++RegNum) { + Row.getRegisterLocations().setRegisterLocation( + RegNum, UnwindLocation::createAtCFAPlusOffset((RegNum - 16) * 8)); + } + break; + default: { + return createStringError( + errc::not_supported, + "DW_CFA opcode %#x is not supported for architecture %s", + Inst.Opcode, Triple::getArchTypeName(CFIP.triple()).str().c_str()); -} // end anonymous namespace + break; + } + } + break; -ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { - static OperandType OpTypes[DW_CFA_restore+1][2]; + case dwarf::DW_CFA_undefined: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + Row.getRegisterLocations().setRegisterLocation( + *RegNum, UnwindLocation::createUndefined()); + break; + } + + case dwarf::DW_CFA_same_value: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + Row.getRegisterLocations().setRegisterLocation( + *RegNum, UnwindLocation::createSame()); + break; + } + + case dwarf::DW_CFA_GNU_args_size: + break; + + case dwarf::DW_CFA_register: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + llvm::Expected<uint64_t> NewRegNum = Inst.getOperandAsUnsigned(CFIP, 1); + if (!NewRegNum) + return NewRegNum.takeError(); + Row.getRegisterLocations().setRegisterLocation( + *RegNum, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum, 0)); + break; + } + + case dwarf::DW_CFA_val_offset: + case dwarf::DW_CFA_val_offset_sf: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1); + if (!Offset) + return Offset.takeError(); + Row.getRegisterLocations().setRegisterLocation( + *RegNum, UnwindLocation::createIsCFAPlusOffset(*Offset)); + break; + } + + case dwarf::DW_CFA_expression: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + Row.getRegisterLocations().setRegisterLocation( + *RegNum, UnwindLocation::createAtDWARFExpression(*Inst.Expression)); + break; + } + + case dwarf::DW_CFA_val_expression: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + Row.getRegisterLocations().setRegisterLocation( + *RegNum, UnwindLocation::createIsDWARFExpression(*Inst.Expression)); + break; + } + + case dwarf::DW_CFA_def_cfa_register: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset) + Row.getCFAValue() = + UnwindLocation::createIsRegisterPlusOffset(*RegNum, 0); + else + Row.getCFAValue().setRegister(*RegNum); + break; + } + + case dwarf::DW_CFA_def_cfa_offset: + case dwarf::DW_CFA_def_cfa_offset_sf: { + llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 0); + if (!Offset) + return Offset.takeError(); + if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset) { + return createStringError( + errc::invalid_argument, + "%s found when CFA rule was not RegPlusOffset", + CFIP.callFrameString(Inst.Opcode).str().c_str()); + } + Row.getCFAValue().setOffset(*Offset); + break; + } + + case dwarf::DW_CFA_def_cfa: + case dwarf::DW_CFA_def_cfa_sf: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1); + if (!Offset) + return Offset.takeError(); + Row.getCFAValue() = + UnwindLocation::createIsRegisterPlusOffset(*RegNum, *Offset); + break; + } + + case dwarf::DW_CFA_LLVM_def_aspace_cfa: + case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf: { + llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); + if (!RegNum) + return RegNum.takeError(); + llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1); + if (!Offset) + return Offset.takeError(); + llvm::Expected<uint32_t> CFAAddrSpace = + Inst.getOperandAsUnsigned(CFIP, 2); + if (!CFAAddrSpace) + return CFAAddrSpace.takeError(); + Row.getCFAValue() = UnwindLocation::createIsRegisterPlusOffset( + *RegNum, *Offset, *CFAAddrSpace); + break; + } + + case dwarf::DW_CFA_def_cfa_expression: + Row.getCFAValue() = + UnwindLocation::createIsDWARFExpression(*Inst.Expression); + break; + } + } + return Error::success(); +} + +ArrayRef<CFIProgram::OperandType[CFIProgram::MaxOperands]> +CFIProgram::getOperandTypes() { + static OperandType OpTypes[DW_CFA_restore + 1][MaxOperands]; static bool Initialized = false; if (Initialized) { - return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); + return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1); } Initialized = true; -#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ - do { \ - OpTypes[OP][0] = OPTYPE0; \ - OpTypes[OP][1] = OPTYPE1; \ +#define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2) \ + do { \ + OpTypes[OP][0] = OPTYPE0; \ + OpTypes[OP][1] = OPTYPE1; \ + OpTypes[OP][2] = OPTYPE2; \ } while (false) +#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ + DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None) #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) @@ -205,6 +818,10 @@ ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); + DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa, OT_Register, OT_Offset, + OT_AddressSpace); + DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf, OT_Register, + OT_SignedFactDataOffset, OT_AddressSpace); DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); @@ -230,7 +847,7 @@ ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { #undef DECLARE_OP1 #undef DECLARE_OP2 - return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); + return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1); } /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. @@ -238,14 +855,14 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI, bool IsEH, const Instruction &Instr, unsigned OperandIdx, uint64_t Operand) const { - assert(OperandIdx < 2); + assert(OperandIdx < MaxOperands); uint8_t Opcode = Instr.Opcode; OperandType Type = getOperandTypes()[Opcode][OperandIdx]; switch (Type) { case OT_Unset: { OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; - auto OpcodeName = CallFrameString(Opcode, Arch); + auto OpcodeName = callFrameString(Opcode); if (!OpcodeName.empty()) OS << " " << OpcodeName; else @@ -285,6 +902,9 @@ void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, OS << ' '; printRegister(OS, MRI, IsEH, Operand); break; + case OT_AddressSpace: + OS << format(" in addrspace%" PRId64, Operand); + break; case OT_Expression: assert(Instr.Expression && "missing DWARFExpression object"); OS << " "; @@ -298,10 +918,8 @@ void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts, unsigned IndentLevel) const { for (const auto &Instr : Instructions) { uint8_t Opcode = Instr.Opcode; - if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) - Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; OS.indent(2 * IndentLevel); - OS << CallFrameString(Opcode, Arch) << ":"; + OS << callFrameString(Opcode) << ":"; for (unsigned i = 0; i < Instr.Ops.size(); ++i) printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]); OS << '\n'; @@ -333,8 +951,10 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, getCIEId(IsDWARF64, IsEH)) << " CIE\n" - << " Format: " << FormatString(IsDWARF64) << "\n" - << format(" Version: %d\n", Version) + << " Format: " << FormatString(IsDWARF64) << "\n"; + if (IsEH && Version != 1) + OS << "WARNING: unsupported CIE version\n"; + OS << format(" Version: %d\n", Version) << " Augmentation: \"" << Augmentation << "\"\n"; if (Version >= 4) { OS << format(" Address size: %u\n", (uint32_t)AddressSize); @@ -355,6 +975,16 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, OS << "\n"; CFIs.dump(OS, DumpOpts, MRI, IsEH); OS << "\n"; + + if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this)) + RowsOrErr->dump(OS, MRI, IsEH, 1); + else { + DumpOpts.RecoverableErrorHandler(joinErrors( + createStringError(errc::invalid_argument, + "decoding the CIE opcodes into rows failed"), + RowsOrErr.takeError())); + } + OS << "\n"; } void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, @@ -374,6 +1004,16 @@ void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); CFIs.dump(OS, DumpOpts, MRI, IsEH); OS << "\n"; + + if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this)) + RowsOrErr->dump(OS, MRI, IsEH, 1); + else { + DumpOpts.RecoverableErrorHandler(joinErrors( + createStringError(errc::invalid_argument, + "decoding the FDE opcodes into rows failed"), + RowsOrErr.takeError())); + } + OS << "\n"; } DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch, @@ -434,11 +1074,6 @@ Error DWARFDebugFrame::parse(DWARFDataExtractor Data) { uint8_t Version = Data.getU8(&Offset); const char *Augmentation = Data.getCStr(&Offset); StringRef AugmentationString(Augmentation ? Augmentation : ""); - // TODO: we should provide a way to report a warning and continue dumping. - if (IsEH && Version != 1) - return createStringError(errc::not_supported, - "unsupported CIE version: %" PRIu8, Version); - uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : Data.getU8(&Offset); Data.setAddressSize(AddressSize); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index 2b7d0c3363a1..7ebb0092c34a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" @@ -30,17 +31,42 @@ bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint64_t *OffsetPtr, uint64_t UEndOffset, uint32_t D) { Offset = *OffsetPtr; Depth = D; - if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) + if (Offset >= UEndOffset) { + U.getContext().getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF unit from offset 0x%8.8" PRIx64 " incl. " + "to offset 0x%8.8" PRIx64 " excl. " + "tries to read DIEs at offset 0x%8.8" PRIx64, + U.getOffset(), U.getNextUnitOffset(), *OffsetPtr)); return false; + } + assert(DebugInfoData.isValidOffset(UEndOffset - 1)); uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); if (0 == AbbrCode) { // NULL debug tag entry. AbbrevDecl = nullptr; return true; } - if (const auto *AbbrevSet = U.getAbbreviations()) - AbbrevDecl = AbbrevSet->getAbbreviationDeclaration(AbbrCode); - if (nullptr == AbbrevDecl) { + const auto *AbbrevSet = U.getAbbreviations(); + if (!AbbrevSet) { + U.getContext().getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF unit at offset 0x%8.8" PRIx64 " " + "contains invalid abbreviation set offset 0x%" PRIx64, + U.getOffset(), U.getAbbreviationsOffset())); + // Restore the original offset. + *OffsetPtr = Offset; + return false; + } + AbbrevDecl = AbbrevSet->getAbbreviationDeclaration(AbbrCode); + if (!AbbrevDecl) { + U.getContext().getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF unit at offset 0x%8.8" PRIx64 " " + "contains invalid abbreviation %" PRIu64 " at " + "offset 0x%8.8" PRIx64 ", valid abbreviations are %s", + U.getOffset(), AbbrCode, *OffsetPtr, + AbbrevSet->getCodeRange().c_str())); // Restore the original offset. *OffsetPtr = Offset; return false; @@ -62,6 +88,11 @@ bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint64_t *OffsetPtr, OffsetPtr, U.getFormParams())) { // We failed to skip this attribute's value, restore the original offset // and return the failure status. + U.getContext().getWarningHandler()(createStringError( + errc::invalid_argument, + "DWARF unit at offset 0x%8.8" PRIx64 " " + "contains invalid FORM_* 0x%" PRIx16 " at offset 0x%8.8" PRIx64, + U.getOffset(), AttrSpec.Form, *OffsetPtr)); *OffsetPtr = Offset; return false; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 427f6f4942c3..0501e3ee3f9b 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -69,39 +69,43 @@ static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, } } -static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, - DWARFUnit *U, unsigned Indent, - DIDumpOptions DumpOpts) { +static void dumpLocationList(raw_ostream &OS, const DWARFFormValue &FormValue, + DWARFUnit *U, unsigned Indent, + DIDumpOptions DumpOpts) { + assert(FormValue.isFormClass(DWARFFormValue::FC_SectionOffset) && + "bad FORM for location list"); DWARFContext &Ctx = U->getContext(); const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); - if (FormValue.isFormClass(DWARFFormValue::FC_Block) || - FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { - ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); - DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), - Ctx.isLittleEndian(), 0); - DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format) - .print(OS, DumpOpts, MRI, U); - return; - } - - if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { - uint64_t Offset = *FormValue.getAsSectionOffset(); + uint64_t Offset = *FormValue.getAsSectionOffset(); - if (FormValue.getForm() == DW_FORM_loclistx) { - FormValue.dump(OS, DumpOpts); + if (FormValue.getForm() == DW_FORM_loclistx) { + FormValue.dump(OS, DumpOpts); - if (auto LoclistOffset = U->getLoclistOffset(Offset)) - Offset = *LoclistOffset; - else - return; - } - U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), - MRI, Ctx.getDWARFObj(), U, DumpOpts, - Indent); - return; + if (auto LoclistOffset = U->getLoclistOffset(Offset)) + Offset = *LoclistOffset; + else + return; } + U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), MRI, + Ctx.getDWARFObj(), U, DumpOpts, + Indent); + return; +} - FormValue.dump(OS, DumpOpts); +static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue, + DWARFUnit *U, unsigned Indent, + DIDumpOptions DumpOpts) { + assert((FormValue.isFormClass(DWARFFormValue::FC_Block) || + FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) && + "bad FORM for location expression"); + DWARFContext &Ctx = U->getContext(); + const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); + ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); + DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), + Ctx.isLittleEndian(), 0); + DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format) + .print(OS, DumpOpts, MRI, U); + return; } /// Dump the name encoded in the type tag. @@ -230,21 +234,22 @@ static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) { } static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, - uint64_t *OffsetPtr, dwarf::Attribute Attr, - dwarf::Form Form, unsigned Indent, + const DWARFAttribute &AttrValue, unsigned Indent, DIDumpOptions DumpOpts) { if (!Die.isValid()) return; const char BaseIndent[] = " "; OS << BaseIndent; OS.indent(Indent + 2); + dwarf::Attribute Attr = AttrValue.Attr; WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr); + dwarf::Form Form = AttrValue.Value.getForm(); if (DumpOpts.Verbose || DumpOpts.ShowForm) OS << formatv(" [{0}]", Form); DWARFUnit *U = Die.getDwarfUnit(); - DWARFFormValue FormValue = DWARFFormValue::createFromUnit(Form, U, OffsetPtr); + const DWARFFormValue &FormValue = AttrValue.Value; OS << "\t("; @@ -288,9 +293,15 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, else FormValue.dump(OS, DumpOpts); } - } else if (Form == dwarf::Form::DW_FORM_exprloc || - DWARFAttribute::mayHaveLocationDescription(Attr)) - dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); + } else if (DWARFAttribute::mayHaveLocationList(Attr) && + FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) + dumpLocationList(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, + DumpOpts); + else if (FormValue.isFormClass(DWARFFormValue::FC_Exprloc) || + (DWARFAttribute::mayHaveLocationExpr(Attr) && + FormValue.isFormClass(DWARFFormValue::FC_Block))) + dumpLocationExpr(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, + DumpOpts); else FormValue.dump(OS, DumpOpts); @@ -570,11 +581,16 @@ uint64_t DWARFDie::getDeclLine() const { std::string DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const { + auto D = getAttributeValueAsReferencedDie(DW_AT_abstract_origin); + if (!D) + D = *this; std::string FileName; - if (auto DeclFile = toUnsigned(findRecursively(DW_AT_decl_file))) { - if (const auto *LT = U->getContext().getLineTableForUnit(U)) { - LT->getFileNameByIndex(*DeclFile, U->getCompilationDir(), Kind, FileName); - } + if (auto DeclFile = toUnsigned(D.find(DW_AT_decl_file))) { + if (const auto *LineTable = + getDwarfUnit()->getContext().getLineTableForUnit( + D.getDwarfUnit()->getLinkedUnit())) + LineTable->getFileNameByIndex( + *DeclFile, D.getDwarfUnit()->getCompilationDir(), Kind, FileName); } return FileName; } @@ -631,25 +647,17 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent, OS << '\n'; // Dump all data in the DIE for the attributes. - for (const auto &AttrSpec : AbbrevDecl->attributes()) { - if (AttrSpec.Form == DW_FORM_implicit_const) { - // We are dumping .debug_info section , - // implicit_const attribute values are not really stored here, - // but in .debug_abbrev section. So we just skip such attrs. - continue; - } - dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, - Indent, DumpOpts); - } + for (const DWARFAttribute &AttrValue : attributes()) + dumpAttribute(OS, *this, AttrValue, Indent, DumpOpts); - DWARFDie child = getFirstChild(); - if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0 && child) { + if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0) { + DWARFDie Child = getFirstChild(); DumpOpts.ChildRecurseDepth--; DIDumpOptions ChildDumpOpts = DumpOpts; ChildDumpOpts.ShowParents = false; - while (child) { - child.dump(OS, Indent + 2, ChildDumpOpts); - child = child.getSibling(); + while (Child) { + Child.dump(OS, Indent + 2, ChildDumpOpts); + Child = Child.getSibling(); } } } else { @@ -723,10 +731,16 @@ void DWARFDie::attribute_iterator::updateForIndex( // Add the previous byte size of any previous attribute value. AttrValue.Offset += AttrValue.ByteSize; uint64_t ParseOffset = AttrValue.Offset; - auto U = Die.getDwarfUnit(); - assert(U && "Die must have valid DWARF unit"); - AttrValue.Value = DWARFFormValue::createFromUnit( - AbbrDecl.getFormByIndex(Index), U, &ParseOffset); + if (AbbrDecl.getAttrIsImplicitConstByIndex(Index)) + AttrValue.Value = DWARFFormValue::createFromSValue( + AbbrDecl.getFormByIndex(Index), + AbbrDecl.getAttrImplicitConstValueByIndex(Index)); + else { + auto U = Die.getDwarfUnit(); + assert(U && "Die must have valid DWARF unit"); + AttrValue.Value = DWARFFormValue::createFromUnit( + AbbrDecl.getFormByIndex(Index), U, &ParseOffset); + } AttrValue.ByteSize = ParseOffset - AttrValue.Offset; } else { assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); @@ -740,11 +754,29 @@ DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { return *this; } -bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { +bool DWARFAttribute::mayHaveLocationList(dwarf::Attribute Attr) { + switch(Attr) { + case DW_AT_location: + case DW_AT_string_length: + case DW_AT_return_addr: + case DW_AT_data_member_location: + case DW_AT_frame_base: + case DW_AT_static_link: + case DW_AT_segment: + case DW_AT_use_location: + case DW_AT_vtable_elem_location: + return true; + default: + return false; + } +} + +bool DWARFAttribute::mayHaveLocationExpr(dwarf::Attribute Attr) { switch (Attr) { // From the DWARF v5 specification. case DW_AT_location: case DW_AT_byte_size: + case DW_AT_bit_offset: case DW_AT_bit_size: case DW_AT_string_length: case DW_AT_lower_bound: @@ -760,6 +792,7 @@ bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { case DW_AT_vtable_elem_location: case DW_AT_allocated: case DW_AT_associated: + case DW_AT_data_location: case DW_AT_byte_stride: case DW_AT_rank: case DW_AT_call_value: diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp index 811716111be5..4b9be85f6885 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -174,7 +174,10 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, case Operation::WasmLocationArg: assert(Operand == 1); switch (Operands[0]) { - case 0: case 1: case 2: + case 0: + case 1: + case 2: + case 4: Operands[Operand] = Data.getULEB128(&Offset); break; case 3: // global as uint32 @@ -294,8 +297,11 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, DIDumpOptions DumpOpts, } else if (Size == Operation::WasmLocationArg) { assert(Operand == 1); switch (Operands[0]) { - case 0: case 1: case 2: + case 0: + case 1: + case 2: case 3: // global as uint32 + case 4: OS << format(" 0x%" PRIx64, Operands[Operand]); break; default: assert(false); @@ -319,6 +325,10 @@ void DWARFExpression::print(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *RegInfo, DWARFUnit *U, bool IsEH) const { uint32_t EntryValExprSize = 0; + uint64_t EntryValStartOffset = 0; + if (Data.getData().empty()) + OS << "<empty>"; + for (auto &Op : *this) { if (!Op.print(OS, DumpOpts, this, RegInfo, U, IsEH)) { uint64_t FailOffset = Op.getEndOffset(); @@ -331,11 +341,12 @@ void DWARFExpression::print(raw_ostream &OS, DIDumpOptions DumpOpts, Op.getCode() == DW_OP_GNU_entry_value) { OS << "("; EntryValExprSize = Op.getRawOperand(0); + EntryValStartOffset = Op.getEndOffset(); continue; } if (EntryValExprSize) { - EntryValExprSize--; + EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset; if (EntryValExprSize == 0) OS << ")"; } @@ -501,4 +512,10 @@ bool DWARFExpression::printCompact(raw_ostream &OS, const MCRegisterInfo &MRI) { return printCompactDWARFExpr(OS, begin(), end(), MRI); } +bool DWARFExpression::operator==(const DWARFExpression &RHS) const { + if (AddressSize != RHS.AddressSize || Format != RHS.Format) + return false; + return Data.getData() == RHS.Data.getData(); +} + } // namespace llvm diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 7a84605211fb..2244a69bc121 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -74,7 +74,7 @@ static const DWARFFormValue::FormClass DWARF5FormClasses[] = { DWARFFormValue::FC_Address, // 0x2a DW_FORM_addrx2 DWARFFormValue::FC_Address, // 0x2b DW_FORM_addrx3 DWARFFormValue::FC_Address, // 0x2c DW_FORM_addrx4 - + DWARFFormValue::FC_Address, // 0x2001 DW_FORM_addrx_offset }; DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) { @@ -168,6 +168,7 @@ bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, case DW_FORM_line_strp: case DW_FORM_GNU_ref_alt: case DW_FORM_GNU_strp_alt: + case DW_FORM_implicit_const: if (Optional<uint8_t> FixedSize = dwarf::getFixedFormByteSize(Form, Params)) { *OffsetPtr += *FixedSize; @@ -191,6 +192,11 @@ bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, DebugInfoData.getULEB128(OffsetPtr); return true; + case DW_FORM_LLVM_addrx_offset: + DebugInfoData.getULEB128(OffsetPtr); + *OffsetPtr += 4; + return true; + case DW_FORM_indirect: Indirect = true; Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr)); @@ -217,6 +223,8 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { case DW_FORM_GNU_str_index: case DW_FORM_GNU_strp_alt: return (FC == FC_String); + case DW_FORM_LLVM_addrx_offset: + return (FC == FC_Address); default: break; } @@ -322,6 +330,10 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, case DW_FORM_strx: Value.uval = Data.getULEB128(OffsetPtr, &Err); break; + case DW_FORM_LLVM_addrx_offset: + Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32; + Value.uval = Data.getU32(OffsetPtr, &Err); + break; case DW_FORM_string: Value.cstr = Data.getCStr(OffsetPtr, &Err); break; @@ -345,6 +357,9 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, case DW_FORM_ref_sig8: Value.uval = Data.getU64(OffsetPtr, &Err); break; + case DW_FORM_implicit_const: + // Value has been already set by DWARFFormValue::createFromSValue. + break; default: // DWARFFormValue::skipValue() will have caught this and caused all // DWARF DIEs to fail to be parsed, so this code is not be reachable. @@ -417,6 +432,23 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { OS << "<unresolved>"; break; } + case DW_FORM_LLVM_addrx_offset: { + if (U == nullptr) { + OS << "<invalid dwarf unit>"; + break; + } + uint32_t Index = UValue >> 32; + uint32_t Offset = UValue & 0xffffffff; + Optional<object::SectionedAddress> A = U->getAddrOffsetSectionItem(Index); + if (!A || DumpOpts.Verbose) + AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset); + if (A) { + A->Address += Offset; + dumpSectionedAddress(AddrOS, DumpOpts, *A); + } else + OS << "<unresolved>"; + break; + } case DW_FORM_flag_present: OS << "true"; break; @@ -482,6 +514,7 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { break; case DW_FORM_sdata: + case DW_FORM_implicit_const: OS << Value.sval; break; case DW_FORM_udata: @@ -636,13 +669,17 @@ 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; + bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset; + if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx || AddrOffset) { + + uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval; if (!U) return None; Optional<object::SectionedAddress> SA = U->getAddrOffsetSectionItem(Index); if (!SA) return None; + if (AddrOffset) + SA->Address += (Value.uval & 0xffffffff); return SA; } return {{Value.uval, Value.SectionIndex}}; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 8493950a29b2..f17dacfce665 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -192,17 +192,18 @@ DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { Optional<object::SectionedAddress> DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { - if (IsDWO) { + if (!AddrOffsetSectionBase) { auto R = Context.info_section_units(); // Surprising if a DWO file has more than one skeleton unit in it - this // probably shouldn't be valid, but if a use case is found, here's where to // support it (probably have to linearly search for the matching skeleton CU // here) - if (hasSingleElement(R)) + if (IsDWO && hasSingleElement(R)) return (*R.begin())->getAddrOffsetSectionItem(Index); - } - if (!AddrOffsetSectionBase) + return None; + } + uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize(); if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) return None; @@ -258,26 +259,73 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton) DWOId = debug_info.getU64(offset_ptr, &Err); - if (errorToBool(std::move(Err))) + if (Err) { + Context.getWarningHandler()(joinErrors( + createStringError( + errc::invalid_argument, + "DWARF unit at 0x%8.8" PRIx64 " cannot be parsed:", Offset), + std::move(Err))); return false; + } // Header fields all parsed, capture the size of this unit header. assert(*offset_ptr - Offset <= 255 && "unexpected header size"); Size = uint8_t(*offset_ptr - Offset); + uint64_t NextCUOffset = Offset + getUnitLengthFieldByteSize() + getLength(); + + if (!debug_info.isValidOffset(getNextUnitOffset() - 1)) { + Context.getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF unit from offset 0x%8.8" PRIx64 " incl. " + "to offset 0x%8.8" PRIx64 " excl. " + "extends past section size 0x%8.8zx", + Offset, NextCUOffset, debug_info.size())); + return false; + } + + if (!DWARFContext::isSupportedVersion(getVersion())) { + Context.getWarningHandler()(createStringError( + errc::invalid_argument, + "DWARF unit at offset 0x%8.8" PRIx64 " " + "has unsupported version %" PRIu16 ", supported are 2-%u", + Offset, getVersion(), DWARFContext::getMaxSupportedVersion())); + return false; + } // Type offset is unit-relative; should be after the header and before // the end of the current unit. - bool TypeOffsetOK = - !isTypeUnit() - ? true - : TypeOffset >= Size && - TypeOffset < getLength() + getUnitLengthFieldByteSize(); - bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); - bool VersionOK = DWARFContext::isSupportedVersion(getVersion()); - bool AddrSizeOK = DWARFContext::isAddressSizeSupported(getAddressByteSize()); + if (isTypeUnit() && TypeOffset < Size) { + Context.getWarningHandler()( + createStringError(errc::invalid_argument, + "DWARF type unit at offset " + "0x%8.8" PRIx64 " " + "has its relocated type_offset 0x%8.8" PRIx64 " " + "pointing inside the header", + Offset, Offset + TypeOffset)); + return false; + } + if (isTypeUnit() && + TypeOffset >= getUnitLengthFieldByteSize() + getLength()) { + Context.getWarningHandler()(createStringError( + errc::invalid_argument, + "DWARF type unit from offset 0x%8.8" PRIx64 " incl. " + "to offset 0x%8.8" PRIx64 " excl. has its " + "relocated type_offset 0x%8.8" PRIx64 " pointing past the unit end", + Offset, NextCUOffset, Offset + TypeOffset)); + return false; + } - if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK) + if (!DWARFContext::isAddressSizeSupported(getAddressByteSize())) { + SmallVector<std::string, 3> Sizes; + for (auto Size : DWARFContext::getSupportedAddressSizes()) + Sizes.push_back(std::to_string(Size)); + Context.getWarningHandler()(createStringError( + errc::invalid_argument, + "DWARF unit at offset 0x%8.8" PRIx64 " " + "has unsupported address size %" PRIu8 ", supported are %s", + Offset, getAddressByteSize(), llvm::join(Sizes, ", ").c_str())); return false; + } // Keep track of the highest DWARF version we encounter across all units. Context.setMaxVersionIfGreater(getVersion()); @@ -340,6 +388,7 @@ void DWARFUnit::clear() { RangeSectionBase = 0; LocSectionBase = 0; AddrOffsetSectionBase = None; + SU = nullptr; clearDIEs(false); DWO.reset(); } @@ -360,6 +409,8 @@ void DWARFUnit::extractDIEsToVector( uint64_t NextCUOffset = getNextUnitOffset(); DWARFDebugInfoEntry DIE; DWARFDataExtractor DebugInfoData = getDebugInfoExtractor(); + // The end offset has been already checked by DWARFUnitHeader::extract. + assert(DebugInfoData.isValidOffset(NextCUOffset - 1)); uint32_t Depth = 0; bool IsCUDie = true; @@ -384,6 +435,8 @@ void DWARFUnit::extractDIEsToVector( // Normal DIE if (AbbrDecl->hasChildren()) ++Depth; + else if (Depth == 0) + break; // This unit has a single DIE with no children. } else { // NULL DIE. if (Depth > 0) @@ -392,17 +445,6 @@ void DWARFUnit::extractDIEsToVector( break; // We are done with this compile unit! } } - - // Give a little bit of info if we encounter corrupt DWARF (our offset - // should always terminate at or before the start of the next compilation - // unit header). - if (DIEOffset > NextCUOffset) - Context.getWarningHandler()( - createStringError(errc::invalid_argument, - "DWARF compile unit extends beyond its " - "bounds cu 0x%8.8" PRIx64 " " - "at 0x%8.8" PRIx64 "\n", - getOffset(), DIEOffset)); } void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { @@ -545,13 +587,11 @@ bool DWARFUnit::parseDWO() { if (!DWOCU) return false; DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); + DWO->setSkeletonUnit(this); // Share .debug_addr and .debug_ranges section with compile unit in .dwo if (AddrOffsetSectionBase) DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase); - if (getVersion() >= 5) { - DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), - DWARFListTableHeader::getHeaderSize(getFormat())); - } else { + if (getVersion() == 4) { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); } @@ -688,15 +728,15 @@ DWARFUnit::getInlinedChainForAddress(uint64_t Address, DWARFDie SubroutineDIE = (DWO ? *DWO : *this).getSubroutineForAddress(Address); - if (!SubroutineDIE) - return; - - while (!SubroutineDIE.isSubprogramDIE()) { + while (SubroutineDIE) { + if (SubroutineDIE.isSubprogramDIE()) { + InlinedChain.push_back(SubroutineDIE); + return; + } if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine) InlinedChain.push_back(SubroutineDIE); SubroutineDIE = SubroutineDIE.getParent(); } - InlinedChain.push_back(SubroutineDIE); } const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context, @@ -793,7 +833,7 @@ DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) { const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { if (!Abbrevs) - Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset()); + Abbrevs = Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset()); return Abbrevs; } |
