Index: llvm/include/llvm/DebugInfo/DWARF/DWARFAttribute.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFAttribute.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFAttribute.h @@ -42,6 +42,10 @@ return isValid(); } + /// Identifies DWARF attributes that may contain a reference to a + /// DWARF expression. + static bool mayHaveLocationDescription(dwarf::Attribute Attr); + void clear() { Offset = 0; ByteSize = 0; Index: llvm/lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -316,9 +316,7 @@ else 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) + } else if (DWARFAttribute::mayHaveLocationDescription(Attr)) dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); else formValue.dump(OS, DumpOpts); @@ -709,3 +707,39 @@ updateForIndex(*AbbrDecl, Index + 1); return *this; } + +bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { + switch (Attr) { + // From the DWARF 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; + } +} Index: llvm/test/tools/dsymutil/X86/op-convert.test =================================================================== --- llvm/test/tools/dsymutil/X86/op-convert.test +++ llvm/test/tools/dsymutil/X86/op-convert.test @@ -1,6 +1,6 @@ # REQUIRES: object-emission # RUN: dsymutil -f -o %t --verify -oso-prepend-path=%p/../Inputs -y %s -# RUN: llvm-dwarfdump -a %t | FileCheck %s +# RUN: llvm-dwarfdump %t | FileCheck %s --- triple: 'x86_64-apple-darwin' @@ -11,5 +11,25 @@ ... -CHECK: XXX +CHECK: DW_TAG_base_type +CHECK-NEXT: DW_AT_name ("DW_ATE_signed_8") +CHECK-NEXT: DW_AT_encoding (DW_ATE_signed) +CHECK-NEXT: DW_AT_byte_size (0x01) + +CHECK: DW_TAG_base_type +CHECK-NEXT: DW_AT_name ("DW_ATE_signed_32") +CHECK-NEXT: DW_AT_encoding (DW_ATE_signed) +CHECK-NEXT: DW_AT_byte_size (0x04) + +CHECK: DW_TAG_variable + +CHECK: DW_TAG_variable +CHECK-NEXT: DW_AT_location (0x00000036 +CHECK-NEXT: [0x0000000000000000, 0x0000000000000002): DW_OP_breg5 RDI+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert (0x0000002a) "DW_ATE_signed_8", DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value +CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert (0x0000002a) "DW_ATE_signed_8", DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value) +CHECK-NEXT: DW_AT_name ("y") + +CHECK: DW_TAG_variable +CHECK-NEXT: DW_AT_location (DW_OP_constu 0x2a, DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value) +CHECK-NEXT: DW_AT_name ("c") Index: llvm/tools/dsymutil/DwarfLinker.h =================================================================== --- llvm/tools/dsymutil/DwarfLinker.h +++ llvm/tools/dsymutil/DwarfLinker.h @@ -136,7 +136,7 @@ CompileUnit::DIEInfo &Info); bool applyValidRelocs(MutableArrayRef Data, uint32_t BaseOffset, - bool isLittleEndian); + bool IsLittleEndian); }; /// Keeps track of data associated with one object during linking. @@ -185,7 +185,7 @@ void lookForDIEsToKeep(RelocationManager &RelocMgr, RangesTy &Ranges, const UnitListTy &Units, const DWARFDie &DIE, const DebugMapObject &DMO, CompileUnit &CU, - unsigned Flags); + unsigned Flags, bool IsLittleEndian); /// If this compile unit is really a skeleton CU that points to a /// clang module, register it in ClangModules and return true. @@ -200,7 +200,8 @@ UniquingStringPool &UniquingStringPoolStringPool, DeclContextTree &ODRContexts, uint64_t ModulesEndOffset, unsigned &UnitID, - unsigned Indent = 0, bool Quiet = false); + bool IsLittleEndian, unsigned Indent = 0, + bool Quiet = false); /// Recursively add the debug info in this clang module .pcm /// file (and all the modules imported by it in a bottom-up fashion) @@ -211,8 +212,8 @@ RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool, UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts, uint64_t ModulesEndOffset, - unsigned &UnitID, unsigned Indent = 0, - bool Quiet = false); + unsigned &UnitID, bool IsLittleEndian, + unsigned Indent = 0, bool Quiet = false); /// Flags passed to DwarfLinker::lookForDIEsToKeep enum TraversalFlags { @@ -224,18 +225,32 @@ TF_SkipPC = 1 << 5, ///< Skip all location attributes. }; + void scanExpressionDIERefs(RelocationManager &RelocMgr, RangesTy &Ranges, + const UnitListTy &Units, const DWARFDie &DIE, + DWARFExpression Expression, + const DebugMapObject &DMO, CompileUnit &CU, + bool IsLittleEndian); + + void scanExpressionDIERefs(RelocationManager &RelocMgr, RangesTy &Ranges, + const UnitListTy &Units, const DWARFDie &DIE, + const DWARFFormValue &AttrValue, + const DebugMapObject &DMO, CompileUnit &CU, + bool IsLittleEndian); + /// Mark the passed DIE as well as all the ones it depends on as kept. void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges, const UnitListTy &Units, const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo, const DebugMapObject &DMO, CompileUnit &CU, - bool UseODR); + bool UseODR, bool IsLittleEndian); unsigned shouldKeepDIE(RelocationManager &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE, const DebugMapObject &DMO, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags); + /// Check if a variable describing DIE should be kept. + /// \returns updated TraversalFlags. unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr, const DWARFDie &DIE, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags); @@ -286,14 +301,15 @@ DIE *cloneDIE(const DWARFDie &InputDIE, const DebugMapObject &DMO, CompileUnit &U, OffsetsStringPool &StringPool, int64_t PCOffset, uint32_t OutOffset, unsigned Flags, - DIE *Die = nullptr); + bool IsLittleEndian, DIE *Die = nullptr); /// Construct the output DIE tree by cloning the DIEs we /// chose to keep above. If there are no valid relocs, then there's /// nothing to clone/emit. void cloneAllCompileUnits(DWARFContext &DwarfContext, const DebugMapObject &DMO, RangesTy &Ranges, - OffsetsStringPool &StringPool); + OffsetsStringPool &StringPool, + bool IsLittleEndian); private: using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec; @@ -335,7 +351,7 @@ OffsetsStringPool &StringPool, const DWARFFormValue &Val, const AttributeSpec AttrSpec, unsigned AttrSize, - AttributesInfo &AttrInfo); + AttributesInfo &AttrInfo, bool IsLittleEndian); /// Clone a string attribute described by \p AttrSpec and add /// it to \p Die. @@ -355,11 +371,24 @@ const DebugMapObject &DMO, CompileUnit &Unit); + /// Clone a DWARF expression that may be referencing another DIE. + void cloneExpression(DIEValueList *Attr, DataExtractor &Data, + const DWARFDie &InputDIE, DWARFExpression Expression, + const DebugMapObject &DMO, CompileUnit &Unit); + + /// Clone a DWARF expression that may be referencing another DIE. + void cloneExpression(DIEValueList *Attr, ArrayRef Expr, + const DWARFDie &InputDIE, const DebugMapObject &DMO, + CompileUnit &Unit, bool IsLittleEndian); + /// Clone an attribute referencing another DIE and add /// it to \p Die. /// \returns the size of the new attribute. - unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec, - const DWARFFormValue &Val, unsigned AttrSize); + unsigned cloneBlockAttribute(DIE &Die, const DWARFDie &InputDIE, + const DebugMapObject &DMO, CompileUnit &Unit, + AttributeSpec AttrSpec, + const DWARFFormValue &Val, unsigned AttrSize, + bool IsLittleEndian); /// Clone an attribute referencing another DIE and add /// it to \p Die. Index: llvm/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/tools/dsymutil/DwarfLinker.cpp +++ llvm/tools/dsymutil/DwarfLinker.cpp @@ -120,12 +120,9 @@ static DWARFDie resolveDIEReference(const DwarfLinker &Linker, const DebugMapObject &DMO, const UnitListTy &Units, - const DWARFFormValue &RefValue, + uint64_t RefOffset, const DWARFUnit &Unit, const DWARFDie &DIE, CompileUnit *&RefCU) { - assert(RefValue.isFormClass(DWARFFormValue::FC_Reference)); - uint64_t RefOffset = *RefValue.getAsReference(); - if ((RefCU = getUnitForOffset(Units, RefOffset))) if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) { // In a file with broken references, an attribute might point to a NULL @@ -138,6 +135,17 @@ return DWARFDie(); } +static DWARFDie resolveDIEReference(const DwarfLinker &Linker, + const DebugMapObject &DMO, + const UnitListTy &Units, + const DWARFFormValue &RefValue, + const DWARFUnit &Unit, const DWARFDie &DIE, + CompileUnit *&RefCU) { + assert(RefValue.isFormClass(DWARFFormValue::FC_Reference)); + uint64_t RefOffset = *RefValue.getAsReference(); + return resolveDIEReference(Linker, DMO, Units, RefOffset, Unit, DIE, RefCU); +} + /// \returns whether the passed \a Attr type might contain a DIE reference /// suitable for ODR uniquing. static bool isODRAttribute(uint16_t Attr) { @@ -585,7 +593,7 @@ MyInfo.InDebugMap = true; return Flags | TF_Keep; } - + Optional LocationIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_location); if (!LocationIdx) @@ -706,6 +714,52 @@ return Flags; } +void DwarfLinker::scanExpressionDIERefs( + RelocationManager &RelocMgr, RangesTy &Ranges, const UnitListTy &Units, + const DWARFDie &DIE, DWARFExpression Expression, const DebugMapObject &DMO, + CompileUnit &CU, bool IsLittleEndian) { + uint32_t OpOffset = 0; + for (auto &Op : Expression) { + if (Op.getCode() == dwarf::DW_OP_convert) { + assert(OpOffset < Op.getEndOffset()); + uint64_t RefOffset = Op.getRawOperand(0); + CompileUnit *ReferencedCU; + auto RefDie = resolveDIEReference(*this, DMO, Units, RefOffset, + CU.getOrigUnit(), DIE, ReferencedCU); + if (!RefDie) + continue; + assert(ReferencedCU == &CU); + lookForDIEsToKeep(RelocMgr, Ranges, Units, RefDie, DMO, *ReferencedCU, + TF_Keep | TF_DependencyWalk, IsLittleEndian); + bool UseODR = false; + uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDie); + CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefIdx); + keepDIEAndDependencies(RelocMgr, Ranges, Units, RefDie, Info, DMO, CU, + UseODR, IsLittleEndian); + } + OpOffset = Op.getEndOffset(); + } +} + +void DwarfLinker::scanExpressionDIERefs( + RelocationManager &RelocMgr, RangesTy &Ranges, const UnitListTy &Units, + const DWARFDie &DIE, const DWARFFormValue &AttrValue, + const DebugMapObject &DMO, CompileUnit &CU, bool IsLittleEndian) { + if (AttrValue.isFormClass(DWARFFormValue::FC_Block) || + AttrValue.isFormClass(DWARFFormValue::FC_Exprloc)) { + ArrayRef Expr = *AttrValue.getAsBlock(); + DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), + IsLittleEndian, 0); + DWARFUnit &Unit = CU.getOrigUnit(); + scanExpressionDIERefs( + RelocMgr, Ranges, Units, DIE, + DWARFExpression(Data, Unit.getVersion(), Unit.getAddressByteSize()), + DMO, CU, IsLittleEndian); + return; + } + // TODO: Implement DWARF 5 forms. +} + /// Mark the passed DIE as well as all the ones it depends on /// as kept. /// @@ -717,7 +771,8 @@ void DwarfLinker::keepDIEAndDependencies( RelocationManager &RelocMgr, RangesTy &Ranges, const UnitListTy &Units, const DWARFDie &Die, CompileUnit::DIEInfo &MyInfo, - const DebugMapObject &DMO, CompileUnit &CU, bool UseODR) { + const DebugMapObject &DMO, CompileUnit &CU, bool UseODR, + bool IsLittleEndian) { DWARFUnit &Unit = CU.getOrigUnit(); MyInfo.Keep = true; @@ -730,9 +785,9 @@ unsigned AncestorIdx = MyInfo.ParentIdx; while (!CU.getInfo(AncestorIdx).Keep) { unsigned ODRFlag = UseODR ? TF_ODR : 0; - lookForDIEsToKeep(RelocMgr, Ranges, Units, Unit.getDIEAtIndex(AncestorIdx), - DMO, CU, - TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag); + lookForDIEsToKeep( + RelocMgr, Ranges, Units, Unit.getDIEAtIndex(AncestorIdx), DMO, CU, + TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag, IsLittleEndian); AncestorIdx = CU.getInfo(AncestorIdx).ParentIdx; } @@ -746,6 +801,11 @@ for (const auto &AttrSpec : Abbrev->attributes()) { DWARFFormValue Val(AttrSpec.Form); + // Scan for DIE references in location descriptions. + if (DWARFAttribute::mayHaveLocationDescription(AttrSpec.Attr)) + scanExpressionDIERefs(RelocMgr, Ranges, Units, Die, + *Die.find(AttrSpec.Attr), DMO, CU, IsLittleEndian); + if (!Val.isFormClass(DWARFFormValue::FC_Reference) || AttrSpec.Attr == dwarf::DW_AT_sibling) { DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, @@ -782,7 +842,7 @@ unsigned ODRFlag = UseODR ? TF_ODR : 0; lookForDIEsToKeep(RelocMgr, Ranges, Units, RefDie, DMO, *ReferencedCU, - TF_Keep | TF_DependencyWalk | ODRFlag); + TF_Keep | TF_DependencyWalk | ODRFlag, IsLittleEndian); // The incomplete property is propagated if the current DIE is complete // but references an incomplete DIE. @@ -859,7 +919,7 @@ RangesTy &Ranges, const UnitListTy &Units, const DWARFDie &Die, const DebugMapObject &DMO, CompileUnit &CU, - unsigned Flags) { + unsigned Flags, bool IsLittleEndian) { // LIFO work list. SmallVector Worklist; Worklist.emplace_back(Die, Flags); @@ -903,7 +963,7 @@ ? (Current.Flags & TF_ODR) : CU.hasODR(); keepDIEAndDependencies(RelocMgr, Ranges, Units, Current.Die, MyInfo, DMO, - CU, UseOdr); + CU, UseOdr, IsLittleEndian); } // The TF_ParentWalk flag tells us that we are currently walking up @@ -1052,10 +1112,64 @@ return AttrSize; } -unsigned DwarfLinker::DIECloner::cloneBlockAttribute(DIE &Die, - AttributeSpec AttrSpec, - const DWARFFormValue &Val, - unsigned AttrSize) { +void DwarfLinker::DIECloner::cloneExpression( + DIEValueList *Attr, DataExtractor &Data, const DWARFDie &InputDIE, + DWARFExpression Expression, const DebugMapObject &DMO, CompileUnit &Unit) { + auto pushByte = [&](uint8_t Byte) { + Attr->addValue(DIEAlloc, static_cast(0), + dwarf::DW_FORM_data1, DIEInteger(Byte)); + }; + + uint32_t OpOffset = 0; + for (auto &Op : Expression) { + if (Op.getCode() == dwarf::DW_OP_convert) { + assert(OpOffset < Op.getEndOffset()); + uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1; + assert(ULEBsize <= 16); + + uint64_t RefOffset = Op.getRawOperand(0); + auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset); + uint32_t RefIdx = Unit.getOrigUnit().getDIEIndex(RefDie); + CompileUnit::DIEInfo &Info = Unit.getInfo(RefIdx); + DIE *Clone = Info.Clone; + assert(Clone && "base type not created at beginning of CU"); + uint32_t Offset = Clone->getOffset(); + pushByte(dwarf::DW_OP_convert); + uint8_t Buffer[16]; + unsigned RealSize = encodeULEB128(Offset, Buffer, ULEBsize); + if (RealSize > ULEBsize) { + memset(Buffer, dwarf::DW_OP_nop, ULEBsize); + Linker.reportWarning("DW_OP_convert type ref doesn't fit.", DMO, + &InputDIE); + } + for (unsigned I = 0; I < ULEBsize; ++I) + pushByte(Buffer[I]); + } else { + // Copy over everything else unmodified. + for (unsigned I = OpOffset; I < Op.getEndOffset(); ++I) + pushByte(Data.getData()[I]); + } + OpOffset = Op.getEndOffset(); + } +} + +void DwarfLinker::DIECloner::cloneExpression( + DIEValueList *Attr, ArrayRef Expr, const DWARFDie &InputDIE, + const DebugMapObject &DMO, CompileUnit &Unit, bool IsLittleEndian) { + DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), + IsLittleEndian, 0); + DWARFUnit &OrigUnit = Unit.getOrigUnit(); + cloneExpression(Attr, Data, InputDIE, + DWARFExpression(Data, OrigUnit.getVersion(), + OrigUnit.getAddressByteSize()), + DMO, Unit); + // TODO: Implement DWARF 5 forms. +} + +unsigned DwarfLinker::DIECloner::cloneBlockAttribute( + DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO, + CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, + unsigned AttrSize, bool IsLittleEndian) { DIEValueList *Attr; DIEValue Value; DIELoc *Loc = nullptr; @@ -1078,9 +1192,15 @@ Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form), Block); ArrayRef Bytes = *Val.getAsBlock(); - for (auto Byte : Bytes) - Attr->addValue(DIEAlloc, static_cast(0), - dwarf::DW_FORM_data1, DIEInteger(Byte)); + if (DWARFAttribute::mayHaveLocationDescription(AttrSpec.Attr) && + (Val.isFormClass(DWARFFormValue::FC_Block) || + Val.isFormClass(DWARFFormValue::FC_Exprloc))) { + cloneExpression(Attr, Bytes, InputDIE, DMO, Unit, IsLittleEndian); + } else { + for (auto Byte : Bytes) + Attr->addValue(DIEAlloc, static_cast(0), + dwarf::DW_FORM_data1, DIEInteger(Byte)); + } // FIXME: If DIEBlock and DIELoc just reuses the Size field of // the DIE class, this if could be replaced by // Attr->setSize(Bytes.size()). @@ -1198,8 +1318,9 @@ // A more generic way to check for location attributes would be // nice, but it's very unlikely that any other attribute needs a // location list. + // FIXME: use DWARFAttribute::mayHaveLocationDescription(). else if (AttrSpec.Attr == dwarf::DW_AT_location || - AttrSpec.Attr == dwarf::DW_AT_frame_base) + AttrSpec.Attr == dwarf::DW_AT_frame_base) Unit.noteLocationAttribute(Patch, Info.PCOffset); else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) Info.IsDeclaration = true; @@ -1213,7 +1334,8 @@ unsigned DwarfLinker::DIECloner::cloneAttribute( DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO, CompileUnit &Unit, OffsetsStringPool &StringPool, const DWARFFormValue &Val, - const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info) { + const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info, + bool IsLittleEndian) { const DWARFUnit &U = Unit.getOrigUnit(); switch (AttrSpec.Form) { @@ -1232,7 +1354,8 @@ case dwarf::DW_FORM_block2: case dwarf::DW_FORM_block4: case dwarf::DW_FORM_exprloc: - return cloneBlockAttribute(Die, AttrSpec, Val, AttrSize); + return cloneBlockAttribute(Die, InputDIE, DMO, Unit, AttrSpec, Val, + AttrSize, IsLittleEndian); case dwarf::DW_FORM_addr: return cloneAddressAttribute(Die, AttrSpec, Val, Unit, Info); case dwarf::DW_FORM_data1: @@ -1264,7 +1387,7 @@ /// /// \returns whether any reloc has been applied. bool DwarfLinker::RelocationManager::applyValidRelocs( - MutableArrayRef Data, uint32_t BaseOffset, bool isLittleEndian) { + MutableArrayRef Data, uint32_t BaseOffset, bool IsLittleEndian) { assert((NextValidReloc == 0 || BaseOffset > ValidRelocs[NextValidReloc - 1].Offset) && "BaseOffset should only be increasing."); @@ -1288,7 +1411,7 @@ uint64_t Value = ValidReloc.Mapping->getValue().BinaryAddress; Value += ValidReloc.Addend; for (unsigned i = 0; i != ValidReloc.Size; ++i) { - unsigned Index = isLittleEndian ? i : (ValidReloc.Size - i - 1); + unsigned Index = IsLittleEndian ? i : (ValidReloc.Size - i - 1); Buf[i] = uint8_t(Value >> (Index * 8)); } assert(ValidReloc.Size <= sizeof(Buf)); @@ -1370,12 +1493,10 @@ } } -DIE *DwarfLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, - const DebugMapObject &DMO, - CompileUnit &Unit, - OffsetsStringPool &StringPool, - int64_t PCOffset, uint32_t OutOffset, - unsigned Flags, DIE *Die) { +DIE *DwarfLinker::DIECloner::cloneDIE( + const DWARFDie &InputDIE, const DebugMapObject &DMO, CompileUnit &Unit, + OffsetsStringPool &StringPool, int64_t PCOffset, uint32_t OutOffset, + unsigned Flags, bool IsLittleEndian, DIE *Die) { DWARFUnit &U = Unit.getOrigUnit(); unsigned Idx = U.getDIEIndex(InputDIE); CompileUnit::DIEInfo &Info = Unit.getInfo(Idx); @@ -1481,7 +1602,7 @@ AttrSize = Offset - AttrSize; OutOffset += cloneAttribute(*Die, InputDIE, DMO, Unit, StringPool, Val, - AttrSpec, AttrSize, AttrInfo); + AttrSpec, AttrSize, AttrInfo, IsLittleEndian); } // Look for accelerator entries. @@ -1556,7 +1677,7 @@ // Recursively clone children. for (auto Child : InputDIE.children()) { if (DIE *Clone = cloneDIE(Child, DMO, Unit, StringPool, PCOffset, OutOffset, - Flags)) { + Flags, IsLittleEndian)) { Die->addChild(Clone); OutOffset = Clone->getOffset() + Clone->getSize(); } @@ -2033,7 +2154,8 @@ const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap, const DebugMapObject &DMO, RangesTy &Ranges, OffsetsStringPool &StringPool, UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts, - uint64_t ModulesEndOffset, unsigned &UnitID, unsigned Indent, bool Quiet) { + uint64_t ModulesEndOffset, unsigned &UnitID, bool IsLittleEndian, + unsigned Indent, bool Quiet) { std::string PCMfile = dwarf::toString( CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); if (PCMfile.empty()) @@ -2075,10 +2197,10 @@ // Cyclic dependencies are disallowed by Clang, but we still // shouldn't run into an infinite loop, so mark it as processed now. ClangModules.insert({PCMfile, DwoId}); - if (Error E = - loadClangModule(PCMfile, PCMpath, Name, DwoId, ModuleMap, DMO, Ranges, - StringPool, UniquingStringPool, ODRContexts, - ModulesEndOffset, UnitID, Indent + 2, Quiet)) { + if (Error E = loadClangModule(PCMfile, PCMpath, Name, DwoId, ModuleMap, DMO, + Ranges, StringPool, UniquingStringPool, + ODRContexts, ModulesEndOffset, UnitID, + IsLittleEndian, Indent + 2, Quiet)) { consumeError(std::move(E)); return false; } @@ -2112,7 +2234,8 @@ uint64_t DwoId, DebugMap &ModuleMap, const DebugMapObject &DMO, RangesTy &Ranges, OffsetsStringPool &StringPool, UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts, - uint64_t ModulesEndOffset, unsigned &UnitID, unsigned Indent, bool Quiet) { + uint64_t ModulesEndOffset, unsigned &UnitID, bool IsLittleEndian, + unsigned Indent, bool Quiet) { SmallString<80> Path(Options.PrependPath); if (sys::path::is_relative(Filename)) sys::path::append(Path, ModulePath, Filename); @@ -2174,7 +2297,8 @@ continue; if (!registerModuleReference(CUDie, *CU, ModuleMap, DMO, Ranges, StringPool, UniquingStringPool, ODRContexts, - ModulesEndOffset, UnitID, Indent, Quiet)) { + ModulesEndOffset, UnitID, IsLittleEndian, + Indent, Quiet)) { if (Unit) { std::string Err = (Filename + @@ -2218,13 +2342,14 @@ UnitListTy CompileUnits; CompileUnits.push_back(std::move(Unit)); DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options) - .cloneAllCompileUnits(*DwarfContext, DMO, Ranges, StringPool); + .cloneAllCompileUnits(*DwarfContext, DMO, Ranges, StringPool, + IsLittleEndian); return Error::success(); } void DwarfLinker::DIECloner::cloneAllCompileUnits( DWARFContext &DwarfContext, const DebugMapObject &DMO, RangesTy &Ranges, - OffsetsStringPool &StringPool) { + OffsetsStringPool &StringPool, bool IsLittleEndian) { if (!Linker.Streamer) return; @@ -2240,7 +2365,8 @@ // already has a DIE inside of it. CurrentUnit->createOutputDIE(); cloneDIE(InputDIE, DMO, *CurrentUnit, StringPool, 0 /* PC offset */, - 11 /* Unit Header size */, 0, CurrentUnit->getOutputUnitDIE()); + 11 /* Unit Header size */, 0, IsLittleEndian, + CurrentUnit->getOutputUnitDIE()); } Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(); @@ -2490,7 +2616,8 @@ if (CUDie && !LLVM_UNLIKELY(Options.Update)) registerModuleReference(CUDie, *CU, ModuleMap, LinkContext.DMO, LinkContext.Ranges, OffsetsStringPool, - UniquingStringPool, ODRContexts, 0, UnitID); + UniquingStringPool, ODRContexts, 0, UnitID, + LinkContext.DwarfContext->isLittleEndian()); } } @@ -2569,10 +2696,10 @@ Streamer->copyInvariantDebugSection(*LinkContext.ObjectFile); } else { for (auto &CurrentUnit : LinkContext.CompileUnits) - lookForDIEsToKeep(LinkContext.RelocMgr, LinkContext.Ranges, - LinkContext.CompileUnits, - CurrentUnit->getOrigUnit().getUnitDIE(), - LinkContext.DMO, *CurrentUnit, 0); + lookForDIEsToKeep( + LinkContext.RelocMgr, LinkContext.Ranges, LinkContext.CompileUnits, + CurrentUnit->getOrigUnit().getUnitDIE(), LinkContext.DMO, + *CurrentUnit, 0, LinkContext.DwarfContext->isLittleEndian()); } // The calls to applyValidRelocs inside cloneDIE will walk the reloc @@ -2583,7 +2710,8 @@ DIECloner(*this, LinkContext.RelocMgr, DIEAlloc, LinkContext.CompileUnits, Options) .cloneAllCompileUnits(*LinkContext.DwarfContext, LinkContext.DMO, - LinkContext.Ranges, OffsetsStringPool); + LinkContext.Ranges, OffsetsStringPool, + LinkContext.DwarfContext->isLittleEndian()); if (!Options.NoOutput && !LinkContext.CompileUnits.empty() && LLVM_LIKELY(!Options.Update)) patchFrameInfoForObject(