1*1db9f3b2SDimitry Andric //=== DWARFLinker.cpp -----------------------------------------------------===// 2*1db9f3b2SDimitry Andric // 3*1db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*1db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*1db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*1db9f3b2SDimitry Andric // 7*1db9f3b2SDimitry Andric //===----------------------------------------------------------------------===// 8*1db9f3b2SDimitry Andric 9*1db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinker.h" 10*1db9f3b2SDimitry Andric #include "llvm/ADT/ArrayRef.h" 11*1db9f3b2SDimitry Andric #include "llvm/ADT/BitVector.h" 12*1db9f3b2SDimitry Andric #include "llvm/ADT/STLExtras.h" 13*1db9f3b2SDimitry Andric #include "llvm/ADT/StringExtras.h" 14*1db9f3b2SDimitry Andric #include "llvm/CodeGen/NonRelocatableStringpool.h" 15*1db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h" 16*1db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFStreamer.h" 17*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 18*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" 19*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 20*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 21*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" 22*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" 23*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" 24*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDie.h" 25*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 26*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 27*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFSection.h" 28*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 29*1db9f3b2SDimitry Andric #include "llvm/MC/MCDwarf.h" 30*1db9f3b2SDimitry Andric #include "llvm/Support/DataExtractor.h" 31*1db9f3b2SDimitry Andric #include "llvm/Support/Error.h" 32*1db9f3b2SDimitry Andric #include "llvm/Support/ErrorHandling.h" 33*1db9f3b2SDimitry Andric #include "llvm/Support/ErrorOr.h" 34*1db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h" 35*1db9f3b2SDimitry Andric #include "llvm/Support/LEB128.h" 36*1db9f3b2SDimitry Andric #include "llvm/Support/Path.h" 37*1db9f3b2SDimitry Andric #include "llvm/Support/ThreadPool.h" 38*1db9f3b2SDimitry Andric #include <vector> 39*1db9f3b2SDimitry Andric 40*1db9f3b2SDimitry Andric namespace llvm { 41*1db9f3b2SDimitry Andric 42*1db9f3b2SDimitry Andric using namespace dwarf_linker; 43*1db9f3b2SDimitry Andric using namespace dwarf_linker::classic; 44*1db9f3b2SDimitry Andric 45*1db9f3b2SDimitry Andric /// Hold the input and output of the debug info size in bytes. 46*1db9f3b2SDimitry Andric struct DebugInfoSize { 47*1db9f3b2SDimitry Andric uint64_t Input; 48*1db9f3b2SDimitry Andric uint64_t Output; 49*1db9f3b2SDimitry Andric }; 50*1db9f3b2SDimitry Andric 51*1db9f3b2SDimitry Andric /// Compute the total size of the debug info. 52*1db9f3b2SDimitry Andric static uint64_t getDebugInfoSize(DWARFContext &Dwarf) { 53*1db9f3b2SDimitry Andric uint64_t Size = 0; 54*1db9f3b2SDimitry Andric for (auto &Unit : Dwarf.compile_units()) { 55*1db9f3b2SDimitry Andric Size += Unit->getLength(); 56*1db9f3b2SDimitry Andric } 57*1db9f3b2SDimitry Andric return Size; 58*1db9f3b2SDimitry Andric } 59*1db9f3b2SDimitry Andric 60*1db9f3b2SDimitry Andric /// Similar to DWARFUnitSection::getUnitForOffset(), but returning our 61*1db9f3b2SDimitry Andric /// CompileUnit object instead. 62*1db9f3b2SDimitry Andric static CompileUnit *getUnitForOffset(const UnitListTy &Units, uint64_t Offset) { 63*1db9f3b2SDimitry Andric auto CU = llvm::upper_bound( 64*1db9f3b2SDimitry Andric Units, Offset, [](uint64_t LHS, const std::unique_ptr<CompileUnit> &RHS) { 65*1db9f3b2SDimitry Andric return LHS < RHS->getOrigUnit().getNextUnitOffset(); 66*1db9f3b2SDimitry Andric }); 67*1db9f3b2SDimitry Andric return CU != Units.end() ? CU->get() : nullptr; 68*1db9f3b2SDimitry Andric } 69*1db9f3b2SDimitry Andric 70*1db9f3b2SDimitry Andric /// Resolve the DIE attribute reference that has been extracted in \p RefValue. 71*1db9f3b2SDimitry Andric /// The resulting DIE might be in another CompileUnit which is stored into \p 72*1db9f3b2SDimitry Andric /// ReferencedCU. \returns null if resolving fails for any reason. 73*1db9f3b2SDimitry Andric DWARFDie DWARFLinker::resolveDIEReference(const DWARFFile &File, 74*1db9f3b2SDimitry Andric const UnitListTy &Units, 75*1db9f3b2SDimitry Andric const DWARFFormValue &RefValue, 76*1db9f3b2SDimitry Andric const DWARFDie &DIE, 77*1db9f3b2SDimitry Andric CompileUnit *&RefCU) { 78*1db9f3b2SDimitry Andric assert(RefValue.isFormClass(DWARFFormValue::FC_Reference)); 79*1db9f3b2SDimitry Andric uint64_t RefOffset = *RefValue.getAsReference(); 80*1db9f3b2SDimitry Andric if ((RefCU = getUnitForOffset(Units, RefOffset))) 81*1db9f3b2SDimitry Andric if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) { 82*1db9f3b2SDimitry Andric // In a file with broken references, an attribute might point to a NULL 83*1db9f3b2SDimitry Andric // DIE. 84*1db9f3b2SDimitry Andric if (!RefDie.isNULL()) 85*1db9f3b2SDimitry Andric return RefDie; 86*1db9f3b2SDimitry Andric } 87*1db9f3b2SDimitry Andric 88*1db9f3b2SDimitry Andric reportWarning("could not find referenced DIE", File, &DIE); 89*1db9f3b2SDimitry Andric return DWARFDie(); 90*1db9f3b2SDimitry Andric } 91*1db9f3b2SDimitry Andric 92*1db9f3b2SDimitry Andric /// \returns whether the passed \a Attr type might contain a DIE reference 93*1db9f3b2SDimitry Andric /// suitable for ODR uniquing. 94*1db9f3b2SDimitry Andric static bool isODRAttribute(uint16_t Attr) { 95*1db9f3b2SDimitry Andric switch (Attr) { 96*1db9f3b2SDimitry Andric default: 97*1db9f3b2SDimitry Andric return false; 98*1db9f3b2SDimitry Andric case dwarf::DW_AT_type: 99*1db9f3b2SDimitry Andric case dwarf::DW_AT_containing_type: 100*1db9f3b2SDimitry Andric case dwarf::DW_AT_specification: 101*1db9f3b2SDimitry Andric case dwarf::DW_AT_abstract_origin: 102*1db9f3b2SDimitry Andric case dwarf::DW_AT_import: 103*1db9f3b2SDimitry Andric return true; 104*1db9f3b2SDimitry Andric } 105*1db9f3b2SDimitry Andric llvm_unreachable("Improper attribute."); 106*1db9f3b2SDimitry Andric } 107*1db9f3b2SDimitry Andric 108*1db9f3b2SDimitry Andric static bool isTypeTag(uint16_t Tag) { 109*1db9f3b2SDimitry Andric switch (Tag) { 110*1db9f3b2SDimitry Andric case dwarf::DW_TAG_array_type: 111*1db9f3b2SDimitry Andric case dwarf::DW_TAG_class_type: 112*1db9f3b2SDimitry Andric case dwarf::DW_TAG_enumeration_type: 113*1db9f3b2SDimitry Andric case dwarf::DW_TAG_pointer_type: 114*1db9f3b2SDimitry Andric case dwarf::DW_TAG_reference_type: 115*1db9f3b2SDimitry Andric case dwarf::DW_TAG_string_type: 116*1db9f3b2SDimitry Andric case dwarf::DW_TAG_structure_type: 117*1db9f3b2SDimitry Andric case dwarf::DW_TAG_subroutine_type: 118*1db9f3b2SDimitry Andric case dwarf::DW_TAG_typedef: 119*1db9f3b2SDimitry Andric case dwarf::DW_TAG_union_type: 120*1db9f3b2SDimitry Andric case dwarf::DW_TAG_ptr_to_member_type: 121*1db9f3b2SDimitry Andric case dwarf::DW_TAG_set_type: 122*1db9f3b2SDimitry Andric case dwarf::DW_TAG_subrange_type: 123*1db9f3b2SDimitry Andric case dwarf::DW_TAG_base_type: 124*1db9f3b2SDimitry Andric case dwarf::DW_TAG_const_type: 125*1db9f3b2SDimitry Andric case dwarf::DW_TAG_constant: 126*1db9f3b2SDimitry Andric case dwarf::DW_TAG_file_type: 127*1db9f3b2SDimitry Andric case dwarf::DW_TAG_namelist: 128*1db9f3b2SDimitry Andric case dwarf::DW_TAG_packed_type: 129*1db9f3b2SDimitry Andric case dwarf::DW_TAG_volatile_type: 130*1db9f3b2SDimitry Andric case dwarf::DW_TAG_restrict_type: 131*1db9f3b2SDimitry Andric case dwarf::DW_TAG_atomic_type: 132*1db9f3b2SDimitry Andric case dwarf::DW_TAG_interface_type: 133*1db9f3b2SDimitry Andric case dwarf::DW_TAG_unspecified_type: 134*1db9f3b2SDimitry Andric case dwarf::DW_TAG_shared_type: 135*1db9f3b2SDimitry Andric case dwarf::DW_TAG_immutable_type: 136*1db9f3b2SDimitry Andric return true; 137*1db9f3b2SDimitry Andric default: 138*1db9f3b2SDimitry Andric break; 139*1db9f3b2SDimitry Andric } 140*1db9f3b2SDimitry Andric return false; 141*1db9f3b2SDimitry Andric } 142*1db9f3b2SDimitry Andric 143*1db9f3b2SDimitry Andric bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die, 144*1db9f3b2SDimitry Andric AttributesInfo &Info, 145*1db9f3b2SDimitry Andric OffsetsStringPool &StringPool, 146*1db9f3b2SDimitry Andric bool StripTemplate) { 147*1db9f3b2SDimitry Andric // This function will be called on DIEs having low_pcs and 148*1db9f3b2SDimitry Andric // ranges. As getting the name might be more expansive, filter out 149*1db9f3b2SDimitry Andric // blocks directly. 150*1db9f3b2SDimitry Andric if (Die.getTag() == dwarf::DW_TAG_lexical_block) 151*1db9f3b2SDimitry Andric return false; 152*1db9f3b2SDimitry Andric 153*1db9f3b2SDimitry Andric if (!Info.MangledName) 154*1db9f3b2SDimitry Andric if (const char *MangledName = Die.getLinkageName()) 155*1db9f3b2SDimitry Andric Info.MangledName = StringPool.getEntry(MangledName); 156*1db9f3b2SDimitry Andric 157*1db9f3b2SDimitry Andric if (!Info.Name) 158*1db9f3b2SDimitry Andric if (const char *Name = Die.getShortName()) 159*1db9f3b2SDimitry Andric Info.Name = StringPool.getEntry(Name); 160*1db9f3b2SDimitry Andric 161*1db9f3b2SDimitry Andric if (!Info.MangledName) 162*1db9f3b2SDimitry Andric Info.MangledName = Info.Name; 163*1db9f3b2SDimitry Andric 164*1db9f3b2SDimitry Andric if (StripTemplate && Info.Name && Info.MangledName != Info.Name) { 165*1db9f3b2SDimitry Andric StringRef Name = Info.Name.getString(); 166*1db9f3b2SDimitry Andric if (std::optional<StringRef> StrippedName = StripTemplateParameters(Name)) 167*1db9f3b2SDimitry Andric Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName); 168*1db9f3b2SDimitry Andric } 169*1db9f3b2SDimitry Andric 170*1db9f3b2SDimitry Andric return Info.Name || Info.MangledName; 171*1db9f3b2SDimitry Andric } 172*1db9f3b2SDimitry Andric 173*1db9f3b2SDimitry Andric /// Resolve the relative path to a build artifact referenced by DWARF by 174*1db9f3b2SDimitry Andric /// applying DW_AT_comp_dir. 175*1db9f3b2SDimitry Andric static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) { 176*1db9f3b2SDimitry Andric sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), "")); 177*1db9f3b2SDimitry Andric } 178*1db9f3b2SDimitry Andric 179*1db9f3b2SDimitry Andric /// Make a best effort to guess the 180*1db9f3b2SDimitry Andric /// Xcode.app/Contents/Developer/Toolchains/ path from an SDK path. 181*1db9f3b2SDimitry Andric static SmallString<128> guessToolchainBaseDir(StringRef SysRoot) { 182*1db9f3b2SDimitry Andric SmallString<128> Result; 183*1db9f3b2SDimitry Andric // Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk 184*1db9f3b2SDimitry Andric StringRef Base = sys::path::parent_path(SysRoot); 185*1db9f3b2SDimitry Andric if (sys::path::filename(Base) != "SDKs") 186*1db9f3b2SDimitry Andric return Result; 187*1db9f3b2SDimitry Andric Base = sys::path::parent_path(Base); 188*1db9f3b2SDimitry Andric Result = Base; 189*1db9f3b2SDimitry Andric Result += "/Toolchains"; 190*1db9f3b2SDimitry Andric return Result; 191*1db9f3b2SDimitry Andric } 192*1db9f3b2SDimitry Andric 193*1db9f3b2SDimitry Andric /// Collect references to parseable Swift interfaces in imported 194*1db9f3b2SDimitry Andric /// DW_TAG_module blocks. 195*1db9f3b2SDimitry Andric static void analyzeImportedModule( 196*1db9f3b2SDimitry Andric const DWARFDie &DIE, CompileUnit &CU, 197*1db9f3b2SDimitry Andric DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, 198*1db9f3b2SDimitry Andric std::function<void(const Twine &, const DWARFDie &)> ReportWarning) { 199*1db9f3b2SDimitry Andric if (CU.getLanguage() != dwarf::DW_LANG_Swift) 200*1db9f3b2SDimitry Andric return; 201*1db9f3b2SDimitry Andric 202*1db9f3b2SDimitry Andric if (!ParseableSwiftInterfaces) 203*1db9f3b2SDimitry Andric return; 204*1db9f3b2SDimitry Andric 205*1db9f3b2SDimitry Andric StringRef Path = dwarf::toStringRef(DIE.find(dwarf::DW_AT_LLVM_include_path)); 206*1db9f3b2SDimitry Andric if (!Path.ends_with(".swiftinterface")) 207*1db9f3b2SDimitry Andric return; 208*1db9f3b2SDimitry Andric // Don't track interfaces that are part of the SDK. 209*1db9f3b2SDimitry Andric StringRef SysRoot = dwarf::toStringRef(DIE.find(dwarf::DW_AT_LLVM_sysroot)); 210*1db9f3b2SDimitry Andric if (SysRoot.empty()) 211*1db9f3b2SDimitry Andric SysRoot = CU.getSysRoot(); 212*1db9f3b2SDimitry Andric if (!SysRoot.empty() && Path.starts_with(SysRoot)) 213*1db9f3b2SDimitry Andric return; 214*1db9f3b2SDimitry Andric // Don't track interfaces that are part of the toolchain. 215*1db9f3b2SDimitry Andric // For example: Swift, _Concurrency, ... 216*1db9f3b2SDimitry Andric SmallString<128> Toolchain = guessToolchainBaseDir(SysRoot); 217*1db9f3b2SDimitry Andric if (!Toolchain.empty() && Path.starts_with(Toolchain)) 218*1db9f3b2SDimitry Andric return; 219*1db9f3b2SDimitry Andric std::optional<const char *> Name = 220*1db9f3b2SDimitry Andric dwarf::toString(DIE.find(dwarf::DW_AT_name)); 221*1db9f3b2SDimitry Andric if (!Name) 222*1db9f3b2SDimitry Andric return; 223*1db9f3b2SDimitry Andric auto &Entry = (*ParseableSwiftInterfaces)[*Name]; 224*1db9f3b2SDimitry Andric // The prepend path is applied later when copying. 225*1db9f3b2SDimitry Andric DWARFDie CUDie = CU.getOrigUnit().getUnitDIE(); 226*1db9f3b2SDimitry Andric SmallString<128> ResolvedPath; 227*1db9f3b2SDimitry Andric if (sys::path::is_relative(Path)) 228*1db9f3b2SDimitry Andric resolveRelativeObjectPath(ResolvedPath, CUDie); 229*1db9f3b2SDimitry Andric sys::path::append(ResolvedPath, Path); 230*1db9f3b2SDimitry Andric if (!Entry.empty() && Entry != ResolvedPath) 231*1db9f3b2SDimitry Andric ReportWarning(Twine("Conflicting parseable interfaces for Swift Module ") + 232*1db9f3b2SDimitry Andric *Name + ": " + Entry + " and " + Path, 233*1db9f3b2SDimitry Andric DIE); 234*1db9f3b2SDimitry Andric Entry = std::string(ResolvedPath.str()); 235*1db9f3b2SDimitry Andric } 236*1db9f3b2SDimitry Andric 237*1db9f3b2SDimitry Andric /// The distinct types of work performed by the work loop in 238*1db9f3b2SDimitry Andric /// analyzeContextInfo. 239*1db9f3b2SDimitry Andric enum class ContextWorklistItemType : uint8_t { 240*1db9f3b2SDimitry Andric AnalyzeContextInfo, 241*1db9f3b2SDimitry Andric UpdateChildPruning, 242*1db9f3b2SDimitry Andric UpdatePruning, 243*1db9f3b2SDimitry Andric }; 244*1db9f3b2SDimitry Andric 245*1db9f3b2SDimitry Andric /// This class represents an item in the work list. The type defines what kind 246*1db9f3b2SDimitry Andric /// of work needs to be performed when processing the current item. Everything 247*1db9f3b2SDimitry Andric /// but the Type and Die fields are optional based on the type. 248*1db9f3b2SDimitry Andric struct ContextWorklistItem { 249*1db9f3b2SDimitry Andric DWARFDie Die; 250*1db9f3b2SDimitry Andric unsigned ParentIdx; 251*1db9f3b2SDimitry Andric union { 252*1db9f3b2SDimitry Andric CompileUnit::DIEInfo *OtherInfo; 253*1db9f3b2SDimitry Andric DeclContext *Context; 254*1db9f3b2SDimitry Andric }; 255*1db9f3b2SDimitry Andric ContextWorklistItemType Type; 256*1db9f3b2SDimitry Andric bool InImportedModule; 257*1db9f3b2SDimitry Andric 258*1db9f3b2SDimitry Andric ContextWorklistItem(DWARFDie Die, ContextWorklistItemType T, 259*1db9f3b2SDimitry Andric CompileUnit::DIEInfo *OtherInfo = nullptr) 260*1db9f3b2SDimitry Andric : Die(Die), ParentIdx(0), OtherInfo(OtherInfo), Type(T), 261*1db9f3b2SDimitry Andric InImportedModule(false) {} 262*1db9f3b2SDimitry Andric 263*1db9f3b2SDimitry Andric ContextWorklistItem(DWARFDie Die, DeclContext *Context, unsigned ParentIdx, 264*1db9f3b2SDimitry Andric bool InImportedModule) 265*1db9f3b2SDimitry Andric : Die(Die), ParentIdx(ParentIdx), Context(Context), 266*1db9f3b2SDimitry Andric Type(ContextWorklistItemType::AnalyzeContextInfo), 267*1db9f3b2SDimitry Andric InImportedModule(InImportedModule) {} 268*1db9f3b2SDimitry Andric }; 269*1db9f3b2SDimitry Andric 270*1db9f3b2SDimitry Andric static bool updatePruning(const DWARFDie &Die, CompileUnit &CU, 271*1db9f3b2SDimitry Andric uint64_t ModulesEndOffset) { 272*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = CU.getInfo(Die); 273*1db9f3b2SDimitry Andric 274*1db9f3b2SDimitry Andric // Prune this DIE if it is either a forward declaration inside a 275*1db9f3b2SDimitry Andric // DW_TAG_module or a DW_TAG_module that contains nothing but 276*1db9f3b2SDimitry Andric // forward declarations. 277*1db9f3b2SDimitry Andric Info.Prune &= (Die.getTag() == dwarf::DW_TAG_module) || 278*1db9f3b2SDimitry Andric (isTypeTag(Die.getTag()) && 279*1db9f3b2SDimitry Andric dwarf::toUnsigned(Die.find(dwarf::DW_AT_declaration), 0)); 280*1db9f3b2SDimitry Andric 281*1db9f3b2SDimitry Andric // Only prune forward declarations inside a DW_TAG_module for which a 282*1db9f3b2SDimitry Andric // definition exists elsewhere. 283*1db9f3b2SDimitry Andric if (ModulesEndOffset == 0) 284*1db9f3b2SDimitry Andric Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset(); 285*1db9f3b2SDimitry Andric else 286*1db9f3b2SDimitry Andric Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() > 0 && 287*1db9f3b2SDimitry Andric Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset; 288*1db9f3b2SDimitry Andric 289*1db9f3b2SDimitry Andric return Info.Prune; 290*1db9f3b2SDimitry Andric } 291*1db9f3b2SDimitry Andric 292*1db9f3b2SDimitry Andric static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU, 293*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &ChildInfo) { 294*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = CU.getInfo(Die); 295*1db9f3b2SDimitry Andric Info.Prune &= ChildInfo.Prune; 296*1db9f3b2SDimitry Andric } 297*1db9f3b2SDimitry Andric 298*1db9f3b2SDimitry Andric /// Recursive helper to build the global DeclContext information and 299*1db9f3b2SDimitry Andric /// gather the child->parent relationships in the original compile unit. 300*1db9f3b2SDimitry Andric /// 301*1db9f3b2SDimitry Andric /// This function uses the same work list approach as lookForDIEsToKeep. 302*1db9f3b2SDimitry Andric /// 303*1db9f3b2SDimitry Andric /// \return true when this DIE and all of its children are only 304*1db9f3b2SDimitry Andric /// forward declarations to types defined in external clang modules 305*1db9f3b2SDimitry Andric /// (i.e., forward declarations that are children of a DW_TAG_module). 306*1db9f3b2SDimitry Andric static void analyzeContextInfo( 307*1db9f3b2SDimitry Andric const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, 308*1db9f3b2SDimitry Andric DeclContext *CurrentDeclContext, DeclContextTree &Contexts, 309*1db9f3b2SDimitry Andric uint64_t ModulesEndOffset, 310*1db9f3b2SDimitry Andric DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces, 311*1db9f3b2SDimitry Andric std::function<void(const Twine &, const DWARFDie &)> ReportWarning) { 312*1db9f3b2SDimitry Andric // LIFO work list. 313*1db9f3b2SDimitry Andric std::vector<ContextWorklistItem> Worklist; 314*1db9f3b2SDimitry Andric Worklist.emplace_back(DIE, CurrentDeclContext, ParentIdx, false); 315*1db9f3b2SDimitry Andric 316*1db9f3b2SDimitry Andric while (!Worklist.empty()) { 317*1db9f3b2SDimitry Andric ContextWorklistItem Current = Worklist.back(); 318*1db9f3b2SDimitry Andric Worklist.pop_back(); 319*1db9f3b2SDimitry Andric 320*1db9f3b2SDimitry Andric switch (Current.Type) { 321*1db9f3b2SDimitry Andric case ContextWorklistItemType::UpdatePruning: 322*1db9f3b2SDimitry Andric updatePruning(Current.Die, CU, ModulesEndOffset); 323*1db9f3b2SDimitry Andric continue; 324*1db9f3b2SDimitry Andric case ContextWorklistItemType::UpdateChildPruning: 325*1db9f3b2SDimitry Andric updateChildPruning(Current.Die, CU, *Current.OtherInfo); 326*1db9f3b2SDimitry Andric continue; 327*1db9f3b2SDimitry Andric case ContextWorklistItemType::AnalyzeContextInfo: 328*1db9f3b2SDimitry Andric break; 329*1db9f3b2SDimitry Andric } 330*1db9f3b2SDimitry Andric 331*1db9f3b2SDimitry Andric unsigned Idx = CU.getOrigUnit().getDIEIndex(Current.Die); 332*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = CU.getInfo(Idx); 333*1db9f3b2SDimitry Andric 334*1db9f3b2SDimitry Andric // Clang imposes an ODR on modules(!) regardless of the language: 335*1db9f3b2SDimitry Andric // "The module-id should consist of only a single identifier, 336*1db9f3b2SDimitry Andric // which provides the name of the module being defined. Each 337*1db9f3b2SDimitry Andric // module shall have a single definition." 338*1db9f3b2SDimitry Andric // 339*1db9f3b2SDimitry Andric // This does not extend to the types inside the modules: 340*1db9f3b2SDimitry Andric // "[I]n C, this implies that if two structs are defined in 341*1db9f3b2SDimitry Andric // different submodules with the same name, those two types are 342*1db9f3b2SDimitry Andric // distinct types (but may be compatible types if their 343*1db9f3b2SDimitry Andric // definitions match)." 344*1db9f3b2SDimitry Andric // 345*1db9f3b2SDimitry Andric // We treat non-C++ modules like namespaces for this reason. 346*1db9f3b2SDimitry Andric if (Current.Die.getTag() == dwarf::DW_TAG_module && 347*1db9f3b2SDimitry Andric Current.ParentIdx == 0 && 348*1db9f3b2SDimitry Andric dwarf::toString(Current.Die.find(dwarf::DW_AT_name), "") != 349*1db9f3b2SDimitry Andric CU.getClangModuleName()) { 350*1db9f3b2SDimitry Andric Current.InImportedModule = true; 351*1db9f3b2SDimitry Andric analyzeImportedModule(Current.Die, CU, ParseableSwiftInterfaces, 352*1db9f3b2SDimitry Andric ReportWarning); 353*1db9f3b2SDimitry Andric } 354*1db9f3b2SDimitry Andric 355*1db9f3b2SDimitry Andric Info.ParentIdx = Current.ParentIdx; 356*1db9f3b2SDimitry Andric Info.InModuleScope = CU.isClangModule() || Current.InImportedModule; 357*1db9f3b2SDimitry Andric if (CU.hasODR() || Info.InModuleScope) { 358*1db9f3b2SDimitry Andric if (Current.Context) { 359*1db9f3b2SDimitry Andric auto PtrInvalidPair = Contexts.getChildDeclContext( 360*1db9f3b2SDimitry Andric *Current.Context, Current.Die, CU, Info.InModuleScope); 361*1db9f3b2SDimitry Andric Current.Context = PtrInvalidPair.getPointer(); 362*1db9f3b2SDimitry Andric Info.Ctxt = 363*1db9f3b2SDimitry Andric PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer(); 364*1db9f3b2SDimitry Andric if (Info.Ctxt) 365*1db9f3b2SDimitry Andric Info.Ctxt->setDefinedInClangModule(Info.InModuleScope); 366*1db9f3b2SDimitry Andric } else 367*1db9f3b2SDimitry Andric Info.Ctxt = Current.Context = nullptr; 368*1db9f3b2SDimitry Andric } 369*1db9f3b2SDimitry Andric 370*1db9f3b2SDimitry Andric Info.Prune = Current.InImportedModule; 371*1db9f3b2SDimitry Andric // Add children in reverse order to the worklist to effectively process 372*1db9f3b2SDimitry Andric // them in order. 373*1db9f3b2SDimitry Andric Worklist.emplace_back(Current.Die, ContextWorklistItemType::UpdatePruning); 374*1db9f3b2SDimitry Andric for (auto Child : reverse(Current.Die.children())) { 375*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &ChildInfo = CU.getInfo(Child); 376*1db9f3b2SDimitry Andric Worklist.emplace_back( 377*1db9f3b2SDimitry Andric Current.Die, ContextWorklistItemType::UpdateChildPruning, &ChildInfo); 378*1db9f3b2SDimitry Andric Worklist.emplace_back(Child, Current.Context, Idx, 379*1db9f3b2SDimitry Andric Current.InImportedModule); 380*1db9f3b2SDimitry Andric } 381*1db9f3b2SDimitry Andric } 382*1db9f3b2SDimitry Andric } 383*1db9f3b2SDimitry Andric 384*1db9f3b2SDimitry Andric static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) { 385*1db9f3b2SDimitry Andric switch (Tag) { 386*1db9f3b2SDimitry Andric default: 387*1db9f3b2SDimitry Andric return false; 388*1db9f3b2SDimitry Andric case dwarf::DW_TAG_class_type: 389*1db9f3b2SDimitry Andric case dwarf::DW_TAG_common_block: 390*1db9f3b2SDimitry Andric case dwarf::DW_TAG_lexical_block: 391*1db9f3b2SDimitry Andric case dwarf::DW_TAG_structure_type: 392*1db9f3b2SDimitry Andric case dwarf::DW_TAG_subprogram: 393*1db9f3b2SDimitry Andric case dwarf::DW_TAG_subroutine_type: 394*1db9f3b2SDimitry Andric case dwarf::DW_TAG_union_type: 395*1db9f3b2SDimitry Andric return true; 396*1db9f3b2SDimitry Andric } 397*1db9f3b2SDimitry Andric llvm_unreachable("Invalid Tag"); 398*1db9f3b2SDimitry Andric } 399*1db9f3b2SDimitry Andric 400*1db9f3b2SDimitry Andric void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) { 401*1db9f3b2SDimitry Andric Context.clear(); 402*1db9f3b2SDimitry Andric 403*1db9f3b2SDimitry Andric for (DIEBlock *I : DIEBlocks) 404*1db9f3b2SDimitry Andric I->~DIEBlock(); 405*1db9f3b2SDimitry Andric for (DIELoc *I : DIELocs) 406*1db9f3b2SDimitry Andric I->~DIELoc(); 407*1db9f3b2SDimitry Andric 408*1db9f3b2SDimitry Andric DIEBlocks.clear(); 409*1db9f3b2SDimitry Andric DIELocs.clear(); 410*1db9f3b2SDimitry Andric DIEAlloc.Reset(); 411*1db9f3b2SDimitry Andric } 412*1db9f3b2SDimitry Andric 413*1db9f3b2SDimitry Andric static bool isTlsAddressCode(uint8_t DW_OP_Code) { 414*1db9f3b2SDimitry Andric return DW_OP_Code == dwarf::DW_OP_form_tls_address || 415*1db9f3b2SDimitry Andric DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address; 416*1db9f3b2SDimitry Andric } 417*1db9f3b2SDimitry Andric 418*1db9f3b2SDimitry Andric std::pair<bool, std::optional<int64_t>> 419*1db9f3b2SDimitry Andric DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr, 420*1db9f3b2SDimitry Andric const DWARFDie &DIE) { 421*1db9f3b2SDimitry Andric assert((DIE.getTag() == dwarf::DW_TAG_variable || 422*1db9f3b2SDimitry Andric DIE.getTag() == dwarf::DW_TAG_constant) && 423*1db9f3b2SDimitry Andric "Wrong type of input die"); 424*1db9f3b2SDimitry Andric 425*1db9f3b2SDimitry Andric const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); 426*1db9f3b2SDimitry Andric 427*1db9f3b2SDimitry Andric // Check if DIE has DW_AT_location attribute. 428*1db9f3b2SDimitry Andric DWARFUnit *U = DIE.getDwarfUnit(); 429*1db9f3b2SDimitry Andric std::optional<uint32_t> LocationIdx = 430*1db9f3b2SDimitry Andric Abbrev->findAttributeIndex(dwarf::DW_AT_location); 431*1db9f3b2SDimitry Andric if (!LocationIdx) 432*1db9f3b2SDimitry Andric return std::make_pair(false, std::nullopt); 433*1db9f3b2SDimitry Andric 434*1db9f3b2SDimitry Andric // Get offset to the DW_AT_location attribute. 435*1db9f3b2SDimitry Andric uint64_t AttrOffset = 436*1db9f3b2SDimitry Andric Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U); 437*1db9f3b2SDimitry Andric 438*1db9f3b2SDimitry Andric // Get value of the DW_AT_location attribute. 439*1db9f3b2SDimitry Andric std::optional<DWARFFormValue> LocationValue = 440*1db9f3b2SDimitry Andric Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U); 441*1db9f3b2SDimitry Andric if (!LocationValue) 442*1db9f3b2SDimitry Andric return std::make_pair(false, std::nullopt); 443*1db9f3b2SDimitry Andric 444*1db9f3b2SDimitry Andric // Check that DW_AT_location attribute is of 'exprloc' class. 445*1db9f3b2SDimitry Andric // Handling value of location expressions for attributes of 'loclist' 446*1db9f3b2SDimitry Andric // class is not implemented yet. 447*1db9f3b2SDimitry Andric std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock(); 448*1db9f3b2SDimitry Andric if (!Expr) 449*1db9f3b2SDimitry Andric return std::make_pair(false, std::nullopt); 450*1db9f3b2SDimitry Andric 451*1db9f3b2SDimitry Andric // Parse 'exprloc' expression. 452*1db9f3b2SDimitry Andric DataExtractor Data(toStringRef(*Expr), U->getContext().isLittleEndian(), 453*1db9f3b2SDimitry Andric U->getAddressByteSize()); 454*1db9f3b2SDimitry Andric DWARFExpression Expression(Data, U->getAddressByteSize(), 455*1db9f3b2SDimitry Andric U->getFormParams().Format); 456*1db9f3b2SDimitry Andric 457*1db9f3b2SDimitry Andric bool HasLocationAddress = false; 458*1db9f3b2SDimitry Andric uint64_t CurExprOffset = 0; 459*1db9f3b2SDimitry Andric for (DWARFExpression::iterator It = Expression.begin(); 460*1db9f3b2SDimitry Andric It != Expression.end(); ++It) { 461*1db9f3b2SDimitry Andric DWARFExpression::iterator NextIt = It; 462*1db9f3b2SDimitry Andric ++NextIt; 463*1db9f3b2SDimitry Andric 464*1db9f3b2SDimitry Andric const DWARFExpression::Operation &Op = *It; 465*1db9f3b2SDimitry Andric switch (Op.getCode()) { 466*1db9f3b2SDimitry Andric case dwarf::DW_OP_const2u: 467*1db9f3b2SDimitry Andric case dwarf::DW_OP_const4u: 468*1db9f3b2SDimitry Andric case dwarf::DW_OP_const8u: 469*1db9f3b2SDimitry Andric case dwarf::DW_OP_const2s: 470*1db9f3b2SDimitry Andric case dwarf::DW_OP_const4s: 471*1db9f3b2SDimitry Andric case dwarf::DW_OP_const8s: 472*1db9f3b2SDimitry Andric if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode())) 473*1db9f3b2SDimitry Andric break; 474*1db9f3b2SDimitry Andric [[fallthrough]]; 475*1db9f3b2SDimitry Andric case dwarf::DW_OP_addr: { 476*1db9f3b2SDimitry Andric HasLocationAddress = true; 477*1db9f3b2SDimitry Andric // Check relocation for the address. 478*1db9f3b2SDimitry Andric if (std::optional<int64_t> RelocAdjustment = 479*1db9f3b2SDimitry Andric RelocMgr.getExprOpAddressRelocAdjustment( 480*1db9f3b2SDimitry Andric *U, Op, AttrOffset + CurExprOffset, 481*1db9f3b2SDimitry Andric AttrOffset + Op.getEndOffset())) 482*1db9f3b2SDimitry Andric return std::make_pair(HasLocationAddress, *RelocAdjustment); 483*1db9f3b2SDimitry Andric } break; 484*1db9f3b2SDimitry Andric case dwarf::DW_OP_constx: 485*1db9f3b2SDimitry Andric case dwarf::DW_OP_addrx: { 486*1db9f3b2SDimitry Andric HasLocationAddress = true; 487*1db9f3b2SDimitry Andric if (std::optional<uint64_t> AddressOffset = 488*1db9f3b2SDimitry Andric DIE.getDwarfUnit()->getIndexedAddressOffset( 489*1db9f3b2SDimitry Andric Op.getRawOperand(0))) { 490*1db9f3b2SDimitry Andric // Check relocation for the address. 491*1db9f3b2SDimitry Andric if (std::optional<int64_t> RelocAdjustment = 492*1db9f3b2SDimitry Andric RelocMgr.getExprOpAddressRelocAdjustment( 493*1db9f3b2SDimitry Andric *U, Op, *AddressOffset, 494*1db9f3b2SDimitry Andric *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize())) 495*1db9f3b2SDimitry Andric return std::make_pair(HasLocationAddress, *RelocAdjustment); 496*1db9f3b2SDimitry Andric } 497*1db9f3b2SDimitry Andric } break; 498*1db9f3b2SDimitry Andric default: { 499*1db9f3b2SDimitry Andric // Nothing to do. 500*1db9f3b2SDimitry Andric } break; 501*1db9f3b2SDimitry Andric } 502*1db9f3b2SDimitry Andric CurExprOffset = Op.getEndOffset(); 503*1db9f3b2SDimitry Andric } 504*1db9f3b2SDimitry Andric 505*1db9f3b2SDimitry Andric return std::make_pair(HasLocationAddress, std::nullopt); 506*1db9f3b2SDimitry Andric } 507*1db9f3b2SDimitry Andric 508*1db9f3b2SDimitry Andric /// Check if a variable describing DIE should be kept. 509*1db9f3b2SDimitry Andric /// \returns updated TraversalFlags. 510*1db9f3b2SDimitry Andric unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr, 511*1db9f3b2SDimitry Andric const DWARFDie &DIE, 512*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &MyInfo, 513*1db9f3b2SDimitry Andric unsigned Flags) { 514*1db9f3b2SDimitry Andric const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); 515*1db9f3b2SDimitry Andric 516*1db9f3b2SDimitry Andric // Global variables with constant value can always be kept. 517*1db9f3b2SDimitry Andric if (!(Flags & TF_InFunctionScope) && 518*1db9f3b2SDimitry Andric Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) { 519*1db9f3b2SDimitry Andric MyInfo.InDebugMap = true; 520*1db9f3b2SDimitry Andric return Flags | TF_Keep; 521*1db9f3b2SDimitry Andric } 522*1db9f3b2SDimitry Andric 523*1db9f3b2SDimitry Andric // See if there is a relocation to a valid debug map entry inside this 524*1db9f3b2SDimitry Andric // variable's location. The order is important here. We want to always check 525*1db9f3b2SDimitry Andric // if the variable has a valid relocation, so that the DIEInfo is filled. 526*1db9f3b2SDimitry Andric // However, we don't want a static variable in a function to force us to keep 527*1db9f3b2SDimitry Andric // the enclosing function, unless requested explicitly. 528*1db9f3b2SDimitry Andric std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment = 529*1db9f3b2SDimitry Andric getVariableRelocAdjustment(RelocMgr, DIE); 530*1db9f3b2SDimitry Andric 531*1db9f3b2SDimitry Andric if (LocExprAddrAndRelocAdjustment.first) 532*1db9f3b2SDimitry Andric MyInfo.HasLocationExpressionAddr = true; 533*1db9f3b2SDimitry Andric 534*1db9f3b2SDimitry Andric if (!LocExprAddrAndRelocAdjustment.second) 535*1db9f3b2SDimitry Andric return Flags; 536*1db9f3b2SDimitry Andric 537*1db9f3b2SDimitry Andric MyInfo.AddrAdjust = *LocExprAddrAndRelocAdjustment.second; 538*1db9f3b2SDimitry Andric MyInfo.InDebugMap = true; 539*1db9f3b2SDimitry Andric 540*1db9f3b2SDimitry Andric if (((Flags & TF_InFunctionScope) && 541*1db9f3b2SDimitry Andric !LLVM_UNLIKELY(Options.KeepFunctionForStatic))) 542*1db9f3b2SDimitry Andric return Flags; 543*1db9f3b2SDimitry Andric 544*1db9f3b2SDimitry Andric if (Options.Verbose) { 545*1db9f3b2SDimitry Andric outs() << "Keeping variable DIE:"; 546*1db9f3b2SDimitry Andric DIDumpOptions DumpOpts; 547*1db9f3b2SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 548*1db9f3b2SDimitry Andric DumpOpts.Verbose = Options.Verbose; 549*1db9f3b2SDimitry Andric DIE.dump(outs(), 8 /* Indent */, DumpOpts); 550*1db9f3b2SDimitry Andric } 551*1db9f3b2SDimitry Andric 552*1db9f3b2SDimitry Andric return Flags | TF_Keep; 553*1db9f3b2SDimitry Andric } 554*1db9f3b2SDimitry Andric 555*1db9f3b2SDimitry Andric /// Check if a function describing DIE should be kept. 556*1db9f3b2SDimitry Andric /// \returns updated TraversalFlags. 557*1db9f3b2SDimitry Andric unsigned DWARFLinker::shouldKeepSubprogramDIE( 558*1db9f3b2SDimitry Andric AddressesMap &RelocMgr, const DWARFDie &DIE, const DWARFFile &File, 559*1db9f3b2SDimitry Andric CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags) { 560*1db9f3b2SDimitry Andric Flags |= TF_InFunctionScope; 561*1db9f3b2SDimitry Andric 562*1db9f3b2SDimitry Andric auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc)); 563*1db9f3b2SDimitry Andric if (!LowPc) 564*1db9f3b2SDimitry Andric return Flags; 565*1db9f3b2SDimitry Andric 566*1db9f3b2SDimitry Andric assert(LowPc && "low_pc attribute is not an address."); 567*1db9f3b2SDimitry Andric std::optional<int64_t> RelocAdjustment = 568*1db9f3b2SDimitry Andric RelocMgr.getSubprogramRelocAdjustment(DIE); 569*1db9f3b2SDimitry Andric if (!RelocAdjustment) 570*1db9f3b2SDimitry Andric return Flags; 571*1db9f3b2SDimitry Andric 572*1db9f3b2SDimitry Andric MyInfo.AddrAdjust = *RelocAdjustment; 573*1db9f3b2SDimitry Andric MyInfo.InDebugMap = true; 574*1db9f3b2SDimitry Andric 575*1db9f3b2SDimitry Andric if (Options.Verbose) { 576*1db9f3b2SDimitry Andric outs() << "Keeping subprogram DIE:"; 577*1db9f3b2SDimitry Andric DIDumpOptions DumpOpts; 578*1db9f3b2SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 579*1db9f3b2SDimitry Andric DumpOpts.Verbose = Options.Verbose; 580*1db9f3b2SDimitry Andric DIE.dump(outs(), 8 /* Indent */, DumpOpts); 581*1db9f3b2SDimitry Andric } 582*1db9f3b2SDimitry Andric 583*1db9f3b2SDimitry Andric if (DIE.getTag() == dwarf::DW_TAG_label) { 584*1db9f3b2SDimitry Andric if (Unit.hasLabelAt(*LowPc)) 585*1db9f3b2SDimitry Andric return Flags; 586*1db9f3b2SDimitry Andric 587*1db9f3b2SDimitry Andric DWARFUnit &OrigUnit = Unit.getOrigUnit(); 588*1db9f3b2SDimitry Andric // FIXME: dsymutil-classic compat. dsymutil-classic doesn't consider labels 589*1db9f3b2SDimitry Andric // that don't fall into the CU's aranges. This is wrong IMO. Debug info 590*1db9f3b2SDimitry Andric // generation bugs aside, this is really wrong in the case of labels, where 591*1db9f3b2SDimitry Andric // a label marking the end of a function will have a PC == CU's high_pc. 592*1db9f3b2SDimitry Andric if (dwarf::toAddress(OrigUnit.getUnitDIE().find(dwarf::DW_AT_high_pc)) 593*1db9f3b2SDimitry Andric .value_or(UINT64_MAX) <= LowPc) 594*1db9f3b2SDimitry Andric return Flags; 595*1db9f3b2SDimitry Andric Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust); 596*1db9f3b2SDimitry Andric return Flags | TF_Keep; 597*1db9f3b2SDimitry Andric } 598*1db9f3b2SDimitry Andric 599*1db9f3b2SDimitry Andric Flags |= TF_Keep; 600*1db9f3b2SDimitry Andric 601*1db9f3b2SDimitry Andric std::optional<uint64_t> HighPc = DIE.getHighPC(*LowPc); 602*1db9f3b2SDimitry Andric if (!HighPc) { 603*1db9f3b2SDimitry Andric reportWarning("Function without high_pc. Range will be discarded.\n", File, 604*1db9f3b2SDimitry Andric &DIE); 605*1db9f3b2SDimitry Andric return Flags; 606*1db9f3b2SDimitry Andric } 607*1db9f3b2SDimitry Andric if (*LowPc > *HighPc) { 608*1db9f3b2SDimitry Andric reportWarning("low_pc greater than high_pc. Range will be discarded.\n", 609*1db9f3b2SDimitry Andric File, &DIE); 610*1db9f3b2SDimitry Andric return Flags; 611*1db9f3b2SDimitry Andric } 612*1db9f3b2SDimitry Andric 613*1db9f3b2SDimitry Andric // Replace the debug map range with a more accurate one. 614*1db9f3b2SDimitry Andric Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust); 615*1db9f3b2SDimitry Andric return Flags; 616*1db9f3b2SDimitry Andric } 617*1db9f3b2SDimitry Andric 618*1db9f3b2SDimitry Andric /// Check if a DIE should be kept. 619*1db9f3b2SDimitry Andric /// \returns updated TraversalFlags. 620*1db9f3b2SDimitry Andric unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE, 621*1db9f3b2SDimitry Andric const DWARFFile &File, CompileUnit &Unit, 622*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &MyInfo, 623*1db9f3b2SDimitry Andric unsigned Flags) { 624*1db9f3b2SDimitry Andric switch (DIE.getTag()) { 625*1db9f3b2SDimitry Andric case dwarf::DW_TAG_constant: 626*1db9f3b2SDimitry Andric case dwarf::DW_TAG_variable: 627*1db9f3b2SDimitry Andric return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags); 628*1db9f3b2SDimitry Andric case dwarf::DW_TAG_subprogram: 629*1db9f3b2SDimitry Andric case dwarf::DW_TAG_label: 630*1db9f3b2SDimitry Andric return shouldKeepSubprogramDIE(RelocMgr, DIE, File, Unit, MyInfo, Flags); 631*1db9f3b2SDimitry Andric case dwarf::DW_TAG_base_type: 632*1db9f3b2SDimitry Andric // DWARF Expressions may reference basic types, but scanning them 633*1db9f3b2SDimitry Andric // is expensive. Basic types are tiny, so just keep all of them. 634*1db9f3b2SDimitry Andric case dwarf::DW_TAG_imported_module: 635*1db9f3b2SDimitry Andric case dwarf::DW_TAG_imported_declaration: 636*1db9f3b2SDimitry Andric case dwarf::DW_TAG_imported_unit: 637*1db9f3b2SDimitry Andric // We always want to keep these. 638*1db9f3b2SDimitry Andric return Flags | TF_Keep; 639*1db9f3b2SDimitry Andric default: 640*1db9f3b2SDimitry Andric break; 641*1db9f3b2SDimitry Andric } 642*1db9f3b2SDimitry Andric 643*1db9f3b2SDimitry Andric return Flags; 644*1db9f3b2SDimitry Andric } 645*1db9f3b2SDimitry Andric 646*1db9f3b2SDimitry Andric /// Helper that updates the completeness of the current DIE based on the 647*1db9f3b2SDimitry Andric /// completeness of one of its children. It depends on the incompleteness of 648*1db9f3b2SDimitry Andric /// the children already being computed. 649*1db9f3b2SDimitry Andric static void updateChildIncompleteness(const DWARFDie &Die, CompileUnit &CU, 650*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &ChildInfo) { 651*1db9f3b2SDimitry Andric switch (Die.getTag()) { 652*1db9f3b2SDimitry Andric case dwarf::DW_TAG_structure_type: 653*1db9f3b2SDimitry Andric case dwarf::DW_TAG_class_type: 654*1db9f3b2SDimitry Andric case dwarf::DW_TAG_union_type: 655*1db9f3b2SDimitry Andric break; 656*1db9f3b2SDimitry Andric default: 657*1db9f3b2SDimitry Andric return; 658*1db9f3b2SDimitry Andric } 659*1db9f3b2SDimitry Andric 660*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &MyInfo = CU.getInfo(Die); 661*1db9f3b2SDimitry Andric 662*1db9f3b2SDimitry Andric if (ChildInfo.Incomplete || ChildInfo.Prune) 663*1db9f3b2SDimitry Andric MyInfo.Incomplete = true; 664*1db9f3b2SDimitry Andric } 665*1db9f3b2SDimitry Andric 666*1db9f3b2SDimitry Andric /// Helper that updates the completeness of the current DIE based on the 667*1db9f3b2SDimitry Andric /// completeness of the DIEs it references. It depends on the incompleteness of 668*1db9f3b2SDimitry Andric /// the referenced DIE already being computed. 669*1db9f3b2SDimitry Andric static void updateRefIncompleteness(const DWARFDie &Die, CompileUnit &CU, 670*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &RefInfo) { 671*1db9f3b2SDimitry Andric switch (Die.getTag()) { 672*1db9f3b2SDimitry Andric case dwarf::DW_TAG_typedef: 673*1db9f3b2SDimitry Andric case dwarf::DW_TAG_member: 674*1db9f3b2SDimitry Andric case dwarf::DW_TAG_reference_type: 675*1db9f3b2SDimitry Andric case dwarf::DW_TAG_ptr_to_member_type: 676*1db9f3b2SDimitry Andric case dwarf::DW_TAG_pointer_type: 677*1db9f3b2SDimitry Andric break; 678*1db9f3b2SDimitry Andric default: 679*1db9f3b2SDimitry Andric return; 680*1db9f3b2SDimitry Andric } 681*1db9f3b2SDimitry Andric 682*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &MyInfo = CU.getInfo(Die); 683*1db9f3b2SDimitry Andric 684*1db9f3b2SDimitry Andric if (MyInfo.Incomplete) 685*1db9f3b2SDimitry Andric return; 686*1db9f3b2SDimitry Andric 687*1db9f3b2SDimitry Andric if (RefInfo.Incomplete) 688*1db9f3b2SDimitry Andric MyInfo.Incomplete = true; 689*1db9f3b2SDimitry Andric } 690*1db9f3b2SDimitry Andric 691*1db9f3b2SDimitry Andric /// Look at the children of the given DIE and decide whether they should be 692*1db9f3b2SDimitry Andric /// kept. 693*1db9f3b2SDimitry Andric void DWARFLinker::lookForChildDIEsToKeep( 694*1db9f3b2SDimitry Andric const DWARFDie &Die, CompileUnit &CU, unsigned Flags, 695*1db9f3b2SDimitry Andric SmallVectorImpl<WorklistItem> &Worklist) { 696*1db9f3b2SDimitry Andric // The TF_ParentWalk flag tells us that we are currently walking up the 697*1db9f3b2SDimitry Andric // parent chain of a required DIE, and we don't want to mark all the children 698*1db9f3b2SDimitry Andric // of the parents as kept (consider for example a DW_TAG_namespace node in 699*1db9f3b2SDimitry Andric // the parent chain). There are however a set of DIE types for which we want 700*1db9f3b2SDimitry Andric // to ignore that directive and still walk their children. 701*1db9f3b2SDimitry Andric if (dieNeedsChildrenToBeMeaningful(Die.getTag())) 702*1db9f3b2SDimitry Andric Flags &= ~DWARFLinker::TF_ParentWalk; 703*1db9f3b2SDimitry Andric 704*1db9f3b2SDimitry Andric // We're finished if this DIE has no children or we're walking the parent 705*1db9f3b2SDimitry Andric // chain. 706*1db9f3b2SDimitry Andric if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk)) 707*1db9f3b2SDimitry Andric return; 708*1db9f3b2SDimitry Andric 709*1db9f3b2SDimitry Andric // Add children in reverse order to the worklist to effectively process them 710*1db9f3b2SDimitry Andric // in order. 711*1db9f3b2SDimitry Andric for (auto Child : reverse(Die.children())) { 712*1db9f3b2SDimitry Andric // Add a worklist item before every child to calculate incompleteness right 713*1db9f3b2SDimitry Andric // after the current child is processed. 714*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &ChildInfo = CU.getInfo(Child); 715*1db9f3b2SDimitry Andric Worklist.emplace_back(Die, CU, WorklistItemType::UpdateChildIncompleteness, 716*1db9f3b2SDimitry Andric &ChildInfo); 717*1db9f3b2SDimitry Andric Worklist.emplace_back(Child, CU, Flags); 718*1db9f3b2SDimitry Andric } 719*1db9f3b2SDimitry Andric } 720*1db9f3b2SDimitry Andric 721*1db9f3b2SDimitry Andric static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU) { 722*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = CU.getInfo(Die); 723*1db9f3b2SDimitry Andric 724*1db9f3b2SDimitry Andric if (!Info.Ctxt || (Die.getTag() == dwarf::DW_TAG_namespace)) 725*1db9f3b2SDimitry Andric return false; 726*1db9f3b2SDimitry Andric 727*1db9f3b2SDimitry Andric if (!CU.hasODR() && !Info.InModuleScope) 728*1db9f3b2SDimitry Andric return false; 729*1db9f3b2SDimitry Andric 730*1db9f3b2SDimitry Andric return !Info.Incomplete && Info.Ctxt != CU.getInfo(Info.ParentIdx).Ctxt; 731*1db9f3b2SDimitry Andric } 732*1db9f3b2SDimitry Andric 733*1db9f3b2SDimitry Andric void DWARFLinker::markODRCanonicalDie(const DWARFDie &Die, CompileUnit &CU) { 734*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = CU.getInfo(Die); 735*1db9f3b2SDimitry Andric 736*1db9f3b2SDimitry Andric Info.ODRMarkingDone = true; 737*1db9f3b2SDimitry Andric if (Info.Keep && isODRCanonicalCandidate(Die, CU) && 738*1db9f3b2SDimitry Andric !Info.Ctxt->hasCanonicalDIE()) 739*1db9f3b2SDimitry Andric Info.Ctxt->setHasCanonicalDIE(); 740*1db9f3b2SDimitry Andric } 741*1db9f3b2SDimitry Andric 742*1db9f3b2SDimitry Andric /// Look at DIEs referenced by the given DIE and decide whether they should be 743*1db9f3b2SDimitry Andric /// kept. All DIEs referenced though attributes should be kept. 744*1db9f3b2SDimitry Andric void DWARFLinker::lookForRefDIEsToKeep( 745*1db9f3b2SDimitry Andric const DWARFDie &Die, CompileUnit &CU, unsigned Flags, 746*1db9f3b2SDimitry Andric const UnitListTy &Units, const DWARFFile &File, 747*1db9f3b2SDimitry Andric SmallVectorImpl<WorklistItem> &Worklist) { 748*1db9f3b2SDimitry Andric bool UseOdr = (Flags & DWARFLinker::TF_DependencyWalk) 749*1db9f3b2SDimitry Andric ? (Flags & DWARFLinker::TF_ODR) 750*1db9f3b2SDimitry Andric : CU.hasODR(); 751*1db9f3b2SDimitry Andric DWARFUnit &Unit = CU.getOrigUnit(); 752*1db9f3b2SDimitry Andric DWARFDataExtractor Data = Unit.getDebugInfoExtractor(); 753*1db9f3b2SDimitry Andric const auto *Abbrev = Die.getAbbreviationDeclarationPtr(); 754*1db9f3b2SDimitry Andric uint64_t Offset = Die.getOffset() + getULEB128Size(Abbrev->getCode()); 755*1db9f3b2SDimitry Andric 756*1db9f3b2SDimitry Andric SmallVector<std::pair<DWARFDie, CompileUnit &>, 4> ReferencedDIEs; 757*1db9f3b2SDimitry Andric for (const auto &AttrSpec : Abbrev->attributes()) { 758*1db9f3b2SDimitry Andric DWARFFormValue Val(AttrSpec.Form); 759*1db9f3b2SDimitry Andric if (!Val.isFormClass(DWARFFormValue::FC_Reference) || 760*1db9f3b2SDimitry Andric AttrSpec.Attr == dwarf::DW_AT_sibling) { 761*1db9f3b2SDimitry Andric DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, 762*1db9f3b2SDimitry Andric Unit.getFormParams()); 763*1db9f3b2SDimitry Andric continue; 764*1db9f3b2SDimitry Andric } 765*1db9f3b2SDimitry Andric 766*1db9f3b2SDimitry Andric Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit); 767*1db9f3b2SDimitry Andric CompileUnit *ReferencedCU; 768*1db9f3b2SDimitry Andric if (auto RefDie = 769*1db9f3b2SDimitry Andric resolveDIEReference(File, Units, Val, Die, ReferencedCU)) { 770*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefDie); 771*1db9f3b2SDimitry Andric // If the referenced DIE has a DeclContext that has already been 772*1db9f3b2SDimitry Andric // emitted, then do not keep the one in this CU. We'll link to 773*1db9f3b2SDimitry Andric // the canonical DIE in cloneDieReferenceAttribute. 774*1db9f3b2SDimitry Andric // 775*1db9f3b2SDimitry Andric // FIXME: compatibility with dsymutil-classic. UseODR shouldn't 776*1db9f3b2SDimitry Andric // be necessary and could be advantageously replaced by 777*1db9f3b2SDimitry Andric // ReferencedCU->hasODR() && CU.hasODR(). 778*1db9f3b2SDimitry Andric // 779*1db9f3b2SDimitry Andric // FIXME: compatibility with dsymutil-classic. There is no 780*1db9f3b2SDimitry Andric // reason not to unique ref_addr references. 781*1db9f3b2SDimitry Andric if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && 782*1db9f3b2SDimitry Andric isODRAttribute(AttrSpec.Attr) && Info.Ctxt && 783*1db9f3b2SDimitry Andric Info.Ctxt->hasCanonicalDIE()) 784*1db9f3b2SDimitry Andric continue; 785*1db9f3b2SDimitry Andric 786*1db9f3b2SDimitry Andric // Keep a module forward declaration if there is no definition. 787*1db9f3b2SDimitry Andric if (!(isODRAttribute(AttrSpec.Attr) && Info.Ctxt && 788*1db9f3b2SDimitry Andric Info.Ctxt->hasCanonicalDIE())) 789*1db9f3b2SDimitry Andric Info.Prune = false; 790*1db9f3b2SDimitry Andric ReferencedDIEs.emplace_back(RefDie, *ReferencedCU); 791*1db9f3b2SDimitry Andric } 792*1db9f3b2SDimitry Andric } 793*1db9f3b2SDimitry Andric 794*1db9f3b2SDimitry Andric unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0; 795*1db9f3b2SDimitry Andric 796*1db9f3b2SDimitry Andric // Add referenced DIEs in reverse order to the worklist to effectively 797*1db9f3b2SDimitry Andric // process them in order. 798*1db9f3b2SDimitry Andric for (auto &P : reverse(ReferencedDIEs)) { 799*1db9f3b2SDimitry Andric // Add a worklist item before every child to calculate incompleteness right 800*1db9f3b2SDimitry Andric // after the current child is processed. 801*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = P.second.getInfo(P.first); 802*1db9f3b2SDimitry Andric Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness, 803*1db9f3b2SDimitry Andric &Info); 804*1db9f3b2SDimitry Andric Worklist.emplace_back(P.first, P.second, 805*1db9f3b2SDimitry Andric DWARFLinker::TF_Keep | 806*1db9f3b2SDimitry Andric DWARFLinker::TF_DependencyWalk | ODRFlag); 807*1db9f3b2SDimitry Andric } 808*1db9f3b2SDimitry Andric } 809*1db9f3b2SDimitry Andric 810*1db9f3b2SDimitry Andric /// Look at the parent of the given DIE and decide whether they should be kept. 811*1db9f3b2SDimitry Andric void DWARFLinker::lookForParentDIEsToKeep( 812*1db9f3b2SDimitry Andric unsigned AncestorIdx, CompileUnit &CU, unsigned Flags, 813*1db9f3b2SDimitry Andric SmallVectorImpl<WorklistItem> &Worklist) { 814*1db9f3b2SDimitry Andric // Stop if we encounter an ancestor that's already marked as kept. 815*1db9f3b2SDimitry Andric if (CU.getInfo(AncestorIdx).Keep) 816*1db9f3b2SDimitry Andric return; 817*1db9f3b2SDimitry Andric 818*1db9f3b2SDimitry Andric DWARFUnit &Unit = CU.getOrigUnit(); 819*1db9f3b2SDimitry Andric DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx); 820*1db9f3b2SDimitry Andric Worklist.emplace_back(CU.getInfo(AncestorIdx).ParentIdx, CU, Flags); 821*1db9f3b2SDimitry Andric Worklist.emplace_back(ParentDIE, CU, Flags); 822*1db9f3b2SDimitry Andric } 823*1db9f3b2SDimitry Andric 824*1db9f3b2SDimitry Andric /// Recursively walk the \p DIE tree and look for DIEs to keep. Store that 825*1db9f3b2SDimitry Andric /// information in \p CU's DIEInfo. 826*1db9f3b2SDimitry Andric /// 827*1db9f3b2SDimitry Andric /// This function is the entry point of the DIE selection algorithm. It is 828*1db9f3b2SDimitry Andric /// expected to walk the DIE tree in file order and (though the mediation of 829*1db9f3b2SDimitry Andric /// its helper) call hasValidRelocation() on each DIE that might be a 'root 830*1db9f3b2SDimitry Andric /// DIE' (See DwarfLinker class comment). 831*1db9f3b2SDimitry Andric /// 832*1db9f3b2SDimitry Andric /// While walking the dependencies of root DIEs, this function is also called, 833*1db9f3b2SDimitry Andric /// but during these dependency walks the file order is not respected. The 834*1db9f3b2SDimitry Andric /// TF_DependencyWalk flag tells us which kind of traversal we are currently 835*1db9f3b2SDimitry Andric /// doing. 836*1db9f3b2SDimitry Andric /// 837*1db9f3b2SDimitry Andric /// The recursive algorithm is implemented iteratively as a work list because 838*1db9f3b2SDimitry Andric /// very deep recursion could exhaust the stack for large projects. The work 839*1db9f3b2SDimitry Andric /// list acts as a scheduler for different types of work that need to be 840*1db9f3b2SDimitry Andric /// performed. 841*1db9f3b2SDimitry Andric /// 842*1db9f3b2SDimitry Andric /// The recursive nature of the algorithm is simulated by running the "main" 843*1db9f3b2SDimitry Andric /// algorithm (LookForDIEsToKeep) followed by either looking at more DIEs 844*1db9f3b2SDimitry Andric /// (LookForChildDIEsToKeep, LookForRefDIEsToKeep, LookForParentDIEsToKeep) or 845*1db9f3b2SDimitry Andric /// fixing up a computed property (UpdateChildIncompleteness, 846*1db9f3b2SDimitry Andric /// UpdateRefIncompleteness). 847*1db9f3b2SDimitry Andric /// 848*1db9f3b2SDimitry Andric /// The return value indicates whether the DIE is incomplete. 849*1db9f3b2SDimitry Andric void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap, 850*1db9f3b2SDimitry Andric const UnitListTy &Units, 851*1db9f3b2SDimitry Andric const DWARFDie &Die, const DWARFFile &File, 852*1db9f3b2SDimitry Andric CompileUnit &Cu, unsigned Flags) { 853*1db9f3b2SDimitry Andric // LIFO work list. 854*1db9f3b2SDimitry Andric SmallVector<WorklistItem, 4> Worklist; 855*1db9f3b2SDimitry Andric Worklist.emplace_back(Die, Cu, Flags); 856*1db9f3b2SDimitry Andric 857*1db9f3b2SDimitry Andric while (!Worklist.empty()) { 858*1db9f3b2SDimitry Andric WorklistItem Current = Worklist.pop_back_val(); 859*1db9f3b2SDimitry Andric 860*1db9f3b2SDimitry Andric // Look at the worklist type to decide what kind of work to perform. 861*1db9f3b2SDimitry Andric switch (Current.Type) { 862*1db9f3b2SDimitry Andric case WorklistItemType::UpdateChildIncompleteness: 863*1db9f3b2SDimitry Andric updateChildIncompleteness(Current.Die, Current.CU, *Current.OtherInfo); 864*1db9f3b2SDimitry Andric continue; 865*1db9f3b2SDimitry Andric case WorklistItemType::UpdateRefIncompleteness: 866*1db9f3b2SDimitry Andric updateRefIncompleteness(Current.Die, Current.CU, *Current.OtherInfo); 867*1db9f3b2SDimitry Andric continue; 868*1db9f3b2SDimitry Andric case WorklistItemType::LookForChildDIEsToKeep: 869*1db9f3b2SDimitry Andric lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist); 870*1db9f3b2SDimitry Andric continue; 871*1db9f3b2SDimitry Andric case WorklistItemType::LookForRefDIEsToKeep: 872*1db9f3b2SDimitry Andric lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File, 873*1db9f3b2SDimitry Andric Worklist); 874*1db9f3b2SDimitry Andric continue; 875*1db9f3b2SDimitry Andric case WorklistItemType::LookForParentDIEsToKeep: 876*1db9f3b2SDimitry Andric lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags, 877*1db9f3b2SDimitry Andric Worklist); 878*1db9f3b2SDimitry Andric continue; 879*1db9f3b2SDimitry Andric case WorklistItemType::MarkODRCanonicalDie: 880*1db9f3b2SDimitry Andric markODRCanonicalDie(Current.Die, Current.CU); 881*1db9f3b2SDimitry Andric continue; 882*1db9f3b2SDimitry Andric case WorklistItemType::LookForDIEsToKeep: 883*1db9f3b2SDimitry Andric break; 884*1db9f3b2SDimitry Andric } 885*1db9f3b2SDimitry Andric 886*1db9f3b2SDimitry Andric unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die); 887*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(Idx); 888*1db9f3b2SDimitry Andric 889*1db9f3b2SDimitry Andric if (MyInfo.Prune) { 890*1db9f3b2SDimitry Andric // We're walking the dependencies of a module forward declaration that was 891*1db9f3b2SDimitry Andric // kept because there is no definition. 892*1db9f3b2SDimitry Andric if (Current.Flags & TF_DependencyWalk) 893*1db9f3b2SDimitry Andric MyInfo.Prune = false; 894*1db9f3b2SDimitry Andric else 895*1db9f3b2SDimitry Andric continue; 896*1db9f3b2SDimitry Andric } 897*1db9f3b2SDimitry Andric 898*1db9f3b2SDimitry Andric // If the Keep flag is set, we are marking a required DIE's dependencies. 899*1db9f3b2SDimitry Andric // If our target is already marked as kept, we're all set. 900*1db9f3b2SDimitry Andric bool AlreadyKept = MyInfo.Keep; 901*1db9f3b2SDimitry Andric if ((Current.Flags & TF_DependencyWalk) && AlreadyKept) 902*1db9f3b2SDimitry Andric continue; 903*1db9f3b2SDimitry Andric 904*1db9f3b2SDimitry Andric if (!(Current.Flags & TF_DependencyWalk)) 905*1db9f3b2SDimitry Andric Current.Flags = shouldKeepDIE(AddressesMap, Current.Die, File, Current.CU, 906*1db9f3b2SDimitry Andric MyInfo, Current.Flags); 907*1db9f3b2SDimitry Andric 908*1db9f3b2SDimitry Andric // We need to mark context for the canonical die in the end of normal 909*1db9f3b2SDimitry Andric // traversing(not TF_DependencyWalk) or after normal traversing if die 910*1db9f3b2SDimitry Andric // was not marked as kept. 911*1db9f3b2SDimitry Andric if (!(Current.Flags & TF_DependencyWalk) || 912*1db9f3b2SDimitry Andric (MyInfo.ODRMarkingDone && !MyInfo.Keep)) { 913*1db9f3b2SDimitry Andric if (Current.CU.hasODR() || MyInfo.InModuleScope) 914*1db9f3b2SDimitry Andric Worklist.emplace_back(Current.Die, Current.CU, 915*1db9f3b2SDimitry Andric WorklistItemType::MarkODRCanonicalDie); 916*1db9f3b2SDimitry Andric } 917*1db9f3b2SDimitry Andric 918*1db9f3b2SDimitry Andric // Finish by looking for child DIEs. Because of the LIFO worklist we need 919*1db9f3b2SDimitry Andric // to schedule that work before any subsequent items are added to the 920*1db9f3b2SDimitry Andric // worklist. 921*1db9f3b2SDimitry Andric Worklist.emplace_back(Current.Die, Current.CU, Current.Flags, 922*1db9f3b2SDimitry Andric WorklistItemType::LookForChildDIEsToKeep); 923*1db9f3b2SDimitry Andric 924*1db9f3b2SDimitry Andric if (AlreadyKept || !(Current.Flags & TF_Keep)) 925*1db9f3b2SDimitry Andric continue; 926*1db9f3b2SDimitry Andric 927*1db9f3b2SDimitry Andric // If it is a newly kept DIE mark it as well as all its dependencies as 928*1db9f3b2SDimitry Andric // kept. 929*1db9f3b2SDimitry Andric MyInfo.Keep = true; 930*1db9f3b2SDimitry Andric 931*1db9f3b2SDimitry Andric // We're looking for incomplete types. 932*1db9f3b2SDimitry Andric MyInfo.Incomplete = 933*1db9f3b2SDimitry Andric Current.Die.getTag() != dwarf::DW_TAG_subprogram && 934*1db9f3b2SDimitry Andric Current.Die.getTag() != dwarf::DW_TAG_member && 935*1db9f3b2SDimitry Andric dwarf::toUnsigned(Current.Die.find(dwarf::DW_AT_declaration), 0); 936*1db9f3b2SDimitry Andric 937*1db9f3b2SDimitry Andric // After looking at the parent chain, look for referenced DIEs. Because of 938*1db9f3b2SDimitry Andric // the LIFO worklist we need to schedule that work before any subsequent 939*1db9f3b2SDimitry Andric // items are added to the worklist. 940*1db9f3b2SDimitry Andric Worklist.emplace_back(Current.Die, Current.CU, Current.Flags, 941*1db9f3b2SDimitry Andric WorklistItemType::LookForRefDIEsToKeep); 942*1db9f3b2SDimitry Andric 943*1db9f3b2SDimitry Andric bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR) 944*1db9f3b2SDimitry Andric : Current.CU.hasODR(); 945*1db9f3b2SDimitry Andric unsigned ODRFlag = UseOdr ? TF_ODR : 0; 946*1db9f3b2SDimitry Andric unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag; 947*1db9f3b2SDimitry Andric 948*1db9f3b2SDimitry Andric // Now schedule the parent walk. 949*1db9f3b2SDimitry Andric Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags); 950*1db9f3b2SDimitry Andric } 951*1db9f3b2SDimitry Andric } 952*1db9f3b2SDimitry Andric 953*1db9f3b2SDimitry Andric #ifndef NDEBUG 954*1db9f3b2SDimitry Andric /// A broken link in the keep chain. By recording both the parent and the child 955*1db9f3b2SDimitry Andric /// we can show only broken links for DIEs with multiple children. 956*1db9f3b2SDimitry Andric struct BrokenLink { 957*1db9f3b2SDimitry Andric BrokenLink(DWARFDie Parent, DWARFDie Child) : Parent(Parent), Child(Child) {} 958*1db9f3b2SDimitry Andric DWARFDie Parent; 959*1db9f3b2SDimitry Andric DWARFDie Child; 960*1db9f3b2SDimitry Andric }; 961*1db9f3b2SDimitry Andric 962*1db9f3b2SDimitry Andric /// Verify the keep chain by looking for DIEs that are kept but who's parent 963*1db9f3b2SDimitry Andric /// isn't. 964*1db9f3b2SDimitry Andric static void verifyKeepChain(CompileUnit &CU) { 965*1db9f3b2SDimitry Andric std::vector<DWARFDie> Worklist; 966*1db9f3b2SDimitry Andric Worklist.push_back(CU.getOrigUnit().getUnitDIE()); 967*1db9f3b2SDimitry Andric 968*1db9f3b2SDimitry Andric // List of broken links. 969*1db9f3b2SDimitry Andric std::vector<BrokenLink> BrokenLinks; 970*1db9f3b2SDimitry Andric 971*1db9f3b2SDimitry Andric while (!Worklist.empty()) { 972*1db9f3b2SDimitry Andric const DWARFDie Current = Worklist.back(); 973*1db9f3b2SDimitry Andric Worklist.pop_back(); 974*1db9f3b2SDimitry Andric 975*1db9f3b2SDimitry Andric const bool CurrentDieIsKept = CU.getInfo(Current).Keep; 976*1db9f3b2SDimitry Andric 977*1db9f3b2SDimitry Andric for (DWARFDie Child : reverse(Current.children())) { 978*1db9f3b2SDimitry Andric Worklist.push_back(Child); 979*1db9f3b2SDimitry Andric 980*1db9f3b2SDimitry Andric const bool ChildDieIsKept = CU.getInfo(Child).Keep; 981*1db9f3b2SDimitry Andric if (!CurrentDieIsKept && ChildDieIsKept) 982*1db9f3b2SDimitry Andric BrokenLinks.emplace_back(Current, Child); 983*1db9f3b2SDimitry Andric } 984*1db9f3b2SDimitry Andric } 985*1db9f3b2SDimitry Andric 986*1db9f3b2SDimitry Andric if (!BrokenLinks.empty()) { 987*1db9f3b2SDimitry Andric for (BrokenLink Link : BrokenLinks) { 988*1db9f3b2SDimitry Andric WithColor::error() << formatv( 989*1db9f3b2SDimitry Andric "Found invalid link in keep chain between {0:x} and {1:x}\n", 990*1db9f3b2SDimitry Andric Link.Parent.getOffset(), Link.Child.getOffset()); 991*1db9f3b2SDimitry Andric 992*1db9f3b2SDimitry Andric errs() << "Parent:"; 993*1db9f3b2SDimitry Andric Link.Parent.dump(errs(), 0, {}); 994*1db9f3b2SDimitry Andric CU.getInfo(Link.Parent).dump(); 995*1db9f3b2SDimitry Andric 996*1db9f3b2SDimitry Andric errs() << "Child:"; 997*1db9f3b2SDimitry Andric Link.Child.dump(errs(), 2, {}); 998*1db9f3b2SDimitry Andric CU.getInfo(Link.Child).dump(); 999*1db9f3b2SDimitry Andric } 1000*1db9f3b2SDimitry Andric report_fatal_error("invalid keep chain"); 1001*1db9f3b2SDimitry Andric } 1002*1db9f3b2SDimitry Andric } 1003*1db9f3b2SDimitry Andric #endif 1004*1db9f3b2SDimitry Andric 1005*1db9f3b2SDimitry Andric /// Assign an abbreviation number to \p Abbrev. 1006*1db9f3b2SDimitry Andric /// 1007*1db9f3b2SDimitry Andric /// Our DIEs get freed after every DebugMapObject has been processed, 1008*1db9f3b2SDimitry Andric /// thus the FoldingSet we use to unique DIEAbbrevs cannot refer to 1009*1db9f3b2SDimitry Andric /// the instances hold by the DIEs. When we encounter an abbreviation 1010*1db9f3b2SDimitry Andric /// that we don't know, we create a permanent copy of it. 1011*1db9f3b2SDimitry Andric void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) { 1012*1db9f3b2SDimitry Andric // Check the set for priors. 1013*1db9f3b2SDimitry Andric FoldingSetNodeID ID; 1014*1db9f3b2SDimitry Andric Abbrev.Profile(ID); 1015*1db9f3b2SDimitry Andric void *InsertToken; 1016*1db9f3b2SDimitry Andric DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken); 1017*1db9f3b2SDimitry Andric 1018*1db9f3b2SDimitry Andric // If it's newly added. 1019*1db9f3b2SDimitry Andric if (InSet) { 1020*1db9f3b2SDimitry Andric // Assign existing abbreviation number. 1021*1db9f3b2SDimitry Andric Abbrev.setNumber(InSet->getNumber()); 1022*1db9f3b2SDimitry Andric } else { 1023*1db9f3b2SDimitry Andric // Add to abbreviation list. 1024*1db9f3b2SDimitry Andric Abbreviations.push_back( 1025*1db9f3b2SDimitry Andric std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren())); 1026*1db9f3b2SDimitry Andric for (const auto &Attr : Abbrev.getData()) 1027*1db9f3b2SDimitry Andric Abbreviations.back()->AddAttribute(Attr); 1028*1db9f3b2SDimitry Andric AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken); 1029*1db9f3b2SDimitry Andric // Assign the unique abbreviation number. 1030*1db9f3b2SDimitry Andric Abbrev.setNumber(Abbreviations.size()); 1031*1db9f3b2SDimitry Andric Abbreviations.back()->setNumber(Abbreviations.size()); 1032*1db9f3b2SDimitry Andric } 1033*1db9f3b2SDimitry Andric } 1034*1db9f3b2SDimitry Andric 1035*1db9f3b2SDimitry Andric unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die, 1036*1db9f3b2SDimitry Andric AttributeSpec AttrSpec, 1037*1db9f3b2SDimitry Andric const DWARFFormValue &Val, 1038*1db9f3b2SDimitry Andric const DWARFUnit &U, 1039*1db9f3b2SDimitry Andric AttributesInfo &Info) { 1040*1db9f3b2SDimitry Andric std::optional<const char *> String = dwarf::toString(Val); 1041*1db9f3b2SDimitry Andric if (!String) 1042*1db9f3b2SDimitry Andric return 0; 1043*1db9f3b2SDimitry Andric DwarfStringPoolEntryRef StringEntry; 1044*1db9f3b2SDimitry Andric if (AttrSpec.Form == dwarf::DW_FORM_line_strp) { 1045*1db9f3b2SDimitry Andric StringEntry = DebugLineStrPool.getEntry(*String); 1046*1db9f3b2SDimitry Andric } else { 1047*1db9f3b2SDimitry Andric StringEntry = DebugStrPool.getEntry(*String); 1048*1db9f3b2SDimitry Andric 1049*1db9f3b2SDimitry Andric if (AttrSpec.Attr == dwarf::DW_AT_APPLE_origin) { 1050*1db9f3b2SDimitry Andric Info.HasAppleOrigin = true; 1051*1db9f3b2SDimitry Andric if (std::optional<StringRef> FileName = 1052*1db9f3b2SDimitry Andric ObjFile.Addresses->getLibraryInstallName()) { 1053*1db9f3b2SDimitry Andric StringEntry = DebugStrPool.getEntry(*FileName); 1054*1db9f3b2SDimitry Andric } 1055*1db9f3b2SDimitry Andric } 1056*1db9f3b2SDimitry Andric 1057*1db9f3b2SDimitry Andric // Update attributes info. 1058*1db9f3b2SDimitry Andric if (AttrSpec.Attr == dwarf::DW_AT_name) 1059*1db9f3b2SDimitry Andric Info.Name = StringEntry; 1060*1db9f3b2SDimitry Andric else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name || 1061*1db9f3b2SDimitry Andric AttrSpec.Attr == dwarf::DW_AT_linkage_name) 1062*1db9f3b2SDimitry Andric Info.MangledName = StringEntry; 1063*1db9f3b2SDimitry Andric if (U.getVersion() >= 5) { 1064*1db9f3b2SDimitry Andric // Switch everything to DW_FORM_strx strings. 1065*1db9f3b2SDimitry Andric auto StringOffsetIndex = 1066*1db9f3b2SDimitry Andric StringOffsetPool.getValueIndex(StringEntry.getOffset()); 1067*1db9f3b2SDimitry Andric return Die 1068*1db9f3b2SDimitry Andric .addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1069*1db9f3b2SDimitry Andric dwarf::DW_FORM_strx, DIEInteger(StringOffsetIndex)) 1070*1db9f3b2SDimitry Andric ->sizeOf(U.getFormParams()); 1071*1db9f3b2SDimitry Andric } 1072*1db9f3b2SDimitry Andric // Switch everything to out of line strings. 1073*1db9f3b2SDimitry Andric AttrSpec.Form = dwarf::DW_FORM_strp; 1074*1db9f3b2SDimitry Andric } 1075*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), AttrSpec.Form, 1076*1db9f3b2SDimitry Andric DIEInteger(StringEntry.getOffset())); 1077*1db9f3b2SDimitry Andric return 4; 1078*1db9f3b2SDimitry Andric } 1079*1db9f3b2SDimitry Andric 1080*1db9f3b2SDimitry Andric unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute( 1081*1db9f3b2SDimitry Andric DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec, 1082*1db9f3b2SDimitry Andric unsigned AttrSize, const DWARFFormValue &Val, const DWARFFile &File, 1083*1db9f3b2SDimitry Andric CompileUnit &Unit) { 1084*1db9f3b2SDimitry Andric const DWARFUnit &U = Unit.getOrigUnit(); 1085*1db9f3b2SDimitry Andric uint64_t Ref = *Val.getAsReference(); 1086*1db9f3b2SDimitry Andric 1087*1db9f3b2SDimitry Andric DIE *NewRefDie = nullptr; 1088*1db9f3b2SDimitry Andric CompileUnit *RefUnit = nullptr; 1089*1db9f3b2SDimitry Andric 1090*1db9f3b2SDimitry Andric DWARFDie RefDie = 1091*1db9f3b2SDimitry Andric Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit); 1092*1db9f3b2SDimitry Andric 1093*1db9f3b2SDimitry Andric // If the referenced DIE is not found, drop the attribute. 1094*1db9f3b2SDimitry Andric if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling) 1095*1db9f3b2SDimitry Andric return 0; 1096*1db9f3b2SDimitry Andric 1097*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie); 1098*1db9f3b2SDimitry Andric 1099*1db9f3b2SDimitry Andric // If we already have emitted an equivalent DeclContext, just point 1100*1db9f3b2SDimitry Andric // at it. 1101*1db9f3b2SDimitry Andric if (isODRAttribute(AttrSpec.Attr) && RefInfo.Ctxt && 1102*1db9f3b2SDimitry Andric RefInfo.Ctxt->getCanonicalDIEOffset()) { 1103*1db9f3b2SDimitry Andric assert(RefInfo.Ctxt->hasCanonicalDIE() && 1104*1db9f3b2SDimitry Andric "Offset to canonical die is set, but context is not marked"); 1105*1db9f3b2SDimitry Andric DIEInteger Attr(RefInfo.Ctxt->getCanonicalDIEOffset()); 1106*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1107*1db9f3b2SDimitry Andric dwarf::DW_FORM_ref_addr, Attr); 1108*1db9f3b2SDimitry Andric return U.getRefAddrByteSize(); 1109*1db9f3b2SDimitry Andric } 1110*1db9f3b2SDimitry Andric 1111*1db9f3b2SDimitry Andric if (!RefInfo.Clone) { 1112*1db9f3b2SDimitry Andric // We haven't cloned this DIE yet. Just create an empty one and 1113*1db9f3b2SDimitry Andric // store it. It'll get really cloned when we process it. 1114*1db9f3b2SDimitry Andric RefInfo.UnclonedReference = true; 1115*1db9f3b2SDimitry Andric RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag())); 1116*1db9f3b2SDimitry Andric } 1117*1db9f3b2SDimitry Andric NewRefDie = RefInfo.Clone; 1118*1db9f3b2SDimitry Andric 1119*1db9f3b2SDimitry Andric if (AttrSpec.Form == dwarf::DW_FORM_ref_addr || 1120*1db9f3b2SDimitry Andric (Unit.hasODR() && isODRAttribute(AttrSpec.Attr))) { 1121*1db9f3b2SDimitry Andric // We cannot currently rely on a DIEEntry to emit ref_addr 1122*1db9f3b2SDimitry Andric // references, because the implementation calls back to DwarfDebug 1123*1db9f3b2SDimitry Andric // to find the unit offset. (We don't have a DwarfDebug) 1124*1db9f3b2SDimitry Andric // FIXME: we should be able to design DIEEntry reliance on 1125*1db9f3b2SDimitry Andric // DwarfDebug away. 1126*1db9f3b2SDimitry Andric uint64_t Attr; 1127*1db9f3b2SDimitry Andric if (Ref < InputDIE.getOffset() && !RefInfo.UnclonedReference) { 1128*1db9f3b2SDimitry Andric // We have already cloned that DIE. 1129*1db9f3b2SDimitry Andric uint32_t NewRefOffset = 1130*1db9f3b2SDimitry Andric RefUnit->getStartOffset() + NewRefDie->getOffset(); 1131*1db9f3b2SDimitry Andric Attr = NewRefOffset; 1132*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1133*1db9f3b2SDimitry Andric dwarf::DW_FORM_ref_addr, DIEInteger(Attr)); 1134*1db9f3b2SDimitry Andric } else { 1135*1db9f3b2SDimitry Andric // A forward reference. Note and fixup later. 1136*1db9f3b2SDimitry Andric Attr = 0xBADDEF; 1137*1db9f3b2SDimitry Andric Unit.noteForwardReference( 1138*1db9f3b2SDimitry Andric NewRefDie, RefUnit, RefInfo.Ctxt, 1139*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1140*1db9f3b2SDimitry Andric dwarf::DW_FORM_ref_addr, DIEInteger(Attr))); 1141*1db9f3b2SDimitry Andric } 1142*1db9f3b2SDimitry Andric return U.getRefAddrByteSize(); 1143*1db9f3b2SDimitry Andric } 1144*1db9f3b2SDimitry Andric 1145*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1146*1db9f3b2SDimitry Andric dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie)); 1147*1db9f3b2SDimitry Andric 1148*1db9f3b2SDimitry Andric return AttrSize; 1149*1db9f3b2SDimitry Andric } 1150*1db9f3b2SDimitry Andric 1151*1db9f3b2SDimitry Andric void DWARFLinker::DIECloner::cloneExpression( 1152*1db9f3b2SDimitry Andric DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File, 1153*1db9f3b2SDimitry Andric CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer, 1154*1db9f3b2SDimitry Andric int64_t AddrRelocAdjustment, bool IsLittleEndian) { 1155*1db9f3b2SDimitry Andric using Encoding = DWARFExpression::Operation::Encoding; 1156*1db9f3b2SDimitry Andric 1157*1db9f3b2SDimitry Andric uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize(); 1158*1db9f3b2SDimitry Andric 1159*1db9f3b2SDimitry Andric uint64_t OpOffset = 0; 1160*1db9f3b2SDimitry Andric for (auto &Op : Expression) { 1161*1db9f3b2SDimitry Andric auto Desc = Op.getDescription(); 1162*1db9f3b2SDimitry Andric // DW_OP_const_type is variable-length and has 3 1163*1db9f3b2SDimitry Andric // operands. Thus far we only support 2. 1164*1db9f3b2SDimitry Andric if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) || 1165*1db9f3b2SDimitry Andric (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef && 1166*1db9f3b2SDimitry Andric Desc.Op[0] != Encoding::Size1)) 1167*1db9f3b2SDimitry Andric Linker.reportWarning("Unsupported DW_OP encoding.", File); 1168*1db9f3b2SDimitry Andric 1169*1db9f3b2SDimitry Andric if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) || 1170*1db9f3b2SDimitry Andric (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef && 1171*1db9f3b2SDimitry Andric Desc.Op[0] == Encoding::Size1)) { 1172*1db9f3b2SDimitry Andric // This code assumes that the other non-typeref operand fits into 1 byte. 1173*1db9f3b2SDimitry Andric assert(OpOffset < Op.getEndOffset()); 1174*1db9f3b2SDimitry Andric uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1; 1175*1db9f3b2SDimitry Andric assert(ULEBsize <= 16); 1176*1db9f3b2SDimitry Andric 1177*1db9f3b2SDimitry Andric // Copy over the operation. 1178*1db9f3b2SDimitry Andric assert(!Op.getSubCode() && "SubOps not yet supported"); 1179*1db9f3b2SDimitry Andric OutputBuffer.push_back(Op.getCode()); 1180*1db9f3b2SDimitry Andric uint64_t RefOffset; 1181*1db9f3b2SDimitry Andric if (Desc.Op.size() == 1) { 1182*1db9f3b2SDimitry Andric RefOffset = Op.getRawOperand(0); 1183*1db9f3b2SDimitry Andric } else { 1184*1db9f3b2SDimitry Andric OutputBuffer.push_back(Op.getRawOperand(0)); 1185*1db9f3b2SDimitry Andric RefOffset = Op.getRawOperand(1); 1186*1db9f3b2SDimitry Andric } 1187*1db9f3b2SDimitry Andric uint32_t Offset = 0; 1188*1db9f3b2SDimitry Andric // Look up the base type. For DW_OP_convert, the operand may be 0 to 1189*1db9f3b2SDimitry Andric // instead indicate the generic type. The same holds for 1190*1db9f3b2SDimitry Andric // DW_OP_reinterpret, which is currently not supported. 1191*1db9f3b2SDimitry Andric if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) { 1192*1db9f3b2SDimitry Andric RefOffset += Unit.getOrigUnit().getOffset(); 1193*1db9f3b2SDimitry Andric auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset); 1194*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = Unit.getInfo(RefDie); 1195*1db9f3b2SDimitry Andric if (DIE *Clone = Info.Clone) 1196*1db9f3b2SDimitry Andric Offset = Clone->getOffset(); 1197*1db9f3b2SDimitry Andric else 1198*1db9f3b2SDimitry Andric Linker.reportWarning( 1199*1db9f3b2SDimitry Andric "base type ref doesn't point to DW_TAG_base_type.", File); 1200*1db9f3b2SDimitry Andric } 1201*1db9f3b2SDimitry Andric uint8_t ULEB[16]; 1202*1db9f3b2SDimitry Andric unsigned RealSize = encodeULEB128(Offset, ULEB, ULEBsize); 1203*1db9f3b2SDimitry Andric if (RealSize > ULEBsize) { 1204*1db9f3b2SDimitry Andric // Emit the generic type as a fallback. 1205*1db9f3b2SDimitry Andric RealSize = encodeULEB128(0, ULEB, ULEBsize); 1206*1db9f3b2SDimitry Andric Linker.reportWarning("base type ref doesn't fit.", File); 1207*1db9f3b2SDimitry Andric } 1208*1db9f3b2SDimitry Andric assert(RealSize == ULEBsize && "padding failed"); 1209*1db9f3b2SDimitry Andric ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize); 1210*1db9f3b2SDimitry Andric OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end()); 1211*1db9f3b2SDimitry Andric } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_addrx) { 1212*1db9f3b2SDimitry Andric if (std::optional<object::SectionedAddress> SA = 1213*1db9f3b2SDimitry Andric Unit.getOrigUnit().getAddrOffsetSectionItem( 1214*1db9f3b2SDimitry Andric Op.getRawOperand(0))) { 1215*1db9f3b2SDimitry Andric // DWARFLinker does not use addrx forms since it generates relocated 1216*1db9f3b2SDimitry Andric // addresses. Replace DW_OP_addrx with DW_OP_addr here. 1217*1db9f3b2SDimitry Andric // Argument of DW_OP_addrx should be relocated here as it is not 1218*1db9f3b2SDimitry Andric // processed by applyValidRelocs. 1219*1db9f3b2SDimitry Andric OutputBuffer.push_back(dwarf::DW_OP_addr); 1220*1db9f3b2SDimitry Andric uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment; 1221*1db9f3b2SDimitry Andric if (IsLittleEndian != sys::IsLittleEndianHost) 1222*1db9f3b2SDimitry Andric sys::swapByteOrder(LinkedAddress); 1223*1db9f3b2SDimitry Andric ArrayRef<uint8_t> AddressBytes( 1224*1db9f3b2SDimitry Andric reinterpret_cast<const uint8_t *>(&LinkedAddress), 1225*1db9f3b2SDimitry Andric OrigAddressByteSize); 1226*1db9f3b2SDimitry Andric OutputBuffer.append(AddressBytes.begin(), AddressBytes.end()); 1227*1db9f3b2SDimitry Andric } else 1228*1db9f3b2SDimitry Andric Linker.reportWarning("cannot read DW_OP_addrx operand.", File); 1229*1db9f3b2SDimitry Andric } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_constx) { 1230*1db9f3b2SDimitry Andric if (std::optional<object::SectionedAddress> SA = 1231*1db9f3b2SDimitry Andric Unit.getOrigUnit().getAddrOffsetSectionItem( 1232*1db9f3b2SDimitry Andric Op.getRawOperand(0))) { 1233*1db9f3b2SDimitry Andric // DWARFLinker does not use constx forms since it generates relocated 1234*1db9f3b2SDimitry Andric // addresses. Replace DW_OP_constx with DW_OP_const[*]u here. 1235*1db9f3b2SDimitry Andric // Argument of DW_OP_constx should be relocated here as it is not 1236*1db9f3b2SDimitry Andric // processed by applyValidRelocs. 1237*1db9f3b2SDimitry Andric std::optional<uint8_t> OutOperandKind; 1238*1db9f3b2SDimitry Andric switch (OrigAddressByteSize) { 1239*1db9f3b2SDimitry Andric case 4: 1240*1db9f3b2SDimitry Andric OutOperandKind = dwarf::DW_OP_const4u; 1241*1db9f3b2SDimitry Andric break; 1242*1db9f3b2SDimitry Andric case 8: 1243*1db9f3b2SDimitry Andric OutOperandKind = dwarf::DW_OP_const8u; 1244*1db9f3b2SDimitry Andric break; 1245*1db9f3b2SDimitry Andric default: 1246*1db9f3b2SDimitry Andric Linker.reportWarning( 1247*1db9f3b2SDimitry Andric formatv(("unsupported address size: {0}."), OrigAddressByteSize), 1248*1db9f3b2SDimitry Andric File); 1249*1db9f3b2SDimitry Andric break; 1250*1db9f3b2SDimitry Andric } 1251*1db9f3b2SDimitry Andric 1252*1db9f3b2SDimitry Andric if (OutOperandKind) { 1253*1db9f3b2SDimitry Andric OutputBuffer.push_back(*OutOperandKind); 1254*1db9f3b2SDimitry Andric uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment; 1255*1db9f3b2SDimitry Andric if (IsLittleEndian != sys::IsLittleEndianHost) 1256*1db9f3b2SDimitry Andric sys::swapByteOrder(LinkedAddress); 1257*1db9f3b2SDimitry Andric ArrayRef<uint8_t> AddressBytes( 1258*1db9f3b2SDimitry Andric reinterpret_cast<const uint8_t *>(&LinkedAddress), 1259*1db9f3b2SDimitry Andric OrigAddressByteSize); 1260*1db9f3b2SDimitry Andric OutputBuffer.append(AddressBytes.begin(), AddressBytes.end()); 1261*1db9f3b2SDimitry Andric } 1262*1db9f3b2SDimitry Andric } else 1263*1db9f3b2SDimitry Andric Linker.reportWarning("cannot read DW_OP_constx operand.", File); 1264*1db9f3b2SDimitry Andric } else { 1265*1db9f3b2SDimitry Andric // Copy over everything else unmodified. 1266*1db9f3b2SDimitry Andric StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset()); 1267*1db9f3b2SDimitry Andric OutputBuffer.append(Bytes.begin(), Bytes.end()); 1268*1db9f3b2SDimitry Andric } 1269*1db9f3b2SDimitry Andric OpOffset = Op.getEndOffset(); 1270*1db9f3b2SDimitry Andric } 1271*1db9f3b2SDimitry Andric } 1272*1db9f3b2SDimitry Andric 1273*1db9f3b2SDimitry Andric unsigned DWARFLinker::DIECloner::cloneBlockAttribute( 1274*1db9f3b2SDimitry Andric DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File, 1275*1db9f3b2SDimitry Andric CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, 1276*1db9f3b2SDimitry Andric bool IsLittleEndian) { 1277*1db9f3b2SDimitry Andric DIEValueList *Attr; 1278*1db9f3b2SDimitry Andric DIEValue Value; 1279*1db9f3b2SDimitry Andric DIELoc *Loc = nullptr; 1280*1db9f3b2SDimitry Andric DIEBlock *Block = nullptr; 1281*1db9f3b2SDimitry Andric if (AttrSpec.Form == dwarf::DW_FORM_exprloc) { 1282*1db9f3b2SDimitry Andric Loc = new (DIEAlloc) DIELoc; 1283*1db9f3b2SDimitry Andric Linker.DIELocs.push_back(Loc); 1284*1db9f3b2SDimitry Andric } else { 1285*1db9f3b2SDimitry Andric Block = new (DIEAlloc) DIEBlock; 1286*1db9f3b2SDimitry Andric Linker.DIEBlocks.push_back(Block); 1287*1db9f3b2SDimitry Andric } 1288*1db9f3b2SDimitry Andric Attr = Loc ? static_cast<DIEValueList *>(Loc) 1289*1db9f3b2SDimitry Andric : static_cast<DIEValueList *>(Block); 1290*1db9f3b2SDimitry Andric 1291*1db9f3b2SDimitry Andric DWARFUnit &OrigUnit = Unit.getOrigUnit(); 1292*1db9f3b2SDimitry Andric // If the block is a DWARF Expression, clone it into the temporary 1293*1db9f3b2SDimitry Andric // buffer using cloneExpression(), otherwise copy the data directly. 1294*1db9f3b2SDimitry Andric SmallVector<uint8_t, 32> Buffer; 1295*1db9f3b2SDimitry Andric ArrayRef<uint8_t> Bytes = *Val.getAsBlock(); 1296*1db9f3b2SDimitry Andric if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) && 1297*1db9f3b2SDimitry Andric (Val.isFormClass(DWARFFormValue::FC_Block) || 1298*1db9f3b2SDimitry Andric Val.isFormClass(DWARFFormValue::FC_Exprloc))) { 1299*1db9f3b2SDimitry Andric DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()), 1300*1db9f3b2SDimitry Andric IsLittleEndian, OrigUnit.getAddressByteSize()); 1301*1db9f3b2SDimitry Andric DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(), 1302*1db9f3b2SDimitry Andric OrigUnit.getFormParams().Format); 1303*1db9f3b2SDimitry Andric cloneExpression(Data, Expr, File, Unit, Buffer, 1304*1db9f3b2SDimitry Andric Unit.getInfo(InputDIE).AddrAdjust, IsLittleEndian); 1305*1db9f3b2SDimitry Andric Bytes = Buffer; 1306*1db9f3b2SDimitry Andric } 1307*1db9f3b2SDimitry Andric for (auto Byte : Bytes) 1308*1db9f3b2SDimitry Andric Attr->addValue(DIEAlloc, static_cast<dwarf::Attribute>(0), 1309*1db9f3b2SDimitry Andric dwarf::DW_FORM_data1, DIEInteger(Byte)); 1310*1db9f3b2SDimitry Andric 1311*1db9f3b2SDimitry Andric // FIXME: If DIEBlock and DIELoc just reuses the Size field of 1312*1db9f3b2SDimitry Andric // the DIE class, this "if" could be replaced by 1313*1db9f3b2SDimitry Andric // Attr->setSize(Bytes.size()). 1314*1db9f3b2SDimitry Andric if (Loc) 1315*1db9f3b2SDimitry Andric Loc->setSize(Bytes.size()); 1316*1db9f3b2SDimitry Andric else 1317*1db9f3b2SDimitry Andric Block->setSize(Bytes.size()); 1318*1db9f3b2SDimitry Andric 1319*1db9f3b2SDimitry Andric if (Loc) 1320*1db9f3b2SDimitry Andric Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), 1321*1db9f3b2SDimitry Andric dwarf::Form(AttrSpec.Form), Loc); 1322*1db9f3b2SDimitry Andric else { 1323*1db9f3b2SDimitry Andric // The expression location data might be updated and exceed the original 1324*1db9f3b2SDimitry Andric // size. Check whether the new data fits into the original form. 1325*1db9f3b2SDimitry Andric if ((AttrSpec.Form == dwarf::DW_FORM_block1 && 1326*1db9f3b2SDimitry Andric (Bytes.size() > UINT8_MAX)) || 1327*1db9f3b2SDimitry Andric (AttrSpec.Form == dwarf::DW_FORM_block2 && 1328*1db9f3b2SDimitry Andric (Bytes.size() > UINT16_MAX)) || 1329*1db9f3b2SDimitry Andric (AttrSpec.Form == dwarf::DW_FORM_block4 && (Bytes.size() > UINT32_MAX))) 1330*1db9f3b2SDimitry Andric AttrSpec.Form = dwarf::DW_FORM_block; 1331*1db9f3b2SDimitry Andric 1332*1db9f3b2SDimitry Andric Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), 1333*1db9f3b2SDimitry Andric dwarf::Form(AttrSpec.Form), Block); 1334*1db9f3b2SDimitry Andric } 1335*1db9f3b2SDimitry Andric 1336*1db9f3b2SDimitry Andric return Die.addValue(DIEAlloc, Value)->sizeOf(OrigUnit.getFormParams()); 1337*1db9f3b2SDimitry Andric } 1338*1db9f3b2SDimitry Andric 1339*1db9f3b2SDimitry Andric unsigned DWARFLinker::DIECloner::cloneAddressAttribute( 1340*1db9f3b2SDimitry Andric DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec, 1341*1db9f3b2SDimitry Andric unsigned AttrSize, const DWARFFormValue &Val, const CompileUnit &Unit, 1342*1db9f3b2SDimitry Andric AttributesInfo &Info) { 1343*1db9f3b2SDimitry Andric if (AttrSpec.Attr == dwarf::DW_AT_low_pc) 1344*1db9f3b2SDimitry Andric Info.HasLowPc = true; 1345*1db9f3b2SDimitry Andric 1346*1db9f3b2SDimitry Andric if (LLVM_UNLIKELY(Linker.Options.Update)) { 1347*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1348*1db9f3b2SDimitry Andric dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue())); 1349*1db9f3b2SDimitry Andric return AttrSize; 1350*1db9f3b2SDimitry Andric } 1351*1db9f3b2SDimitry Andric 1352*1db9f3b2SDimitry Andric // Cloned Die may have address attributes relocated to a 1353*1db9f3b2SDimitry Andric // totally unrelated value. This can happen: 1354*1db9f3b2SDimitry Andric // - If high_pc is an address (Dwarf version == 2), then it might have been 1355*1db9f3b2SDimitry Andric // relocated to a totally unrelated value (because the end address in the 1356*1db9f3b2SDimitry Andric // object file might be start address of another function which got moved 1357*1db9f3b2SDimitry Andric // independently by the linker). 1358*1db9f3b2SDimitry Andric // - If address relocated in an inline_subprogram that happens at the 1359*1db9f3b2SDimitry Andric // beginning of its inlining function. 1360*1db9f3b2SDimitry Andric // To avoid above cases and to not apply relocation twice (in 1361*1db9f3b2SDimitry Andric // applyValidRelocs and here), read address attribute from InputDIE and apply 1362*1db9f3b2SDimitry Andric // Info.PCOffset here. 1363*1db9f3b2SDimitry Andric 1364*1db9f3b2SDimitry Andric std::optional<DWARFFormValue> AddrAttribute = InputDIE.find(AttrSpec.Attr); 1365*1db9f3b2SDimitry Andric if (!AddrAttribute) 1366*1db9f3b2SDimitry Andric llvm_unreachable("Cann't find attribute."); 1367*1db9f3b2SDimitry Andric 1368*1db9f3b2SDimitry Andric std::optional<uint64_t> Addr = AddrAttribute->getAsAddress(); 1369*1db9f3b2SDimitry Andric if (!Addr) { 1370*1db9f3b2SDimitry Andric Linker.reportWarning("Cann't read address attribute value.", ObjFile); 1371*1db9f3b2SDimitry Andric return 0; 1372*1db9f3b2SDimitry Andric } 1373*1db9f3b2SDimitry Andric 1374*1db9f3b2SDimitry Andric if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit && 1375*1db9f3b2SDimitry Andric AttrSpec.Attr == dwarf::DW_AT_low_pc) { 1376*1db9f3b2SDimitry Andric if (std::optional<uint64_t> LowPC = Unit.getLowPc()) 1377*1db9f3b2SDimitry Andric Addr = *LowPC; 1378*1db9f3b2SDimitry Andric else 1379*1db9f3b2SDimitry Andric return 0; 1380*1db9f3b2SDimitry Andric } else if (InputDIE.getTag() == dwarf::DW_TAG_compile_unit && 1381*1db9f3b2SDimitry Andric AttrSpec.Attr == dwarf::DW_AT_high_pc) { 1382*1db9f3b2SDimitry Andric if (uint64_t HighPc = Unit.getHighPc()) 1383*1db9f3b2SDimitry Andric Addr = HighPc; 1384*1db9f3b2SDimitry Andric else 1385*1db9f3b2SDimitry Andric return 0; 1386*1db9f3b2SDimitry Andric } else { 1387*1db9f3b2SDimitry Andric *Addr += Info.PCOffset; 1388*1db9f3b2SDimitry Andric } 1389*1db9f3b2SDimitry Andric 1390*1db9f3b2SDimitry Andric if (AttrSpec.Form == dwarf::DW_FORM_addr) { 1391*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr), 1392*1db9f3b2SDimitry Andric AttrSpec.Form, DIEInteger(*Addr)); 1393*1db9f3b2SDimitry Andric return Unit.getOrigUnit().getAddressByteSize(); 1394*1db9f3b2SDimitry Andric } 1395*1db9f3b2SDimitry Andric 1396*1db9f3b2SDimitry Andric auto AddrIndex = AddrPool.getValueIndex(*Addr); 1397*1db9f3b2SDimitry Andric 1398*1db9f3b2SDimitry Andric return Die 1399*1db9f3b2SDimitry Andric .addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr), 1400*1db9f3b2SDimitry Andric dwarf::Form::DW_FORM_addrx, DIEInteger(AddrIndex)) 1401*1db9f3b2SDimitry Andric ->sizeOf(Unit.getOrigUnit().getFormParams()); 1402*1db9f3b2SDimitry Andric } 1403*1db9f3b2SDimitry Andric 1404*1db9f3b2SDimitry Andric unsigned DWARFLinker::DIECloner::cloneScalarAttribute( 1405*1db9f3b2SDimitry Andric DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File, 1406*1db9f3b2SDimitry Andric CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, 1407*1db9f3b2SDimitry Andric unsigned AttrSize, AttributesInfo &Info) { 1408*1db9f3b2SDimitry Andric uint64_t Value; 1409*1db9f3b2SDimitry Andric 1410*1db9f3b2SDimitry Andric // Check for the offset to the macro table. If offset is incorrect then we 1411*1db9f3b2SDimitry Andric // need to remove the attribute. 1412*1db9f3b2SDimitry Andric if (AttrSpec.Attr == dwarf::DW_AT_macro_info) { 1413*1db9f3b2SDimitry Andric if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) { 1414*1db9f3b2SDimitry Andric const llvm::DWARFDebugMacro *Macro = File.Dwarf->getDebugMacinfo(); 1415*1db9f3b2SDimitry Andric if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset)) 1416*1db9f3b2SDimitry Andric return 0; 1417*1db9f3b2SDimitry Andric } 1418*1db9f3b2SDimitry Andric } 1419*1db9f3b2SDimitry Andric 1420*1db9f3b2SDimitry Andric if (AttrSpec.Attr == dwarf::DW_AT_macros) { 1421*1db9f3b2SDimitry Andric if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) { 1422*1db9f3b2SDimitry Andric const llvm::DWARFDebugMacro *Macro = File.Dwarf->getDebugMacro(); 1423*1db9f3b2SDimitry Andric if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset)) 1424*1db9f3b2SDimitry Andric return 0; 1425*1db9f3b2SDimitry Andric } 1426*1db9f3b2SDimitry Andric } 1427*1db9f3b2SDimitry Andric 1428*1db9f3b2SDimitry Andric if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) { 1429*1db9f3b2SDimitry Andric // DWARFLinker generates common .debug_str_offsets table used for all 1430*1db9f3b2SDimitry Andric // compile units. The offset to the common .debug_str_offsets table is 8 on 1431*1db9f3b2SDimitry Andric // DWARF32. 1432*1db9f3b2SDimitry Andric Info.AttrStrOffsetBaseSeen = true; 1433*1db9f3b2SDimitry Andric return Die 1434*1db9f3b2SDimitry Andric .addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base, 1435*1db9f3b2SDimitry Andric dwarf::DW_FORM_sec_offset, DIEInteger(8)) 1436*1db9f3b2SDimitry Andric ->sizeOf(Unit.getOrigUnit().getFormParams()); 1437*1db9f3b2SDimitry Andric } 1438*1db9f3b2SDimitry Andric 1439*1db9f3b2SDimitry Andric if (LLVM_UNLIKELY(Linker.Options.Update)) { 1440*1db9f3b2SDimitry Andric if (auto OptionalValue = Val.getAsUnsignedConstant()) 1441*1db9f3b2SDimitry Andric Value = *OptionalValue; 1442*1db9f3b2SDimitry Andric else if (auto OptionalValue = Val.getAsSignedConstant()) 1443*1db9f3b2SDimitry Andric Value = *OptionalValue; 1444*1db9f3b2SDimitry Andric else if (auto OptionalValue = Val.getAsSectionOffset()) 1445*1db9f3b2SDimitry Andric Value = *OptionalValue; 1446*1db9f3b2SDimitry Andric else { 1447*1db9f3b2SDimitry Andric Linker.reportWarning( 1448*1db9f3b2SDimitry Andric "Unsupported scalar attribute form. Dropping attribute.", File, 1449*1db9f3b2SDimitry Andric &InputDIE); 1450*1db9f3b2SDimitry Andric return 0; 1451*1db9f3b2SDimitry Andric } 1452*1db9f3b2SDimitry Andric if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) 1453*1db9f3b2SDimitry Andric Info.IsDeclaration = true; 1454*1db9f3b2SDimitry Andric 1455*1db9f3b2SDimitry Andric if (AttrSpec.Form == dwarf::DW_FORM_loclistx) 1456*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1457*1db9f3b2SDimitry Andric dwarf::Form(AttrSpec.Form), DIELocList(Value)); 1458*1db9f3b2SDimitry Andric else 1459*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1460*1db9f3b2SDimitry Andric dwarf::Form(AttrSpec.Form), DIEInteger(Value)); 1461*1db9f3b2SDimitry Andric return AttrSize; 1462*1db9f3b2SDimitry Andric } 1463*1db9f3b2SDimitry Andric 1464*1db9f3b2SDimitry Andric [[maybe_unused]] dwarf::Form OriginalForm = AttrSpec.Form; 1465*1db9f3b2SDimitry Andric if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) { 1466*1db9f3b2SDimitry Andric // DWARFLinker does not generate .debug_addr table. Thus we need to change 1467*1db9f3b2SDimitry Andric // all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx 1468*1db9f3b2SDimitry Andric // to DW_FORM_sec_offset here. 1469*1db9f3b2SDimitry Andric std::optional<uint64_t> Index = Val.getAsSectionOffset(); 1470*1db9f3b2SDimitry Andric if (!Index) { 1471*1db9f3b2SDimitry Andric Linker.reportWarning("Cannot read the attribute. Dropping.", File, 1472*1db9f3b2SDimitry Andric &InputDIE); 1473*1db9f3b2SDimitry Andric return 0; 1474*1db9f3b2SDimitry Andric } 1475*1db9f3b2SDimitry Andric std::optional<uint64_t> Offset = 1476*1db9f3b2SDimitry Andric Unit.getOrigUnit().getRnglistOffset(*Index); 1477*1db9f3b2SDimitry Andric if (!Offset) { 1478*1db9f3b2SDimitry Andric Linker.reportWarning("Cannot read the attribute. Dropping.", File, 1479*1db9f3b2SDimitry Andric &InputDIE); 1480*1db9f3b2SDimitry Andric return 0; 1481*1db9f3b2SDimitry Andric } 1482*1db9f3b2SDimitry Andric 1483*1db9f3b2SDimitry Andric Value = *Offset; 1484*1db9f3b2SDimitry Andric AttrSpec.Form = dwarf::DW_FORM_sec_offset; 1485*1db9f3b2SDimitry Andric AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize(); 1486*1db9f3b2SDimitry Andric } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) { 1487*1db9f3b2SDimitry Andric // DWARFLinker does not generate .debug_addr table. Thus we need to change 1488*1db9f3b2SDimitry Andric // all "addrx" related forms to "addr" version. Change DW_FORM_loclistx 1489*1db9f3b2SDimitry Andric // to DW_FORM_sec_offset here. 1490*1db9f3b2SDimitry Andric std::optional<uint64_t> Index = Val.getAsSectionOffset(); 1491*1db9f3b2SDimitry Andric if (!Index) { 1492*1db9f3b2SDimitry Andric Linker.reportWarning("Cannot read the attribute. Dropping.", File, 1493*1db9f3b2SDimitry Andric &InputDIE); 1494*1db9f3b2SDimitry Andric return 0; 1495*1db9f3b2SDimitry Andric } 1496*1db9f3b2SDimitry Andric std::optional<uint64_t> Offset = 1497*1db9f3b2SDimitry Andric Unit.getOrigUnit().getLoclistOffset(*Index); 1498*1db9f3b2SDimitry Andric if (!Offset) { 1499*1db9f3b2SDimitry Andric Linker.reportWarning("Cannot read the attribute. Dropping.", File, 1500*1db9f3b2SDimitry Andric &InputDIE); 1501*1db9f3b2SDimitry Andric return 0; 1502*1db9f3b2SDimitry Andric } 1503*1db9f3b2SDimitry Andric 1504*1db9f3b2SDimitry Andric Value = *Offset; 1505*1db9f3b2SDimitry Andric AttrSpec.Form = dwarf::DW_FORM_sec_offset; 1506*1db9f3b2SDimitry Andric AttrSize = Unit.getOrigUnit().getFormParams().getDwarfOffsetByteSize(); 1507*1db9f3b2SDimitry Andric } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc && 1508*1db9f3b2SDimitry Andric Die.getTag() == dwarf::DW_TAG_compile_unit) { 1509*1db9f3b2SDimitry Andric std::optional<uint64_t> LowPC = Unit.getLowPc(); 1510*1db9f3b2SDimitry Andric if (!LowPC) 1511*1db9f3b2SDimitry Andric return 0; 1512*1db9f3b2SDimitry Andric // Dwarf >= 4 high_pc is an size, not an address. 1513*1db9f3b2SDimitry Andric Value = Unit.getHighPc() - *LowPC; 1514*1db9f3b2SDimitry Andric } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset) 1515*1db9f3b2SDimitry Andric Value = *Val.getAsSectionOffset(); 1516*1db9f3b2SDimitry Andric else if (AttrSpec.Form == dwarf::DW_FORM_sdata) 1517*1db9f3b2SDimitry Andric Value = *Val.getAsSignedConstant(); 1518*1db9f3b2SDimitry Andric else if (auto OptionalValue = Val.getAsUnsignedConstant()) 1519*1db9f3b2SDimitry Andric Value = *OptionalValue; 1520*1db9f3b2SDimitry Andric else { 1521*1db9f3b2SDimitry Andric Linker.reportWarning( 1522*1db9f3b2SDimitry Andric "Unsupported scalar attribute form. Dropping attribute.", File, 1523*1db9f3b2SDimitry Andric &InputDIE); 1524*1db9f3b2SDimitry Andric return 0; 1525*1db9f3b2SDimitry Andric } 1526*1db9f3b2SDimitry Andric 1527*1db9f3b2SDimitry Andric DIE::value_iterator Patch = 1528*1db9f3b2SDimitry Andric Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), 1529*1db9f3b2SDimitry Andric dwarf::Form(AttrSpec.Form), DIEInteger(Value)); 1530*1db9f3b2SDimitry Andric if (AttrSpec.Attr == dwarf::DW_AT_ranges || 1531*1db9f3b2SDimitry Andric AttrSpec.Attr == dwarf::DW_AT_start_scope) { 1532*1db9f3b2SDimitry Andric Unit.noteRangeAttribute(Die, Patch); 1533*1db9f3b2SDimitry Andric Info.HasRanges = true; 1534*1db9f3b2SDimitry Andric } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) && 1535*1db9f3b2SDimitry Andric dwarf::doesFormBelongToClass(AttrSpec.Form, 1536*1db9f3b2SDimitry Andric DWARFFormValue::FC_SectionOffset, 1537*1db9f3b2SDimitry Andric Unit.getOrigUnit().getVersion())) { 1538*1db9f3b2SDimitry Andric 1539*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &LocationDieInfo = Unit.getInfo(InputDIE); 1540*1db9f3b2SDimitry Andric Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap 1541*1db9f3b2SDimitry Andric ? LocationDieInfo.AddrAdjust 1542*1db9f3b2SDimitry Andric : Info.PCOffset}); 1543*1db9f3b2SDimitry Andric } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) 1544*1db9f3b2SDimitry Andric Info.IsDeclaration = true; 1545*1db9f3b2SDimitry Andric 1546*1db9f3b2SDimitry Andric // check that all dwarf::DW_FORM_rnglistx are handled previously. 1547*1db9f3b2SDimitry Andric assert((Info.HasRanges || (OriginalForm != dwarf::DW_FORM_rnglistx)) && 1548*1db9f3b2SDimitry Andric "Unhandled DW_FORM_rnglistx attribute"); 1549*1db9f3b2SDimitry Andric 1550*1db9f3b2SDimitry Andric return AttrSize; 1551*1db9f3b2SDimitry Andric } 1552*1db9f3b2SDimitry Andric 1553*1db9f3b2SDimitry Andric /// Clone \p InputDIE's attribute described by \p AttrSpec with 1554*1db9f3b2SDimitry Andric /// value \p Val, and add it to \p Die. 1555*1db9f3b2SDimitry Andric /// \returns the size of the cloned attribute. 1556*1db9f3b2SDimitry Andric unsigned DWARFLinker::DIECloner::cloneAttribute( 1557*1db9f3b2SDimitry Andric DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File, 1558*1db9f3b2SDimitry Andric CompileUnit &Unit, const DWARFFormValue &Val, const AttributeSpec AttrSpec, 1559*1db9f3b2SDimitry Andric unsigned AttrSize, AttributesInfo &Info, bool IsLittleEndian) { 1560*1db9f3b2SDimitry Andric const DWARFUnit &U = Unit.getOrigUnit(); 1561*1db9f3b2SDimitry Andric 1562*1db9f3b2SDimitry Andric switch (AttrSpec.Form) { 1563*1db9f3b2SDimitry Andric case dwarf::DW_FORM_strp: 1564*1db9f3b2SDimitry Andric case dwarf::DW_FORM_line_strp: 1565*1db9f3b2SDimitry Andric case dwarf::DW_FORM_string: 1566*1db9f3b2SDimitry Andric case dwarf::DW_FORM_strx: 1567*1db9f3b2SDimitry Andric case dwarf::DW_FORM_strx1: 1568*1db9f3b2SDimitry Andric case dwarf::DW_FORM_strx2: 1569*1db9f3b2SDimitry Andric case dwarf::DW_FORM_strx3: 1570*1db9f3b2SDimitry Andric case dwarf::DW_FORM_strx4: 1571*1db9f3b2SDimitry Andric return cloneStringAttribute(Die, AttrSpec, Val, U, Info); 1572*1db9f3b2SDimitry Andric case dwarf::DW_FORM_ref_addr: 1573*1db9f3b2SDimitry Andric case dwarf::DW_FORM_ref1: 1574*1db9f3b2SDimitry Andric case dwarf::DW_FORM_ref2: 1575*1db9f3b2SDimitry Andric case dwarf::DW_FORM_ref4: 1576*1db9f3b2SDimitry Andric case dwarf::DW_FORM_ref8: 1577*1db9f3b2SDimitry Andric return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, 1578*1db9f3b2SDimitry Andric File, Unit); 1579*1db9f3b2SDimitry Andric case dwarf::DW_FORM_block: 1580*1db9f3b2SDimitry Andric case dwarf::DW_FORM_block1: 1581*1db9f3b2SDimitry Andric case dwarf::DW_FORM_block2: 1582*1db9f3b2SDimitry Andric case dwarf::DW_FORM_block4: 1583*1db9f3b2SDimitry Andric case dwarf::DW_FORM_exprloc: 1584*1db9f3b2SDimitry Andric return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val, 1585*1db9f3b2SDimitry Andric IsLittleEndian); 1586*1db9f3b2SDimitry Andric case dwarf::DW_FORM_addr: 1587*1db9f3b2SDimitry Andric case dwarf::DW_FORM_addrx: 1588*1db9f3b2SDimitry Andric case dwarf::DW_FORM_addrx1: 1589*1db9f3b2SDimitry Andric case dwarf::DW_FORM_addrx2: 1590*1db9f3b2SDimitry Andric case dwarf::DW_FORM_addrx3: 1591*1db9f3b2SDimitry Andric case dwarf::DW_FORM_addrx4: 1592*1db9f3b2SDimitry Andric return cloneAddressAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, Unit, 1593*1db9f3b2SDimitry Andric Info); 1594*1db9f3b2SDimitry Andric case dwarf::DW_FORM_data1: 1595*1db9f3b2SDimitry Andric case dwarf::DW_FORM_data2: 1596*1db9f3b2SDimitry Andric case dwarf::DW_FORM_data4: 1597*1db9f3b2SDimitry Andric case dwarf::DW_FORM_data8: 1598*1db9f3b2SDimitry Andric case dwarf::DW_FORM_udata: 1599*1db9f3b2SDimitry Andric case dwarf::DW_FORM_sdata: 1600*1db9f3b2SDimitry Andric case dwarf::DW_FORM_sec_offset: 1601*1db9f3b2SDimitry Andric case dwarf::DW_FORM_flag: 1602*1db9f3b2SDimitry Andric case dwarf::DW_FORM_flag_present: 1603*1db9f3b2SDimitry Andric case dwarf::DW_FORM_rnglistx: 1604*1db9f3b2SDimitry Andric case dwarf::DW_FORM_loclistx: 1605*1db9f3b2SDimitry Andric case dwarf::DW_FORM_implicit_const: 1606*1db9f3b2SDimitry Andric return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val, 1607*1db9f3b2SDimitry Andric AttrSize, Info); 1608*1db9f3b2SDimitry Andric default: 1609*1db9f3b2SDimitry Andric Linker.reportWarning("Unsupported attribute form " + 1610*1db9f3b2SDimitry Andric dwarf::FormEncodingString(AttrSpec.Form) + 1611*1db9f3b2SDimitry Andric " in cloneAttribute. Dropping.", 1612*1db9f3b2SDimitry Andric File, &InputDIE); 1613*1db9f3b2SDimitry Andric } 1614*1db9f3b2SDimitry Andric 1615*1db9f3b2SDimitry Andric return 0; 1616*1db9f3b2SDimitry Andric } 1617*1db9f3b2SDimitry Andric 1618*1db9f3b2SDimitry Andric void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit, 1619*1db9f3b2SDimitry Andric const DIE *Die, 1620*1db9f3b2SDimitry Andric DwarfStringPoolEntryRef Name, 1621*1db9f3b2SDimitry Andric OffsetsStringPool &StringPool, 1622*1db9f3b2SDimitry Andric bool SkipPubSection) { 1623*1db9f3b2SDimitry Andric std::optional<ObjCSelectorNames> Names = 1624*1db9f3b2SDimitry Andric getObjCNamesIfSelector(Name.getString()); 1625*1db9f3b2SDimitry Andric if (!Names) 1626*1db9f3b2SDimitry Andric return; 1627*1db9f3b2SDimitry Andric Unit.addNameAccelerator(Die, StringPool.getEntry(Names->Selector), 1628*1db9f3b2SDimitry Andric SkipPubSection); 1629*1db9f3b2SDimitry Andric Unit.addObjCAccelerator(Die, StringPool.getEntry(Names->ClassName), 1630*1db9f3b2SDimitry Andric SkipPubSection); 1631*1db9f3b2SDimitry Andric if (Names->ClassNameNoCategory) 1632*1db9f3b2SDimitry Andric Unit.addObjCAccelerator( 1633*1db9f3b2SDimitry Andric Die, StringPool.getEntry(*Names->ClassNameNoCategory), SkipPubSection); 1634*1db9f3b2SDimitry Andric if (Names->MethodNameNoCategory) 1635*1db9f3b2SDimitry Andric Unit.addNameAccelerator( 1636*1db9f3b2SDimitry Andric Die, StringPool.getEntry(*Names->MethodNameNoCategory), SkipPubSection); 1637*1db9f3b2SDimitry Andric } 1638*1db9f3b2SDimitry Andric 1639*1db9f3b2SDimitry Andric static bool 1640*1db9f3b2SDimitry Andric shouldSkipAttribute(bool Update, 1641*1db9f3b2SDimitry Andric DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, 1642*1db9f3b2SDimitry Andric bool SkipPC) { 1643*1db9f3b2SDimitry Andric switch (AttrSpec.Attr) { 1644*1db9f3b2SDimitry Andric default: 1645*1db9f3b2SDimitry Andric return false; 1646*1db9f3b2SDimitry Andric case dwarf::DW_AT_low_pc: 1647*1db9f3b2SDimitry Andric case dwarf::DW_AT_high_pc: 1648*1db9f3b2SDimitry Andric case dwarf::DW_AT_ranges: 1649*1db9f3b2SDimitry Andric return !Update && SkipPC; 1650*1db9f3b2SDimitry Andric case dwarf::DW_AT_rnglists_base: 1651*1db9f3b2SDimitry Andric // In case !Update the .debug_addr table is not generated/preserved. 1652*1db9f3b2SDimitry Andric // Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used. 1653*1db9f3b2SDimitry Andric // Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the 1654*1db9f3b2SDimitry Andric // DW_AT_rnglists_base is removed. 1655*1db9f3b2SDimitry Andric return !Update; 1656*1db9f3b2SDimitry Andric case dwarf::DW_AT_loclists_base: 1657*1db9f3b2SDimitry Andric // In case !Update the .debug_addr table is not generated/preserved. 1658*1db9f3b2SDimitry Andric // Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used. 1659*1db9f3b2SDimitry Andric // Since DW_AT_loclists_base is used for only DW_FORM_loclistx the 1660*1db9f3b2SDimitry Andric // DW_AT_loclists_base is removed. 1661*1db9f3b2SDimitry Andric return !Update; 1662*1db9f3b2SDimitry Andric case dwarf::DW_AT_location: 1663*1db9f3b2SDimitry Andric case dwarf::DW_AT_frame_base: 1664*1db9f3b2SDimitry Andric return !Update && SkipPC; 1665*1db9f3b2SDimitry Andric } 1666*1db9f3b2SDimitry Andric } 1667*1db9f3b2SDimitry Andric 1668*1db9f3b2SDimitry Andric struct AttributeLinkedOffsetFixup { 1669*1db9f3b2SDimitry Andric int64_t LinkedOffsetFixupVal; 1670*1db9f3b2SDimitry Andric uint64_t InputAttrStartOffset; 1671*1db9f3b2SDimitry Andric uint64_t InputAttrEndOffset; 1672*1db9f3b2SDimitry Andric }; 1673*1db9f3b2SDimitry Andric 1674*1db9f3b2SDimitry Andric DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, 1675*1db9f3b2SDimitry Andric const DWARFFile &File, CompileUnit &Unit, 1676*1db9f3b2SDimitry Andric int64_t PCOffset, uint32_t OutOffset, 1677*1db9f3b2SDimitry Andric unsigned Flags, bool IsLittleEndian, 1678*1db9f3b2SDimitry Andric DIE *Die) { 1679*1db9f3b2SDimitry Andric DWARFUnit &U = Unit.getOrigUnit(); 1680*1db9f3b2SDimitry Andric unsigned Idx = U.getDIEIndex(InputDIE); 1681*1db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = Unit.getInfo(Idx); 1682*1db9f3b2SDimitry Andric 1683*1db9f3b2SDimitry Andric // Should the DIE appear in the output? 1684*1db9f3b2SDimitry Andric if (!Unit.getInfo(Idx).Keep) 1685*1db9f3b2SDimitry Andric return nullptr; 1686*1db9f3b2SDimitry Andric 1687*1db9f3b2SDimitry Andric uint64_t Offset = InputDIE.getOffset(); 1688*1db9f3b2SDimitry Andric assert(!(Die && Info.Clone) && "Can't supply a DIE and a cloned DIE"); 1689*1db9f3b2SDimitry Andric if (!Die) { 1690*1db9f3b2SDimitry Andric // The DIE might have been already created by a forward reference 1691*1db9f3b2SDimitry Andric // (see cloneDieReferenceAttribute()). 1692*1db9f3b2SDimitry Andric if (!Info.Clone) 1693*1db9f3b2SDimitry Andric Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag())); 1694*1db9f3b2SDimitry Andric Die = Info.Clone; 1695*1db9f3b2SDimitry Andric } 1696*1db9f3b2SDimitry Andric 1697*1db9f3b2SDimitry Andric assert(Die->getTag() == InputDIE.getTag()); 1698*1db9f3b2SDimitry Andric Die->setOffset(OutOffset); 1699*1db9f3b2SDimitry Andric if (isODRCanonicalCandidate(InputDIE, Unit) && Info.Ctxt && 1700*1db9f3b2SDimitry Andric (Info.Ctxt->getCanonicalDIEOffset() == 0)) { 1701*1db9f3b2SDimitry Andric if (!Info.Ctxt->hasCanonicalDIE()) 1702*1db9f3b2SDimitry Andric Info.Ctxt->setHasCanonicalDIE(); 1703*1db9f3b2SDimitry Andric // We are about to emit a DIE that is the root of its own valid 1704*1db9f3b2SDimitry Andric // DeclContext tree. Make the current offset the canonical offset 1705*1db9f3b2SDimitry Andric // for this context. 1706*1db9f3b2SDimitry Andric Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset()); 1707*1db9f3b2SDimitry Andric } 1708*1db9f3b2SDimitry Andric 1709*1db9f3b2SDimitry Andric // Extract and clone every attribute. 1710*1db9f3b2SDimitry Andric DWARFDataExtractor Data = U.getDebugInfoExtractor(); 1711*1db9f3b2SDimitry Andric // Point to the next DIE (generally there is always at least a NULL 1712*1db9f3b2SDimitry Andric // entry after the current one). If this is a lone 1713*1db9f3b2SDimitry Andric // DW_TAG_compile_unit without any children, point to the next unit. 1714*1db9f3b2SDimitry Andric uint64_t NextOffset = (Idx + 1 < U.getNumDIEs()) 1715*1db9f3b2SDimitry Andric ? U.getDIEAtIndex(Idx + 1).getOffset() 1716*1db9f3b2SDimitry Andric : U.getNextUnitOffset(); 1717*1db9f3b2SDimitry Andric AttributesInfo AttrInfo; 1718*1db9f3b2SDimitry Andric 1719*1db9f3b2SDimitry Andric // We could copy the data only if we need to apply a relocation to it. After 1720*1db9f3b2SDimitry Andric // testing, it seems there is no performance downside to doing the copy 1721*1db9f3b2SDimitry Andric // unconditionally, and it makes the code simpler. 1722*1db9f3b2SDimitry Andric SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset)); 1723*1db9f3b2SDimitry Andric Data = 1724*1db9f3b2SDimitry Andric DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize()); 1725*1db9f3b2SDimitry Andric 1726*1db9f3b2SDimitry Andric // Modify the copy with relocated addresses. 1727*1db9f3b2SDimitry Andric ObjFile.Addresses->applyValidRelocs(DIECopy, Offset, Data.isLittleEndian()); 1728*1db9f3b2SDimitry Andric 1729*1db9f3b2SDimitry Andric // Reset the Offset to 0 as we will be working on the local copy of 1730*1db9f3b2SDimitry Andric // the data. 1731*1db9f3b2SDimitry Andric Offset = 0; 1732*1db9f3b2SDimitry Andric 1733*1db9f3b2SDimitry Andric const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr(); 1734*1db9f3b2SDimitry Andric Offset += getULEB128Size(Abbrev->getCode()); 1735*1db9f3b2SDimitry Andric 1736*1db9f3b2SDimitry Andric // We are entering a subprogram. Get and propagate the PCOffset. 1737*1db9f3b2SDimitry Andric if (Die->getTag() == dwarf::DW_TAG_subprogram) 1738*1db9f3b2SDimitry Andric PCOffset = Info.AddrAdjust; 1739*1db9f3b2SDimitry Andric AttrInfo.PCOffset = PCOffset; 1740*1db9f3b2SDimitry Andric 1741*1db9f3b2SDimitry Andric if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) { 1742*1db9f3b2SDimitry Andric Flags |= TF_InFunctionScope; 1743*1db9f3b2SDimitry Andric if (!Info.InDebugMap && LLVM_LIKELY(!Update)) 1744*1db9f3b2SDimitry Andric Flags |= TF_SkipPC; 1745*1db9f3b2SDimitry Andric } else if (Abbrev->getTag() == dwarf::DW_TAG_variable) { 1746*1db9f3b2SDimitry Andric // Function-local globals could be in the debug map even when the function 1747*1db9f3b2SDimitry Andric // is not, e.g., inlined functions. 1748*1db9f3b2SDimitry Andric if ((Flags & TF_InFunctionScope) && Info.InDebugMap) 1749*1db9f3b2SDimitry Andric Flags &= ~TF_SkipPC; 1750*1db9f3b2SDimitry Andric // Location expressions referencing an address which is not in debug map 1751*1db9f3b2SDimitry Andric // should be deleted. 1752*1db9f3b2SDimitry Andric else if (!Info.InDebugMap && Info.HasLocationExpressionAddr && 1753*1db9f3b2SDimitry Andric LLVM_LIKELY(!Update)) 1754*1db9f3b2SDimitry Andric Flags |= TF_SkipPC; 1755*1db9f3b2SDimitry Andric } 1756*1db9f3b2SDimitry Andric 1757*1db9f3b2SDimitry Andric std::optional<StringRef> LibraryInstallName = 1758*1db9f3b2SDimitry Andric ObjFile.Addresses->getLibraryInstallName(); 1759*1db9f3b2SDimitry Andric SmallVector<AttributeLinkedOffsetFixup> AttributesFixups; 1760*1db9f3b2SDimitry Andric for (const auto &AttrSpec : Abbrev->attributes()) { 1761*1db9f3b2SDimitry Andric if (shouldSkipAttribute(Update, AttrSpec, Flags & TF_SkipPC)) { 1762*1db9f3b2SDimitry Andric DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, 1763*1db9f3b2SDimitry Andric U.getFormParams()); 1764*1db9f3b2SDimitry Andric continue; 1765*1db9f3b2SDimitry Andric } 1766*1db9f3b2SDimitry Andric 1767*1db9f3b2SDimitry Andric AttributeLinkedOffsetFixup CurAttrFixup; 1768*1db9f3b2SDimitry Andric CurAttrFixup.InputAttrStartOffset = InputDIE.getOffset() + Offset; 1769*1db9f3b2SDimitry Andric CurAttrFixup.LinkedOffsetFixupVal = 1770*1db9f3b2SDimitry Andric Unit.getStartOffset() + OutOffset - CurAttrFixup.InputAttrStartOffset; 1771*1db9f3b2SDimitry Andric 1772*1db9f3b2SDimitry Andric DWARFFormValue Val = AttrSpec.getFormValue(); 1773*1db9f3b2SDimitry Andric uint64_t AttrSize = Offset; 1774*1db9f3b2SDimitry Andric Val.extractValue(Data, &Offset, U.getFormParams(), &U); 1775*1db9f3b2SDimitry Andric CurAttrFixup.InputAttrEndOffset = InputDIE.getOffset() + Offset; 1776*1db9f3b2SDimitry Andric AttrSize = Offset - AttrSize; 1777*1db9f3b2SDimitry Andric 1778*1db9f3b2SDimitry Andric uint64_t FinalAttrSize = 1779*1db9f3b2SDimitry Andric cloneAttribute(*Die, InputDIE, File, Unit, Val, AttrSpec, AttrSize, 1780*1db9f3b2SDimitry Andric AttrInfo, IsLittleEndian); 1781*1db9f3b2SDimitry Andric if (FinalAttrSize != 0 && ObjFile.Addresses->needToSaveValidRelocs()) 1782*1db9f3b2SDimitry Andric AttributesFixups.push_back(CurAttrFixup); 1783*1db9f3b2SDimitry Andric 1784*1db9f3b2SDimitry Andric OutOffset += FinalAttrSize; 1785*1db9f3b2SDimitry Andric } 1786*1db9f3b2SDimitry Andric 1787*1db9f3b2SDimitry Andric uint16_t Tag = InputDIE.getTag(); 1788*1db9f3b2SDimitry Andric // Add the DW_AT_APPLE_origin attribute to Compile Unit die if we have 1789*1db9f3b2SDimitry Andric // an install name and the DWARF doesn't have the attribute yet. 1790*1db9f3b2SDimitry Andric const bool NeedsAppleOrigin = (Tag == dwarf::DW_TAG_compile_unit) && 1791*1db9f3b2SDimitry Andric LibraryInstallName.has_value() && 1792*1db9f3b2SDimitry Andric !AttrInfo.HasAppleOrigin; 1793*1db9f3b2SDimitry Andric if (NeedsAppleOrigin) { 1794*1db9f3b2SDimitry Andric auto StringEntry = DebugStrPool.getEntry(LibraryInstallName.value()); 1795*1db9f3b2SDimitry Andric Die->addValue(DIEAlloc, dwarf::Attribute(dwarf::DW_AT_APPLE_origin), 1796*1db9f3b2SDimitry Andric dwarf::DW_FORM_strp, DIEInteger(StringEntry.getOffset())); 1797*1db9f3b2SDimitry Andric AttrInfo.Name = StringEntry; 1798*1db9f3b2SDimitry Andric OutOffset += 4; 1799*1db9f3b2SDimitry Andric } 1800*1db9f3b2SDimitry Andric 1801*1db9f3b2SDimitry Andric // Look for accelerator entries. 1802*1db9f3b2SDimitry Andric // FIXME: This is slightly wrong. An inline_subroutine without a 1803*1db9f3b2SDimitry Andric // low_pc, but with AT_ranges might be interesting to get into the 1804*1db9f3b2SDimitry Andric // accelerator tables too. For now stick with dsymutil's behavior. 1805*1db9f3b2SDimitry Andric if ((Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) && 1806*1db9f3b2SDimitry Andric Tag != dwarf::DW_TAG_compile_unit && 1807*1db9f3b2SDimitry Andric getDIENames(InputDIE, AttrInfo, DebugStrPool, 1808*1db9f3b2SDimitry Andric Tag != dwarf::DW_TAG_inlined_subroutine)) { 1809*1db9f3b2SDimitry Andric if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name) 1810*1db9f3b2SDimitry Andric Unit.addNameAccelerator(Die, AttrInfo.MangledName, 1811*1db9f3b2SDimitry Andric Tag == dwarf::DW_TAG_inlined_subroutine); 1812*1db9f3b2SDimitry Andric if (AttrInfo.Name) { 1813*1db9f3b2SDimitry Andric if (AttrInfo.NameWithoutTemplate) 1814*1db9f3b2SDimitry Andric Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate, 1815*1db9f3b2SDimitry Andric /* SkipPubSection */ true); 1816*1db9f3b2SDimitry Andric Unit.addNameAccelerator(Die, AttrInfo.Name, 1817*1db9f3b2SDimitry Andric Tag == dwarf::DW_TAG_inlined_subroutine); 1818*1db9f3b2SDimitry Andric } 1819*1db9f3b2SDimitry Andric if (AttrInfo.Name) 1820*1db9f3b2SDimitry Andric addObjCAccelerator(Unit, Die, AttrInfo.Name, DebugStrPool, 1821*1db9f3b2SDimitry Andric /* SkipPubSection =*/true); 1822*1db9f3b2SDimitry Andric 1823*1db9f3b2SDimitry Andric } else if (Tag == dwarf::DW_TAG_namespace) { 1824*1db9f3b2SDimitry Andric if (!AttrInfo.Name) 1825*1db9f3b2SDimitry Andric AttrInfo.Name = DebugStrPool.getEntry("(anonymous namespace)"); 1826*1db9f3b2SDimitry Andric Unit.addNamespaceAccelerator(Die, AttrInfo.Name); 1827*1db9f3b2SDimitry Andric } else if (Tag == dwarf::DW_TAG_imported_declaration && AttrInfo.Name) { 1828*1db9f3b2SDimitry Andric Unit.addNamespaceAccelerator(Die, AttrInfo.Name); 1829*1db9f3b2SDimitry Andric } else if (isTypeTag(Tag) && !AttrInfo.IsDeclaration && 1830*1db9f3b2SDimitry Andric getDIENames(InputDIE, AttrInfo, DebugStrPool) && AttrInfo.Name && 1831*1db9f3b2SDimitry Andric AttrInfo.Name.getString()[0]) { 1832*1db9f3b2SDimitry Andric uint32_t Hash = hashFullyQualifiedName(InputDIE, Unit, File); 1833*1db9f3b2SDimitry Andric uint64_t RuntimeLang = 1834*1db9f3b2SDimitry Andric dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class)) 1835*1db9f3b2SDimitry Andric .value_or(0); 1836*1db9f3b2SDimitry Andric bool ObjCClassIsImplementation = 1837*1db9f3b2SDimitry Andric (RuntimeLang == dwarf::DW_LANG_ObjC || 1838*1db9f3b2SDimitry Andric RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) && 1839*1db9f3b2SDimitry Andric dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type)) 1840*1db9f3b2SDimitry Andric .value_or(0); 1841*1db9f3b2SDimitry Andric Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation, 1842*1db9f3b2SDimitry Andric Hash); 1843*1db9f3b2SDimitry Andric } 1844*1db9f3b2SDimitry Andric 1845*1db9f3b2SDimitry Andric // Determine whether there are any children that we want to keep. 1846*1db9f3b2SDimitry Andric bool HasChildren = false; 1847*1db9f3b2SDimitry Andric for (auto Child : InputDIE.children()) { 1848*1db9f3b2SDimitry Andric unsigned Idx = U.getDIEIndex(Child); 1849*1db9f3b2SDimitry Andric if (Unit.getInfo(Idx).Keep) { 1850*1db9f3b2SDimitry Andric HasChildren = true; 1851*1db9f3b2SDimitry Andric break; 1852*1db9f3b2SDimitry Andric } 1853*1db9f3b2SDimitry Andric } 1854*1db9f3b2SDimitry Andric 1855*1db9f3b2SDimitry Andric if (Unit.getOrigUnit().getVersion() >= 5 && !AttrInfo.AttrStrOffsetBaseSeen && 1856*1db9f3b2SDimitry Andric Die->getTag() == dwarf::DW_TAG_compile_unit) { 1857*1db9f3b2SDimitry Andric // No DW_AT_str_offsets_base seen, add it to the DIE. 1858*1db9f3b2SDimitry Andric Die->addValue(DIEAlloc, dwarf::DW_AT_str_offsets_base, 1859*1db9f3b2SDimitry Andric dwarf::DW_FORM_sec_offset, DIEInteger(8)); 1860*1db9f3b2SDimitry Andric OutOffset += 4; 1861*1db9f3b2SDimitry Andric } 1862*1db9f3b2SDimitry Andric 1863*1db9f3b2SDimitry Andric DIEAbbrev NewAbbrev = Die->generateAbbrev(); 1864*1db9f3b2SDimitry Andric if (HasChildren) 1865*1db9f3b2SDimitry Andric NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); 1866*1db9f3b2SDimitry Andric // Assign a permanent abbrev number 1867*1db9f3b2SDimitry Andric Linker.assignAbbrev(NewAbbrev); 1868*1db9f3b2SDimitry Andric Die->setAbbrevNumber(NewAbbrev.getNumber()); 1869*1db9f3b2SDimitry Andric 1870*1db9f3b2SDimitry Andric uint64_t AbbrevNumberSize = getULEB128Size(Die->getAbbrevNumber()); 1871*1db9f3b2SDimitry Andric 1872*1db9f3b2SDimitry Andric // Add the size of the abbreviation number to the output offset. 1873*1db9f3b2SDimitry Andric OutOffset += AbbrevNumberSize; 1874*1db9f3b2SDimitry Andric 1875*1db9f3b2SDimitry Andric // Update fixups with the size of the abbreviation number 1876*1db9f3b2SDimitry Andric for (AttributeLinkedOffsetFixup &F : AttributesFixups) 1877*1db9f3b2SDimitry Andric F.LinkedOffsetFixupVal += AbbrevNumberSize; 1878*1db9f3b2SDimitry Andric 1879*1db9f3b2SDimitry Andric for (AttributeLinkedOffsetFixup &F : AttributesFixups) 1880*1db9f3b2SDimitry Andric ObjFile.Addresses->updateAndSaveValidRelocs( 1881*1db9f3b2SDimitry Andric Unit.getOrigUnit().getVersion() >= 5, Unit.getOrigUnit().getOffset(), 1882*1db9f3b2SDimitry Andric F.LinkedOffsetFixupVal, F.InputAttrStartOffset, F.InputAttrEndOffset); 1883*1db9f3b2SDimitry Andric 1884*1db9f3b2SDimitry Andric if (!HasChildren) { 1885*1db9f3b2SDimitry Andric // Update our size. 1886*1db9f3b2SDimitry Andric Die->setSize(OutOffset - Die->getOffset()); 1887*1db9f3b2SDimitry Andric return Die; 1888*1db9f3b2SDimitry Andric } 1889*1db9f3b2SDimitry Andric 1890*1db9f3b2SDimitry Andric // Recursively clone children. 1891*1db9f3b2SDimitry Andric for (auto Child : InputDIE.children()) { 1892*1db9f3b2SDimitry Andric if (DIE *Clone = cloneDIE(Child, File, Unit, PCOffset, OutOffset, Flags, 1893*1db9f3b2SDimitry Andric IsLittleEndian)) { 1894*1db9f3b2SDimitry Andric Die->addChild(Clone); 1895*1db9f3b2SDimitry Andric OutOffset = Clone->getOffset() + Clone->getSize(); 1896*1db9f3b2SDimitry Andric } 1897*1db9f3b2SDimitry Andric } 1898*1db9f3b2SDimitry Andric 1899*1db9f3b2SDimitry Andric // Account for the end of children marker. 1900*1db9f3b2SDimitry Andric OutOffset += sizeof(int8_t); 1901*1db9f3b2SDimitry Andric // Update our size. 1902*1db9f3b2SDimitry Andric Die->setSize(OutOffset - Die->getOffset()); 1903*1db9f3b2SDimitry Andric return Die; 1904*1db9f3b2SDimitry Andric } 1905*1db9f3b2SDimitry Andric 1906*1db9f3b2SDimitry Andric /// Patch the input object file relevant debug_ranges or debug_rnglists 1907*1db9f3b2SDimitry Andric /// entries and emit them in the output file. Update the relevant attributes 1908*1db9f3b2SDimitry Andric /// to point at the new entries. 1909*1db9f3b2SDimitry Andric void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File, 1910*1db9f3b2SDimitry Andric DebugDieValuePool &AddrPool) const { 1911*1db9f3b2SDimitry Andric if (LLVM_UNLIKELY(Options.Update)) 1912*1db9f3b2SDimitry Andric return; 1913*1db9f3b2SDimitry Andric 1914*1db9f3b2SDimitry Andric const auto &FunctionRanges = Unit.getFunctionRanges(); 1915*1db9f3b2SDimitry Andric 1916*1db9f3b2SDimitry Andric // Build set of linked address ranges for unit function ranges. 1917*1db9f3b2SDimitry Andric AddressRanges LinkedFunctionRanges; 1918*1db9f3b2SDimitry Andric for (const AddressRangeValuePair &Range : FunctionRanges) 1919*1db9f3b2SDimitry Andric LinkedFunctionRanges.insert( 1920*1db9f3b2SDimitry Andric {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value}); 1921*1db9f3b2SDimitry Andric 1922*1db9f3b2SDimitry Andric // Emit LinkedFunctionRanges into .debug_aranges 1923*1db9f3b2SDimitry Andric if (!LinkedFunctionRanges.empty()) 1924*1db9f3b2SDimitry Andric TheDwarfEmitter->emitDwarfDebugArangesTable(Unit, LinkedFunctionRanges); 1925*1db9f3b2SDimitry Andric 1926*1db9f3b2SDimitry Andric RngListAttributesTy AllRngListAttributes = Unit.getRangesAttributes(); 1927*1db9f3b2SDimitry Andric std::optional<PatchLocation> UnitRngListAttribute = 1928*1db9f3b2SDimitry Andric Unit.getUnitRangesAttribute(); 1929*1db9f3b2SDimitry Andric 1930*1db9f3b2SDimitry Andric if (!AllRngListAttributes.empty() || UnitRngListAttribute) { 1931*1db9f3b2SDimitry Andric std::optional<AddressRangeValuePair> CachedRange; 1932*1db9f3b2SDimitry Andric MCSymbol *EndLabel = TheDwarfEmitter->emitDwarfDebugRangeListHeader(Unit); 1933*1db9f3b2SDimitry Andric 1934*1db9f3b2SDimitry Andric // Read original address ranges, apply relocation value, emit linked address 1935*1db9f3b2SDimitry Andric // ranges. 1936*1db9f3b2SDimitry Andric for (PatchLocation &AttributePatch : AllRngListAttributes) { 1937*1db9f3b2SDimitry Andric // Get ranges from the source DWARF corresponding to the current 1938*1db9f3b2SDimitry Andric // attribute. 1939*1db9f3b2SDimitry Andric AddressRanges LinkedRanges; 1940*1db9f3b2SDimitry Andric if (Expected<DWARFAddressRangesVector> OriginalRanges = 1941*1db9f3b2SDimitry Andric Unit.getOrigUnit().findRnglistFromOffset(AttributePatch.get())) { 1942*1db9f3b2SDimitry Andric // Apply relocation adjustment. 1943*1db9f3b2SDimitry Andric for (const auto &Range : *OriginalRanges) { 1944*1db9f3b2SDimitry Andric if (!CachedRange || !CachedRange->Range.contains(Range.LowPC)) 1945*1db9f3b2SDimitry Andric CachedRange = FunctionRanges.getRangeThatContains(Range.LowPC); 1946*1db9f3b2SDimitry Andric 1947*1db9f3b2SDimitry Andric // All range entries should lie in the function range. 1948*1db9f3b2SDimitry Andric if (!CachedRange) { 1949*1db9f3b2SDimitry Andric reportWarning("inconsistent range data.", File); 1950*1db9f3b2SDimitry Andric continue; 1951*1db9f3b2SDimitry Andric } 1952*1db9f3b2SDimitry Andric 1953*1db9f3b2SDimitry Andric // Store range for emiting. 1954*1db9f3b2SDimitry Andric LinkedRanges.insert({Range.LowPC + CachedRange->Value, 1955*1db9f3b2SDimitry Andric Range.HighPC + CachedRange->Value}); 1956*1db9f3b2SDimitry Andric } 1957*1db9f3b2SDimitry Andric } else { 1958*1db9f3b2SDimitry Andric llvm::consumeError(OriginalRanges.takeError()); 1959*1db9f3b2SDimitry Andric reportWarning("invalid range list ignored.", File); 1960*1db9f3b2SDimitry Andric } 1961*1db9f3b2SDimitry Andric 1962*1db9f3b2SDimitry Andric // Emit linked ranges. 1963*1db9f3b2SDimitry Andric TheDwarfEmitter->emitDwarfDebugRangeListFragment( 1964*1db9f3b2SDimitry Andric Unit, LinkedRanges, AttributePatch, AddrPool); 1965*1db9f3b2SDimitry Andric } 1966*1db9f3b2SDimitry Andric 1967*1db9f3b2SDimitry Andric // Emit ranges for Unit AT_ranges attribute. 1968*1db9f3b2SDimitry Andric if (UnitRngListAttribute.has_value()) 1969*1db9f3b2SDimitry Andric TheDwarfEmitter->emitDwarfDebugRangeListFragment( 1970*1db9f3b2SDimitry Andric Unit, LinkedFunctionRanges, *UnitRngListAttribute, AddrPool); 1971*1db9f3b2SDimitry Andric 1972*1db9f3b2SDimitry Andric // Emit ranges footer. 1973*1db9f3b2SDimitry Andric TheDwarfEmitter->emitDwarfDebugRangeListFooter(Unit, EndLabel); 1974*1db9f3b2SDimitry Andric } 1975*1db9f3b2SDimitry Andric } 1976*1db9f3b2SDimitry Andric 1977*1db9f3b2SDimitry Andric void DWARFLinker::DIECloner::generateUnitLocations( 1978*1db9f3b2SDimitry Andric CompileUnit &Unit, const DWARFFile &File, 1979*1db9f3b2SDimitry Andric ExpressionHandlerRef ExprHandler) { 1980*1db9f3b2SDimitry Andric if (LLVM_UNLIKELY(Linker.Options.Update)) 1981*1db9f3b2SDimitry Andric return; 1982*1db9f3b2SDimitry Andric 1983*1db9f3b2SDimitry Andric const LocListAttributesTy &AllLocListAttributes = 1984*1db9f3b2SDimitry Andric Unit.getLocationAttributes(); 1985*1db9f3b2SDimitry Andric 1986*1db9f3b2SDimitry Andric if (AllLocListAttributes.empty()) 1987*1db9f3b2SDimitry Andric return; 1988*1db9f3b2SDimitry Andric 1989*1db9f3b2SDimitry Andric // Emit locations list table header. 1990*1db9f3b2SDimitry Andric MCSymbol *EndLabel = Emitter->emitDwarfDebugLocListHeader(Unit); 1991*1db9f3b2SDimitry Andric 1992*1db9f3b2SDimitry Andric for (auto &CurLocAttr : AllLocListAttributes) { 1993*1db9f3b2SDimitry Andric // Get location expressions vector corresponding to the current attribute 1994*1db9f3b2SDimitry Andric // from the source DWARF. 1995*1db9f3b2SDimitry Andric Expected<DWARFLocationExpressionsVector> OriginalLocations = 1996*1db9f3b2SDimitry Andric Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get()); 1997*1db9f3b2SDimitry Andric 1998*1db9f3b2SDimitry Andric if (!OriginalLocations) { 1999*1db9f3b2SDimitry Andric llvm::consumeError(OriginalLocations.takeError()); 2000*1db9f3b2SDimitry Andric Linker.reportWarning("Invalid location attribute ignored.", File); 2001*1db9f3b2SDimitry Andric continue; 2002*1db9f3b2SDimitry Andric } 2003*1db9f3b2SDimitry Andric 2004*1db9f3b2SDimitry Andric DWARFLocationExpressionsVector LinkedLocationExpressions; 2005*1db9f3b2SDimitry Andric for (DWARFLocationExpression &CurExpression : *OriginalLocations) { 2006*1db9f3b2SDimitry Andric DWARFLocationExpression LinkedExpression; 2007*1db9f3b2SDimitry Andric 2008*1db9f3b2SDimitry Andric if (CurExpression.Range) { 2009*1db9f3b2SDimitry Andric // Relocate address range. 2010*1db9f3b2SDimitry Andric LinkedExpression.Range = { 2011*1db9f3b2SDimitry Andric CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment, 2012*1db9f3b2SDimitry Andric CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment}; 2013*1db9f3b2SDimitry Andric } 2014*1db9f3b2SDimitry Andric 2015*1db9f3b2SDimitry Andric // Clone expression. 2016*1db9f3b2SDimitry Andric LinkedExpression.Expr.reserve(CurExpression.Expr.size()); 2017*1db9f3b2SDimitry Andric ExprHandler(CurExpression.Expr, LinkedExpression.Expr, 2018*1db9f3b2SDimitry Andric CurLocAttr.RelocAdjustment); 2019*1db9f3b2SDimitry Andric 2020*1db9f3b2SDimitry Andric LinkedLocationExpressions.push_back(LinkedExpression); 2021*1db9f3b2SDimitry Andric } 2022*1db9f3b2SDimitry Andric 2023*1db9f3b2SDimitry Andric // Emit locations list table fragment corresponding to the CurLocAttr. 2024*1db9f3b2SDimitry Andric Emitter->emitDwarfDebugLocListFragment(Unit, LinkedLocationExpressions, 2025*1db9f3b2SDimitry Andric CurLocAttr, AddrPool); 2026*1db9f3b2SDimitry Andric } 2027*1db9f3b2SDimitry Andric 2028*1db9f3b2SDimitry Andric // Emit locations list table footer. 2029*1db9f3b2SDimitry Andric Emitter->emitDwarfDebugLocListFooter(Unit, EndLabel); 2030*1db9f3b2SDimitry Andric } 2031*1db9f3b2SDimitry Andric 2032*1db9f3b2SDimitry Andric static void patchAddrBase(DIE &Die, DIEInteger Offset) { 2033*1db9f3b2SDimitry Andric for (auto &V : Die.values()) 2034*1db9f3b2SDimitry Andric if (V.getAttribute() == dwarf::DW_AT_addr_base) { 2035*1db9f3b2SDimitry Andric V = DIEValue(V.getAttribute(), V.getForm(), Offset); 2036*1db9f3b2SDimitry Andric return; 2037*1db9f3b2SDimitry Andric } 2038*1db9f3b2SDimitry Andric 2039*1db9f3b2SDimitry Andric llvm_unreachable("Didn't find a DW_AT_addr_base in cloned DIE!"); 2040*1db9f3b2SDimitry Andric } 2041*1db9f3b2SDimitry Andric 2042*1db9f3b2SDimitry Andric void DWARFLinker::DIECloner::emitDebugAddrSection( 2043*1db9f3b2SDimitry Andric CompileUnit &Unit, const uint16_t DwarfVersion) const { 2044*1db9f3b2SDimitry Andric 2045*1db9f3b2SDimitry Andric if (LLVM_UNLIKELY(Linker.Options.Update)) 2046*1db9f3b2SDimitry Andric return; 2047*1db9f3b2SDimitry Andric 2048*1db9f3b2SDimitry Andric if (DwarfVersion < 5) 2049*1db9f3b2SDimitry Andric return; 2050*1db9f3b2SDimitry Andric 2051*1db9f3b2SDimitry Andric if (AddrPool.DieValues.empty()) 2052*1db9f3b2SDimitry Andric return; 2053*1db9f3b2SDimitry Andric 2054*1db9f3b2SDimitry Andric MCSymbol *EndLabel = Emitter->emitDwarfDebugAddrsHeader(Unit); 2055*1db9f3b2SDimitry Andric patchAddrBase(*Unit.getOutputUnitDIE(), 2056*1db9f3b2SDimitry Andric DIEInteger(Emitter->getDebugAddrSectionSize())); 2057*1db9f3b2SDimitry Andric Emitter->emitDwarfDebugAddrs(AddrPool.DieValues, 2058*1db9f3b2SDimitry Andric Unit.getOrigUnit().getAddressByteSize()); 2059*1db9f3b2SDimitry Andric Emitter->emitDwarfDebugAddrsFooter(Unit, EndLabel); 2060*1db9f3b2SDimitry Andric } 2061*1db9f3b2SDimitry Andric 2062*1db9f3b2SDimitry Andric /// Insert the new line info sequence \p Seq into the current 2063*1db9f3b2SDimitry Andric /// set of already linked line info \p Rows. 2064*1db9f3b2SDimitry Andric static void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq, 2065*1db9f3b2SDimitry Andric std::vector<DWARFDebugLine::Row> &Rows) { 2066*1db9f3b2SDimitry Andric if (Seq.empty()) 2067*1db9f3b2SDimitry Andric return; 2068*1db9f3b2SDimitry Andric 2069*1db9f3b2SDimitry Andric if (!Rows.empty() && Rows.back().Address < Seq.front().Address) { 2070*1db9f3b2SDimitry Andric llvm::append_range(Rows, Seq); 2071*1db9f3b2SDimitry Andric Seq.clear(); 2072*1db9f3b2SDimitry Andric return; 2073*1db9f3b2SDimitry Andric } 2074*1db9f3b2SDimitry Andric 2075*1db9f3b2SDimitry Andric object::SectionedAddress Front = Seq.front().Address; 2076*1db9f3b2SDimitry Andric auto InsertPoint = partition_point( 2077*1db9f3b2SDimitry Andric Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; }); 2078*1db9f3b2SDimitry Andric 2079*1db9f3b2SDimitry Andric // FIXME: this only removes the unneeded end_sequence if the 2080*1db9f3b2SDimitry Andric // sequences have been inserted in order. Using a global sort like 2081*1db9f3b2SDimitry Andric // described in generateLineTableForUnit() and delaying the end_sequene 2082*1db9f3b2SDimitry Andric // elimination to emitLineTableForUnit() we can get rid of all of them. 2083*1db9f3b2SDimitry Andric if (InsertPoint != Rows.end() && InsertPoint->Address == Front && 2084*1db9f3b2SDimitry Andric InsertPoint->EndSequence) { 2085*1db9f3b2SDimitry Andric *InsertPoint = Seq.front(); 2086*1db9f3b2SDimitry Andric Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end()); 2087*1db9f3b2SDimitry Andric } else { 2088*1db9f3b2SDimitry Andric Rows.insert(InsertPoint, Seq.begin(), Seq.end()); 2089*1db9f3b2SDimitry Andric } 2090*1db9f3b2SDimitry Andric 2091*1db9f3b2SDimitry Andric Seq.clear(); 2092*1db9f3b2SDimitry Andric } 2093*1db9f3b2SDimitry Andric 2094*1db9f3b2SDimitry Andric static void patchStmtList(DIE &Die, DIEInteger Offset) { 2095*1db9f3b2SDimitry Andric for (auto &V : Die.values()) 2096*1db9f3b2SDimitry Andric if (V.getAttribute() == dwarf::DW_AT_stmt_list) { 2097*1db9f3b2SDimitry Andric V = DIEValue(V.getAttribute(), V.getForm(), Offset); 2098*1db9f3b2SDimitry Andric return; 2099*1db9f3b2SDimitry Andric } 2100*1db9f3b2SDimitry Andric 2101*1db9f3b2SDimitry Andric llvm_unreachable("Didn't find DW_AT_stmt_list in cloned DIE!"); 2102*1db9f3b2SDimitry Andric } 2103*1db9f3b2SDimitry Andric 2104*1db9f3b2SDimitry Andric void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) { 2105*1db9f3b2SDimitry Andric DWARFUnit &OrigUnit = Unit.getOrigUnit(); 2106*1db9f3b2SDimitry Andric DWARFDie OrigUnitDie = OrigUnit.getUnitDIE(); 2107*1db9f3b2SDimitry Andric 2108*1db9f3b2SDimitry Andric if (std::optional<uint64_t> MacroAttr = 2109*1db9f3b2SDimitry Andric dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macros))) { 2110*1db9f3b2SDimitry Andric UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit)); 2111*1db9f3b2SDimitry Andric return; 2112*1db9f3b2SDimitry Andric } 2113*1db9f3b2SDimitry Andric 2114*1db9f3b2SDimitry Andric if (std::optional<uint64_t> MacroAttr = 2115*1db9f3b2SDimitry Andric dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macro_info))) { 2116*1db9f3b2SDimitry Andric UnitMacroMap.insert(std::make_pair(*MacroAttr, &Unit)); 2117*1db9f3b2SDimitry Andric return; 2118*1db9f3b2SDimitry Andric } 2119*1db9f3b2SDimitry Andric } 2120*1db9f3b2SDimitry Andric 2121*1db9f3b2SDimitry Andric void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) { 2122*1db9f3b2SDimitry Andric if (LLVM_UNLIKELY(Emitter == nullptr)) 2123*1db9f3b2SDimitry Andric return; 2124*1db9f3b2SDimitry Andric 2125*1db9f3b2SDimitry Andric // Check whether DW_AT_stmt_list attribute is presented. 2126*1db9f3b2SDimitry Andric DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE(); 2127*1db9f3b2SDimitry Andric auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list)); 2128*1db9f3b2SDimitry Andric if (!StmtList) 2129*1db9f3b2SDimitry Andric return; 2130*1db9f3b2SDimitry Andric 2131*1db9f3b2SDimitry Andric // Update the cloned DW_AT_stmt_list with the correct debug_line offset. 2132*1db9f3b2SDimitry Andric if (auto *OutputDIE = Unit.getOutputUnitDIE()) 2133*1db9f3b2SDimitry Andric patchStmtList(*OutputDIE, DIEInteger(Emitter->getLineSectionSize())); 2134*1db9f3b2SDimitry Andric 2135*1db9f3b2SDimitry Andric if (const DWARFDebugLine::LineTable *LT = 2136*1db9f3b2SDimitry Andric ObjFile.Dwarf->getLineTableForUnit(&Unit.getOrigUnit())) { 2137*1db9f3b2SDimitry Andric 2138*1db9f3b2SDimitry Andric DWARFDebugLine::LineTable LineTable; 2139*1db9f3b2SDimitry Andric 2140*1db9f3b2SDimitry Andric // Set Line Table header. 2141*1db9f3b2SDimitry Andric LineTable.Prologue = LT->Prologue; 2142*1db9f3b2SDimitry Andric 2143*1db9f3b2SDimitry Andric // Set Line Table Rows. 2144*1db9f3b2SDimitry Andric if (Linker.Options.Update) { 2145*1db9f3b2SDimitry Andric LineTable.Rows = LT->Rows; 2146*1db9f3b2SDimitry Andric // If all the line table contains is a DW_LNE_end_sequence, clear the line 2147*1db9f3b2SDimitry Andric // table rows, it will be inserted again in the DWARFStreamer. 2148*1db9f3b2SDimitry Andric if (LineTable.Rows.size() == 1 && LineTable.Rows[0].EndSequence) 2149*1db9f3b2SDimitry Andric LineTable.Rows.clear(); 2150*1db9f3b2SDimitry Andric 2151*1db9f3b2SDimitry Andric LineTable.Sequences = LT->Sequences; 2152*1db9f3b2SDimitry Andric } else { 2153*1db9f3b2SDimitry Andric // This vector is the output line table. 2154*1db9f3b2SDimitry Andric std::vector<DWARFDebugLine::Row> NewRows; 2155*1db9f3b2SDimitry Andric NewRows.reserve(LT->Rows.size()); 2156*1db9f3b2SDimitry Andric 2157*1db9f3b2SDimitry Andric // Current sequence of rows being extracted, before being inserted 2158*1db9f3b2SDimitry Andric // in NewRows. 2159*1db9f3b2SDimitry Andric std::vector<DWARFDebugLine::Row> Seq; 2160*1db9f3b2SDimitry Andric 2161*1db9f3b2SDimitry Andric const auto &FunctionRanges = Unit.getFunctionRanges(); 2162*1db9f3b2SDimitry Andric std::optional<AddressRangeValuePair> CurrRange; 2163*1db9f3b2SDimitry Andric 2164*1db9f3b2SDimitry Andric // FIXME: This logic is meant to generate exactly the same output as 2165*1db9f3b2SDimitry Andric // Darwin's classic dsymutil. There is a nicer way to implement this 2166*1db9f3b2SDimitry Andric // by simply putting all the relocated line info in NewRows and simply 2167*1db9f3b2SDimitry Andric // sorting NewRows before passing it to emitLineTableForUnit. This 2168*1db9f3b2SDimitry Andric // should be correct as sequences for a function should stay 2169*1db9f3b2SDimitry Andric // together in the sorted output. There are a few corner cases that 2170*1db9f3b2SDimitry Andric // look suspicious though, and that required to implement the logic 2171*1db9f3b2SDimitry Andric // this way. Revisit that once initial validation is finished. 2172*1db9f3b2SDimitry Andric 2173*1db9f3b2SDimitry Andric // Iterate over the object file line info and extract the sequences 2174*1db9f3b2SDimitry Andric // that correspond to linked functions. 2175*1db9f3b2SDimitry Andric for (DWARFDebugLine::Row Row : LT->Rows) { 2176*1db9f3b2SDimitry Andric // Check whether we stepped out of the range. The range is 2177*1db9f3b2SDimitry Andric // half-open, but consider accept the end address of the range if 2178*1db9f3b2SDimitry Andric // it is marked as end_sequence in the input (because in that 2179*1db9f3b2SDimitry Andric // case, the relocation offset is accurate and that entry won't 2180*1db9f3b2SDimitry Andric // serve as the start of another function). 2181*1db9f3b2SDimitry Andric if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) { 2182*1db9f3b2SDimitry Andric // We just stepped out of a known range. Insert a end_sequence 2183*1db9f3b2SDimitry Andric // corresponding to the end of the range. 2184*1db9f3b2SDimitry Andric uint64_t StopAddress = 2185*1db9f3b2SDimitry Andric CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL; 2186*1db9f3b2SDimitry Andric CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address); 2187*1db9f3b2SDimitry Andric if (StopAddress != -1ULL && !Seq.empty()) { 2188*1db9f3b2SDimitry Andric // Insert end sequence row with the computed end address, but 2189*1db9f3b2SDimitry Andric // the same line as the previous one. 2190*1db9f3b2SDimitry Andric auto NextLine = Seq.back(); 2191*1db9f3b2SDimitry Andric NextLine.Address.Address = StopAddress; 2192*1db9f3b2SDimitry Andric NextLine.EndSequence = 1; 2193*1db9f3b2SDimitry Andric NextLine.PrologueEnd = 0; 2194*1db9f3b2SDimitry Andric NextLine.BasicBlock = 0; 2195*1db9f3b2SDimitry Andric NextLine.EpilogueBegin = 0; 2196*1db9f3b2SDimitry Andric Seq.push_back(NextLine); 2197*1db9f3b2SDimitry Andric insertLineSequence(Seq, NewRows); 2198*1db9f3b2SDimitry Andric } 2199*1db9f3b2SDimitry Andric 2200*1db9f3b2SDimitry Andric if (!CurrRange) 2201*1db9f3b2SDimitry Andric continue; 2202*1db9f3b2SDimitry Andric } 2203*1db9f3b2SDimitry Andric 2204*1db9f3b2SDimitry Andric // Ignore empty sequences. 2205*1db9f3b2SDimitry Andric if (Row.EndSequence && Seq.empty()) 2206*1db9f3b2SDimitry Andric continue; 2207*1db9f3b2SDimitry Andric 2208*1db9f3b2SDimitry Andric // Relocate row address and add it to the current sequence. 2209*1db9f3b2SDimitry Andric Row.Address.Address += CurrRange->Value; 2210*1db9f3b2SDimitry Andric Seq.emplace_back(Row); 2211*1db9f3b2SDimitry Andric 2212*1db9f3b2SDimitry Andric if (Row.EndSequence) 2213*1db9f3b2SDimitry Andric insertLineSequence(Seq, NewRows); 2214*1db9f3b2SDimitry Andric } 2215*1db9f3b2SDimitry Andric 2216*1db9f3b2SDimitry Andric LineTable.Rows = std::move(NewRows); 2217*1db9f3b2SDimitry Andric } 2218*1db9f3b2SDimitry Andric 2219*1db9f3b2SDimitry Andric Emitter->emitLineTableForUnit(LineTable, Unit, DebugStrPool, 2220*1db9f3b2SDimitry Andric DebugLineStrPool); 2221*1db9f3b2SDimitry Andric } else 2222*1db9f3b2SDimitry Andric Linker.reportWarning("Cann't load line table.", ObjFile); 2223*1db9f3b2SDimitry Andric } 2224*1db9f3b2SDimitry Andric 2225*1db9f3b2SDimitry Andric void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) { 2226*1db9f3b2SDimitry Andric for (AccelTableKind AccelTableKind : Options.AccelTables) { 2227*1db9f3b2SDimitry Andric switch (AccelTableKind) { 2228*1db9f3b2SDimitry Andric case AccelTableKind::Apple: { 2229*1db9f3b2SDimitry Andric // Add namespaces. 2230*1db9f3b2SDimitry Andric for (const auto &Namespace : Unit.getNamespaces()) 2231*1db9f3b2SDimitry Andric AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() + 2232*1db9f3b2SDimitry Andric Unit.getStartOffset()); 2233*1db9f3b2SDimitry Andric // Add names. 2234*1db9f3b2SDimitry Andric for (const auto &Pubname : Unit.getPubnames()) 2235*1db9f3b2SDimitry Andric AppleNames.addName(Pubname.Name, 2236*1db9f3b2SDimitry Andric Pubname.Die->getOffset() + Unit.getStartOffset()); 2237*1db9f3b2SDimitry Andric // Add types. 2238*1db9f3b2SDimitry Andric for (const auto &Pubtype : Unit.getPubtypes()) 2239*1db9f3b2SDimitry Andric AppleTypes.addName( 2240*1db9f3b2SDimitry Andric Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(), 2241*1db9f3b2SDimitry Andric Pubtype.Die->getTag(), 2242*1db9f3b2SDimitry Andric Pubtype.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation 2243*1db9f3b2SDimitry Andric : 0, 2244*1db9f3b2SDimitry Andric Pubtype.QualifiedNameHash); 2245*1db9f3b2SDimitry Andric // Add ObjC names. 2246*1db9f3b2SDimitry Andric for (const auto &ObjC : Unit.getObjC()) 2247*1db9f3b2SDimitry Andric AppleObjc.addName(ObjC.Name, 2248*1db9f3b2SDimitry Andric ObjC.Die->getOffset() + Unit.getStartOffset()); 2249*1db9f3b2SDimitry Andric } break; 2250*1db9f3b2SDimitry Andric case AccelTableKind::Pub: { 2251*1db9f3b2SDimitry Andric TheDwarfEmitter->emitPubNamesForUnit(Unit); 2252*1db9f3b2SDimitry Andric TheDwarfEmitter->emitPubTypesForUnit(Unit); 2253*1db9f3b2SDimitry Andric } break; 2254*1db9f3b2SDimitry Andric case AccelTableKind::DebugNames: { 2255*1db9f3b2SDimitry Andric for (const auto &Namespace : Unit.getNamespaces()) 2256*1db9f3b2SDimitry Andric DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(), 2257*1db9f3b2SDimitry Andric Namespace.Die->getTag(), Unit.getUniqueID()); 2258*1db9f3b2SDimitry Andric for (const auto &Pubname : Unit.getPubnames()) 2259*1db9f3b2SDimitry Andric DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(), 2260*1db9f3b2SDimitry Andric Pubname.Die->getTag(), Unit.getUniqueID()); 2261*1db9f3b2SDimitry Andric for (const auto &Pubtype : Unit.getPubtypes()) 2262*1db9f3b2SDimitry Andric DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(), 2263*1db9f3b2SDimitry Andric Pubtype.Die->getTag(), Unit.getUniqueID()); 2264*1db9f3b2SDimitry Andric } break; 2265*1db9f3b2SDimitry Andric } 2266*1db9f3b2SDimitry Andric } 2267*1db9f3b2SDimitry Andric } 2268*1db9f3b2SDimitry Andric 2269*1db9f3b2SDimitry Andric /// Read the frame info stored in the object, and emit the 2270*1db9f3b2SDimitry Andric /// patched frame descriptions for the resulting file. 2271*1db9f3b2SDimitry Andric /// 2272*1db9f3b2SDimitry Andric /// This is actually pretty easy as the data of the CIEs and FDEs can 2273*1db9f3b2SDimitry Andric /// be considered as black boxes and moved as is. The only thing to do 2274*1db9f3b2SDimitry Andric /// is to patch the addresses in the headers. 2275*1db9f3b2SDimitry Andric void DWARFLinker::patchFrameInfoForObject(LinkContext &Context) { 2276*1db9f3b2SDimitry Andric DWARFContext &OrigDwarf = *Context.File.Dwarf; 2277*1db9f3b2SDimitry Andric unsigned SrcAddrSize = OrigDwarf.getDWARFObj().getAddressSize(); 2278*1db9f3b2SDimitry Andric 2279*1db9f3b2SDimitry Andric StringRef FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data; 2280*1db9f3b2SDimitry Andric if (FrameData.empty()) 2281*1db9f3b2SDimitry Andric return; 2282*1db9f3b2SDimitry Andric 2283*1db9f3b2SDimitry Andric RangesTy AllUnitsRanges; 2284*1db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &Unit : Context.CompileUnits) { 2285*1db9f3b2SDimitry Andric for (auto CurRange : Unit->getFunctionRanges()) 2286*1db9f3b2SDimitry Andric AllUnitsRanges.insert(CurRange.Range, CurRange.Value); 2287*1db9f3b2SDimitry Andric } 2288*1db9f3b2SDimitry Andric 2289*1db9f3b2SDimitry Andric DataExtractor Data(FrameData, OrigDwarf.isLittleEndian(), 0); 2290*1db9f3b2SDimitry Andric uint64_t InputOffset = 0; 2291*1db9f3b2SDimitry Andric 2292*1db9f3b2SDimitry Andric // Store the data of the CIEs defined in this object, keyed by their 2293*1db9f3b2SDimitry Andric // offsets. 2294*1db9f3b2SDimitry Andric DenseMap<uint64_t, StringRef> LocalCIES; 2295*1db9f3b2SDimitry Andric 2296*1db9f3b2SDimitry Andric while (Data.isValidOffset(InputOffset)) { 2297*1db9f3b2SDimitry Andric uint64_t EntryOffset = InputOffset; 2298*1db9f3b2SDimitry Andric uint32_t InitialLength = Data.getU32(&InputOffset); 2299*1db9f3b2SDimitry Andric if (InitialLength == 0xFFFFFFFF) 2300*1db9f3b2SDimitry Andric return reportWarning("Dwarf64 bits no supported", Context.File); 2301*1db9f3b2SDimitry Andric 2302*1db9f3b2SDimitry Andric uint32_t CIEId = Data.getU32(&InputOffset); 2303*1db9f3b2SDimitry Andric if (CIEId == 0xFFFFFFFF) { 2304*1db9f3b2SDimitry Andric // This is a CIE, store it. 2305*1db9f3b2SDimitry Andric StringRef CIEData = FrameData.substr(EntryOffset, InitialLength + 4); 2306*1db9f3b2SDimitry Andric LocalCIES[EntryOffset] = CIEData; 2307*1db9f3b2SDimitry Andric // The -4 is to account for the CIEId we just read. 2308*1db9f3b2SDimitry Andric InputOffset += InitialLength - 4; 2309*1db9f3b2SDimitry Andric continue; 2310*1db9f3b2SDimitry Andric } 2311*1db9f3b2SDimitry Andric 2312*1db9f3b2SDimitry Andric uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize); 2313*1db9f3b2SDimitry Andric 2314*1db9f3b2SDimitry Andric // Some compilers seem to emit frame info that doesn't start at 2315*1db9f3b2SDimitry Andric // the function entry point, thus we can't just lookup the address 2316*1db9f3b2SDimitry Andric // in the debug map. Use the AddressInfo's range map to see if the FDE 2317*1db9f3b2SDimitry Andric // describes something that we can relocate. 2318*1db9f3b2SDimitry Andric std::optional<AddressRangeValuePair> Range = 2319*1db9f3b2SDimitry Andric AllUnitsRanges.getRangeThatContains(Loc); 2320*1db9f3b2SDimitry Andric if (!Range) { 2321*1db9f3b2SDimitry Andric // The +4 is to account for the size of the InitialLength field itself. 2322*1db9f3b2SDimitry Andric InputOffset = EntryOffset + InitialLength + 4; 2323*1db9f3b2SDimitry Andric continue; 2324*1db9f3b2SDimitry Andric } 2325*1db9f3b2SDimitry Andric 2326*1db9f3b2SDimitry Andric // This is an FDE, and we have a mapping. 2327*1db9f3b2SDimitry Andric // Have we already emitted a corresponding CIE? 2328*1db9f3b2SDimitry Andric StringRef CIEData = LocalCIES[CIEId]; 2329*1db9f3b2SDimitry Andric if (CIEData.empty()) 2330*1db9f3b2SDimitry Andric return reportWarning("Inconsistent debug_frame content. Dropping.", 2331*1db9f3b2SDimitry Andric Context.File); 2332*1db9f3b2SDimitry Andric 2333*1db9f3b2SDimitry Andric // Look if we already emitted a CIE that corresponds to the 2334*1db9f3b2SDimitry Andric // referenced one (the CIE data is the key of that lookup). 2335*1db9f3b2SDimitry Andric auto IteratorInserted = EmittedCIEs.insert( 2336*1db9f3b2SDimitry Andric std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize())); 2337*1db9f3b2SDimitry Andric // If there is no CIE yet for this ID, emit it. 2338*1db9f3b2SDimitry Andric if (IteratorInserted.second) { 2339*1db9f3b2SDimitry Andric LastCIEOffset = TheDwarfEmitter->getFrameSectionSize(); 2340*1db9f3b2SDimitry Andric IteratorInserted.first->getValue() = LastCIEOffset; 2341*1db9f3b2SDimitry Andric TheDwarfEmitter->emitCIE(CIEData); 2342*1db9f3b2SDimitry Andric } 2343*1db9f3b2SDimitry Andric 2344*1db9f3b2SDimitry Andric // Emit the FDE with updated address and CIE pointer. 2345*1db9f3b2SDimitry Andric // (4 + AddrSize) is the size of the CIEId + initial_location 2346*1db9f3b2SDimitry Andric // fields that will get reconstructed by emitFDE(). 2347*1db9f3b2SDimitry Andric unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize); 2348*1db9f3b2SDimitry Andric TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), SrcAddrSize, 2349*1db9f3b2SDimitry Andric Loc + Range->Value, 2350*1db9f3b2SDimitry Andric FrameData.substr(InputOffset, FDERemainingBytes)); 2351*1db9f3b2SDimitry Andric InputOffset += FDERemainingBytes; 2352*1db9f3b2SDimitry Andric } 2353*1db9f3b2SDimitry Andric } 2354*1db9f3b2SDimitry Andric 2355*1db9f3b2SDimitry Andric uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE, 2356*1db9f3b2SDimitry Andric CompileUnit &U, 2357*1db9f3b2SDimitry Andric const DWARFFile &File, 2358*1db9f3b2SDimitry Andric int ChildRecurseDepth) { 2359*1db9f3b2SDimitry Andric const char *Name = nullptr; 2360*1db9f3b2SDimitry Andric DWARFUnit *OrigUnit = &U.getOrigUnit(); 2361*1db9f3b2SDimitry Andric CompileUnit *CU = &U; 2362*1db9f3b2SDimitry Andric std::optional<DWARFFormValue> Ref; 2363*1db9f3b2SDimitry Andric 2364*1db9f3b2SDimitry Andric while (true) { 2365*1db9f3b2SDimitry Andric if (const char *CurrentName = DIE.getName(DINameKind::ShortName)) 2366*1db9f3b2SDimitry Andric Name = CurrentName; 2367*1db9f3b2SDimitry Andric 2368*1db9f3b2SDimitry Andric if (!(Ref = DIE.find(dwarf::DW_AT_specification)) && 2369*1db9f3b2SDimitry Andric !(Ref = DIE.find(dwarf::DW_AT_abstract_origin))) 2370*1db9f3b2SDimitry Andric break; 2371*1db9f3b2SDimitry Andric 2372*1db9f3b2SDimitry Andric if (!Ref->isFormClass(DWARFFormValue::FC_Reference)) 2373*1db9f3b2SDimitry Andric break; 2374*1db9f3b2SDimitry Andric 2375*1db9f3b2SDimitry Andric CompileUnit *RefCU; 2376*1db9f3b2SDimitry Andric if (auto RefDIE = 2377*1db9f3b2SDimitry Andric Linker.resolveDIEReference(File, CompileUnits, *Ref, DIE, RefCU)) { 2378*1db9f3b2SDimitry Andric CU = RefCU; 2379*1db9f3b2SDimitry Andric OrigUnit = &RefCU->getOrigUnit(); 2380*1db9f3b2SDimitry Andric DIE = RefDIE; 2381*1db9f3b2SDimitry Andric } 2382*1db9f3b2SDimitry Andric } 2383*1db9f3b2SDimitry Andric 2384*1db9f3b2SDimitry Andric unsigned Idx = OrigUnit->getDIEIndex(DIE); 2385*1db9f3b2SDimitry Andric if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace) 2386*1db9f3b2SDimitry Andric Name = "(anonymous namespace)"; 2387*1db9f3b2SDimitry Andric 2388*1db9f3b2SDimitry Andric if (CU->getInfo(Idx).ParentIdx == 0 || 2389*1db9f3b2SDimitry Andric // FIXME: dsymutil-classic compatibility. Ignore modules. 2390*1db9f3b2SDimitry Andric CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() == 2391*1db9f3b2SDimitry Andric dwarf::DW_TAG_module) 2392*1db9f3b2SDimitry Andric return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::")); 2393*1db9f3b2SDimitry Andric 2394*1db9f3b2SDimitry Andric DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx); 2395*1db9f3b2SDimitry Andric return djbHash( 2396*1db9f3b2SDimitry Andric (Name ? Name : ""), 2397*1db9f3b2SDimitry Andric djbHash((Name ? "::" : ""), 2398*1db9f3b2SDimitry Andric hashFullyQualifiedName(Die, *CU, File, ++ChildRecurseDepth))); 2399*1db9f3b2SDimitry Andric } 2400*1db9f3b2SDimitry Andric 2401*1db9f3b2SDimitry Andric static uint64_t getDwoId(const DWARFDie &CUDie) { 2402*1db9f3b2SDimitry Andric auto DwoId = dwarf::toUnsigned( 2403*1db9f3b2SDimitry Andric CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id})); 2404*1db9f3b2SDimitry Andric if (DwoId) 2405*1db9f3b2SDimitry Andric return *DwoId; 2406*1db9f3b2SDimitry Andric return 0; 2407*1db9f3b2SDimitry Andric } 2408*1db9f3b2SDimitry Andric 2409*1db9f3b2SDimitry Andric static std::string 2410*1db9f3b2SDimitry Andric remapPath(StringRef Path, 2411*1db9f3b2SDimitry Andric const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap) { 2412*1db9f3b2SDimitry Andric if (ObjectPrefixMap.empty()) 2413*1db9f3b2SDimitry Andric return Path.str(); 2414*1db9f3b2SDimitry Andric 2415*1db9f3b2SDimitry Andric SmallString<256> p = Path; 2416*1db9f3b2SDimitry Andric for (const auto &Entry : ObjectPrefixMap) 2417*1db9f3b2SDimitry Andric if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second)) 2418*1db9f3b2SDimitry Andric break; 2419*1db9f3b2SDimitry Andric return p.str().str(); 2420*1db9f3b2SDimitry Andric } 2421*1db9f3b2SDimitry Andric 2422*1db9f3b2SDimitry Andric static std::string 2423*1db9f3b2SDimitry Andric getPCMFile(const DWARFDie &CUDie, 2424*1db9f3b2SDimitry Andric const DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap) { 2425*1db9f3b2SDimitry Andric std::string PCMFile = dwarf::toString( 2426*1db9f3b2SDimitry Andric CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); 2427*1db9f3b2SDimitry Andric 2428*1db9f3b2SDimitry Andric if (PCMFile.empty()) 2429*1db9f3b2SDimitry Andric return PCMFile; 2430*1db9f3b2SDimitry Andric 2431*1db9f3b2SDimitry Andric if (ObjectPrefixMap) 2432*1db9f3b2SDimitry Andric PCMFile = remapPath(PCMFile, *ObjectPrefixMap); 2433*1db9f3b2SDimitry Andric 2434*1db9f3b2SDimitry Andric return PCMFile; 2435*1db9f3b2SDimitry Andric } 2436*1db9f3b2SDimitry Andric 2437*1db9f3b2SDimitry Andric std::pair<bool, bool> DWARFLinker::isClangModuleRef(const DWARFDie &CUDie, 2438*1db9f3b2SDimitry Andric std::string &PCMFile, 2439*1db9f3b2SDimitry Andric LinkContext &Context, 2440*1db9f3b2SDimitry Andric unsigned Indent, 2441*1db9f3b2SDimitry Andric bool Quiet) { 2442*1db9f3b2SDimitry Andric if (PCMFile.empty()) 2443*1db9f3b2SDimitry Andric return std::make_pair(false, false); 2444*1db9f3b2SDimitry Andric 2445*1db9f3b2SDimitry Andric // Clang module DWARF skeleton CUs abuse this for the path to the module. 2446*1db9f3b2SDimitry Andric uint64_t DwoId = getDwoId(CUDie); 2447*1db9f3b2SDimitry Andric 2448*1db9f3b2SDimitry Andric std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); 2449*1db9f3b2SDimitry Andric if (Name.empty()) { 2450*1db9f3b2SDimitry Andric if (!Quiet) 2451*1db9f3b2SDimitry Andric reportWarning("Anonymous module skeleton CU for " + PCMFile, 2452*1db9f3b2SDimitry Andric Context.File); 2453*1db9f3b2SDimitry Andric return std::make_pair(true, true); 2454*1db9f3b2SDimitry Andric } 2455*1db9f3b2SDimitry Andric 2456*1db9f3b2SDimitry Andric if (!Quiet && Options.Verbose) { 2457*1db9f3b2SDimitry Andric outs().indent(Indent); 2458*1db9f3b2SDimitry Andric outs() << "Found clang module reference " << PCMFile; 2459*1db9f3b2SDimitry Andric } 2460*1db9f3b2SDimitry Andric 2461*1db9f3b2SDimitry Andric auto Cached = ClangModules.find(PCMFile); 2462*1db9f3b2SDimitry Andric if (Cached != ClangModules.end()) { 2463*1db9f3b2SDimitry Andric // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is 2464*1db9f3b2SDimitry Andric // fixed in clang, only warn about DWO_id mismatches in verbose mode. 2465*1db9f3b2SDimitry Andric // ASTFileSignatures will change randomly when a module is rebuilt. 2466*1db9f3b2SDimitry Andric if (!Quiet && Options.Verbose && (Cached->second != DwoId)) 2467*1db9f3b2SDimitry Andric reportWarning(Twine("hash mismatch: this object file was built against a " 2468*1db9f3b2SDimitry Andric "different version of the module ") + 2469*1db9f3b2SDimitry Andric PCMFile, 2470*1db9f3b2SDimitry Andric Context.File); 2471*1db9f3b2SDimitry Andric if (!Quiet && Options.Verbose) 2472*1db9f3b2SDimitry Andric outs() << " [cached].\n"; 2473*1db9f3b2SDimitry Andric return std::make_pair(true, true); 2474*1db9f3b2SDimitry Andric } 2475*1db9f3b2SDimitry Andric 2476*1db9f3b2SDimitry Andric return std::make_pair(true, false); 2477*1db9f3b2SDimitry Andric } 2478*1db9f3b2SDimitry Andric 2479*1db9f3b2SDimitry Andric bool DWARFLinker::registerModuleReference(const DWARFDie &CUDie, 2480*1db9f3b2SDimitry Andric LinkContext &Context, 2481*1db9f3b2SDimitry Andric ObjFileLoaderTy Loader, 2482*1db9f3b2SDimitry Andric CompileUnitHandlerTy OnCUDieLoaded, 2483*1db9f3b2SDimitry Andric unsigned Indent) { 2484*1db9f3b2SDimitry Andric std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap); 2485*1db9f3b2SDimitry Andric std::pair<bool, bool> IsClangModuleRef = 2486*1db9f3b2SDimitry Andric isClangModuleRef(CUDie, PCMFile, Context, Indent, false); 2487*1db9f3b2SDimitry Andric 2488*1db9f3b2SDimitry Andric if (!IsClangModuleRef.first) 2489*1db9f3b2SDimitry Andric return false; 2490*1db9f3b2SDimitry Andric 2491*1db9f3b2SDimitry Andric if (IsClangModuleRef.second) 2492*1db9f3b2SDimitry Andric return true; 2493*1db9f3b2SDimitry Andric 2494*1db9f3b2SDimitry Andric if (Options.Verbose) 2495*1db9f3b2SDimitry Andric outs() << " ...\n"; 2496*1db9f3b2SDimitry Andric 2497*1db9f3b2SDimitry Andric // Cyclic dependencies are disallowed by Clang, but we still 2498*1db9f3b2SDimitry Andric // shouldn't run into an infinite loop, so mark it as processed now. 2499*1db9f3b2SDimitry Andric ClangModules.insert({PCMFile, getDwoId(CUDie)}); 2500*1db9f3b2SDimitry Andric 2501*1db9f3b2SDimitry Andric if (Error E = loadClangModule(Loader, CUDie, PCMFile, Context, OnCUDieLoaded, 2502*1db9f3b2SDimitry Andric Indent + 2)) { 2503*1db9f3b2SDimitry Andric consumeError(std::move(E)); 2504*1db9f3b2SDimitry Andric return false; 2505*1db9f3b2SDimitry Andric } 2506*1db9f3b2SDimitry Andric return true; 2507*1db9f3b2SDimitry Andric } 2508*1db9f3b2SDimitry Andric 2509*1db9f3b2SDimitry Andric Error DWARFLinker::loadClangModule( 2510*1db9f3b2SDimitry Andric ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile, 2511*1db9f3b2SDimitry Andric LinkContext &Context, CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) { 2512*1db9f3b2SDimitry Andric 2513*1db9f3b2SDimitry Andric uint64_t DwoId = getDwoId(CUDie); 2514*1db9f3b2SDimitry Andric std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); 2515*1db9f3b2SDimitry Andric 2516*1db9f3b2SDimitry Andric /// Using a SmallString<0> because loadClangModule() is recursive. 2517*1db9f3b2SDimitry Andric SmallString<0> Path(Options.PrependPath); 2518*1db9f3b2SDimitry Andric if (sys::path::is_relative(PCMFile)) 2519*1db9f3b2SDimitry Andric resolveRelativeObjectPath(Path, CUDie); 2520*1db9f3b2SDimitry Andric sys::path::append(Path, PCMFile); 2521*1db9f3b2SDimitry Andric // Don't use the cached binary holder because we have no thread-safety 2522*1db9f3b2SDimitry Andric // guarantee and the lifetime is limited. 2523*1db9f3b2SDimitry Andric 2524*1db9f3b2SDimitry Andric if (Loader == nullptr) { 2525*1db9f3b2SDimitry Andric reportError("Could not load clang module: loader is not specified.\n", 2526*1db9f3b2SDimitry Andric Context.File); 2527*1db9f3b2SDimitry Andric return Error::success(); 2528*1db9f3b2SDimitry Andric } 2529*1db9f3b2SDimitry Andric 2530*1db9f3b2SDimitry Andric auto ErrOrObj = Loader(Context.File.FileName, Path); 2531*1db9f3b2SDimitry Andric if (!ErrOrObj) 2532*1db9f3b2SDimitry Andric return Error::success(); 2533*1db9f3b2SDimitry Andric 2534*1db9f3b2SDimitry Andric std::unique_ptr<CompileUnit> Unit; 2535*1db9f3b2SDimitry Andric for (const auto &CU : ErrOrObj->Dwarf->compile_units()) { 2536*1db9f3b2SDimitry Andric OnCUDieLoaded(*CU); 2537*1db9f3b2SDimitry Andric // Recursively get all modules imported by this one. 2538*1db9f3b2SDimitry Andric auto ChildCUDie = CU->getUnitDIE(); 2539*1db9f3b2SDimitry Andric if (!ChildCUDie) 2540*1db9f3b2SDimitry Andric continue; 2541*1db9f3b2SDimitry Andric if (!registerModuleReference(ChildCUDie, Context, Loader, OnCUDieLoaded, 2542*1db9f3b2SDimitry Andric Indent)) { 2543*1db9f3b2SDimitry Andric if (Unit) { 2544*1db9f3b2SDimitry Andric std::string Err = 2545*1db9f3b2SDimitry Andric (PCMFile + 2546*1db9f3b2SDimitry Andric ": Clang modules are expected to have exactly 1 compile unit.\n"); 2547*1db9f3b2SDimitry Andric reportError(Err, Context.File); 2548*1db9f3b2SDimitry Andric return make_error<StringError>(Err, inconvertibleErrorCode()); 2549*1db9f3b2SDimitry Andric } 2550*1db9f3b2SDimitry Andric // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is 2551*1db9f3b2SDimitry Andric // fixed in clang, only warn about DWO_id mismatches in verbose mode. 2552*1db9f3b2SDimitry Andric // ASTFileSignatures will change randomly when a module is rebuilt. 2553*1db9f3b2SDimitry Andric uint64_t PCMDwoId = getDwoId(ChildCUDie); 2554*1db9f3b2SDimitry Andric if (PCMDwoId != DwoId) { 2555*1db9f3b2SDimitry Andric if (Options.Verbose) 2556*1db9f3b2SDimitry Andric reportWarning( 2557*1db9f3b2SDimitry Andric Twine("hash mismatch: this object file was built against a " 2558*1db9f3b2SDimitry Andric "different version of the module ") + 2559*1db9f3b2SDimitry Andric PCMFile, 2560*1db9f3b2SDimitry Andric Context.File); 2561*1db9f3b2SDimitry Andric // Update the cache entry with the DwoId of the module loaded from disk. 2562*1db9f3b2SDimitry Andric ClangModules[PCMFile] = PCMDwoId; 2563*1db9f3b2SDimitry Andric } 2564*1db9f3b2SDimitry Andric 2565*1db9f3b2SDimitry Andric // Add this module. 2566*1db9f3b2SDimitry Andric Unit = std::make_unique<CompileUnit>(*CU, UniqueUnitID++, !Options.NoODR, 2567*1db9f3b2SDimitry Andric ModuleName); 2568*1db9f3b2SDimitry Andric } 2569*1db9f3b2SDimitry Andric } 2570*1db9f3b2SDimitry Andric 2571*1db9f3b2SDimitry Andric if (Unit) 2572*1db9f3b2SDimitry Andric Context.ModuleUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)}); 2573*1db9f3b2SDimitry Andric 2574*1db9f3b2SDimitry Andric return Error::success(); 2575*1db9f3b2SDimitry Andric } 2576*1db9f3b2SDimitry Andric 2577*1db9f3b2SDimitry Andric uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( 2578*1db9f3b2SDimitry Andric DWARFContext &DwarfContext, const DWARFFile &File, bool IsLittleEndian) { 2579*1db9f3b2SDimitry Andric uint64_t OutputDebugInfoSize = 2580*1db9f3b2SDimitry Andric (Emitter == nullptr) ? 0 : Emitter->getDebugInfoSectionSize(); 2581*1db9f3b2SDimitry Andric const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize; 2582*1db9f3b2SDimitry Andric 2583*1db9f3b2SDimitry Andric for (auto &CurrentUnit : CompileUnits) { 2584*1db9f3b2SDimitry Andric const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion(); 2585*1db9f3b2SDimitry Andric const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11; 2586*1db9f3b2SDimitry Andric auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); 2587*1db9f3b2SDimitry Andric CurrentUnit->setStartOffset(OutputDebugInfoSize); 2588*1db9f3b2SDimitry Andric if (!InputDIE) { 2589*1db9f3b2SDimitry Andric OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion); 2590*1db9f3b2SDimitry Andric continue; 2591*1db9f3b2SDimitry Andric } 2592*1db9f3b2SDimitry Andric if (CurrentUnit->getInfo(0).Keep) { 2593*1db9f3b2SDimitry Andric // Clone the InputDIE into your Unit DIE in our compile unit since it 2594*1db9f3b2SDimitry Andric // already has a DIE inside of it. 2595*1db9f3b2SDimitry Andric CurrentUnit->createOutputDIE(); 2596*1db9f3b2SDimitry Andric rememberUnitForMacroOffset(*CurrentUnit); 2597*1db9f3b2SDimitry Andric cloneDIE(InputDIE, File, *CurrentUnit, 0 /* PC offset */, UnitHeaderSize, 2598*1db9f3b2SDimitry Andric 0, IsLittleEndian, CurrentUnit->getOutputUnitDIE()); 2599*1db9f3b2SDimitry Andric } 2600*1db9f3b2SDimitry Andric 2601*1db9f3b2SDimitry Andric OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion); 2602*1db9f3b2SDimitry Andric 2603*1db9f3b2SDimitry Andric if (Emitter != nullptr) { 2604*1db9f3b2SDimitry Andric 2605*1db9f3b2SDimitry Andric generateLineTableForUnit(*CurrentUnit); 2606*1db9f3b2SDimitry Andric 2607*1db9f3b2SDimitry Andric Linker.emitAcceleratorEntriesForUnit(*CurrentUnit); 2608*1db9f3b2SDimitry Andric 2609*1db9f3b2SDimitry Andric if (LLVM_UNLIKELY(Linker.Options.Update)) 2610*1db9f3b2SDimitry Andric continue; 2611*1db9f3b2SDimitry Andric 2612*1db9f3b2SDimitry Andric Linker.generateUnitRanges(*CurrentUnit, File, AddrPool); 2613*1db9f3b2SDimitry Andric 2614*1db9f3b2SDimitry Andric auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes, 2615*1db9f3b2SDimitry Andric SmallVectorImpl<uint8_t> &OutBytes, 2616*1db9f3b2SDimitry Andric int64_t RelocAdjustment) { 2617*1db9f3b2SDimitry Andric DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit(); 2618*1db9f3b2SDimitry Andric DataExtractor Data(SrcBytes, IsLittleEndian, 2619*1db9f3b2SDimitry Andric OrigUnit.getAddressByteSize()); 2620*1db9f3b2SDimitry Andric cloneExpression(Data, 2621*1db9f3b2SDimitry Andric DWARFExpression(Data, OrigUnit.getAddressByteSize(), 2622*1db9f3b2SDimitry Andric OrigUnit.getFormParams().Format), 2623*1db9f3b2SDimitry Andric File, *CurrentUnit, OutBytes, RelocAdjustment, 2624*1db9f3b2SDimitry Andric IsLittleEndian); 2625*1db9f3b2SDimitry Andric }; 2626*1db9f3b2SDimitry Andric generateUnitLocations(*CurrentUnit, File, ProcessExpr); 2627*1db9f3b2SDimitry Andric emitDebugAddrSection(*CurrentUnit, DwarfVersion); 2628*1db9f3b2SDimitry Andric } 2629*1db9f3b2SDimitry Andric AddrPool.clear(); 2630*1db9f3b2SDimitry Andric } 2631*1db9f3b2SDimitry Andric 2632*1db9f3b2SDimitry Andric if (Emitter != nullptr) { 2633*1db9f3b2SDimitry Andric assert(Emitter); 2634*1db9f3b2SDimitry Andric // Emit macro tables. 2635*1db9f3b2SDimitry Andric Emitter->emitMacroTables(File.Dwarf.get(), UnitMacroMap, DebugStrPool); 2636*1db9f3b2SDimitry Andric 2637*1db9f3b2SDimitry Andric // Emit all the compile unit's debug information. 2638*1db9f3b2SDimitry Andric for (auto &CurrentUnit : CompileUnits) { 2639*1db9f3b2SDimitry Andric CurrentUnit->fixupForwardReferences(); 2640*1db9f3b2SDimitry Andric 2641*1db9f3b2SDimitry Andric if (!CurrentUnit->getOutputUnitDIE()) 2642*1db9f3b2SDimitry Andric continue; 2643*1db9f3b2SDimitry Andric 2644*1db9f3b2SDimitry Andric unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion(); 2645*1db9f3b2SDimitry Andric 2646*1db9f3b2SDimitry Andric assert(Emitter->getDebugInfoSectionSize() == 2647*1db9f3b2SDimitry Andric CurrentUnit->getStartOffset()); 2648*1db9f3b2SDimitry Andric Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion); 2649*1db9f3b2SDimitry Andric Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE()); 2650*1db9f3b2SDimitry Andric assert(Emitter->getDebugInfoSectionSize() == 2651*1db9f3b2SDimitry Andric CurrentUnit->computeNextUnitOffset(DwarfVersion)); 2652*1db9f3b2SDimitry Andric } 2653*1db9f3b2SDimitry Andric } 2654*1db9f3b2SDimitry Andric 2655*1db9f3b2SDimitry Andric return OutputDebugInfoSize - StartOutputDebugInfoSize; 2656*1db9f3b2SDimitry Andric } 2657*1db9f3b2SDimitry Andric 2658*1db9f3b2SDimitry Andric void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) { 2659*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getLocSection().Data, 2660*1db9f3b2SDimitry Andric "debug_loc"); 2661*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents( 2662*1db9f3b2SDimitry Andric Dwarf.getDWARFObj().getRangesSection().Data, "debug_ranges"); 2663*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents( 2664*1db9f3b2SDimitry Andric Dwarf.getDWARFObj().getFrameSection().Data, "debug_frame"); 2665*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(), 2666*1db9f3b2SDimitry Andric "debug_aranges"); 2667*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents( 2668*1db9f3b2SDimitry Andric Dwarf.getDWARFObj().getAddrSection().Data, "debug_addr"); 2669*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents( 2670*1db9f3b2SDimitry Andric Dwarf.getDWARFObj().getRnglistsSection().Data, "debug_rnglists"); 2671*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents( 2672*1db9f3b2SDimitry Andric Dwarf.getDWARFObj().getLoclistsSection().Data, "debug_loclists"); 2673*1db9f3b2SDimitry Andric } 2674*1db9f3b2SDimitry Andric 2675*1db9f3b2SDimitry Andric void DWARFLinker::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader, 2676*1db9f3b2SDimitry Andric CompileUnitHandlerTy OnCUDieLoaded) { 2677*1db9f3b2SDimitry Andric ObjectContexts.emplace_back(LinkContext(File)); 2678*1db9f3b2SDimitry Andric 2679*1db9f3b2SDimitry Andric if (ObjectContexts.back().File.Dwarf) { 2680*1db9f3b2SDimitry Andric for (const std::unique_ptr<DWARFUnit> &CU : 2681*1db9f3b2SDimitry Andric ObjectContexts.back().File.Dwarf->compile_units()) { 2682*1db9f3b2SDimitry Andric DWARFDie CUDie = CU->getUnitDIE(); 2683*1db9f3b2SDimitry Andric 2684*1db9f3b2SDimitry Andric if (!CUDie) 2685*1db9f3b2SDimitry Andric continue; 2686*1db9f3b2SDimitry Andric 2687*1db9f3b2SDimitry Andric OnCUDieLoaded(*CU); 2688*1db9f3b2SDimitry Andric 2689*1db9f3b2SDimitry Andric if (!LLVM_UNLIKELY(Options.Update)) 2690*1db9f3b2SDimitry Andric registerModuleReference(CUDie, ObjectContexts.back(), Loader, 2691*1db9f3b2SDimitry Andric OnCUDieLoaded); 2692*1db9f3b2SDimitry Andric } 2693*1db9f3b2SDimitry Andric } 2694*1db9f3b2SDimitry Andric } 2695*1db9f3b2SDimitry Andric 2696*1db9f3b2SDimitry Andric Error DWARFLinker::link() { 2697*1db9f3b2SDimitry Andric assert((Options.TargetDWARFVersion != 0) && 2698*1db9f3b2SDimitry Andric "TargetDWARFVersion should be set"); 2699*1db9f3b2SDimitry Andric 2700*1db9f3b2SDimitry Andric // First populate the data structure we need for each iteration of the 2701*1db9f3b2SDimitry Andric // parallel loop. 2702*1db9f3b2SDimitry Andric unsigned NumObjects = ObjectContexts.size(); 2703*1db9f3b2SDimitry Andric 2704*1db9f3b2SDimitry Andric // This Dwarf string pool which is used for emission. It must be used 2705*1db9f3b2SDimitry Andric // serially as the order of calling getStringOffset matters for 2706*1db9f3b2SDimitry Andric // reproducibility. 2707*1db9f3b2SDimitry Andric OffsetsStringPool DebugStrPool(StringsTranslator, true); 2708*1db9f3b2SDimitry Andric OffsetsStringPool DebugLineStrPool(StringsTranslator, false); 2709*1db9f3b2SDimitry Andric DebugDieValuePool StringOffsetPool; 2710*1db9f3b2SDimitry Andric 2711*1db9f3b2SDimitry Andric // ODR Contexts for the optimize. 2712*1db9f3b2SDimitry Andric DeclContextTree ODRContexts; 2713*1db9f3b2SDimitry Andric 2714*1db9f3b2SDimitry Andric for (LinkContext &OptContext : ObjectContexts) { 2715*1db9f3b2SDimitry Andric if (Options.Verbose) 2716*1db9f3b2SDimitry Andric outs() << "DEBUG MAP OBJECT: " << OptContext.File.FileName << "\n"; 2717*1db9f3b2SDimitry Andric 2718*1db9f3b2SDimitry Andric if (!OptContext.File.Dwarf) 2719*1db9f3b2SDimitry Andric continue; 2720*1db9f3b2SDimitry Andric 2721*1db9f3b2SDimitry Andric if (Options.VerifyInputDWARF) 2722*1db9f3b2SDimitry Andric verifyInput(OptContext.File); 2723*1db9f3b2SDimitry Andric 2724*1db9f3b2SDimitry Andric // Look for relocations that correspond to address map entries. 2725*1db9f3b2SDimitry Andric 2726*1db9f3b2SDimitry Andric // there was findvalidrelocations previously ... probably we need to gather 2727*1db9f3b2SDimitry Andric // info here 2728*1db9f3b2SDimitry Andric if (LLVM_LIKELY(!Options.Update) && 2729*1db9f3b2SDimitry Andric !OptContext.File.Addresses->hasValidRelocs()) { 2730*1db9f3b2SDimitry Andric if (Options.Verbose) 2731*1db9f3b2SDimitry Andric outs() << "No valid relocations found. Skipping.\n"; 2732*1db9f3b2SDimitry Andric 2733*1db9f3b2SDimitry Andric // Set "Skip" flag as a signal to other loops that we should not 2734*1db9f3b2SDimitry Andric // process this iteration. 2735*1db9f3b2SDimitry Andric OptContext.Skip = true; 2736*1db9f3b2SDimitry Andric continue; 2737*1db9f3b2SDimitry Andric } 2738*1db9f3b2SDimitry Andric 2739*1db9f3b2SDimitry Andric // Setup access to the debug info. 2740*1db9f3b2SDimitry Andric if (!OptContext.File.Dwarf) 2741*1db9f3b2SDimitry Andric continue; 2742*1db9f3b2SDimitry Andric 2743*1db9f3b2SDimitry Andric // Check whether type units are presented. 2744*1db9f3b2SDimitry Andric if (!OptContext.File.Dwarf->types_section_units().empty()) { 2745*1db9f3b2SDimitry Andric reportWarning("type units are not currently supported: file will " 2746*1db9f3b2SDimitry Andric "be skipped", 2747*1db9f3b2SDimitry Andric OptContext.File); 2748*1db9f3b2SDimitry Andric OptContext.Skip = true; 2749*1db9f3b2SDimitry Andric continue; 2750*1db9f3b2SDimitry Andric } 2751*1db9f3b2SDimitry Andric 2752*1db9f3b2SDimitry Andric // Clone all the clang modules with requires extracting the DIE units. We 2753*1db9f3b2SDimitry Andric // don't need the full debug info until the Analyze phase. 2754*1db9f3b2SDimitry Andric OptContext.CompileUnits.reserve( 2755*1db9f3b2SDimitry Andric OptContext.File.Dwarf->getNumCompileUnits()); 2756*1db9f3b2SDimitry Andric for (const auto &CU : OptContext.File.Dwarf->compile_units()) { 2757*1db9f3b2SDimitry Andric auto CUDie = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/true); 2758*1db9f3b2SDimitry Andric if (Options.Verbose) { 2759*1db9f3b2SDimitry Andric outs() << "Input compilation unit:"; 2760*1db9f3b2SDimitry Andric DIDumpOptions DumpOpts; 2761*1db9f3b2SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 2762*1db9f3b2SDimitry Andric DumpOpts.Verbose = Options.Verbose; 2763*1db9f3b2SDimitry Andric CUDie.dump(outs(), 0, DumpOpts); 2764*1db9f3b2SDimitry Andric } 2765*1db9f3b2SDimitry Andric } 2766*1db9f3b2SDimitry Andric 2767*1db9f3b2SDimitry Andric for (auto &CU : OptContext.ModuleUnits) { 2768*1db9f3b2SDimitry Andric if (Error Err = cloneModuleUnit(OptContext, CU, ODRContexts, DebugStrPool, 2769*1db9f3b2SDimitry Andric DebugLineStrPool, StringOffsetPool)) 2770*1db9f3b2SDimitry Andric reportWarning(toString(std::move(Err)), CU.File); 2771*1db9f3b2SDimitry Andric } 2772*1db9f3b2SDimitry Andric } 2773*1db9f3b2SDimitry Andric 2774*1db9f3b2SDimitry Andric // At this point we know how much data we have emitted. We use this value to 2775*1db9f3b2SDimitry Andric // compare canonical DIE offsets in analyzeContextInfo to see if a definition 2776*1db9f3b2SDimitry Andric // is already emitted, without being affected by canonical die offsets set 2777*1db9f3b2SDimitry Andric // later. This prevents undeterminism when analyze and clone execute 2778*1db9f3b2SDimitry Andric // concurrently, as clone set the canonical DIE offset and analyze reads it. 2779*1db9f3b2SDimitry Andric const uint64_t ModulesEndOffset = 2780*1db9f3b2SDimitry Andric (TheDwarfEmitter == nullptr) ? 0 2781*1db9f3b2SDimitry Andric : TheDwarfEmitter->getDebugInfoSectionSize(); 2782*1db9f3b2SDimitry Andric 2783*1db9f3b2SDimitry Andric // These variables manage the list of processed object files. 2784*1db9f3b2SDimitry Andric // The mutex and condition variable are to ensure that this is thread safe. 2785*1db9f3b2SDimitry Andric std::mutex ProcessedFilesMutex; 2786*1db9f3b2SDimitry Andric std::condition_variable ProcessedFilesConditionVariable; 2787*1db9f3b2SDimitry Andric BitVector ProcessedFiles(NumObjects, false); 2788*1db9f3b2SDimitry Andric 2789*1db9f3b2SDimitry Andric // Analyzing the context info is particularly expensive so it is executed in 2790*1db9f3b2SDimitry Andric // parallel with emitting the previous compile unit. 2791*1db9f3b2SDimitry Andric auto AnalyzeLambda = [&](size_t I) { 2792*1db9f3b2SDimitry Andric auto &Context = ObjectContexts[I]; 2793*1db9f3b2SDimitry Andric 2794*1db9f3b2SDimitry Andric if (Context.Skip || !Context.File.Dwarf) 2795*1db9f3b2SDimitry Andric return; 2796*1db9f3b2SDimitry Andric 2797*1db9f3b2SDimitry Andric for (const auto &CU : Context.File.Dwarf->compile_units()) { 2798*1db9f3b2SDimitry Andric // Previously we only extracted the unit DIEs. We need the full debug info 2799*1db9f3b2SDimitry Andric // now. 2800*1db9f3b2SDimitry Andric auto CUDie = CU->getUnitDIE(/*ExtractUnitDIEOnly=*/false); 2801*1db9f3b2SDimitry Andric std::string PCMFile = getPCMFile(CUDie, Options.ObjectPrefixMap); 2802*1db9f3b2SDimitry Andric 2803*1db9f3b2SDimitry Andric if (!CUDie || LLVM_UNLIKELY(Options.Update) || 2804*1db9f3b2SDimitry Andric !isClangModuleRef(CUDie, PCMFile, Context, 0, true).first) { 2805*1db9f3b2SDimitry Andric Context.CompileUnits.push_back(std::make_unique<CompileUnit>( 2806*1db9f3b2SDimitry Andric *CU, UniqueUnitID++, !Options.NoODR && !Options.Update, "")); 2807*1db9f3b2SDimitry Andric } 2808*1db9f3b2SDimitry Andric } 2809*1db9f3b2SDimitry Andric 2810*1db9f3b2SDimitry Andric // Now build the DIE parent links that we will use during the next phase. 2811*1db9f3b2SDimitry Andric for (auto &CurrentUnit : Context.CompileUnits) { 2812*1db9f3b2SDimitry Andric auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE(); 2813*1db9f3b2SDimitry Andric if (!CUDie) 2814*1db9f3b2SDimitry Andric continue; 2815*1db9f3b2SDimitry Andric analyzeContextInfo(CurrentUnit->getOrigUnit().getUnitDIE(), 0, 2816*1db9f3b2SDimitry Andric *CurrentUnit, &ODRContexts.getRoot(), ODRContexts, 2817*1db9f3b2SDimitry Andric ModulesEndOffset, Options.ParseableSwiftInterfaces, 2818*1db9f3b2SDimitry Andric [&](const Twine &Warning, const DWARFDie &DIE) { 2819*1db9f3b2SDimitry Andric reportWarning(Warning, Context.File, &DIE); 2820*1db9f3b2SDimitry Andric }); 2821*1db9f3b2SDimitry Andric } 2822*1db9f3b2SDimitry Andric }; 2823*1db9f3b2SDimitry Andric 2824*1db9f3b2SDimitry Andric // For each object file map how many bytes were emitted. 2825*1db9f3b2SDimitry Andric StringMap<DebugInfoSize> SizeByObject; 2826*1db9f3b2SDimitry Andric 2827*1db9f3b2SDimitry Andric // And then the remaining work in serial again. 2828*1db9f3b2SDimitry Andric // Note, although this loop runs in serial, it can run in parallel with 2829*1db9f3b2SDimitry Andric // the analyzeContextInfo loop so long as we process files with indices >= 2830*1db9f3b2SDimitry Andric // than those processed by analyzeContextInfo. 2831*1db9f3b2SDimitry Andric auto CloneLambda = [&](size_t I) { 2832*1db9f3b2SDimitry Andric auto &OptContext = ObjectContexts[I]; 2833*1db9f3b2SDimitry Andric if (OptContext.Skip || !OptContext.File.Dwarf) 2834*1db9f3b2SDimitry Andric return; 2835*1db9f3b2SDimitry Andric 2836*1db9f3b2SDimitry Andric // Then mark all the DIEs that need to be present in the generated output 2837*1db9f3b2SDimitry Andric // and collect some information about them. 2838*1db9f3b2SDimitry Andric // Note that this loop can not be merged with the previous one because 2839*1db9f3b2SDimitry Andric // cross-cu references require the ParentIdx to be setup for every CU in 2840*1db9f3b2SDimitry Andric // the object file before calling this. 2841*1db9f3b2SDimitry Andric if (LLVM_UNLIKELY(Options.Update)) { 2842*1db9f3b2SDimitry Andric for (auto &CurrentUnit : OptContext.CompileUnits) 2843*1db9f3b2SDimitry Andric CurrentUnit->markEverythingAsKept(); 2844*1db9f3b2SDimitry Andric copyInvariantDebugSection(*OptContext.File.Dwarf); 2845*1db9f3b2SDimitry Andric } else { 2846*1db9f3b2SDimitry Andric for (auto &CurrentUnit : OptContext.CompileUnits) { 2847*1db9f3b2SDimitry Andric lookForDIEsToKeep(*OptContext.File.Addresses, OptContext.CompileUnits, 2848*1db9f3b2SDimitry Andric CurrentUnit->getOrigUnit().getUnitDIE(), 2849*1db9f3b2SDimitry Andric OptContext.File, *CurrentUnit, 0); 2850*1db9f3b2SDimitry Andric #ifndef NDEBUG 2851*1db9f3b2SDimitry Andric verifyKeepChain(*CurrentUnit); 2852*1db9f3b2SDimitry Andric #endif 2853*1db9f3b2SDimitry Andric } 2854*1db9f3b2SDimitry Andric } 2855*1db9f3b2SDimitry Andric 2856*1db9f3b2SDimitry Andric // The calls to applyValidRelocs inside cloneDIE will walk the reloc 2857*1db9f3b2SDimitry Andric // array again (in the same way findValidRelocsInDebugInfo() did). We 2858*1db9f3b2SDimitry Andric // need to reset the NextValidReloc index to the beginning. 2859*1db9f3b2SDimitry Andric if (OptContext.File.Addresses->hasValidRelocs() || 2860*1db9f3b2SDimitry Andric LLVM_UNLIKELY(Options.Update)) { 2861*1db9f3b2SDimitry Andric SizeByObject[OptContext.File.FileName].Input = 2862*1db9f3b2SDimitry Andric getDebugInfoSize(*OptContext.File.Dwarf); 2863*1db9f3b2SDimitry Andric SizeByObject[OptContext.File.FileName].Output = 2864*1db9f3b2SDimitry Andric DIECloner(*this, TheDwarfEmitter.get(), OptContext.File, DIEAlloc, 2865*1db9f3b2SDimitry Andric OptContext.CompileUnits, Options.Update, DebugStrPool, 2866*1db9f3b2SDimitry Andric DebugLineStrPool, StringOffsetPool) 2867*1db9f3b2SDimitry Andric .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File, 2868*1db9f3b2SDimitry Andric OptContext.File.Dwarf->isLittleEndian()); 2869*1db9f3b2SDimitry Andric } 2870*1db9f3b2SDimitry Andric if ((TheDwarfEmitter != nullptr) && !OptContext.CompileUnits.empty() && 2871*1db9f3b2SDimitry Andric LLVM_LIKELY(!Options.Update)) 2872*1db9f3b2SDimitry Andric patchFrameInfoForObject(OptContext); 2873*1db9f3b2SDimitry Andric 2874*1db9f3b2SDimitry Andric // Clean-up before starting working on the next object. 2875*1db9f3b2SDimitry Andric cleanupAuxiliarryData(OptContext); 2876*1db9f3b2SDimitry Andric }; 2877*1db9f3b2SDimitry Andric 2878*1db9f3b2SDimitry Andric auto EmitLambda = [&]() { 2879*1db9f3b2SDimitry Andric // Emit everything that's global. 2880*1db9f3b2SDimitry Andric if (TheDwarfEmitter != nullptr) { 2881*1db9f3b2SDimitry Andric TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion); 2882*1db9f3b2SDimitry Andric TheDwarfEmitter->emitStrings(DebugStrPool); 2883*1db9f3b2SDimitry Andric TheDwarfEmitter->emitStringOffsets(StringOffsetPool.DieValues, 2884*1db9f3b2SDimitry Andric Options.TargetDWARFVersion); 2885*1db9f3b2SDimitry Andric TheDwarfEmitter->emitLineStrings(DebugLineStrPool); 2886*1db9f3b2SDimitry Andric for (AccelTableKind TableKind : Options.AccelTables) { 2887*1db9f3b2SDimitry Andric switch (TableKind) { 2888*1db9f3b2SDimitry Andric case AccelTableKind::Apple: 2889*1db9f3b2SDimitry Andric TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces); 2890*1db9f3b2SDimitry Andric TheDwarfEmitter->emitAppleNames(AppleNames); 2891*1db9f3b2SDimitry Andric TheDwarfEmitter->emitAppleTypes(AppleTypes); 2892*1db9f3b2SDimitry Andric TheDwarfEmitter->emitAppleObjc(AppleObjc); 2893*1db9f3b2SDimitry Andric break; 2894*1db9f3b2SDimitry Andric case AccelTableKind::Pub: 2895*1db9f3b2SDimitry Andric // Already emitted by emitAcceleratorEntriesForUnit. 2896*1db9f3b2SDimitry Andric // Already emitted by emitAcceleratorEntriesForUnit. 2897*1db9f3b2SDimitry Andric break; 2898*1db9f3b2SDimitry Andric case AccelTableKind::DebugNames: 2899*1db9f3b2SDimitry Andric TheDwarfEmitter->emitDebugNames(DebugNames); 2900*1db9f3b2SDimitry Andric break; 2901*1db9f3b2SDimitry Andric } 2902*1db9f3b2SDimitry Andric } 2903*1db9f3b2SDimitry Andric } 2904*1db9f3b2SDimitry Andric }; 2905*1db9f3b2SDimitry Andric 2906*1db9f3b2SDimitry Andric auto AnalyzeAll = [&]() { 2907*1db9f3b2SDimitry Andric for (unsigned I = 0, E = NumObjects; I != E; ++I) { 2908*1db9f3b2SDimitry Andric AnalyzeLambda(I); 2909*1db9f3b2SDimitry Andric 2910*1db9f3b2SDimitry Andric std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex); 2911*1db9f3b2SDimitry Andric ProcessedFiles.set(I); 2912*1db9f3b2SDimitry Andric ProcessedFilesConditionVariable.notify_one(); 2913*1db9f3b2SDimitry Andric } 2914*1db9f3b2SDimitry Andric }; 2915*1db9f3b2SDimitry Andric 2916*1db9f3b2SDimitry Andric auto CloneAll = [&]() { 2917*1db9f3b2SDimitry Andric for (unsigned I = 0, E = NumObjects; I != E; ++I) { 2918*1db9f3b2SDimitry Andric { 2919*1db9f3b2SDimitry Andric std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex); 2920*1db9f3b2SDimitry Andric if (!ProcessedFiles[I]) { 2921*1db9f3b2SDimitry Andric ProcessedFilesConditionVariable.wait( 2922*1db9f3b2SDimitry Andric LockGuard, [&]() { return ProcessedFiles[I]; }); 2923*1db9f3b2SDimitry Andric } 2924*1db9f3b2SDimitry Andric } 2925*1db9f3b2SDimitry Andric 2926*1db9f3b2SDimitry Andric CloneLambda(I); 2927*1db9f3b2SDimitry Andric } 2928*1db9f3b2SDimitry Andric EmitLambda(); 2929*1db9f3b2SDimitry Andric }; 2930*1db9f3b2SDimitry Andric 2931*1db9f3b2SDimitry Andric // To limit memory usage in the single threaded case, analyze and clone are 2932*1db9f3b2SDimitry Andric // run sequentially so the OptContext is freed after processing each object 2933*1db9f3b2SDimitry Andric // in endDebugObject. 2934*1db9f3b2SDimitry Andric if (Options.Threads == 1) { 2935*1db9f3b2SDimitry Andric for (unsigned I = 0, E = NumObjects; I != E; ++I) { 2936*1db9f3b2SDimitry Andric AnalyzeLambda(I); 2937*1db9f3b2SDimitry Andric CloneLambda(I); 2938*1db9f3b2SDimitry Andric } 2939*1db9f3b2SDimitry Andric EmitLambda(); 2940*1db9f3b2SDimitry Andric } else { 2941*1db9f3b2SDimitry Andric ThreadPool Pool(hardware_concurrency(2)); 2942*1db9f3b2SDimitry Andric Pool.async(AnalyzeAll); 2943*1db9f3b2SDimitry Andric Pool.async(CloneAll); 2944*1db9f3b2SDimitry Andric Pool.wait(); 2945*1db9f3b2SDimitry Andric } 2946*1db9f3b2SDimitry Andric 2947*1db9f3b2SDimitry Andric if (Options.Statistics) { 2948*1db9f3b2SDimitry Andric // Create a vector sorted in descending order by output size. 2949*1db9f3b2SDimitry Andric std::vector<std::pair<StringRef, DebugInfoSize>> Sorted; 2950*1db9f3b2SDimitry Andric for (auto &E : SizeByObject) 2951*1db9f3b2SDimitry Andric Sorted.emplace_back(E.first(), E.second); 2952*1db9f3b2SDimitry Andric llvm::sort(Sorted, [](auto &LHS, auto &RHS) { 2953*1db9f3b2SDimitry Andric return LHS.second.Output > RHS.second.Output; 2954*1db9f3b2SDimitry Andric }); 2955*1db9f3b2SDimitry Andric 2956*1db9f3b2SDimitry Andric auto ComputePercentange = [](int64_t Input, int64_t Output) -> float { 2957*1db9f3b2SDimitry Andric const float Difference = Output - Input; 2958*1db9f3b2SDimitry Andric const float Sum = Input + Output; 2959*1db9f3b2SDimitry Andric if (Sum == 0) 2960*1db9f3b2SDimitry Andric return 0; 2961*1db9f3b2SDimitry Andric return (Difference / (Sum / 2)); 2962*1db9f3b2SDimitry Andric }; 2963*1db9f3b2SDimitry Andric 2964*1db9f3b2SDimitry Andric int64_t InputTotal = 0; 2965*1db9f3b2SDimitry Andric int64_t OutputTotal = 0; 2966*1db9f3b2SDimitry Andric const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n"; 2967*1db9f3b2SDimitry Andric 2968*1db9f3b2SDimitry Andric // Print header. 2969*1db9f3b2SDimitry Andric outs() << ".debug_info section size (in bytes)\n"; 2970*1db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 2971*1db9f3b2SDimitry Andric "---------------\n"; 2972*1db9f3b2SDimitry Andric outs() << "Filename Object " 2973*1db9f3b2SDimitry Andric " dSYM Change\n"; 2974*1db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 2975*1db9f3b2SDimitry Andric "---------------\n"; 2976*1db9f3b2SDimitry Andric 2977*1db9f3b2SDimitry Andric // Print body. 2978*1db9f3b2SDimitry Andric for (auto &E : Sorted) { 2979*1db9f3b2SDimitry Andric InputTotal += E.second.Input; 2980*1db9f3b2SDimitry Andric OutputTotal += E.second.Output; 2981*1db9f3b2SDimitry Andric llvm::outs() << formatv( 2982*1db9f3b2SDimitry Andric FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input, 2983*1db9f3b2SDimitry Andric E.second.Output, ComputePercentange(E.second.Input, E.second.Output)); 2984*1db9f3b2SDimitry Andric } 2985*1db9f3b2SDimitry Andric // Print total and footer. 2986*1db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 2987*1db9f3b2SDimitry Andric "---------------\n"; 2988*1db9f3b2SDimitry Andric llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal, 2989*1db9f3b2SDimitry Andric ComputePercentange(InputTotal, OutputTotal)); 2990*1db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 2991*1db9f3b2SDimitry Andric "---------------\n\n"; 2992*1db9f3b2SDimitry Andric } 2993*1db9f3b2SDimitry Andric 2994*1db9f3b2SDimitry Andric return Error::success(); 2995*1db9f3b2SDimitry Andric } 2996*1db9f3b2SDimitry Andric 2997*1db9f3b2SDimitry Andric Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit, 2998*1db9f3b2SDimitry Andric DeclContextTree &ODRContexts, 2999*1db9f3b2SDimitry Andric OffsetsStringPool &DebugStrPool, 3000*1db9f3b2SDimitry Andric OffsetsStringPool &DebugLineStrPool, 3001*1db9f3b2SDimitry Andric DebugDieValuePool &StringOffsetPool, 3002*1db9f3b2SDimitry Andric unsigned Indent) { 3003*1db9f3b2SDimitry Andric assert(Unit.Unit.get() != nullptr); 3004*1db9f3b2SDimitry Andric 3005*1db9f3b2SDimitry Andric if (!Unit.Unit->getOrigUnit().getUnitDIE().hasChildren()) 3006*1db9f3b2SDimitry Andric return Error::success(); 3007*1db9f3b2SDimitry Andric 3008*1db9f3b2SDimitry Andric if (Options.Verbose) { 3009*1db9f3b2SDimitry Andric outs().indent(Indent); 3010*1db9f3b2SDimitry Andric outs() << "cloning .debug_info from " << Unit.File.FileName << "\n"; 3011*1db9f3b2SDimitry Andric } 3012*1db9f3b2SDimitry Andric 3013*1db9f3b2SDimitry Andric // Analyze context for the module. 3014*1db9f3b2SDimitry Andric analyzeContextInfo(Unit.Unit->getOrigUnit().getUnitDIE(), 0, *(Unit.Unit), 3015*1db9f3b2SDimitry Andric &ODRContexts.getRoot(), ODRContexts, 0, 3016*1db9f3b2SDimitry Andric Options.ParseableSwiftInterfaces, 3017*1db9f3b2SDimitry Andric [&](const Twine &Warning, const DWARFDie &DIE) { 3018*1db9f3b2SDimitry Andric reportWarning(Warning, Context.File, &DIE); 3019*1db9f3b2SDimitry Andric }); 3020*1db9f3b2SDimitry Andric // Keep everything. 3021*1db9f3b2SDimitry Andric Unit.Unit->markEverythingAsKept(); 3022*1db9f3b2SDimitry Andric 3023*1db9f3b2SDimitry Andric // Clone unit. 3024*1db9f3b2SDimitry Andric UnitListTy CompileUnits; 3025*1db9f3b2SDimitry Andric CompileUnits.emplace_back(std::move(Unit.Unit)); 3026*1db9f3b2SDimitry Andric assert(TheDwarfEmitter); 3027*1db9f3b2SDimitry Andric DIECloner(*this, TheDwarfEmitter.get(), Unit.File, DIEAlloc, CompileUnits, 3028*1db9f3b2SDimitry Andric Options.Update, DebugStrPool, DebugLineStrPool, StringOffsetPool) 3029*1db9f3b2SDimitry Andric .cloneAllCompileUnits(*Unit.File.Dwarf, Unit.File, 3030*1db9f3b2SDimitry Andric Unit.File.Dwarf->isLittleEndian()); 3031*1db9f3b2SDimitry Andric return Error::success(); 3032*1db9f3b2SDimitry Andric } 3033*1db9f3b2SDimitry Andric 3034*1db9f3b2SDimitry Andric void DWARFLinker::verifyInput(const DWARFFile &File) { 3035*1db9f3b2SDimitry Andric assert(File.Dwarf); 3036*1db9f3b2SDimitry Andric 3037*1db9f3b2SDimitry Andric std::string Buffer; 3038*1db9f3b2SDimitry Andric raw_string_ostream OS(Buffer); 3039*1db9f3b2SDimitry Andric DIDumpOptions DumpOpts; 3040*1db9f3b2SDimitry Andric if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) { 3041*1db9f3b2SDimitry Andric if (Options.InputVerificationHandler) 3042*1db9f3b2SDimitry Andric Options.InputVerificationHandler(File, OS.str()); 3043*1db9f3b2SDimitry Andric } 3044*1db9f3b2SDimitry Andric } 3045*1db9f3b2SDimitry Andric 3046*1db9f3b2SDimitry Andric Error DWARFLinker::createEmitter(const Triple &TheTriple, 3047*1db9f3b2SDimitry Andric OutputFileType FileType, 3048*1db9f3b2SDimitry Andric raw_pwrite_stream &OutFile) { 3049*1db9f3b2SDimitry Andric 3050*1db9f3b2SDimitry Andric TheDwarfEmitter = std::make_unique<DwarfStreamer>( 3051*1db9f3b2SDimitry Andric FileType, OutFile, StringsTranslator, WarningHandler); 3052*1db9f3b2SDimitry Andric 3053*1db9f3b2SDimitry Andric return TheDwarfEmitter->init(TheTriple, "__DWARF"); 3054*1db9f3b2SDimitry Andric } 3055*1db9f3b2SDimitry Andric 3056*1db9f3b2SDimitry Andric DwarfEmitter *DWARFLinker::getEmitter() { return TheDwarfEmitter.get(); } 3057*1db9f3b2SDimitry Andric 3058*1db9f3b2SDimitry Andric } // namespace llvm 3059