11db9f3b2SDimitry Andric //=== DWARFLinkerCompileUnit.cpp ------------------------------------------===// 21db9f3b2SDimitry Andric // 31db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 51db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61db9f3b2SDimitry Andric // 71db9f3b2SDimitry Andric //===----------------------------------------------------------------------===// 81db9f3b2SDimitry Andric 91db9f3b2SDimitry Andric #include "DWARFLinkerCompileUnit.h" 101db9f3b2SDimitry Andric #include "AcceleratorRecordsSaver.h" 111db9f3b2SDimitry Andric #include "DIEAttributeCloner.h" 121db9f3b2SDimitry Andric #include "DIEGenerator.h" 131db9f3b2SDimitry Andric #include "DependencyTracker.h" 141db9f3b2SDimitry Andric #include "SyntheticTypeNameBuilder.h" 15297eecfbSDimitry Andric #include "llvm/DWARFLinker/Utils.h" 161db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 171db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" 181db9f3b2SDimitry Andric #include "llvm/Support/DJB.h" 191db9f3b2SDimitry Andric #include "llvm/Support/FileSystem.h" 201db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h" 211db9f3b2SDimitry Andric #include "llvm/Support/Path.h" 221db9f3b2SDimitry Andric #include <utility> 231db9f3b2SDimitry Andric 241db9f3b2SDimitry Andric using namespace llvm; 251db9f3b2SDimitry Andric using namespace dwarf_linker; 261db9f3b2SDimitry Andric using namespace dwarf_linker::parallel; 271db9f3b2SDimitry Andric 281db9f3b2SDimitry Andric CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, unsigned ID, 291db9f3b2SDimitry Andric StringRef ClangModuleName, DWARFFile &File, 301db9f3b2SDimitry Andric OffsetToUnitTy UnitFromOffset, 311db9f3b2SDimitry Andric dwarf::FormParams Format, llvm::endianness Endianess) 321db9f3b2SDimitry Andric : DwarfUnit(GlobalData, ID, ClangModuleName), File(File), 331db9f3b2SDimitry Andric getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded), 341db9f3b2SDimitry Andric AcceleratorRecords(&GlobalData.getAllocator()) { 351db9f3b2SDimitry Andric UnitName = File.FileName; 361db9f3b2SDimitry Andric setOutputFormat(Format, Endianess); 371db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); 381db9f3b2SDimitry Andric } 391db9f3b2SDimitry Andric 401db9f3b2SDimitry Andric CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit, 411db9f3b2SDimitry Andric unsigned ID, StringRef ClangModuleName, 421db9f3b2SDimitry Andric DWARFFile &File, OffsetToUnitTy UnitFromOffset, 431db9f3b2SDimitry Andric dwarf::FormParams Format, llvm::endianness Endianess) 441db9f3b2SDimitry Andric : DwarfUnit(GlobalData, ID, ClangModuleName), File(File), 451db9f3b2SDimitry Andric OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset), 461db9f3b2SDimitry Andric Stage(Stage::CreatedNotLoaded), 471db9f3b2SDimitry Andric AcceleratorRecords(&GlobalData.getAllocator()) { 481db9f3b2SDimitry Andric setOutputFormat(Format, Endianess); 491db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); 501db9f3b2SDimitry Andric 511db9f3b2SDimitry Andric DWARFDie CUDie = OrigUnit.getUnitDIE(); 521db9f3b2SDimitry Andric if (!CUDie) 531db9f3b2SDimitry Andric return; 541db9f3b2SDimitry Andric 551db9f3b2SDimitry Andric if (std::optional<DWARFFormValue> Val = CUDie.find(dwarf::DW_AT_language)) { 561db9f3b2SDimitry Andric uint16_t LangVal = dwarf::toUnsigned(Val, 0); 571db9f3b2SDimitry Andric if (isODRLanguage(LangVal)) 581db9f3b2SDimitry Andric Language = LangVal; 591db9f3b2SDimitry Andric } 601db9f3b2SDimitry Andric 611db9f3b2SDimitry Andric if (!GlobalData.getOptions().NoODR && Language.has_value()) 621db9f3b2SDimitry Andric NoODR = false; 631db9f3b2SDimitry Andric 641db9f3b2SDimitry Andric if (const char *CUName = CUDie.getName(DINameKind::ShortName)) 651db9f3b2SDimitry Andric UnitName = CUName; 661db9f3b2SDimitry Andric else 671db9f3b2SDimitry Andric UnitName = File.FileName; 681db9f3b2SDimitry Andric SysRoot = dwarf::toStringRef(CUDie.find(dwarf::DW_AT_LLVM_sysroot)).str(); 691db9f3b2SDimitry Andric } 701db9f3b2SDimitry Andric 711db9f3b2SDimitry Andric void CompileUnit::loadLineTable() { 721db9f3b2SDimitry Andric LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit()); 731db9f3b2SDimitry Andric } 741db9f3b2SDimitry Andric 751db9f3b2SDimitry Andric void CompileUnit::maybeResetToLoadedStage() { 761db9f3b2SDimitry Andric // Nothing to reset if stage is less than "Loaded". 771db9f3b2SDimitry Andric if (getStage() < Stage::Loaded) 781db9f3b2SDimitry Andric return; 791db9f3b2SDimitry Andric 801db9f3b2SDimitry Andric // Note: We need to do erasing for "Loaded" stage because 811db9f3b2SDimitry Andric // if live analysys failed then we will have "Loaded" stage 821db9f3b2SDimitry Andric // with marking from "LivenessAnalysisDone" stage partially 831db9f3b2SDimitry Andric // done. That marking should be cleared. 841db9f3b2SDimitry Andric 851db9f3b2SDimitry Andric for (DIEInfo &Info : DieInfoArray) 861db9f3b2SDimitry Andric Info.unsetFlagsWhichSetDuringLiveAnalysis(); 871db9f3b2SDimitry Andric 881db9f3b2SDimitry Andric LowPc = std::nullopt; 891db9f3b2SDimitry Andric HighPc = 0; 901db9f3b2SDimitry Andric Labels.clear(); 911db9f3b2SDimitry Andric Ranges.clear(); 921db9f3b2SDimitry Andric Dependencies.reset(nullptr); 931db9f3b2SDimitry Andric 941db9f3b2SDimitry Andric if (getStage() < Stage::Cloned) { 951db9f3b2SDimitry Andric setStage(Stage::Loaded); 961db9f3b2SDimitry Andric return; 971db9f3b2SDimitry Andric } 981db9f3b2SDimitry Andric 991db9f3b2SDimitry Andric AcceleratorRecords.erase(); 1001db9f3b2SDimitry Andric AbbreviationsSet.clear(); 1011db9f3b2SDimitry Andric Abbreviations.clear(); 1021db9f3b2SDimitry Andric OutUnitDIE = nullptr; 1031db9f3b2SDimitry Andric DebugAddrIndexMap.clear(); 1041db9f3b2SDimitry Andric 1051db9f3b2SDimitry Andric for (uint64_t &Offset : OutDieOffsetArray) 1061db9f3b2SDimitry Andric Offset = 0; 1071db9f3b2SDimitry Andric for (TypeEntry *&Name : TypeEntries) 1081db9f3b2SDimitry Andric Name = nullptr; 1091db9f3b2SDimitry Andric eraseSections(); 1101db9f3b2SDimitry Andric 1111db9f3b2SDimitry Andric setStage(Stage::CreatedNotLoaded); 1121db9f3b2SDimitry Andric } 1131db9f3b2SDimitry Andric 1141db9f3b2SDimitry Andric bool CompileUnit::loadInputDIEs() { 1151db9f3b2SDimitry Andric DWARFDie InputUnitDIE = getUnitDIE(false); 1161db9f3b2SDimitry Andric if (!InputUnitDIE) 1171db9f3b2SDimitry Andric return false; 1181db9f3b2SDimitry Andric 1191db9f3b2SDimitry Andric // load input dies, resize Info structures array. 1201db9f3b2SDimitry Andric DieInfoArray.resize(getOrigUnit().getNumDIEs()); 1211db9f3b2SDimitry Andric OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0); 1221db9f3b2SDimitry Andric if (!NoODR) 1231db9f3b2SDimitry Andric TypeEntries.resize(getOrigUnit().getNumDIEs()); 1241db9f3b2SDimitry Andric return true; 1251db9f3b2SDimitry Andric } 1261db9f3b2SDimitry Andric 1271db9f3b2SDimitry Andric void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry, 1281db9f3b2SDimitry Andric bool IsODRUnavailableFunctionScope) { 1291db9f3b2SDimitry Andric CompileUnit::DIEInfo &DieInfo = getDIEInfo(DieEntry); 1301db9f3b2SDimitry Andric 1311db9f3b2SDimitry Andric for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry); 1321db9f3b2SDimitry Andric CurChild && CurChild->getAbbreviationDeclarationPtr(); 1331db9f3b2SDimitry Andric CurChild = getSiblingEntry(CurChild)) { 1341db9f3b2SDimitry Andric CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild); 1351db9f3b2SDimitry Andric bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope; 1361db9f3b2SDimitry Andric 1371db9f3b2SDimitry Andric if (DieInfo.getIsInMouduleScope()) 1381db9f3b2SDimitry Andric ChildInfo.setIsInMouduleScope(); 1391db9f3b2SDimitry Andric 1401db9f3b2SDimitry Andric if (DieInfo.getIsInFunctionScope()) 1411db9f3b2SDimitry Andric ChildInfo.setIsInFunctionScope(); 1421db9f3b2SDimitry Andric 1431db9f3b2SDimitry Andric if (DieInfo.getIsInAnonNamespaceScope()) 1441db9f3b2SDimitry Andric ChildInfo.setIsInAnonNamespaceScope(); 1451db9f3b2SDimitry Andric 1461db9f3b2SDimitry Andric switch (CurChild->getTag()) { 1471db9f3b2SDimitry Andric case dwarf::DW_TAG_module: 1481db9f3b2SDimitry Andric ChildInfo.setIsInMouduleScope(); 1491db9f3b2SDimitry Andric if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit && 1501db9f3b2SDimitry Andric dwarf::toString(find(CurChild, dwarf::DW_AT_name), "") != 1511db9f3b2SDimitry Andric getClangModuleName()) 1521db9f3b2SDimitry Andric analyzeImportedModule(CurChild); 1531db9f3b2SDimitry Andric break; 1541db9f3b2SDimitry Andric case dwarf::DW_TAG_subprogram: 1551db9f3b2SDimitry Andric ChildInfo.setIsInFunctionScope(); 1561db9f3b2SDimitry Andric if (!ChildIsODRUnavailableFunctionScope && 1571db9f3b2SDimitry Andric !ChildInfo.getIsInMouduleScope()) { 1581db9f3b2SDimitry Andric if (find(CurChild, 1591db9f3b2SDimitry Andric {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification})) 1601db9f3b2SDimitry Andric ChildIsODRUnavailableFunctionScope = true; 1611db9f3b2SDimitry Andric } 1621db9f3b2SDimitry Andric break; 1631db9f3b2SDimitry Andric case dwarf::DW_TAG_namespace: { 1641db9f3b2SDimitry Andric UnitEntryPairTy NamespaceEntry = {this, CurChild}; 1651db9f3b2SDimitry Andric 1661db9f3b2SDimitry Andric if (find(CurChild, dwarf::DW_AT_extension)) 1671db9f3b2SDimitry Andric NamespaceEntry = NamespaceEntry.getNamespaceOrigin(); 1681db9f3b2SDimitry Andric 1691db9f3b2SDimitry Andric if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name)) 1701db9f3b2SDimitry Andric ChildInfo.setIsInAnonNamespaceScope(); 1711db9f3b2SDimitry Andric } break; 1721db9f3b2SDimitry Andric default: 1731db9f3b2SDimitry Andric break; 1741db9f3b2SDimitry Andric } 1751db9f3b2SDimitry Andric 1761db9f3b2SDimitry Andric if (!isClangModule() && !getGlobalData().getOptions().UpdateIndexTablesOnly) 1771db9f3b2SDimitry Andric ChildInfo.setTrackLiveness(); 1781db9f3b2SDimitry Andric 1791db9f3b2SDimitry Andric if ((!ChildInfo.getIsInAnonNamespaceScope() && 1801db9f3b2SDimitry Andric !ChildIsODRUnavailableFunctionScope && !NoODR)) 1811db9f3b2SDimitry Andric ChildInfo.setODRAvailable(); 1821db9f3b2SDimitry Andric 1831db9f3b2SDimitry Andric if (CurChild->hasChildren()) 1841db9f3b2SDimitry Andric analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope); 1851db9f3b2SDimitry Andric } 1861db9f3b2SDimitry Andric } 1871db9f3b2SDimitry Andric 1881db9f3b2SDimitry Andric StringEntry *CompileUnit::getFileName(unsigned FileIdx, 1891db9f3b2SDimitry Andric StringPool &GlobalStrings) { 1901db9f3b2SDimitry Andric if (LineTablePtr) { 1911db9f3b2SDimitry Andric if (LineTablePtr->hasFileAtIndex(FileIdx)) { 1921db9f3b2SDimitry Andric // Cache the resolved paths based on the index in the line table, 1931db9f3b2SDimitry Andric // because calling realpath is expensive. 1941db9f3b2SDimitry Andric ResolvedPathsMap::const_iterator It = ResolvedFullPaths.find(FileIdx); 1951db9f3b2SDimitry Andric if (It == ResolvedFullPaths.end()) { 1961db9f3b2SDimitry Andric std::string OrigFileName; 1971db9f3b2SDimitry Andric bool FoundFileName = LineTablePtr->getFileNameByIndex( 1981db9f3b2SDimitry Andric FileIdx, getOrigUnit().getCompilationDir(), 1991db9f3b2SDimitry Andric DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 2001db9f3b2SDimitry Andric OrigFileName); 2011db9f3b2SDimitry Andric (void)FoundFileName; 2021db9f3b2SDimitry Andric assert(FoundFileName && "Must get file name from line table"); 2031db9f3b2SDimitry Andric 2041db9f3b2SDimitry Andric // Second level of caching, this time based on the file's parent 2051db9f3b2SDimitry Andric // path. 2061db9f3b2SDimitry Andric StringRef FileName = sys::path::filename(OrigFileName); 2071db9f3b2SDimitry Andric StringRef ParentPath = sys::path::parent_path(OrigFileName); 2081db9f3b2SDimitry Andric 2091db9f3b2SDimitry Andric // If the ParentPath has not yet been resolved, resolve and cache it for 2101db9f3b2SDimitry Andric // future look-ups. 2111db9f3b2SDimitry Andric StringMap<StringEntry *>::iterator ParentIt = 2121db9f3b2SDimitry Andric ResolvedParentPaths.find(ParentPath); 2131db9f3b2SDimitry Andric if (ParentIt == ResolvedParentPaths.end()) { 2141db9f3b2SDimitry Andric SmallString<256> RealPath; 2151db9f3b2SDimitry Andric sys::fs::real_path(ParentPath, RealPath); 2161db9f3b2SDimitry Andric ParentIt = 2171db9f3b2SDimitry Andric ResolvedParentPaths 2181db9f3b2SDimitry Andric .insert({ParentPath, GlobalStrings.insert(RealPath).first}) 2191db9f3b2SDimitry Andric .first; 2201db9f3b2SDimitry Andric } 2211db9f3b2SDimitry Andric 2221db9f3b2SDimitry Andric // Join the file name again with the resolved path. 2231db9f3b2SDimitry Andric SmallString<256> ResolvedPath(ParentIt->second->first()); 2241db9f3b2SDimitry Andric sys::path::append(ResolvedPath, FileName); 2251db9f3b2SDimitry Andric 2261db9f3b2SDimitry Andric It = ResolvedFullPaths 2271db9f3b2SDimitry Andric .insert(std::make_pair( 2281db9f3b2SDimitry Andric FileIdx, GlobalStrings.insert(ResolvedPath).first)) 2291db9f3b2SDimitry Andric .first; 2301db9f3b2SDimitry Andric } 2311db9f3b2SDimitry Andric 2321db9f3b2SDimitry Andric return It->second; 2331db9f3b2SDimitry Andric } 2341db9f3b2SDimitry Andric } 2351db9f3b2SDimitry Andric 2361db9f3b2SDimitry Andric return nullptr; 2371db9f3b2SDimitry Andric } 2381db9f3b2SDimitry Andric 2391db9f3b2SDimitry Andric void CompileUnit::cleanupDataAfterClonning() { 2401db9f3b2SDimitry Andric AbbreviationsSet.clear(); 2411db9f3b2SDimitry Andric ResolvedFullPaths.shrink_and_clear(); 2421db9f3b2SDimitry Andric ResolvedParentPaths.clear(); 2431db9f3b2SDimitry Andric FileNames.shrink_and_clear(); 2441db9f3b2SDimitry Andric DieInfoArray = SmallVector<DIEInfo>(); 2451db9f3b2SDimitry Andric OutDieOffsetArray = SmallVector<uint64_t>(); 2461db9f3b2SDimitry Andric TypeEntries = SmallVector<TypeEntry *>(); 2471db9f3b2SDimitry Andric Dependencies.reset(nullptr); 2481db9f3b2SDimitry Andric getOrigUnit().clear(); 2491db9f3b2SDimitry Andric } 2501db9f3b2SDimitry Andric 2511db9f3b2SDimitry Andric /// Collect references to parseable Swift interfaces in imported 2521db9f3b2SDimitry Andric /// DW_TAG_module blocks. 2531db9f3b2SDimitry Andric void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) { 2541db9f3b2SDimitry Andric if (!Language || Language != dwarf::DW_LANG_Swift) 2551db9f3b2SDimitry Andric return; 2561db9f3b2SDimitry Andric 2571db9f3b2SDimitry Andric if (!GlobalData.getOptions().ParseableSwiftInterfaces) 2581db9f3b2SDimitry Andric return; 2591db9f3b2SDimitry Andric 2601db9f3b2SDimitry Andric StringRef Path = 2611db9f3b2SDimitry Andric dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_include_path)); 2621db9f3b2SDimitry Andric if (!Path.ends_with(".swiftinterface")) 2631db9f3b2SDimitry Andric return; 2641db9f3b2SDimitry Andric // Don't track interfaces that are part of the SDK. 2651db9f3b2SDimitry Andric StringRef SysRoot = 2661db9f3b2SDimitry Andric dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_sysroot)); 2671db9f3b2SDimitry Andric if (SysRoot.empty()) 2681db9f3b2SDimitry Andric SysRoot = getSysRoot(); 2691db9f3b2SDimitry Andric if (!SysRoot.empty() && Path.starts_with(SysRoot)) 2701db9f3b2SDimitry Andric return; 2711db9f3b2SDimitry Andric // Don't track interfaces that are part of the toolchain. 2721db9f3b2SDimitry Andric // For example: Swift, _Concurrency, ... 273*0fca6ea1SDimitry Andric StringRef DeveloperDir = guessDeveloperDir(SysRoot); 274*0fca6ea1SDimitry Andric if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir)) 275*0fca6ea1SDimitry Andric return; 276*0fca6ea1SDimitry Andric if (isInToolchainDir(Path)) 2771db9f3b2SDimitry Andric return; 2781db9f3b2SDimitry Andric if (std::optional<DWARFFormValue> Val = find(DieEntry, dwarf::DW_AT_name)) { 2791db9f3b2SDimitry Andric Expected<const char *> Name = Val->getAsCString(); 2801db9f3b2SDimitry Andric if (!Name) { 2811db9f3b2SDimitry Andric warn(Name.takeError()); 2821db9f3b2SDimitry Andric return; 2831db9f3b2SDimitry Andric } 2841db9f3b2SDimitry Andric 2851db9f3b2SDimitry Andric auto &Entry = (*GlobalData.getOptions().ParseableSwiftInterfaces)[*Name]; 2861db9f3b2SDimitry Andric // The prepend path is applied later when copying. 2871db9f3b2SDimitry Andric SmallString<128> ResolvedPath; 2881db9f3b2SDimitry Andric if (sys::path::is_relative(Path)) 2891db9f3b2SDimitry Andric sys::path::append( 2901db9f3b2SDimitry Andric ResolvedPath, 2911db9f3b2SDimitry Andric dwarf::toString(getUnitDIE().find(dwarf::DW_AT_comp_dir), "")); 2921db9f3b2SDimitry Andric sys::path::append(ResolvedPath, Path); 2931db9f3b2SDimitry Andric if (!Entry.empty() && Entry != ResolvedPath) { 2941db9f3b2SDimitry Andric DWARFDie Die = getDIE(DieEntry); 2951db9f3b2SDimitry Andric warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name + 2961db9f3b2SDimitry Andric ": " + Entry + " and " + Path + ".", 2971db9f3b2SDimitry Andric &Die); 2981db9f3b2SDimitry Andric } 2997a6dacacSDimitry Andric Entry = std::string(ResolvedPath); 3001db9f3b2SDimitry Andric } 3011db9f3b2SDimitry Andric } 3021db9f3b2SDimitry Andric 3031db9f3b2SDimitry Andric Error CompileUnit::assignTypeNames(TypePool &TypePoolRef) { 3041db9f3b2SDimitry Andric if (!getUnitDIE().isValid()) 3051db9f3b2SDimitry Andric return Error::success(); 3061db9f3b2SDimitry Andric 3071db9f3b2SDimitry Andric SyntheticTypeNameBuilder NameBuilder(TypePoolRef); 3081db9f3b2SDimitry Andric return assignTypeNamesRec(getDebugInfoEntry(0), NameBuilder); 3091db9f3b2SDimitry Andric } 3101db9f3b2SDimitry Andric 3111db9f3b2SDimitry Andric Error CompileUnit::assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry, 3121db9f3b2SDimitry Andric SyntheticTypeNameBuilder &NameBuilder) { 3131db9f3b2SDimitry Andric OrderedChildrenIndexAssigner ChildrenIndexAssigner(*this, DieEntry); 3141db9f3b2SDimitry Andric for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry); 3151db9f3b2SDimitry Andric CurChild && CurChild->getAbbreviationDeclarationPtr(); 3161db9f3b2SDimitry Andric CurChild = getSiblingEntry(CurChild)) { 3171db9f3b2SDimitry Andric CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild); 3181db9f3b2SDimitry Andric if (!ChildInfo.needToPlaceInTypeTable()) 3191db9f3b2SDimitry Andric continue; 3201db9f3b2SDimitry Andric 3211db9f3b2SDimitry Andric assert(ChildInfo.getODRAvailable()); 3221db9f3b2SDimitry Andric if (Error Err = NameBuilder.assignName( 3231db9f3b2SDimitry Andric {this, CurChild}, 3241db9f3b2SDimitry Andric ChildrenIndexAssigner.getChildIndex(*this, CurChild))) 3251db9f3b2SDimitry Andric return Err; 3261db9f3b2SDimitry Andric 3271db9f3b2SDimitry Andric if (Error Err = assignTypeNamesRec(CurChild, NameBuilder)) 3281db9f3b2SDimitry Andric return Err; 3291db9f3b2SDimitry Andric } 3301db9f3b2SDimitry Andric 3311db9f3b2SDimitry Andric return Error::success(); 3321db9f3b2SDimitry Andric } 3331db9f3b2SDimitry Andric 3341db9f3b2SDimitry Andric void CompileUnit::updateDieRefPatchesWithClonedOffsets() { 3351db9f3b2SDimitry Andric if (std::optional<SectionDescriptor *> DebugInfoSection = 3361db9f3b2SDimitry Andric tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) { 3371db9f3b2SDimitry Andric 3381db9f3b2SDimitry Andric (*DebugInfoSection) 3391db9f3b2SDimitry Andric ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) { 3401db9f3b2SDimitry Andric /// Replace stored DIE indexes with DIE output offsets. 3411db9f3b2SDimitry Andric Patch.RefDieIdxOrClonedOffset = 3421db9f3b2SDimitry Andric Patch.RefCU.getPointer()->getDieOutOffset( 3431db9f3b2SDimitry Andric Patch.RefDieIdxOrClonedOffset); 3441db9f3b2SDimitry Andric }); 3451db9f3b2SDimitry Andric 3461db9f3b2SDimitry Andric (*DebugInfoSection) 3471db9f3b2SDimitry Andric ->ListDebugULEB128DieRefPatch.forEach( 3481db9f3b2SDimitry Andric [&](DebugULEB128DieRefPatch &Patch) { 3491db9f3b2SDimitry Andric /// Replace stored DIE indexes with DIE output offsets. 3501db9f3b2SDimitry Andric Patch.RefDieIdxOrClonedOffset = 3511db9f3b2SDimitry Andric Patch.RefCU.getPointer()->getDieOutOffset( 3521db9f3b2SDimitry Andric Patch.RefDieIdxOrClonedOffset); 3531db9f3b2SDimitry Andric }); 3541db9f3b2SDimitry Andric } 3551db9f3b2SDimitry Andric 3561db9f3b2SDimitry Andric if (std::optional<SectionDescriptor *> DebugLocSection = 3571db9f3b2SDimitry Andric tryGetSectionDescriptor(DebugSectionKind::DebugLoc)) { 3581db9f3b2SDimitry Andric (*DebugLocSection) 3591db9f3b2SDimitry Andric ->ListDebugULEB128DieRefPatch.forEach( 3601db9f3b2SDimitry Andric [](DebugULEB128DieRefPatch &Patch) { 3611db9f3b2SDimitry Andric /// Replace stored DIE indexes with DIE output offsets. 3621db9f3b2SDimitry Andric Patch.RefDieIdxOrClonedOffset = 3631db9f3b2SDimitry Andric Patch.RefCU.getPointer()->getDieOutOffset( 3641db9f3b2SDimitry Andric Patch.RefDieIdxOrClonedOffset); 3651db9f3b2SDimitry Andric }); 3661db9f3b2SDimitry Andric } 3671db9f3b2SDimitry Andric 3681db9f3b2SDimitry Andric if (std::optional<SectionDescriptor *> DebugLocListsSection = 3691db9f3b2SDimitry Andric tryGetSectionDescriptor(DebugSectionKind::DebugLocLists)) { 3701db9f3b2SDimitry Andric (*DebugLocListsSection) 3711db9f3b2SDimitry Andric ->ListDebugULEB128DieRefPatch.forEach( 3721db9f3b2SDimitry Andric [](DebugULEB128DieRefPatch &Patch) { 3731db9f3b2SDimitry Andric /// Replace stored DIE indexes with DIE output offsets. 3741db9f3b2SDimitry Andric Patch.RefDieIdxOrClonedOffset = 3751db9f3b2SDimitry Andric Patch.RefCU.getPointer()->getDieOutOffset( 3761db9f3b2SDimitry Andric Patch.RefDieIdxOrClonedOffset); 3771db9f3b2SDimitry Andric }); 3781db9f3b2SDimitry Andric } 3791db9f3b2SDimitry Andric } 3801db9f3b2SDimitry Andric 3811db9f3b2SDimitry Andric std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference( 3821db9f3b2SDimitry Andric const DWARFFormValue &RefValue, 3831db9f3b2SDimitry Andric ResolveInterCUReferencesMode CanResolveInterCUReferences) { 384*0fca6ea1SDimitry Andric CompileUnit *RefCU; 385*0fca6ea1SDimitry Andric uint64_t RefDIEOffset; 386*0fca6ea1SDimitry Andric if (std::optional<uint64_t> Offset = RefValue.getAsRelativeReference()) { 387*0fca6ea1SDimitry Andric RefCU = this; 388*0fca6ea1SDimitry Andric RefDIEOffset = RefValue.getUnit()->getOffset() + *Offset; 389*0fca6ea1SDimitry Andric } else if (Offset = RefValue.getAsDebugInfoReference(); Offset) { 390*0fca6ea1SDimitry Andric RefCU = getUnitFromOffset(*Offset); 391*0fca6ea1SDimitry Andric RefDIEOffset = *Offset; 392*0fca6ea1SDimitry Andric } else { 393*0fca6ea1SDimitry Andric return std::nullopt; 3941db9f3b2SDimitry Andric } 395*0fca6ea1SDimitry Andric 3961db9f3b2SDimitry Andric if (RefCU == this) { 3971db9f3b2SDimitry Andric // Referenced DIE is in current compile unit. 398*0fca6ea1SDimitry Andric if (std::optional<uint32_t> RefDieIdx = getDIEIndexForOffset(RefDIEOffset)) 3991db9f3b2SDimitry Andric return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)}; 400*0fca6ea1SDimitry Andric } else if (RefCU && CanResolveInterCUReferences) { 4011db9f3b2SDimitry Andric // Referenced DIE is in other compile unit. 4021db9f3b2SDimitry Andric 4031db9f3b2SDimitry Andric // Check whether DIEs are loaded for that compile unit. 4041db9f3b2SDimitry Andric enum Stage ReferredCUStage = RefCU->getStage(); 4051db9f3b2SDimitry Andric if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned) 4061db9f3b2SDimitry Andric return UnitEntryPairTy{RefCU, nullptr}; 4071db9f3b2SDimitry Andric 4081db9f3b2SDimitry Andric if (std::optional<uint32_t> RefDieIdx = 4091db9f3b2SDimitry Andric RefCU->getDIEIndexForOffset(RefDIEOffset)) 4101db9f3b2SDimitry Andric return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)}; 411*0fca6ea1SDimitry Andric } else { 4121db9f3b2SDimitry Andric return UnitEntryPairTy{RefCU, nullptr}; 4131db9f3b2SDimitry Andric } 4141db9f3b2SDimitry Andric return std::nullopt; 4151db9f3b2SDimitry Andric } 4161db9f3b2SDimitry Andric 4171db9f3b2SDimitry Andric std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference( 4181db9f3b2SDimitry Andric const DWARFDebugInfoEntry *DieEntry, dwarf::Attribute Attr, 4191db9f3b2SDimitry Andric ResolveInterCUReferencesMode CanResolveInterCUReferences) { 4201db9f3b2SDimitry Andric if (std::optional<DWARFFormValue> AttrVal = find(DieEntry, Attr)) 4211db9f3b2SDimitry Andric return resolveDIEReference(*AttrVal, CanResolveInterCUReferences); 4221db9f3b2SDimitry Andric 4231db9f3b2SDimitry Andric return std::nullopt; 4241db9f3b2SDimitry Andric } 4251db9f3b2SDimitry Andric 4261db9f3b2SDimitry Andric void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc, 4271db9f3b2SDimitry Andric int64_t PcOffset) { 4281db9f3b2SDimitry Andric std::lock_guard<std::mutex> Guard(RangesMutex); 4291db9f3b2SDimitry Andric 4301db9f3b2SDimitry Andric Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset); 4311db9f3b2SDimitry Andric if (LowPc) 4321db9f3b2SDimitry Andric LowPc = std::min(*LowPc, FuncLowPc + PcOffset); 4331db9f3b2SDimitry Andric else 4341db9f3b2SDimitry Andric LowPc = FuncLowPc + PcOffset; 4351db9f3b2SDimitry Andric this->HighPc = std::max(HighPc, FuncHighPc + PcOffset); 4361db9f3b2SDimitry Andric } 4371db9f3b2SDimitry Andric 4381db9f3b2SDimitry Andric void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) { 4391db9f3b2SDimitry Andric std::lock_guard<std::mutex> Guard(LabelsMutex); 4401db9f3b2SDimitry Andric Labels.insert({LabelLowPc, PcOffset}); 4411db9f3b2SDimitry Andric } 4421db9f3b2SDimitry Andric 4431db9f3b2SDimitry Andric Error CompileUnit::cloneAndEmitDebugLocations() { 4441db9f3b2SDimitry Andric if (getGlobalData().getOptions().UpdateIndexTablesOnly) 4451db9f3b2SDimitry Andric return Error::success(); 4461db9f3b2SDimitry Andric 4471db9f3b2SDimitry Andric if (getOrigUnit().getVersion() < 5) { 4481db9f3b2SDimitry Andric emitLocations(DebugSectionKind::DebugLoc); 4491db9f3b2SDimitry Andric return Error::success(); 4501db9f3b2SDimitry Andric } 4511db9f3b2SDimitry Andric 4521db9f3b2SDimitry Andric emitLocations(DebugSectionKind::DebugLocLists); 4531db9f3b2SDimitry Andric return Error::success(); 4541db9f3b2SDimitry Andric } 4551db9f3b2SDimitry Andric 4561db9f3b2SDimitry Andric void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) { 4571db9f3b2SDimitry Andric SectionDescriptor &DebugInfoSection = 4581db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); 4591db9f3b2SDimitry Andric 4601db9f3b2SDimitry Andric if (!DebugInfoSection.ListDebugLocPatch.empty()) { 4611db9f3b2SDimitry Andric SectionDescriptor &OutLocationSection = 4621db9f3b2SDimitry Andric getOrCreateSectionDescriptor(LocationSectionKind); 4631db9f3b2SDimitry Andric DWARFUnit &OrigUnit = getOrigUnit(); 4641db9f3b2SDimitry Andric 4651db9f3b2SDimitry Andric uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection); 4661db9f3b2SDimitry Andric 4671db9f3b2SDimitry Andric DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) { 4681db9f3b2SDimitry Andric // Get location expressions vector corresponding to the current 4691db9f3b2SDimitry Andric // attribute from the source DWARF. 4701db9f3b2SDimitry Andric uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal( 4711db9f3b2SDimitry Andric Patch.PatchOffset, 4721db9f3b2SDimitry Andric DebugInfoSection.getFormParams().getDwarfOffsetByteSize()); 4731db9f3b2SDimitry Andric Expected<DWARFLocationExpressionsVector> OriginalLocations = 4741db9f3b2SDimitry Andric OrigUnit.findLoclistFromOffset(InputDebugLocSectionOffset); 4751db9f3b2SDimitry Andric 4761db9f3b2SDimitry Andric if (!OriginalLocations) { 4771db9f3b2SDimitry Andric warn(OriginalLocations.takeError()); 4781db9f3b2SDimitry Andric return; 4791db9f3b2SDimitry Andric } 4801db9f3b2SDimitry Andric 4811db9f3b2SDimitry Andric LinkedLocationExpressionsVector LinkedLocationExpressions; 4821db9f3b2SDimitry Andric for (DWARFLocationExpression &CurExpression : *OriginalLocations) { 4831db9f3b2SDimitry Andric LinkedLocationExpressionsWithOffsetPatches LinkedExpression; 4841db9f3b2SDimitry Andric 4851db9f3b2SDimitry Andric if (CurExpression.Range) { 4861db9f3b2SDimitry Andric // Relocate address range. 4871db9f3b2SDimitry Andric LinkedExpression.Expression.Range = { 4881db9f3b2SDimitry Andric CurExpression.Range->LowPC + Patch.AddrAdjustmentValue, 4891db9f3b2SDimitry Andric CurExpression.Range->HighPC + Patch.AddrAdjustmentValue}; 4901db9f3b2SDimitry Andric } 4911db9f3b2SDimitry Andric 4921db9f3b2SDimitry Andric DataExtractor Data(CurExpression.Expr, OrigUnit.isLittleEndian(), 4931db9f3b2SDimitry Andric OrigUnit.getAddressByteSize()); 4941db9f3b2SDimitry Andric 4951db9f3b2SDimitry Andric DWARFExpression InputExpression(Data, OrigUnit.getAddressByteSize(), 4961db9f3b2SDimitry Andric OrigUnit.getFormParams().Format); 4971db9f3b2SDimitry Andric cloneDieAttrExpression(InputExpression, 4981db9f3b2SDimitry Andric LinkedExpression.Expression.Expr, 4991db9f3b2SDimitry Andric OutLocationSection, Patch.AddrAdjustmentValue, 5001db9f3b2SDimitry Andric LinkedExpression.Patches); 5011db9f3b2SDimitry Andric 5021db9f3b2SDimitry Andric LinkedLocationExpressions.push_back({LinkedExpression}); 5031db9f3b2SDimitry Andric } 5041db9f3b2SDimitry Andric 5051db9f3b2SDimitry Andric // Emit locations list table fragment corresponding to the CurLocAttr. 5061db9f3b2SDimitry Andric DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, 5071db9f3b2SDimitry Andric OutLocationSection.OS.tell()); 5081db9f3b2SDimitry Andric emitLocListFragment(LinkedLocationExpressions, OutLocationSection); 5091db9f3b2SDimitry Andric }); 5101db9f3b2SDimitry Andric 5111db9f3b2SDimitry Andric if (OffsetAfterUnitLength > 0) { 5121db9f3b2SDimitry Andric assert(OffsetAfterUnitLength - 5131db9f3b2SDimitry Andric OutLocationSection.getFormParams().getDwarfOffsetByteSize() < 5141db9f3b2SDimitry Andric OffsetAfterUnitLength); 5151db9f3b2SDimitry Andric OutLocationSection.apply( 5161db9f3b2SDimitry Andric OffsetAfterUnitLength - 5171db9f3b2SDimitry Andric OutLocationSection.getFormParams().getDwarfOffsetByteSize(), 5181db9f3b2SDimitry Andric dwarf::DW_FORM_sec_offset, 5191db9f3b2SDimitry Andric OutLocationSection.OS.tell() - OffsetAfterUnitLength); 5201db9f3b2SDimitry Andric } 5211db9f3b2SDimitry Andric } 5221db9f3b2SDimitry Andric } 5231db9f3b2SDimitry Andric 5241db9f3b2SDimitry Andric /// Emit debug locations(.debug_loc, .debug_loclists) header. 5251db9f3b2SDimitry Andric uint64_t CompileUnit::emitLocListHeader(SectionDescriptor &OutLocationSection) { 5261db9f3b2SDimitry Andric if (getOrigUnit().getVersion() < 5) 5271db9f3b2SDimitry Andric return 0; 5281db9f3b2SDimitry Andric 5291db9f3b2SDimitry Andric // unit_length. 5301db9f3b2SDimitry Andric OutLocationSection.emitUnitLength(0xBADDEF); 5311db9f3b2SDimitry Andric uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell(); 5321db9f3b2SDimitry Andric 5331db9f3b2SDimitry Andric // Version. 5341db9f3b2SDimitry Andric OutLocationSection.emitIntVal(5, 2); 5351db9f3b2SDimitry Andric 5361db9f3b2SDimitry Andric // Address size. 5371db9f3b2SDimitry Andric OutLocationSection.emitIntVal(OutLocationSection.getFormParams().AddrSize, 1); 5381db9f3b2SDimitry Andric 5391db9f3b2SDimitry Andric // Seg_size 5401db9f3b2SDimitry Andric OutLocationSection.emitIntVal(0, 1); 5411db9f3b2SDimitry Andric 5421db9f3b2SDimitry Andric // Offset entry count 5431db9f3b2SDimitry Andric OutLocationSection.emitIntVal(0, 4); 5441db9f3b2SDimitry Andric 5451db9f3b2SDimitry Andric return OffsetAfterUnitLength; 5461db9f3b2SDimitry Andric } 5471db9f3b2SDimitry Andric 5481db9f3b2SDimitry Andric /// Emit debug locations(.debug_loc, .debug_loclists) fragment. 5491db9f3b2SDimitry Andric uint64_t CompileUnit::emitLocListFragment( 5501db9f3b2SDimitry Andric const LinkedLocationExpressionsVector &LinkedLocationExpression, 5511db9f3b2SDimitry Andric SectionDescriptor &OutLocationSection) { 5521db9f3b2SDimitry Andric uint64_t OffsetBeforeLocationExpression = 0; 5531db9f3b2SDimitry Andric 5541db9f3b2SDimitry Andric if (getOrigUnit().getVersion() < 5) { 5551db9f3b2SDimitry Andric uint64_t BaseAddress = 0; 5561db9f3b2SDimitry Andric if (std::optional<uint64_t> LowPC = getLowPc()) 5571db9f3b2SDimitry Andric BaseAddress = *LowPC; 5581db9f3b2SDimitry Andric 5591db9f3b2SDimitry Andric for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression : 5601db9f3b2SDimitry Andric LinkedLocationExpression) { 5611db9f3b2SDimitry Andric if (LocExpression.Expression.Range) { 5621db9f3b2SDimitry Andric OutLocationSection.emitIntVal( 5631db9f3b2SDimitry Andric LocExpression.Expression.Range->LowPC - BaseAddress, 5641db9f3b2SDimitry Andric OutLocationSection.getFormParams().AddrSize); 5651db9f3b2SDimitry Andric OutLocationSection.emitIntVal( 5661db9f3b2SDimitry Andric LocExpression.Expression.Range->HighPC - BaseAddress, 5671db9f3b2SDimitry Andric OutLocationSection.getFormParams().AddrSize); 5681db9f3b2SDimitry Andric } 5691db9f3b2SDimitry Andric 5701db9f3b2SDimitry Andric OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2); 5711db9f3b2SDimitry Andric OffsetBeforeLocationExpression = OutLocationSection.OS.tell(); 5721db9f3b2SDimitry Andric for (uint64_t *OffsetPtr : LocExpression.Patches) 5731db9f3b2SDimitry Andric *OffsetPtr += OffsetBeforeLocationExpression; 5741db9f3b2SDimitry Andric 5751db9f3b2SDimitry Andric OutLocationSection.OS 5761db9f3b2SDimitry Andric << StringRef((const char *)LocExpression.Expression.Expr.data(), 5771db9f3b2SDimitry Andric LocExpression.Expression.Expr.size()); 5781db9f3b2SDimitry Andric } 5791db9f3b2SDimitry Andric 5801db9f3b2SDimitry Andric // Emit the terminator entry. 5811db9f3b2SDimitry Andric OutLocationSection.emitIntVal(0, 5821db9f3b2SDimitry Andric OutLocationSection.getFormParams().AddrSize); 5831db9f3b2SDimitry Andric OutLocationSection.emitIntVal(0, 5841db9f3b2SDimitry Andric OutLocationSection.getFormParams().AddrSize); 5851db9f3b2SDimitry Andric return OffsetBeforeLocationExpression; 5861db9f3b2SDimitry Andric } 5871db9f3b2SDimitry Andric 5881db9f3b2SDimitry Andric std::optional<uint64_t> BaseAddress; 5891db9f3b2SDimitry Andric for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression : 5901db9f3b2SDimitry Andric LinkedLocationExpression) { 5911db9f3b2SDimitry Andric if (LocExpression.Expression.Range) { 5921db9f3b2SDimitry Andric // Check whether base address is set. If it is not set yet 5931db9f3b2SDimitry Andric // then set current base address and emit base address selection entry. 5941db9f3b2SDimitry Andric if (!BaseAddress) { 5951db9f3b2SDimitry Andric BaseAddress = LocExpression.Expression.Range->LowPC; 5961db9f3b2SDimitry Andric 5971db9f3b2SDimitry Andric // Emit base address. 5981db9f3b2SDimitry Andric OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1); 5991db9f3b2SDimitry Andric encodeULEB128(DebugAddrIndexMap.getValueIndex(*BaseAddress), 6001db9f3b2SDimitry Andric OutLocationSection.OS); 6011db9f3b2SDimitry Andric } 6021db9f3b2SDimitry Andric 6031db9f3b2SDimitry Andric // Emit type of entry. 6041db9f3b2SDimitry Andric OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1); 6051db9f3b2SDimitry Andric 6061db9f3b2SDimitry Andric // Emit start offset relative to base address. 6071db9f3b2SDimitry Andric encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress, 6081db9f3b2SDimitry Andric OutLocationSection.OS); 6091db9f3b2SDimitry Andric 6101db9f3b2SDimitry Andric // Emit end offset relative to base address. 6111db9f3b2SDimitry Andric encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress, 6121db9f3b2SDimitry Andric OutLocationSection.OS); 6131db9f3b2SDimitry Andric } else 6141db9f3b2SDimitry Andric // Emit type of entry. 6151db9f3b2SDimitry Andric OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1); 6161db9f3b2SDimitry Andric 6171db9f3b2SDimitry Andric encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS); 6181db9f3b2SDimitry Andric OffsetBeforeLocationExpression = OutLocationSection.OS.tell(); 6191db9f3b2SDimitry Andric for (uint64_t *OffsetPtr : LocExpression.Patches) 6201db9f3b2SDimitry Andric *OffsetPtr += OffsetBeforeLocationExpression; 6211db9f3b2SDimitry Andric 6221db9f3b2SDimitry Andric OutLocationSection.OS << StringRef( 6231db9f3b2SDimitry Andric (const char *)LocExpression.Expression.Expr.data(), 6241db9f3b2SDimitry Andric LocExpression.Expression.Expr.size()); 6251db9f3b2SDimitry Andric } 6261db9f3b2SDimitry Andric 6271db9f3b2SDimitry Andric // Emit the terminator entry. 6281db9f3b2SDimitry Andric OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1); 6291db9f3b2SDimitry Andric return OffsetBeforeLocationExpression; 6301db9f3b2SDimitry Andric } 6311db9f3b2SDimitry Andric 6321db9f3b2SDimitry Andric Error CompileUnit::emitDebugAddrSection() { 6331db9f3b2SDimitry Andric if (GlobalData.getOptions().UpdateIndexTablesOnly) 6341db9f3b2SDimitry Andric return Error::success(); 6351db9f3b2SDimitry Andric 6361db9f3b2SDimitry Andric if (getVersion() < 5) 6371db9f3b2SDimitry Andric return Error::success(); 6381db9f3b2SDimitry Andric 6391db9f3b2SDimitry Andric if (DebugAddrIndexMap.empty()) 6401db9f3b2SDimitry Andric return Error::success(); 6411db9f3b2SDimitry Andric 6421db9f3b2SDimitry Andric SectionDescriptor &OutAddrSection = 6431db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr); 6441db9f3b2SDimitry Andric 6451db9f3b2SDimitry Andric // Emit section header. 6461db9f3b2SDimitry Andric 6471db9f3b2SDimitry Andric // Emit length. 6481db9f3b2SDimitry Andric OutAddrSection.emitUnitLength(0xBADDEF); 6491db9f3b2SDimitry Andric uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell(); 6501db9f3b2SDimitry Andric 6511db9f3b2SDimitry Andric // Emit version. 6521db9f3b2SDimitry Andric OutAddrSection.emitIntVal(5, 2); 6531db9f3b2SDimitry Andric 6541db9f3b2SDimitry Andric // Emit address size. 6551db9f3b2SDimitry Andric OutAddrSection.emitIntVal(getFormParams().AddrSize, 1); 6561db9f3b2SDimitry Andric 6571db9f3b2SDimitry Andric // Emit segment size. 6581db9f3b2SDimitry Andric OutAddrSection.emitIntVal(0, 1); 6591db9f3b2SDimitry Andric 6601db9f3b2SDimitry Andric // Emit addresses. 6611db9f3b2SDimitry Andric for (uint64_t AddrValue : DebugAddrIndexMap.getValues()) 6621db9f3b2SDimitry Andric OutAddrSection.emitIntVal(AddrValue, getFormParams().AddrSize); 6631db9f3b2SDimitry Andric 6641db9f3b2SDimitry Andric // Patch section length. 6651db9f3b2SDimitry Andric OutAddrSection.apply( 6661db9f3b2SDimitry Andric OffsetAfterSectionLength - 6671db9f3b2SDimitry Andric OutAddrSection.getFormParams().getDwarfOffsetByteSize(), 6681db9f3b2SDimitry Andric dwarf::DW_FORM_sec_offset, 6691db9f3b2SDimitry Andric OutAddrSection.OS.tell() - OffsetAfterSectionLength); 6701db9f3b2SDimitry Andric 6711db9f3b2SDimitry Andric return Error::success(); 6721db9f3b2SDimitry Andric } 6731db9f3b2SDimitry Andric 6741db9f3b2SDimitry Andric Error CompileUnit::cloneAndEmitRanges() { 6751db9f3b2SDimitry Andric if (getGlobalData().getOptions().UpdateIndexTablesOnly) 6761db9f3b2SDimitry Andric return Error::success(); 6771db9f3b2SDimitry Andric 6781db9f3b2SDimitry Andric // Build set of linked address ranges for unit function ranges. 6791db9f3b2SDimitry Andric AddressRanges LinkedFunctionRanges; 6801db9f3b2SDimitry Andric for (const AddressRangeValuePair &Range : getFunctionRanges()) 6811db9f3b2SDimitry Andric LinkedFunctionRanges.insert( 6821db9f3b2SDimitry Andric {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value}); 6831db9f3b2SDimitry Andric 6841db9f3b2SDimitry Andric emitAranges(LinkedFunctionRanges); 6851db9f3b2SDimitry Andric 6861db9f3b2SDimitry Andric if (getOrigUnit().getVersion() < 5) { 6871db9f3b2SDimitry Andric cloneAndEmitRangeList(DebugSectionKind::DebugRange, LinkedFunctionRanges); 6881db9f3b2SDimitry Andric return Error::success(); 6891db9f3b2SDimitry Andric } 6901db9f3b2SDimitry Andric 6911db9f3b2SDimitry Andric cloneAndEmitRangeList(DebugSectionKind::DebugRngLists, LinkedFunctionRanges); 6921db9f3b2SDimitry Andric return Error::success(); 6931db9f3b2SDimitry Andric } 6941db9f3b2SDimitry Andric 6951db9f3b2SDimitry Andric void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind, 6961db9f3b2SDimitry Andric AddressRanges &LinkedFunctionRanges) { 6971db9f3b2SDimitry Andric SectionDescriptor &DebugInfoSection = 6981db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); 6991db9f3b2SDimitry Andric SectionDescriptor &OutRangeSection = 7001db9f3b2SDimitry Andric getOrCreateSectionDescriptor(RngSectionKind); 7011db9f3b2SDimitry Andric 7021db9f3b2SDimitry Andric if (!DebugInfoSection.ListDebugRangePatch.empty()) { 7031db9f3b2SDimitry Andric std::optional<AddressRangeValuePair> CachedRange; 7041db9f3b2SDimitry Andric uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection); 7051db9f3b2SDimitry Andric 7061db9f3b2SDimitry Andric DebugRangePatch *CompileUnitRangePtr = nullptr; 7071db9f3b2SDimitry Andric DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) { 7081db9f3b2SDimitry Andric if (Patch.IsCompileUnitRanges) { 7091db9f3b2SDimitry Andric CompileUnitRangePtr = &Patch; 7101db9f3b2SDimitry Andric } else { 7111db9f3b2SDimitry Andric // Get ranges from the source DWARF corresponding to the current 7121db9f3b2SDimitry Andric // attribute. 7131db9f3b2SDimitry Andric AddressRanges LinkedRanges; 7141db9f3b2SDimitry Andric uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal( 7151db9f3b2SDimitry Andric Patch.PatchOffset, 7161db9f3b2SDimitry Andric DebugInfoSection.getFormParams().getDwarfOffsetByteSize()); 7171db9f3b2SDimitry Andric if (Expected<DWARFAddressRangesVector> InputRanges = 7181db9f3b2SDimitry Andric getOrigUnit().findRnglistFromOffset( 7191db9f3b2SDimitry Andric InputDebugRangesSectionOffset)) { 7201db9f3b2SDimitry Andric // Apply relocation adjustment. 7211db9f3b2SDimitry Andric for (const auto &Range : *InputRanges) { 7221db9f3b2SDimitry Andric if (!CachedRange || !CachedRange->Range.contains(Range.LowPC)) 7231db9f3b2SDimitry Andric CachedRange = 7241db9f3b2SDimitry Andric getFunctionRanges().getRangeThatContains(Range.LowPC); 7251db9f3b2SDimitry Andric 7261db9f3b2SDimitry Andric // All range entries should lie in the function range. 7271db9f3b2SDimitry Andric if (!CachedRange) { 7281db9f3b2SDimitry Andric warn("inconsistent range data."); 7291db9f3b2SDimitry Andric continue; 7301db9f3b2SDimitry Andric } 7311db9f3b2SDimitry Andric 7321db9f3b2SDimitry Andric // Store range for emiting. 7331db9f3b2SDimitry Andric LinkedRanges.insert({Range.LowPC + CachedRange->Value, 7341db9f3b2SDimitry Andric Range.HighPC + CachedRange->Value}); 7351db9f3b2SDimitry Andric } 7361db9f3b2SDimitry Andric } else { 7371db9f3b2SDimitry Andric llvm::consumeError(InputRanges.takeError()); 7381db9f3b2SDimitry Andric warn("invalid range list ignored."); 7391db9f3b2SDimitry Andric } 7401db9f3b2SDimitry Andric 7411db9f3b2SDimitry Andric // Emit linked ranges. 7421db9f3b2SDimitry Andric DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, 7431db9f3b2SDimitry Andric OutRangeSection.OS.tell()); 7441db9f3b2SDimitry Andric emitRangeListFragment(LinkedRanges, OutRangeSection); 7451db9f3b2SDimitry Andric } 7461db9f3b2SDimitry Andric }); 7471db9f3b2SDimitry Andric 7481db9f3b2SDimitry Andric if (CompileUnitRangePtr != nullptr) { 7491db9f3b2SDimitry Andric // Emit compile unit ranges last to be binary compatible with classic 7501db9f3b2SDimitry Andric // dsymutil. 7511db9f3b2SDimitry Andric DebugInfoSection.apply(CompileUnitRangePtr->PatchOffset, 7521db9f3b2SDimitry Andric dwarf::DW_FORM_sec_offset, 7531db9f3b2SDimitry Andric OutRangeSection.OS.tell()); 7541db9f3b2SDimitry Andric emitRangeListFragment(LinkedFunctionRanges, OutRangeSection); 7551db9f3b2SDimitry Andric } 7561db9f3b2SDimitry Andric 7571db9f3b2SDimitry Andric if (OffsetAfterUnitLength > 0) { 7581db9f3b2SDimitry Andric assert(OffsetAfterUnitLength - 7591db9f3b2SDimitry Andric OutRangeSection.getFormParams().getDwarfOffsetByteSize() < 7601db9f3b2SDimitry Andric OffsetAfterUnitLength); 7611db9f3b2SDimitry Andric OutRangeSection.apply( 7621db9f3b2SDimitry Andric OffsetAfterUnitLength - 7631db9f3b2SDimitry Andric OutRangeSection.getFormParams().getDwarfOffsetByteSize(), 7641db9f3b2SDimitry Andric dwarf::DW_FORM_sec_offset, 7651db9f3b2SDimitry Andric OutRangeSection.OS.tell() - OffsetAfterUnitLength); 7661db9f3b2SDimitry Andric } 7671db9f3b2SDimitry Andric } 7681db9f3b2SDimitry Andric } 7691db9f3b2SDimitry Andric 7701db9f3b2SDimitry Andric uint64_t CompileUnit::emitRangeListHeader(SectionDescriptor &OutRangeSection) { 7711db9f3b2SDimitry Andric if (OutRangeSection.getFormParams().Version < 5) 7721db9f3b2SDimitry Andric return 0; 7731db9f3b2SDimitry Andric 7741db9f3b2SDimitry Andric // unit_length. 7751db9f3b2SDimitry Andric OutRangeSection.emitUnitLength(0xBADDEF); 7761db9f3b2SDimitry Andric uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell(); 7771db9f3b2SDimitry Andric 7781db9f3b2SDimitry Andric // Version. 7791db9f3b2SDimitry Andric OutRangeSection.emitIntVal(5, 2); 7801db9f3b2SDimitry Andric 7811db9f3b2SDimitry Andric // Address size. 7821db9f3b2SDimitry Andric OutRangeSection.emitIntVal(OutRangeSection.getFormParams().AddrSize, 1); 7831db9f3b2SDimitry Andric 7841db9f3b2SDimitry Andric // Seg_size 7851db9f3b2SDimitry Andric OutRangeSection.emitIntVal(0, 1); 7861db9f3b2SDimitry Andric 7871db9f3b2SDimitry Andric // Offset entry count 7881db9f3b2SDimitry Andric OutRangeSection.emitIntVal(0, 4); 7891db9f3b2SDimitry Andric 7901db9f3b2SDimitry Andric return OffsetAfterUnitLength; 7911db9f3b2SDimitry Andric } 7921db9f3b2SDimitry Andric 7931db9f3b2SDimitry Andric void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges, 7941db9f3b2SDimitry Andric SectionDescriptor &OutRangeSection) { 7951db9f3b2SDimitry Andric if (OutRangeSection.getFormParams().Version < 5) { 7961db9f3b2SDimitry Andric // Emit ranges. 7971db9f3b2SDimitry Andric uint64_t BaseAddress = 0; 7981db9f3b2SDimitry Andric if (std::optional<uint64_t> LowPC = getLowPc()) 7991db9f3b2SDimitry Andric BaseAddress = *LowPC; 8001db9f3b2SDimitry Andric 8011db9f3b2SDimitry Andric for (const AddressRange &Range : LinkedRanges) { 8021db9f3b2SDimitry Andric OutRangeSection.emitIntVal(Range.start() - BaseAddress, 8031db9f3b2SDimitry Andric OutRangeSection.getFormParams().AddrSize); 8041db9f3b2SDimitry Andric OutRangeSection.emitIntVal(Range.end() - BaseAddress, 8051db9f3b2SDimitry Andric OutRangeSection.getFormParams().AddrSize); 8061db9f3b2SDimitry Andric } 8071db9f3b2SDimitry Andric 8081db9f3b2SDimitry Andric // Add the terminator entry. 8091db9f3b2SDimitry Andric OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize); 8101db9f3b2SDimitry Andric OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize); 8111db9f3b2SDimitry Andric return; 8121db9f3b2SDimitry Andric } 8131db9f3b2SDimitry Andric 8141db9f3b2SDimitry Andric std::optional<uint64_t> BaseAddress; 8151db9f3b2SDimitry Andric for (const AddressRange &Range : LinkedRanges) { 8161db9f3b2SDimitry Andric if (!BaseAddress) { 8171db9f3b2SDimitry Andric BaseAddress = Range.start(); 8181db9f3b2SDimitry Andric 8191db9f3b2SDimitry Andric // Emit base address. 8201db9f3b2SDimitry Andric OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1); 8211db9f3b2SDimitry Andric encodeULEB128(getDebugAddrIndex(*BaseAddress), OutRangeSection.OS); 8221db9f3b2SDimitry Andric } 8231db9f3b2SDimitry Andric 8241db9f3b2SDimitry Andric // Emit type of entry. 8251db9f3b2SDimitry Andric OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1); 8261db9f3b2SDimitry Andric 8271db9f3b2SDimitry Andric // Emit start offset relative to base address. 8281db9f3b2SDimitry Andric encodeULEB128(Range.start() - *BaseAddress, OutRangeSection.OS); 8291db9f3b2SDimitry Andric 8301db9f3b2SDimitry Andric // Emit end offset relative to base address. 8311db9f3b2SDimitry Andric encodeULEB128(Range.end() - *BaseAddress, OutRangeSection.OS); 8321db9f3b2SDimitry Andric } 8331db9f3b2SDimitry Andric 8341db9f3b2SDimitry Andric // Emit the terminator entry. 8351db9f3b2SDimitry Andric OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1); 8361db9f3b2SDimitry Andric } 8371db9f3b2SDimitry Andric 8381db9f3b2SDimitry Andric void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) { 8391db9f3b2SDimitry Andric if (LinkedFunctionRanges.empty()) 8401db9f3b2SDimitry Andric return; 8411db9f3b2SDimitry Andric 8421db9f3b2SDimitry Andric SectionDescriptor &DebugInfoSection = 8431db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); 8441db9f3b2SDimitry Andric SectionDescriptor &OutArangesSection = 8451db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges); 8461db9f3b2SDimitry Andric 8471db9f3b2SDimitry Andric // Emit Header. 8481db9f3b2SDimitry Andric unsigned HeaderSize = 8491db9f3b2SDimitry Andric sizeof(int32_t) + // Size of contents (w/o this field 8501db9f3b2SDimitry Andric sizeof(int16_t) + // DWARF ARange version number 8511db9f3b2SDimitry Andric sizeof(int32_t) + // Offset of CU in the .debug_info section 8521db9f3b2SDimitry Andric sizeof(int8_t) + // Pointer Size (in bytes) 8531db9f3b2SDimitry Andric sizeof(int8_t); // Segment Size (in bytes) 8541db9f3b2SDimitry Andric 8551db9f3b2SDimitry Andric unsigned TupleSize = OutArangesSection.getFormParams().AddrSize * 2; 8561db9f3b2SDimitry Andric unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize)); 8571db9f3b2SDimitry Andric 8581db9f3b2SDimitry Andric OutArangesSection.emitOffset(0xBADDEF); // Aranges length 8591db9f3b2SDimitry Andric uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell(); 8601db9f3b2SDimitry Andric 8611db9f3b2SDimitry Andric OutArangesSection.emitIntVal(dwarf::DW_ARANGES_VERSION, 2); // Version number 8621db9f3b2SDimitry Andric OutArangesSection.notePatch( 8631db9f3b2SDimitry Andric DebugOffsetPatch{OutArangesSection.OS.tell(), &DebugInfoSection}); 8641db9f3b2SDimitry Andric OutArangesSection.emitOffset(0xBADDEF); // Corresponding unit's offset 8651db9f3b2SDimitry Andric OutArangesSection.emitIntVal(OutArangesSection.getFormParams().AddrSize, 8661db9f3b2SDimitry Andric 1); // Address size 8671db9f3b2SDimitry Andric OutArangesSection.emitIntVal(0, 1); // Segment size 8681db9f3b2SDimitry Andric 8691db9f3b2SDimitry Andric for (size_t Idx = 0; Idx < Padding; Idx++) 8701db9f3b2SDimitry Andric OutArangesSection.emitIntVal(0, 1); // Padding 8711db9f3b2SDimitry Andric 8721db9f3b2SDimitry Andric // Emit linked ranges. 8731db9f3b2SDimitry Andric for (const AddressRange &Range : LinkedFunctionRanges) { 8741db9f3b2SDimitry Andric OutArangesSection.emitIntVal(Range.start(), 8751db9f3b2SDimitry Andric OutArangesSection.getFormParams().AddrSize); 8761db9f3b2SDimitry Andric OutArangesSection.emitIntVal(Range.end() - Range.start(), 8771db9f3b2SDimitry Andric OutArangesSection.getFormParams().AddrSize); 8781db9f3b2SDimitry Andric } 8791db9f3b2SDimitry Andric 8801db9f3b2SDimitry Andric // Emit terminator. 8811db9f3b2SDimitry Andric OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize); 8821db9f3b2SDimitry Andric OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize); 8831db9f3b2SDimitry Andric 8841db9f3b2SDimitry Andric uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell(); 8851db9f3b2SDimitry Andric 8861db9f3b2SDimitry Andric // Update Aranges lentgh. 8871db9f3b2SDimitry Andric OutArangesSection.apply( 8881db9f3b2SDimitry Andric OffsetAfterArangesLengthField - 8891db9f3b2SDimitry Andric OutArangesSection.getFormParams().getDwarfOffsetByteSize(), 8901db9f3b2SDimitry Andric dwarf::DW_FORM_sec_offset, 8911db9f3b2SDimitry Andric OffsetAfterArangesEnd - OffsetAfterArangesLengthField); 8921db9f3b2SDimitry Andric } 8931db9f3b2SDimitry Andric 8941db9f3b2SDimitry Andric Error CompileUnit::cloneAndEmitDebugMacro() { 8951db9f3b2SDimitry Andric if (getOutUnitDIE() == nullptr) 8961db9f3b2SDimitry Andric return Error::success(); 8971db9f3b2SDimitry Andric 8981db9f3b2SDimitry Andric DWARFUnit &OrigUnit = getOrigUnit(); 8991db9f3b2SDimitry Andric DWARFDie OrigUnitDie = OrigUnit.getUnitDIE(); 9001db9f3b2SDimitry Andric 9011db9f3b2SDimitry Andric // Check for .debug_macro table. 9021db9f3b2SDimitry Andric if (std::optional<uint64_t> MacroAttr = 9031db9f3b2SDimitry Andric dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macros))) { 9041db9f3b2SDimitry Andric if (const DWARFDebugMacro *Table = 9051db9f3b2SDimitry Andric getContaingFile().Dwarf->getDebugMacro()) { 9061db9f3b2SDimitry Andric emitMacroTableImpl(Table, *MacroAttr, true); 9071db9f3b2SDimitry Andric } 9081db9f3b2SDimitry Andric } 9091db9f3b2SDimitry Andric 9101db9f3b2SDimitry Andric // Check for .debug_macinfo table. 9111db9f3b2SDimitry Andric if (std::optional<uint64_t> MacroAttr = 9121db9f3b2SDimitry Andric dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macro_info))) { 9131db9f3b2SDimitry Andric if (const DWARFDebugMacro *Table = 9141db9f3b2SDimitry Andric getContaingFile().Dwarf->getDebugMacinfo()) { 9151db9f3b2SDimitry Andric emitMacroTableImpl(Table, *MacroAttr, false); 9161db9f3b2SDimitry Andric } 9171db9f3b2SDimitry Andric } 9181db9f3b2SDimitry Andric 9191db9f3b2SDimitry Andric return Error::success(); 9201db9f3b2SDimitry Andric } 9211db9f3b2SDimitry Andric 9221db9f3b2SDimitry Andric void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable, 9231db9f3b2SDimitry Andric uint64_t OffsetToMacroTable, 9241db9f3b2SDimitry Andric bool hasDWARFv5Header) { 9251db9f3b2SDimitry Andric SectionDescriptor &OutSection = 9261db9f3b2SDimitry Andric hasDWARFv5Header 9271db9f3b2SDimitry Andric ? getOrCreateSectionDescriptor(DebugSectionKind::DebugMacro) 9281db9f3b2SDimitry Andric : getOrCreateSectionDescriptor(DebugSectionKind::DebugMacinfo); 9291db9f3b2SDimitry Andric 9301db9f3b2SDimitry Andric bool DefAttributeIsReported = false; 9311db9f3b2SDimitry Andric bool UndefAttributeIsReported = false; 9321db9f3b2SDimitry Andric bool ImportAttributeIsReported = false; 9331db9f3b2SDimitry Andric 9341db9f3b2SDimitry Andric for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) { 9351db9f3b2SDimitry Andric if (OffsetToMacroTable == List.Offset) { 9361db9f3b2SDimitry Andric // Write DWARFv5 header. 9371db9f3b2SDimitry Andric if (hasDWARFv5Header) { 9381db9f3b2SDimitry Andric // Write header version. 9391db9f3b2SDimitry Andric OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version)); 9401db9f3b2SDimitry Andric 9411db9f3b2SDimitry Andric uint8_t Flags = List.Header.Flags; 9421db9f3b2SDimitry Andric 9431db9f3b2SDimitry Andric // Check for OPCODE_OPERANDS_TABLE. 9441db9f3b2SDimitry Andric if (Flags & 9451db9f3b2SDimitry Andric DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) { 9461db9f3b2SDimitry Andric Flags &= 9471db9f3b2SDimitry Andric ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE; 9481db9f3b2SDimitry Andric warn("opcode_operands_table is not supported yet."); 9491db9f3b2SDimitry Andric } 9501db9f3b2SDimitry Andric 9511db9f3b2SDimitry Andric // Check for DEBUG_LINE_OFFSET. 9521db9f3b2SDimitry Andric std::optional<uint64_t> StmtListOffset; 9531db9f3b2SDimitry Andric if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) { 9541db9f3b2SDimitry Andric // Get offset to the line table from the cloned compile unit. 9551db9f3b2SDimitry Andric for (auto &V : getOutUnitDIE()->values()) { 9561db9f3b2SDimitry Andric if (V.getAttribute() == dwarf::DW_AT_stmt_list) { 9571db9f3b2SDimitry Andric StmtListOffset = V.getDIEInteger().getValue(); 9581db9f3b2SDimitry Andric break; 9591db9f3b2SDimitry Andric } 9601db9f3b2SDimitry Andric } 9611db9f3b2SDimitry Andric 9621db9f3b2SDimitry Andric if (!StmtListOffset) { 9631db9f3b2SDimitry Andric Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET; 9641db9f3b2SDimitry Andric warn("couldn`t find line table for macro table."); 9651db9f3b2SDimitry Andric } 9661db9f3b2SDimitry Andric } 9671db9f3b2SDimitry Andric 9681db9f3b2SDimitry Andric // Write flags. 9691db9f3b2SDimitry Andric OutSection.emitIntVal(Flags, sizeof(Flags)); 9701db9f3b2SDimitry Andric 9711db9f3b2SDimitry Andric // Write offset to line table. 9721db9f3b2SDimitry Andric if (StmtListOffset) { 9731db9f3b2SDimitry Andric OutSection.notePatch(DebugOffsetPatch{ 9741db9f3b2SDimitry Andric OutSection.OS.tell(), 9751db9f3b2SDimitry Andric &getOrCreateSectionDescriptor(DebugSectionKind::DebugLine)}); 9761db9f3b2SDimitry Andric // TODO: check that List.Header.getOffsetByteSize() and 9771db9f3b2SDimitry Andric // DebugOffsetPatch agree on size. 9781db9f3b2SDimitry Andric OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize()); 9791db9f3b2SDimitry Andric } 9801db9f3b2SDimitry Andric } 9811db9f3b2SDimitry Andric 9821db9f3b2SDimitry Andric // Write macro entries. 9831db9f3b2SDimitry Andric for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) { 9841db9f3b2SDimitry Andric if (MacroEntry.Type == 0) { 9851db9f3b2SDimitry Andric encodeULEB128(MacroEntry.Type, OutSection.OS); 9861db9f3b2SDimitry Andric continue; 9871db9f3b2SDimitry Andric } 9881db9f3b2SDimitry Andric 9891db9f3b2SDimitry Andric uint8_t MacroType = MacroEntry.Type; 9901db9f3b2SDimitry Andric switch (MacroType) { 9911db9f3b2SDimitry Andric default: { 9921db9f3b2SDimitry Andric bool HasVendorSpecificExtension = 9931db9f3b2SDimitry Andric (!hasDWARFv5Header && 9941db9f3b2SDimitry Andric MacroType == dwarf::DW_MACINFO_vendor_ext) || 9951db9f3b2SDimitry Andric (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user && 9961db9f3b2SDimitry Andric MacroType <= dwarf::DW_MACRO_hi_user)); 9971db9f3b2SDimitry Andric 9981db9f3b2SDimitry Andric if (HasVendorSpecificExtension) { 9991db9f3b2SDimitry Andric // Write macinfo type. 10001db9f3b2SDimitry Andric OutSection.emitIntVal(MacroType, 1); 10011db9f3b2SDimitry Andric 10021db9f3b2SDimitry Andric // Write vendor extension constant. 10031db9f3b2SDimitry Andric encodeULEB128(MacroEntry.ExtConstant, OutSection.OS); 10041db9f3b2SDimitry Andric 10051db9f3b2SDimitry Andric // Write vendor extension string. 10061db9f3b2SDimitry Andric OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr); 10071db9f3b2SDimitry Andric } else 10081db9f3b2SDimitry Andric warn("unknown macro type. skip."); 10091db9f3b2SDimitry Andric } break; 10101db9f3b2SDimitry Andric // debug_macro and debug_macinfo share some common encodings. 10111db9f3b2SDimitry Andric // DW_MACRO_define == DW_MACINFO_define 10121db9f3b2SDimitry Andric // DW_MACRO_undef == DW_MACINFO_undef 10131db9f3b2SDimitry Andric // DW_MACRO_start_file == DW_MACINFO_start_file 10141db9f3b2SDimitry Andric // DW_MACRO_end_file == DW_MACINFO_end_file 10151db9f3b2SDimitry Andric // For readibility/uniformity we are using DW_MACRO_*. 10161db9f3b2SDimitry Andric case dwarf::DW_MACRO_define: 10171db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef: { 10181db9f3b2SDimitry Andric // Write macinfo type. 10191db9f3b2SDimitry Andric OutSection.emitIntVal(MacroType, 1); 10201db9f3b2SDimitry Andric 10211db9f3b2SDimitry Andric // Write source line. 10221db9f3b2SDimitry Andric encodeULEB128(MacroEntry.Line, OutSection.OS); 10231db9f3b2SDimitry Andric 10241db9f3b2SDimitry Andric // Write macro string. 10251db9f3b2SDimitry Andric OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr); 10261db9f3b2SDimitry Andric } break; 10271db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strp: 10281db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strp: 10291db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strx: 10301db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strx: { 10311db9f3b2SDimitry Andric // DW_MACRO_*_strx forms are not supported currently. 10321db9f3b2SDimitry Andric // Convert to *_strp. 10331db9f3b2SDimitry Andric switch (MacroType) { 10341db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strx: { 10351db9f3b2SDimitry Andric MacroType = dwarf::DW_MACRO_define_strp; 10361db9f3b2SDimitry Andric if (!DefAttributeIsReported) { 10371db9f3b2SDimitry Andric warn("DW_MACRO_define_strx unsupported yet. Convert to " 10381db9f3b2SDimitry Andric "DW_MACRO_define_strp."); 10391db9f3b2SDimitry Andric DefAttributeIsReported = true; 10401db9f3b2SDimitry Andric } 10411db9f3b2SDimitry Andric } break; 10421db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strx: { 10431db9f3b2SDimitry Andric MacroType = dwarf::DW_MACRO_undef_strp; 10441db9f3b2SDimitry Andric if (!UndefAttributeIsReported) { 10451db9f3b2SDimitry Andric warn("DW_MACRO_undef_strx unsupported yet. Convert to " 10461db9f3b2SDimitry Andric "DW_MACRO_undef_strp."); 10471db9f3b2SDimitry Andric UndefAttributeIsReported = true; 10481db9f3b2SDimitry Andric } 10491db9f3b2SDimitry Andric } break; 10501db9f3b2SDimitry Andric default: 10511db9f3b2SDimitry Andric // Nothing to do. 10521db9f3b2SDimitry Andric break; 10531db9f3b2SDimitry Andric } 10541db9f3b2SDimitry Andric 10551db9f3b2SDimitry Andric // Write macinfo type. 10561db9f3b2SDimitry Andric OutSection.emitIntVal(MacroType, 1); 10571db9f3b2SDimitry Andric 10581db9f3b2SDimitry Andric // Write source line. 10591db9f3b2SDimitry Andric encodeULEB128(MacroEntry.Line, OutSection.OS); 10601db9f3b2SDimitry Andric 10611db9f3b2SDimitry Andric // Write macro string. 10621db9f3b2SDimitry Andric OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr); 10631db9f3b2SDimitry Andric break; 10641db9f3b2SDimitry Andric } 10651db9f3b2SDimitry Andric case dwarf::DW_MACRO_start_file: { 10661db9f3b2SDimitry Andric // Write macinfo type. 10671db9f3b2SDimitry Andric OutSection.emitIntVal(MacroType, 1); 10681db9f3b2SDimitry Andric // Write source line. 10691db9f3b2SDimitry Andric encodeULEB128(MacroEntry.Line, OutSection.OS); 10701db9f3b2SDimitry Andric // Write source file id. 10711db9f3b2SDimitry Andric encodeULEB128(MacroEntry.File, OutSection.OS); 10721db9f3b2SDimitry Andric } break; 10731db9f3b2SDimitry Andric case dwarf::DW_MACRO_end_file: { 10741db9f3b2SDimitry Andric // Write macinfo type. 10751db9f3b2SDimitry Andric OutSection.emitIntVal(MacroType, 1); 10761db9f3b2SDimitry Andric } break; 10771db9f3b2SDimitry Andric case dwarf::DW_MACRO_import: 10781db9f3b2SDimitry Andric case dwarf::DW_MACRO_import_sup: { 10791db9f3b2SDimitry Andric if (!ImportAttributeIsReported) { 10801db9f3b2SDimitry Andric warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported " 10811db9f3b2SDimitry Andric "yet. remove."); 10821db9f3b2SDimitry Andric ImportAttributeIsReported = true; 10831db9f3b2SDimitry Andric } 10841db9f3b2SDimitry Andric } break; 10851db9f3b2SDimitry Andric } 10861db9f3b2SDimitry Andric } 10871db9f3b2SDimitry Andric 10881db9f3b2SDimitry Andric return; 10891db9f3b2SDimitry Andric } 10901db9f3b2SDimitry Andric } 10911db9f3b2SDimitry Andric } 10921db9f3b2SDimitry Andric 10931db9f3b2SDimitry Andric void CompileUnit::cloneDieAttrExpression( 10941db9f3b2SDimitry Andric const DWARFExpression &InputExpression, 10951db9f3b2SDimitry Andric SmallVectorImpl<uint8_t> &OutputExpression, SectionDescriptor &Section, 10961db9f3b2SDimitry Andric std::optional<int64_t> VarAddressAdjustment, 10971db9f3b2SDimitry Andric OffsetsPtrVector &PatchesOffsets) { 10981db9f3b2SDimitry Andric using Encoding = DWARFExpression::Operation::Encoding; 10991db9f3b2SDimitry Andric 11001db9f3b2SDimitry Andric DWARFUnit &OrigUnit = getOrigUnit(); 11011db9f3b2SDimitry Andric uint8_t OrigAddressByteSize = OrigUnit.getAddressByteSize(); 11021db9f3b2SDimitry Andric 11031db9f3b2SDimitry Andric uint64_t OpOffset = 0; 11041db9f3b2SDimitry Andric for (auto &Op : InputExpression) { 11051db9f3b2SDimitry Andric auto Desc = Op.getDescription(); 11061db9f3b2SDimitry Andric // DW_OP_const_type is variable-length and has 3 11071db9f3b2SDimitry Andric // operands. Thus far we only support 2. 11081db9f3b2SDimitry Andric if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) || 11091db9f3b2SDimitry Andric (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef && 11101db9f3b2SDimitry Andric Desc.Op[0] != Encoding::Size1)) 11111db9f3b2SDimitry Andric warn("unsupported DW_OP encoding."); 11121db9f3b2SDimitry Andric 11131db9f3b2SDimitry Andric if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) || 11141db9f3b2SDimitry Andric (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef && 11151db9f3b2SDimitry Andric Desc.Op[0] == Encoding::Size1)) { 11161db9f3b2SDimitry Andric // This code assumes that the other non-typeref operand fits into 1 byte. 11171db9f3b2SDimitry Andric assert(OpOffset < Op.getEndOffset()); 11181db9f3b2SDimitry Andric uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1; 11191db9f3b2SDimitry Andric assert(ULEBsize <= 16); 11201db9f3b2SDimitry Andric 11211db9f3b2SDimitry Andric // Copy over the operation. 11221db9f3b2SDimitry Andric assert(!Op.getSubCode() && "SubOps not yet supported"); 11231db9f3b2SDimitry Andric OutputExpression.push_back(Op.getCode()); 11241db9f3b2SDimitry Andric uint64_t RefOffset; 11251db9f3b2SDimitry Andric if (Desc.Op.size() == 1) { 11261db9f3b2SDimitry Andric RefOffset = Op.getRawOperand(0); 11271db9f3b2SDimitry Andric } else { 11281db9f3b2SDimitry Andric OutputExpression.push_back(Op.getRawOperand(0)); 11291db9f3b2SDimitry Andric RefOffset = Op.getRawOperand(1); 11301db9f3b2SDimitry Andric } 11311db9f3b2SDimitry Andric uint8_t ULEB[16]; 11321db9f3b2SDimitry Andric uint32_t Offset = 0; 11331db9f3b2SDimitry Andric unsigned RealSize = 0; 11341db9f3b2SDimitry Andric // Look up the base type. For DW_OP_convert, the operand may be 0 to 11351db9f3b2SDimitry Andric // instead indicate the generic type. The same holds for 11361db9f3b2SDimitry Andric // DW_OP_reinterpret, which is currently not supported. 11371db9f3b2SDimitry Andric if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) { 11381db9f3b2SDimitry Andric RefOffset += OrigUnit.getOffset(); 11391db9f3b2SDimitry Andric uint32_t RefDieIdx = 0; 11401db9f3b2SDimitry Andric if (std::optional<uint32_t> Idx = 11411db9f3b2SDimitry Andric OrigUnit.getDIEIndexForOffset(RefOffset)) 11421db9f3b2SDimitry Andric RefDieIdx = *Idx; 11431db9f3b2SDimitry Andric 11441db9f3b2SDimitry Andric // Use fixed size for ULEB128 data, since we need to update that size 11451db9f3b2SDimitry Andric // later with the proper offsets. Use 5 for DWARF32, 9 for DWARF64. 11461db9f3b2SDimitry Andric ULEBsize = getFormParams().getDwarfOffsetByteSize() + 1; 11471db9f3b2SDimitry Andric 11481db9f3b2SDimitry Andric RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize); 11491db9f3b2SDimitry Andric 11501db9f3b2SDimitry Andric Section.notePatchWithOffsetUpdate( 11511db9f3b2SDimitry Andric DebugULEB128DieRefPatch(OutputExpression.size(), this, this, 11521db9f3b2SDimitry Andric RefDieIdx), 11531db9f3b2SDimitry Andric PatchesOffsets); 11541db9f3b2SDimitry Andric } else 11551db9f3b2SDimitry Andric RealSize = encodeULEB128(Offset, ULEB, ULEBsize); 11561db9f3b2SDimitry Andric 11571db9f3b2SDimitry Andric if (RealSize > ULEBsize) { 11581db9f3b2SDimitry Andric // Emit the generic type as a fallback. 11591db9f3b2SDimitry Andric RealSize = encodeULEB128(0, ULEB, ULEBsize); 11601db9f3b2SDimitry Andric warn("base type ref doesn't fit."); 11611db9f3b2SDimitry Andric } 11621db9f3b2SDimitry Andric assert(RealSize == ULEBsize && "padding failed"); 11631db9f3b2SDimitry Andric ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize); 11641db9f3b2SDimitry Andric OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end()); 11651db9f3b2SDimitry Andric } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly && 11661db9f3b2SDimitry Andric Op.getCode() == dwarf::DW_OP_addrx) { 11671db9f3b2SDimitry Andric if (std::optional<object::SectionedAddress> SA = 11681db9f3b2SDimitry Andric OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) { 11691db9f3b2SDimitry Andric // DWARFLinker does not use addrx forms since it generates relocated 11701db9f3b2SDimitry Andric // addresses. Replace DW_OP_addrx with DW_OP_addr here. 11711db9f3b2SDimitry Andric // Argument of DW_OP_addrx should be relocated here as it is not 11721db9f3b2SDimitry Andric // processed by applyValidRelocs. 11731db9f3b2SDimitry Andric OutputExpression.push_back(dwarf::DW_OP_addr); 11741db9f3b2SDimitry Andric uint64_t LinkedAddress = 11751db9f3b2SDimitry Andric SA->Address + (VarAddressAdjustment ? *VarAddressAdjustment : 0); 11761db9f3b2SDimitry Andric if (getEndianness() != llvm::endianness::native) 11771db9f3b2SDimitry Andric sys::swapByteOrder(LinkedAddress); 11781db9f3b2SDimitry Andric ArrayRef<uint8_t> AddressBytes( 11791db9f3b2SDimitry Andric reinterpret_cast<const uint8_t *>(&LinkedAddress), 11801db9f3b2SDimitry Andric OrigAddressByteSize); 11811db9f3b2SDimitry Andric OutputExpression.append(AddressBytes.begin(), AddressBytes.end()); 11821db9f3b2SDimitry Andric } else 11831db9f3b2SDimitry Andric warn("cann't read DW_OP_addrx operand."); 11841db9f3b2SDimitry Andric } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly && 11851db9f3b2SDimitry Andric Op.getCode() == dwarf::DW_OP_constx) { 11861db9f3b2SDimitry Andric if (std::optional<object::SectionedAddress> SA = 11871db9f3b2SDimitry Andric OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) { 11881db9f3b2SDimitry Andric // DWARFLinker does not use constx forms since it generates relocated 11891db9f3b2SDimitry Andric // addresses. Replace DW_OP_constx with DW_OP_const[*]u here. 11901db9f3b2SDimitry Andric // Argument of DW_OP_constx should be relocated here as it is not 11911db9f3b2SDimitry Andric // processed by applyValidRelocs. 11921db9f3b2SDimitry Andric std::optional<uint8_t> OutOperandKind; 11931db9f3b2SDimitry Andric switch (OrigAddressByteSize) { 11941db9f3b2SDimitry Andric case 2: 11951db9f3b2SDimitry Andric OutOperandKind = dwarf::DW_OP_const2u; 11961db9f3b2SDimitry Andric break; 11971db9f3b2SDimitry Andric case 4: 11981db9f3b2SDimitry Andric OutOperandKind = dwarf::DW_OP_const4u; 11991db9f3b2SDimitry Andric break; 12001db9f3b2SDimitry Andric case 8: 12011db9f3b2SDimitry Andric OutOperandKind = dwarf::DW_OP_const8u; 12021db9f3b2SDimitry Andric break; 12031db9f3b2SDimitry Andric default: 12041db9f3b2SDimitry Andric warn( 12051db9f3b2SDimitry Andric formatv(("unsupported address size: {0}."), OrigAddressByteSize)); 12061db9f3b2SDimitry Andric break; 12071db9f3b2SDimitry Andric } 12081db9f3b2SDimitry Andric 12091db9f3b2SDimitry Andric if (OutOperandKind) { 12101db9f3b2SDimitry Andric OutputExpression.push_back(*OutOperandKind); 12111db9f3b2SDimitry Andric uint64_t LinkedAddress = 12121db9f3b2SDimitry Andric SA->Address + (VarAddressAdjustment ? *VarAddressAdjustment : 0); 12131db9f3b2SDimitry Andric if (getEndianness() != llvm::endianness::native) 12141db9f3b2SDimitry Andric sys::swapByteOrder(LinkedAddress); 12151db9f3b2SDimitry Andric ArrayRef<uint8_t> AddressBytes( 12161db9f3b2SDimitry Andric reinterpret_cast<const uint8_t *>(&LinkedAddress), 12171db9f3b2SDimitry Andric OrigAddressByteSize); 12181db9f3b2SDimitry Andric OutputExpression.append(AddressBytes.begin(), AddressBytes.end()); 12191db9f3b2SDimitry Andric } 12201db9f3b2SDimitry Andric } else 12211db9f3b2SDimitry Andric warn("cann't read DW_OP_constx operand."); 12221db9f3b2SDimitry Andric } else { 12231db9f3b2SDimitry Andric // Copy over everything else unmodified. 12241db9f3b2SDimitry Andric StringRef Bytes = 12251db9f3b2SDimitry Andric InputExpression.getData().slice(OpOffset, Op.getEndOffset()); 12261db9f3b2SDimitry Andric OutputExpression.append(Bytes.begin(), Bytes.end()); 12271db9f3b2SDimitry Andric } 12281db9f3b2SDimitry Andric OpOffset = Op.getEndOffset(); 12291db9f3b2SDimitry Andric } 12301db9f3b2SDimitry Andric } 12311db9f3b2SDimitry Andric 12327a6dacacSDimitry Andric Error CompileUnit::cloneAndEmit( 12337a6dacacSDimitry Andric std::optional<std::reference_wrapper<const Triple>> TargetTriple, 12341db9f3b2SDimitry Andric TypeUnit *ArtificialTypeUnit) { 12351db9f3b2SDimitry Andric BumpPtrAllocator Allocator; 12361db9f3b2SDimitry Andric 12371db9f3b2SDimitry Andric DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE(); 12381db9f3b2SDimitry Andric if (!OrigUnitDIE.isValid()) 12391db9f3b2SDimitry Andric return Error::success(); 12401db9f3b2SDimitry Andric 12411db9f3b2SDimitry Andric TypeEntry *RootEntry = nullptr; 12421db9f3b2SDimitry Andric if (ArtificialTypeUnit) 12431db9f3b2SDimitry Andric RootEntry = ArtificialTypeUnit->getTypePool().getRoot(); 12441db9f3b2SDimitry Andric 12451db9f3b2SDimitry Andric // Clone input DIE entry recursively. 12461db9f3b2SDimitry Andric std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE( 12471db9f3b2SDimitry Andric OrigUnitDIE.getDebugInfoEntry(), RootEntry, getDebugInfoHeaderSize(), 12481db9f3b2SDimitry Andric std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit); 12491db9f3b2SDimitry Andric setOutUnitDIE(OutCUDie.first); 12501db9f3b2SDimitry Andric 12517a6dacacSDimitry Andric if (!TargetTriple.has_value() || (OutCUDie.first == nullptr)) 12521db9f3b2SDimitry Andric return Error::success(); 12531db9f3b2SDimitry Andric 12547a6dacacSDimitry Andric if (Error Err = cloneAndEmitLineTable((*TargetTriple).get())) 12551db9f3b2SDimitry Andric return Err; 12561db9f3b2SDimitry Andric 12571db9f3b2SDimitry Andric if (Error Err = cloneAndEmitDebugMacro()) 12581db9f3b2SDimitry Andric return Err; 12591db9f3b2SDimitry Andric 12601db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo); 12617a6dacacSDimitry Andric if (Error Err = emitDebugInfo((*TargetTriple).get())) 12621db9f3b2SDimitry Andric return Err; 12631db9f3b2SDimitry Andric 12641db9f3b2SDimitry Andric // ASSUMPTION: .debug_info section should already be emitted at this point. 12651db9f3b2SDimitry Andric // cloneAndEmitRanges & cloneAndEmitDebugLocations use .debug_info section 12661db9f3b2SDimitry Andric // data. 12671db9f3b2SDimitry Andric 12681db9f3b2SDimitry Andric if (Error Err = cloneAndEmitRanges()) 12691db9f3b2SDimitry Andric return Err; 12701db9f3b2SDimitry Andric 12711db9f3b2SDimitry Andric if (Error Err = cloneAndEmitDebugLocations()) 12721db9f3b2SDimitry Andric return Err; 12731db9f3b2SDimitry Andric 12741db9f3b2SDimitry Andric if (Error Err = emitDebugAddrSection()) 12751db9f3b2SDimitry Andric return Err; 12761db9f3b2SDimitry Andric 12771db9f3b2SDimitry Andric // Generate Pub accelerator tables. 12781db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.getOptions().AccelTables, 12791db9f3b2SDimitry Andric DWARFLinker::AccelTableKind::Pub)) 12801db9f3b2SDimitry Andric emitPubAccelerators(); 12811db9f3b2SDimitry Andric 12821db9f3b2SDimitry Andric if (Error Err = emitDebugStringOffsetSection()) 12831db9f3b2SDimitry Andric return Err; 12841db9f3b2SDimitry Andric 12851db9f3b2SDimitry Andric return emitAbbreviations(); 12861db9f3b2SDimitry Andric } 12871db9f3b2SDimitry Andric 12881db9f3b2SDimitry Andric std::pair<DIE *, TypeEntry *> CompileUnit::cloneDIE( 12891db9f3b2SDimitry Andric const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE, 12901db9f3b2SDimitry Andric uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment, 12911db9f3b2SDimitry Andric std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator, 12921db9f3b2SDimitry Andric TypeUnit *ArtificialTypeUnit) { 12931db9f3b2SDimitry Andric uint32_t InputDieIdx = getDIEIndex(InputDieEntry); 12941db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx); 12951db9f3b2SDimitry Andric 12961db9f3b2SDimitry Andric bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf(); 12971db9f3b2SDimitry Andric bool NeedToCloneTypeDIE = 12981db9f3b2SDimitry Andric (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) && 12991db9f3b2SDimitry Andric Info.needToPlaceInTypeTable(); 13001db9f3b2SDimitry Andric std::pair<DIE *, TypeEntry *> ClonedDIE; 13011db9f3b2SDimitry Andric 13021db9f3b2SDimitry Andric DIEGenerator PlainDIEGenerator(Allocator, *this); 13031db9f3b2SDimitry Andric 13041db9f3b2SDimitry Andric if (NeedToClonePlainDIE) 13051db9f3b2SDimitry Andric // Create a cloned DIE which would be placed into the cloned version 13061db9f3b2SDimitry Andric // of input compile unit. 13071db9f3b2SDimitry Andric ClonedDIE.first = createPlainDIEandCloneAttributes( 13081db9f3b2SDimitry Andric InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment, 13091db9f3b2SDimitry Andric VarAddressAdjustment); 13101db9f3b2SDimitry Andric if (NeedToCloneTypeDIE) { 13111db9f3b2SDimitry Andric // Create a cloned DIE which would be placed into the artificial type 13121db9f3b2SDimitry Andric // unit. 13131db9f3b2SDimitry Andric assert(ArtificialTypeUnit != nullptr); 13141db9f3b2SDimitry Andric DIEGenerator TypeDIEGenerator( 13151db9f3b2SDimitry Andric ArtificialTypeUnit->getTypePool().getThreadLocalAllocator(), *this); 13161db9f3b2SDimitry Andric 13171db9f3b2SDimitry Andric ClonedDIE.second = createTypeDIEandCloneAttributes( 13181db9f3b2SDimitry Andric InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE, 13191db9f3b2SDimitry Andric ArtificialTypeUnit); 13201db9f3b2SDimitry Andric } 13211db9f3b2SDimitry Andric TypeEntry *TypeParentForChild = 13221db9f3b2SDimitry Andric ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE; 13231db9f3b2SDimitry Andric 13241db9f3b2SDimitry Andric bool HasPlainChildrenToClone = 13251db9f3b2SDimitry Andric (ClonedDIE.first && Info.getKeepPlainChildren()); 13261db9f3b2SDimitry Andric 13271db9f3b2SDimitry Andric bool HasTypeChildrenToClone = 13281db9f3b2SDimitry Andric ((ClonedDIE.second || 13291db9f3b2SDimitry Andric InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) && 13301db9f3b2SDimitry Andric Info.getKeepTypeChildren()); 13311db9f3b2SDimitry Andric 13321db9f3b2SDimitry Andric // Recursively clone children. 13331db9f3b2SDimitry Andric if (HasPlainChildrenToClone || HasTypeChildrenToClone) { 13341db9f3b2SDimitry Andric for (const DWARFDebugInfoEntry *CurChild = 13351db9f3b2SDimitry Andric getFirstChildEntry(InputDieEntry); 13361db9f3b2SDimitry Andric CurChild && CurChild->getAbbreviationDeclarationPtr(); 13371db9f3b2SDimitry Andric CurChild = getSiblingEntry(CurChild)) { 13381db9f3b2SDimitry Andric std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE( 13391db9f3b2SDimitry Andric CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment, 13401db9f3b2SDimitry Andric VarAddressAdjustment, Allocator, ArtificialTypeUnit); 13411db9f3b2SDimitry Andric 13421db9f3b2SDimitry Andric if (ClonedChild.first) { 13431db9f3b2SDimitry Andric OutOffset = 13441db9f3b2SDimitry Andric ClonedChild.first->getOffset() + ClonedChild.first->getSize(); 13451db9f3b2SDimitry Andric PlainDIEGenerator.addChild(ClonedChild.first); 13461db9f3b2SDimitry Andric } 13471db9f3b2SDimitry Andric } 13481db9f3b2SDimitry Andric assert(ClonedDIE.first == nullptr || 13491db9f3b2SDimitry Andric HasPlainChildrenToClone == ClonedDIE.first->hasChildren()); 13501db9f3b2SDimitry Andric 13511db9f3b2SDimitry Andric // Account for the end of children marker. 13521db9f3b2SDimitry Andric if (HasPlainChildrenToClone) 13531db9f3b2SDimitry Andric OutOffset += sizeof(int8_t); 13541db9f3b2SDimitry Andric } 13551db9f3b2SDimitry Andric 13561db9f3b2SDimitry Andric // Update our size. 13571db9f3b2SDimitry Andric if (ClonedDIE.first != nullptr) 13581db9f3b2SDimitry Andric ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset()); 13591db9f3b2SDimitry Andric 13601db9f3b2SDimitry Andric return ClonedDIE; 13611db9f3b2SDimitry Andric } 13621db9f3b2SDimitry Andric 13631db9f3b2SDimitry Andric DIE *CompileUnit::createPlainDIEandCloneAttributes( 13641db9f3b2SDimitry Andric const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator, 13651db9f3b2SDimitry Andric uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment, 13661db9f3b2SDimitry Andric std::optional<int64_t> &VarAddressAdjustment) { 13671db9f3b2SDimitry Andric uint32_t InputDieIdx = getDIEIndex(InputDieEntry); 13681db9f3b2SDimitry Andric CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx); 13691db9f3b2SDimitry Andric DIE *ClonedDIE = nullptr; 13701db9f3b2SDimitry Andric bool HasLocationExpressionAddress = false; 13711db9f3b2SDimitry Andric if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) { 13721db9f3b2SDimitry Andric // Get relocation adjustment value for the current function. 13731db9f3b2SDimitry Andric FuncAddressAdjustment = 13741db9f3b2SDimitry Andric getContaingFile().Addresses->getSubprogramRelocAdjustment( 13757a6dacacSDimitry Andric getDIE(InputDieEntry), false); 13761db9f3b2SDimitry Andric } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) { 13771db9f3b2SDimitry Andric // Get relocation adjustment value for the current label. 13781db9f3b2SDimitry Andric std::optional<uint64_t> lowPC = 13791db9f3b2SDimitry Andric dwarf::toAddress(find(InputDieEntry, dwarf::DW_AT_low_pc)); 13801db9f3b2SDimitry Andric if (lowPC) { 13811db9f3b2SDimitry Andric LabelMapTy::iterator It = Labels.find(*lowPC); 13821db9f3b2SDimitry Andric if (It != Labels.end()) 13831db9f3b2SDimitry Andric FuncAddressAdjustment = It->second; 13841db9f3b2SDimitry Andric } 13851db9f3b2SDimitry Andric } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) { 13861db9f3b2SDimitry Andric // Get relocation adjustment value for the current variable. 13871db9f3b2SDimitry Andric std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment = 13881db9f3b2SDimitry Andric getContaingFile().Addresses->getVariableRelocAdjustment( 13897a6dacacSDimitry Andric getDIE(InputDieEntry), false); 13901db9f3b2SDimitry Andric 13911db9f3b2SDimitry Andric HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first; 13921db9f3b2SDimitry Andric if (LocExprAddrAndRelocAdjustment.first && 13931db9f3b2SDimitry Andric LocExprAddrAndRelocAdjustment.second) 13941db9f3b2SDimitry Andric VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second; 13951db9f3b2SDimitry Andric } 13961db9f3b2SDimitry Andric 13971db9f3b2SDimitry Andric ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset); 13981db9f3b2SDimitry Andric 13991db9f3b2SDimitry Andric // Offset to the DIE would be used after output DIE tree is deleted. 14001db9f3b2SDimitry Andric // Thus we need to remember DIE offset separately. 14011db9f3b2SDimitry Andric rememberDieOutOffset(InputDieIdx, OutOffset); 14021db9f3b2SDimitry Andric 14031db9f3b2SDimitry Andric // Clone Attributes. 14041db9f3b2SDimitry Andric DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry, 14051db9f3b2SDimitry Andric PlainDIEGenerator, FuncAddressAdjustment, 14061db9f3b2SDimitry Andric VarAddressAdjustment, 14071db9f3b2SDimitry Andric HasLocationExpressionAddress); 14081db9f3b2SDimitry Andric AttributesCloner.clone(); 14091db9f3b2SDimitry Andric 14101db9f3b2SDimitry Andric // Remember accelerator info. 14111db9f3b2SDimitry Andric AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this); 14121db9f3b2SDimitry Andric AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo, 14131db9f3b2SDimitry Andric nullptr); 14141db9f3b2SDimitry Andric 14151db9f3b2SDimitry Andric OutOffset = 14161db9f3b2SDimitry Andric AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren()); 14171db9f3b2SDimitry Andric 14181db9f3b2SDimitry Andric return ClonedDIE; 14191db9f3b2SDimitry Andric } 14201db9f3b2SDimitry Andric 14211db9f3b2SDimitry Andric /// Allocates output DIE for the specified \p TypeDescriptor. 14221db9f3b2SDimitry Andric DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor, 14231db9f3b2SDimitry Andric DIEGenerator &TypeDIEGenerator, 14241db9f3b2SDimitry Andric dwarf::Tag DieTag, bool IsDeclaration, 14251db9f3b2SDimitry Andric bool IsParentDeclaration) { 14261db9f3b2SDimitry Andric DIE *DefinitionDie = TypeDescriptor->Die; 14271db9f3b2SDimitry Andric // Do not allocate any new DIE if definition DIE is already met. 14281db9f3b2SDimitry Andric if (DefinitionDie) 14291db9f3b2SDimitry Andric return nullptr; 14301db9f3b2SDimitry Andric 14311db9f3b2SDimitry Andric DIE *DeclarationDie = TypeDescriptor->DeclarationDie; 14321db9f3b2SDimitry Andric bool OldParentIsDeclaration = TypeDescriptor->ParentIsDeclaration; 14331db9f3b2SDimitry Andric 14341db9f3b2SDimitry Andric if (IsDeclaration && !DeclarationDie) { 14351db9f3b2SDimitry Andric // Alocate declaration DIE. 14361db9f3b2SDimitry Andric DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0); 14371db9f3b2SDimitry Andric if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie, 14381db9f3b2SDimitry Andric NewDie)) 14391db9f3b2SDimitry Andric return NewDie; 14401db9f3b2SDimitry Andric } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) { 14411db9f3b2SDimitry Andric // Overwrite existing declaration DIE if it's parent is also an declaration 14421db9f3b2SDimitry Andric // while parent of current declaration DIE is a definition. 14431db9f3b2SDimitry Andric if (TypeDescriptor->ParentIsDeclaration.compare_exchange_weak( 14441db9f3b2SDimitry Andric OldParentIsDeclaration, false)) { 14451db9f3b2SDimitry Andric DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0); 14461db9f3b2SDimitry Andric TypeDescriptor->DeclarationDie = NewDie; 14471db9f3b2SDimitry Andric return NewDie; 14481db9f3b2SDimitry Andric } 14491db9f3b2SDimitry Andric } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) { 14501db9f3b2SDimitry Andric // Alocate declaration DIE since parent of current DIE is marked as 14511db9f3b2SDimitry Andric // declaration. 14521db9f3b2SDimitry Andric DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0); 14531db9f3b2SDimitry Andric if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie, 14541db9f3b2SDimitry Andric NewDie)) 14551db9f3b2SDimitry Andric return NewDie; 14561db9f3b2SDimitry Andric } else if (!IsDeclaration && !IsParentDeclaration) { 14571db9f3b2SDimitry Andric // Allocate definition DIE. 14581db9f3b2SDimitry Andric DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0); 14591db9f3b2SDimitry Andric if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) { 14601db9f3b2SDimitry Andric TypeDescriptor->ParentIsDeclaration = false; 14611db9f3b2SDimitry Andric return NewDie; 14621db9f3b2SDimitry Andric } 14631db9f3b2SDimitry Andric } 14641db9f3b2SDimitry Andric 14651db9f3b2SDimitry Andric return nullptr; 14661db9f3b2SDimitry Andric } 14671db9f3b2SDimitry Andric 14681db9f3b2SDimitry Andric TypeEntry *CompileUnit::createTypeDIEandCloneAttributes( 14691db9f3b2SDimitry Andric const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator, 14701db9f3b2SDimitry Andric TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit) { 14711db9f3b2SDimitry Andric assert(ArtificialTypeUnit != nullptr); 14721db9f3b2SDimitry Andric uint32_t InputDieIdx = getDIEIndex(InputDieEntry); 14731db9f3b2SDimitry Andric 14741db9f3b2SDimitry Andric TypeEntry *Entry = getDieTypeEntry(InputDieIdx); 14751db9f3b2SDimitry Andric assert(Entry != nullptr); 14761db9f3b2SDimitry Andric assert(ClonedParentTypeDIE != nullptr); 14771db9f3b2SDimitry Andric TypeEntryBody *EntryBody = 14781db9f3b2SDimitry Andric ArtificialTypeUnit->getTypePool().getOrCreateTypeEntryBody( 14791db9f3b2SDimitry Andric Entry, ClonedParentTypeDIE); 14801db9f3b2SDimitry Andric assert(EntryBody); 14811db9f3b2SDimitry Andric 14821db9f3b2SDimitry Andric bool IsDeclaration = 14831db9f3b2SDimitry Andric dwarf::toUnsigned(find(InputDieEntry, dwarf::DW_AT_declaration), 0); 14841db9f3b2SDimitry Andric 14851db9f3b2SDimitry Andric bool ParentIsDeclaration = false; 14861db9f3b2SDimitry Andric if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx()) 14871db9f3b2SDimitry Andric ParentIsDeclaration = 14881db9f3b2SDimitry Andric dwarf::toUnsigned(find(*ParentIdx, dwarf::DW_AT_declaration), 0); 14891db9f3b2SDimitry Andric 14901db9f3b2SDimitry Andric DIE *OutDIE = 14911db9f3b2SDimitry Andric allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(), 14921db9f3b2SDimitry Andric IsDeclaration, ParentIsDeclaration); 14931db9f3b2SDimitry Andric 14941db9f3b2SDimitry Andric if (OutDIE != nullptr) { 14951db9f3b2SDimitry Andric assert(ArtificialTypeUnit != nullptr); 14961db9f3b2SDimitry Andric ArtificialTypeUnit->getSectionDescriptor(DebugSectionKind::DebugInfo); 14971db9f3b2SDimitry Andric 14981db9f3b2SDimitry Andric DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit, 14991db9f3b2SDimitry Andric InputDieEntry, TypeDIEGenerator, 15001db9f3b2SDimitry Andric std::nullopt, std::nullopt, false); 15011db9f3b2SDimitry Andric AttributesCloner.clone(); 15021db9f3b2SDimitry Andric 15031db9f3b2SDimitry Andric // Remember accelerator info. 15041db9f3b2SDimitry Andric AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, 15051db9f3b2SDimitry Andric ArtificialTypeUnit); 15061db9f3b2SDimitry Andric AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo, 15071db9f3b2SDimitry Andric Entry); 15081db9f3b2SDimitry Andric 15091db9f3b2SDimitry Andric // if AttributesCloner.getOutOffset() == 0 then we need to add 15101db9f3b2SDimitry Andric // 1 to avoid assertion for zero size. We will subtract it back later. 15111db9f3b2SDimitry Andric OutDIE->setSize(AttributesCloner.getOutOffset() + 1); 15121db9f3b2SDimitry Andric } 15131db9f3b2SDimitry Andric 15141db9f3b2SDimitry Andric return Entry; 15151db9f3b2SDimitry Andric } 15161db9f3b2SDimitry Andric 15177a6dacacSDimitry Andric Error CompileUnit::cloneAndEmitLineTable(const Triple &TargetTriple) { 15181db9f3b2SDimitry Andric const DWARFDebugLine::LineTable *InputLineTable = 15191db9f3b2SDimitry Andric getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit()); 15201db9f3b2SDimitry Andric if (InputLineTable == nullptr) { 15211db9f3b2SDimitry Andric if (getOrigUnit().getUnitDIE().find(dwarf::DW_AT_stmt_list)) 15221db9f3b2SDimitry Andric warn("cann't load line table."); 15231db9f3b2SDimitry Andric return Error::success(); 15241db9f3b2SDimitry Andric } 15251db9f3b2SDimitry Andric 15261db9f3b2SDimitry Andric DWARFDebugLine::LineTable OutLineTable; 15271db9f3b2SDimitry Andric 15281db9f3b2SDimitry Andric // Set Line Table header. 15291db9f3b2SDimitry Andric OutLineTable.Prologue = InputLineTable->Prologue; 15301db9f3b2SDimitry Andric OutLineTable.Prologue.FormParams.AddrSize = getFormParams().AddrSize; 15311db9f3b2SDimitry Andric 15321db9f3b2SDimitry Andric // Set Line Table Rows. 15331db9f3b2SDimitry Andric if (getGlobalData().getOptions().UpdateIndexTablesOnly) { 15341db9f3b2SDimitry Andric OutLineTable.Rows = InputLineTable->Rows; 15351db9f3b2SDimitry Andric // If all the line table contains is a DW_LNE_end_sequence, clear the line 15361db9f3b2SDimitry Andric // table rows, it will be inserted again in the DWARFStreamer. 15371db9f3b2SDimitry Andric if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence) 15381db9f3b2SDimitry Andric OutLineTable.Rows.clear(); 15391db9f3b2SDimitry Andric 15401db9f3b2SDimitry Andric OutLineTable.Sequences = InputLineTable->Sequences; 15411db9f3b2SDimitry Andric } else { 15421db9f3b2SDimitry Andric // This vector is the output line table. 15431db9f3b2SDimitry Andric std::vector<DWARFDebugLine::Row> NewRows; 15441db9f3b2SDimitry Andric NewRows.reserve(InputLineTable->Rows.size()); 15451db9f3b2SDimitry Andric 15461db9f3b2SDimitry Andric // Current sequence of rows being extracted, before being inserted 15471db9f3b2SDimitry Andric // in NewRows. 15481db9f3b2SDimitry Andric std::vector<DWARFDebugLine::Row> Seq; 15491db9f3b2SDimitry Andric 15501db9f3b2SDimitry Andric const auto &FunctionRanges = getFunctionRanges(); 15511db9f3b2SDimitry Andric std::optional<AddressRangeValuePair> CurrRange; 15521db9f3b2SDimitry Andric 15531db9f3b2SDimitry Andric // FIXME: This logic is meant to generate exactly the same output as 15541db9f3b2SDimitry Andric // Darwin's classic dsymutil. There is a nicer way to implement this 15551db9f3b2SDimitry Andric // by simply putting all the relocated line info in NewRows and simply 15561db9f3b2SDimitry Andric // sorting NewRows before passing it to emitLineTableForUnit. This 15571db9f3b2SDimitry Andric // should be correct as sequences for a function should stay 15581db9f3b2SDimitry Andric // together in the sorted output. There are a few corner cases that 15591db9f3b2SDimitry Andric // look suspicious though, and that required to implement the logic 15601db9f3b2SDimitry Andric // this way. Revisit that once initial validation is finished. 15611db9f3b2SDimitry Andric 15621db9f3b2SDimitry Andric // Iterate over the object file line info and extract the sequences 15631db9f3b2SDimitry Andric // that correspond to linked functions. 15641db9f3b2SDimitry Andric for (DWARFDebugLine::Row Row : InputLineTable->Rows) { 15651db9f3b2SDimitry Andric // Check whether we stepped out of the range. The range is 15661db9f3b2SDimitry Andric // half-open, but consider accept the end address of the range if 15671db9f3b2SDimitry Andric // it is marked as end_sequence in the input (because in that 15681db9f3b2SDimitry Andric // case, the relocation offset is accurate and that entry won't 15691db9f3b2SDimitry Andric // serve as the start of another function). 15701db9f3b2SDimitry Andric if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) { 15711db9f3b2SDimitry Andric // We just stepped out of a known range. Insert a end_sequence 15721db9f3b2SDimitry Andric // corresponding to the end of the range. 15731db9f3b2SDimitry Andric uint64_t StopAddress = 15741db9f3b2SDimitry Andric CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL; 15751db9f3b2SDimitry Andric CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address); 15761db9f3b2SDimitry Andric if (StopAddress != -1ULL && !Seq.empty()) { 15771db9f3b2SDimitry Andric // Insert end sequence row with the computed end address, but 15781db9f3b2SDimitry Andric // the same line as the previous one. 15791db9f3b2SDimitry Andric auto NextLine = Seq.back(); 15801db9f3b2SDimitry Andric NextLine.Address.Address = StopAddress; 15811db9f3b2SDimitry Andric NextLine.EndSequence = 1; 15821db9f3b2SDimitry Andric NextLine.PrologueEnd = 0; 15831db9f3b2SDimitry Andric NextLine.BasicBlock = 0; 15841db9f3b2SDimitry Andric NextLine.EpilogueBegin = 0; 15851db9f3b2SDimitry Andric Seq.push_back(NextLine); 15861db9f3b2SDimitry Andric insertLineSequence(Seq, NewRows); 15871db9f3b2SDimitry Andric } 15881db9f3b2SDimitry Andric 15891db9f3b2SDimitry Andric if (!CurrRange) 15901db9f3b2SDimitry Andric continue; 15911db9f3b2SDimitry Andric } 15921db9f3b2SDimitry Andric 15931db9f3b2SDimitry Andric // Ignore empty sequences. 15941db9f3b2SDimitry Andric if (Row.EndSequence && Seq.empty()) 15951db9f3b2SDimitry Andric continue; 15961db9f3b2SDimitry Andric 15971db9f3b2SDimitry Andric // Relocate row address and add it to the current sequence. 15981db9f3b2SDimitry Andric Row.Address.Address += CurrRange->Value; 15991db9f3b2SDimitry Andric Seq.emplace_back(Row); 16001db9f3b2SDimitry Andric 16011db9f3b2SDimitry Andric if (Row.EndSequence) 16021db9f3b2SDimitry Andric insertLineSequence(Seq, NewRows); 16031db9f3b2SDimitry Andric } 16041db9f3b2SDimitry Andric 16051db9f3b2SDimitry Andric OutLineTable.Rows = std::move(NewRows); 16061db9f3b2SDimitry Andric } 16071db9f3b2SDimitry Andric 16081db9f3b2SDimitry Andric return emitDebugLine(TargetTriple, OutLineTable); 16091db9f3b2SDimitry Andric } 16101db9f3b2SDimitry Andric 16111db9f3b2SDimitry Andric void CompileUnit::insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq, 16121db9f3b2SDimitry Andric std::vector<DWARFDebugLine::Row> &Rows) { 16131db9f3b2SDimitry Andric if (Seq.empty()) 16141db9f3b2SDimitry Andric return; 16151db9f3b2SDimitry Andric 16161db9f3b2SDimitry Andric if (!Rows.empty() && Rows.back().Address < Seq.front().Address) { 16171db9f3b2SDimitry Andric llvm::append_range(Rows, Seq); 16181db9f3b2SDimitry Andric Seq.clear(); 16191db9f3b2SDimitry Andric return; 16201db9f3b2SDimitry Andric } 16211db9f3b2SDimitry Andric 16221db9f3b2SDimitry Andric object::SectionedAddress Front = Seq.front().Address; 16231db9f3b2SDimitry Andric auto InsertPoint = partition_point( 16241db9f3b2SDimitry Andric Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; }); 16251db9f3b2SDimitry Andric 16261db9f3b2SDimitry Andric // FIXME: this only removes the unneeded end_sequence if the 16271db9f3b2SDimitry Andric // sequences have been inserted in order. Using a global sort like 16281db9f3b2SDimitry Andric // described in cloneAndEmitLineTable() and delaying the end_sequene 16291db9f3b2SDimitry Andric // elimination to DebugLineEmitter::emit() we can get rid of all of them. 16301db9f3b2SDimitry Andric if (InsertPoint != Rows.end() && InsertPoint->Address == Front && 16311db9f3b2SDimitry Andric InsertPoint->EndSequence) { 16321db9f3b2SDimitry Andric *InsertPoint = Seq.front(); 16331db9f3b2SDimitry Andric Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end()); 16341db9f3b2SDimitry Andric } else { 16351db9f3b2SDimitry Andric Rows.insert(InsertPoint, Seq.begin(), Seq.end()); 16361db9f3b2SDimitry Andric } 16371db9f3b2SDimitry Andric 16381db9f3b2SDimitry Andric Seq.clear(); 16391db9f3b2SDimitry Andric } 16401db9f3b2SDimitry Andric 16411db9f3b2SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 16421db9f3b2SDimitry Andric LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() { 16431db9f3b2SDimitry Andric llvm::errs() << "{"; 16441db9f3b2SDimitry Andric llvm::errs() << " Placement: "; 16451db9f3b2SDimitry Andric switch (getPlacement()) { 16461db9f3b2SDimitry Andric case NotSet: 16471db9f3b2SDimitry Andric llvm::errs() << "NotSet"; 16481db9f3b2SDimitry Andric break; 16491db9f3b2SDimitry Andric case TypeTable: 16501db9f3b2SDimitry Andric llvm::errs() << "TypeTable"; 16511db9f3b2SDimitry Andric break; 16521db9f3b2SDimitry Andric case PlainDwarf: 16531db9f3b2SDimitry Andric llvm::errs() << "PlainDwarf"; 16541db9f3b2SDimitry Andric break; 16551db9f3b2SDimitry Andric case Both: 16561db9f3b2SDimitry Andric llvm::errs() << "Both"; 16571db9f3b2SDimitry Andric break; 16581db9f3b2SDimitry Andric } 16591db9f3b2SDimitry Andric 16601db9f3b2SDimitry Andric llvm::errs() << " Keep: " << getKeep(); 16611db9f3b2SDimitry Andric llvm::errs() << " KeepPlainChildren: " << getKeepPlainChildren(); 16621db9f3b2SDimitry Andric llvm::errs() << " KeepTypeChildren: " << getKeepTypeChildren(); 16631db9f3b2SDimitry Andric llvm::errs() << " IsInMouduleScope: " << getIsInMouduleScope(); 16641db9f3b2SDimitry Andric llvm::errs() << " IsInFunctionScope: " << getIsInFunctionScope(); 16651db9f3b2SDimitry Andric llvm::errs() << " IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope(); 16661db9f3b2SDimitry Andric llvm::errs() << " ODRAvailable: " << getODRAvailable(); 16671db9f3b2SDimitry Andric llvm::errs() << " TrackLiveness: " << getTrackLiveness(); 16681db9f3b2SDimitry Andric llvm::errs() << "}\n"; 16691db9f3b2SDimitry Andric } 16701db9f3b2SDimitry Andric #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 16711db9f3b2SDimitry Andric 16721db9f3b2SDimitry Andric std::optional<std::pair<StringRef, StringRef>> 16731db9f3b2SDimitry Andric CompileUnit::getDirAndFilenameFromLineTable( 16741db9f3b2SDimitry Andric const DWARFFormValue &FileIdxValue) { 16751db9f3b2SDimitry Andric uint64_t FileIdx; 16761db9f3b2SDimitry Andric if (std::optional<uint64_t> Val = FileIdxValue.getAsUnsignedConstant()) 16771db9f3b2SDimitry Andric FileIdx = *Val; 16781db9f3b2SDimitry Andric else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant()) 16791db9f3b2SDimitry Andric FileIdx = *Val; 16801db9f3b2SDimitry Andric else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset()) 16811db9f3b2SDimitry Andric FileIdx = *Val; 16821db9f3b2SDimitry Andric else 16831db9f3b2SDimitry Andric return std::nullopt; 16841db9f3b2SDimitry Andric 16851db9f3b2SDimitry Andric return getDirAndFilenameFromLineTable(FileIdx); 16861db9f3b2SDimitry Andric } 16871db9f3b2SDimitry Andric 16881db9f3b2SDimitry Andric std::optional<std::pair<StringRef, StringRef>> 16891db9f3b2SDimitry Andric CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) { 16901db9f3b2SDimitry Andric FileNamesCache::iterator FileData = FileNames.find(FileIdx); 16911db9f3b2SDimitry Andric if (FileData != FileNames.end()) 16921db9f3b2SDimitry Andric return std::make_pair(StringRef(FileData->second.first), 16931db9f3b2SDimitry Andric StringRef(FileData->second.second)); 16941db9f3b2SDimitry Andric 16951db9f3b2SDimitry Andric if (const DWARFDebugLine::LineTable *LineTable = 16961db9f3b2SDimitry Andric getOrigUnit().getContext().getLineTableForUnit(&getOrigUnit())) { 16971db9f3b2SDimitry Andric if (LineTable->hasFileAtIndex(FileIdx)) { 16981db9f3b2SDimitry Andric 16991db9f3b2SDimitry Andric const llvm::DWARFDebugLine::FileNameEntry &Entry = 17001db9f3b2SDimitry Andric LineTable->Prologue.getFileNameEntry(FileIdx); 17011db9f3b2SDimitry Andric 17021db9f3b2SDimitry Andric Expected<const char *> Name = Entry.Name.getAsCString(); 17031db9f3b2SDimitry Andric if (!Name) { 17041db9f3b2SDimitry Andric warn(Name.takeError()); 17051db9f3b2SDimitry Andric return std::nullopt; 17061db9f3b2SDimitry Andric } 17071db9f3b2SDimitry Andric 17081db9f3b2SDimitry Andric std::string FileName = *Name; 17091db9f3b2SDimitry Andric if (isPathAbsoluteOnWindowsOrPosix(FileName)) { 17101db9f3b2SDimitry Andric FileNamesCache::iterator FileData = 17111db9f3b2SDimitry Andric FileNames 17121db9f3b2SDimitry Andric .insert(std::make_pair( 17131db9f3b2SDimitry Andric FileIdx, 17141db9f3b2SDimitry Andric std::make_pair(std::string(""), std::move(FileName)))) 17151db9f3b2SDimitry Andric .first; 17161db9f3b2SDimitry Andric return std::make_pair(StringRef(FileData->second.first), 17171db9f3b2SDimitry Andric StringRef(FileData->second.second)); 17181db9f3b2SDimitry Andric } 17191db9f3b2SDimitry Andric 17201db9f3b2SDimitry Andric SmallString<256> FilePath; 17211db9f3b2SDimitry Andric StringRef IncludeDir; 17221db9f3b2SDimitry Andric // Be defensive about the contents of Entry. 17231db9f3b2SDimitry Andric if (getVersion() >= 5) { 17241db9f3b2SDimitry Andric // DirIdx 0 is the compilation directory, so don't include it for 17251db9f3b2SDimitry Andric // relative names. 17261db9f3b2SDimitry Andric if ((Entry.DirIdx != 0) && 17271db9f3b2SDimitry Andric Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) { 17281db9f3b2SDimitry Andric Expected<const char *> DirName = 17291db9f3b2SDimitry Andric LineTable->Prologue.IncludeDirectories[Entry.DirIdx] 17301db9f3b2SDimitry Andric .getAsCString(); 17311db9f3b2SDimitry Andric if (DirName) 17321db9f3b2SDimitry Andric IncludeDir = *DirName; 17331db9f3b2SDimitry Andric else { 17341db9f3b2SDimitry Andric warn(DirName.takeError()); 17351db9f3b2SDimitry Andric return std::nullopt; 17361db9f3b2SDimitry Andric } 17371db9f3b2SDimitry Andric } 17381db9f3b2SDimitry Andric } else { 17391db9f3b2SDimitry Andric if (0 < Entry.DirIdx && 17401db9f3b2SDimitry Andric Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) { 17411db9f3b2SDimitry Andric Expected<const char *> DirName = 17421db9f3b2SDimitry Andric LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1] 17431db9f3b2SDimitry Andric .getAsCString(); 17441db9f3b2SDimitry Andric if (DirName) 17451db9f3b2SDimitry Andric IncludeDir = *DirName; 17461db9f3b2SDimitry Andric else { 17471db9f3b2SDimitry Andric warn(DirName.takeError()); 17481db9f3b2SDimitry Andric return std::nullopt; 17491db9f3b2SDimitry Andric } 17501db9f3b2SDimitry Andric } 17511db9f3b2SDimitry Andric } 17521db9f3b2SDimitry Andric 17531db9f3b2SDimitry Andric StringRef CompDir = getOrigUnit().getCompilationDir(); 17541db9f3b2SDimitry Andric 17551db9f3b2SDimitry Andric if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) { 17561db9f3b2SDimitry Andric sys::path::append(FilePath, sys::path::Style::native, CompDir); 17571db9f3b2SDimitry Andric } 17581db9f3b2SDimitry Andric 17591db9f3b2SDimitry Andric sys::path::append(FilePath, sys::path::Style::native, IncludeDir); 17601db9f3b2SDimitry Andric 17611db9f3b2SDimitry Andric FileNamesCache::iterator FileData = 17621db9f3b2SDimitry Andric FileNames 17631db9f3b2SDimitry Andric .insert( 17641db9f3b2SDimitry Andric std::make_pair(FileIdx, std::make_pair(std::string(FilePath), 17651db9f3b2SDimitry Andric std::move(FileName)))) 17661db9f3b2SDimitry Andric .first; 17671db9f3b2SDimitry Andric return std::make_pair(StringRef(FileData->second.first), 17681db9f3b2SDimitry Andric StringRef(FileData->second.second)); 17691db9f3b2SDimitry Andric } 17701db9f3b2SDimitry Andric } 17711db9f3b2SDimitry Andric 17721db9f3b2SDimitry Andric return std::nullopt; 17731db9f3b2SDimitry Andric } 17741db9f3b2SDimitry Andric 17751db9f3b2SDimitry Andric #define MAX_REFERENCIES_DEPTH 1000 17761db9f3b2SDimitry Andric UnitEntryPairTy UnitEntryPairTy::getNamespaceOrigin() { 17771db9f3b2SDimitry Andric UnitEntryPairTy CUDiePair(*this); 17781db9f3b2SDimitry Andric std::optional<UnitEntryPairTy> RefDiePair; 17791db9f3b2SDimitry Andric int refDepth = 0; 17801db9f3b2SDimitry Andric do { 17811db9f3b2SDimitry Andric RefDiePair = CUDiePair.CU->resolveDIEReference( 17821db9f3b2SDimitry Andric CUDiePair.DieEntry, dwarf::DW_AT_extension, 17831db9f3b2SDimitry Andric ResolveInterCUReferencesMode::Resolve); 17841db9f3b2SDimitry Andric if (!RefDiePair || !RefDiePair->DieEntry) 17851db9f3b2SDimitry Andric return CUDiePair; 17861db9f3b2SDimitry Andric 17871db9f3b2SDimitry Andric CUDiePair = *RefDiePair; 17881db9f3b2SDimitry Andric } while (refDepth++ < MAX_REFERENCIES_DEPTH); 17891db9f3b2SDimitry Andric 17901db9f3b2SDimitry Andric return CUDiePair; 17911db9f3b2SDimitry Andric } 17921db9f3b2SDimitry Andric 17931db9f3b2SDimitry Andric std::optional<UnitEntryPairTy> UnitEntryPairTy::getParent() { 17941db9f3b2SDimitry Andric if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx()) 17951db9f3b2SDimitry Andric return UnitEntryPairTy{CU, CU->getDebugInfoEntry(*ParentIdx)}; 17961db9f3b2SDimitry Andric 17971db9f3b2SDimitry Andric return std::nullopt; 17981db9f3b2SDimitry Andric } 17991db9f3b2SDimitry Andric 18001db9f3b2SDimitry Andric CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(CompileUnit *U) 18011db9f3b2SDimitry Andric : Ptr(U) { 18021db9f3b2SDimitry Andric assert(U != nullptr); 18031db9f3b2SDimitry Andric } 18041db9f3b2SDimitry Andric 18051db9f3b2SDimitry Andric CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(TypeUnit *U) : Ptr(U) { 18061db9f3b2SDimitry Andric assert(U != nullptr); 18071db9f3b2SDimitry Andric } 18081db9f3b2SDimitry Andric 18091db9f3b2SDimitry Andric DwarfUnit *CompileUnit::OutputUnitVariantPtr::operator->() { 18101db9f3b2SDimitry Andric if (isCompileUnit()) 18111db9f3b2SDimitry Andric return getAsCompileUnit(); 18121db9f3b2SDimitry Andric else 18131db9f3b2SDimitry Andric return getAsTypeUnit(); 18141db9f3b2SDimitry Andric } 18151db9f3b2SDimitry Andric 18161db9f3b2SDimitry Andric bool CompileUnit::OutputUnitVariantPtr::isCompileUnit() { 18171db9f3b2SDimitry Andric return Ptr.is<CompileUnit *>(); 18181db9f3b2SDimitry Andric } 18191db9f3b2SDimitry Andric 18201db9f3b2SDimitry Andric bool CompileUnit::OutputUnitVariantPtr::isTypeUnit() { 18211db9f3b2SDimitry Andric return Ptr.is<TypeUnit *>(); 18221db9f3b2SDimitry Andric } 18231db9f3b2SDimitry Andric 18241db9f3b2SDimitry Andric CompileUnit *CompileUnit::OutputUnitVariantPtr::getAsCompileUnit() { 18251db9f3b2SDimitry Andric return Ptr.get<CompileUnit *>(); 18261db9f3b2SDimitry Andric } 18271db9f3b2SDimitry Andric 18281db9f3b2SDimitry Andric TypeUnit *CompileUnit::OutputUnitVariantPtr::getAsTypeUnit() { 18291db9f3b2SDimitry Andric return Ptr.get<TypeUnit *>(); 18301db9f3b2SDimitry Andric } 18311db9f3b2SDimitry Andric 18321db9f3b2SDimitry Andric bool CompileUnit::resolveDependenciesAndMarkLiveness( 18331db9f3b2SDimitry Andric bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) { 1834*0fca6ea1SDimitry Andric if (!Dependencies) 18351db9f3b2SDimitry Andric Dependencies.reset(new DependencyTracker(*this)); 18361db9f3b2SDimitry Andric 18371db9f3b2SDimitry Andric return Dependencies->resolveDependenciesAndMarkLiveness( 18381db9f3b2SDimitry Andric InterCUProcessingStarted, HasNewInterconnectedCUs); 18391db9f3b2SDimitry Andric } 18401db9f3b2SDimitry Andric 18411db9f3b2SDimitry Andric bool CompileUnit::updateDependenciesCompleteness() { 18421db9f3b2SDimitry Andric assert(Dependencies.get()); 18431db9f3b2SDimitry Andric 1844*0fca6ea1SDimitry Andric return Dependencies->updateDependenciesCompleteness(); 18451db9f3b2SDimitry Andric } 18461db9f3b2SDimitry Andric 18471db9f3b2SDimitry Andric void CompileUnit::verifyDependencies() { 18481db9f3b2SDimitry Andric assert(Dependencies.get()); 18491db9f3b2SDimitry Andric 1850*0fca6ea1SDimitry Andric Dependencies->verifyKeepChain(); 18511db9f3b2SDimitry Andric } 18521db9f3b2SDimitry Andric 18531db9f3b2SDimitry Andric ArrayRef<dwarf::Attribute> dwarf_linker::parallel::getODRAttributes() { 18541db9f3b2SDimitry Andric static dwarf::Attribute ODRAttributes[] = { 18551db9f3b2SDimitry Andric dwarf::DW_AT_type, dwarf::DW_AT_specification, 18561db9f3b2SDimitry Andric dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import}; 18571db9f3b2SDimitry Andric 18581db9f3b2SDimitry Andric return ODRAttributes; 18591db9f3b2SDimitry Andric } 1860