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
CompileUnit(LinkingGlobalData & GlobalData,unsigned ID,StringRef ClangModuleName,DWARFFile & File,OffsetToUnitTy UnitFromOffset,dwarf::FormParams Format,llvm::endianness Endianess)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
CompileUnit(LinkingGlobalData & GlobalData,DWARFUnit & OrigUnit,unsigned ID,StringRef ClangModuleName,DWARFFile & File,OffsetToUnitTy UnitFromOffset,dwarf::FormParams Format,llvm::endianness Endianess)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
loadLineTable()711db9f3b2SDimitry Andric void CompileUnit::loadLineTable() {
721db9f3b2SDimitry Andric LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());
731db9f3b2SDimitry Andric }
741db9f3b2SDimitry Andric
maybeResetToLoadedStage()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
loadInputDIEs()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
analyzeDWARFStructureRec(const DWARFDebugInfoEntry * DieEntry,bool IsODRUnavailableFunctionScope)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
getFileName(unsigned FileIdx,StringPool & GlobalStrings)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
cleanupDataAfterClonning()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.
analyzeImportedModule(const DWARFDebugInfoEntry * DieEntry)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
assignTypeNames(TypePool & TypePoolRef)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
assignTypeNamesRec(const DWARFDebugInfoEntry * DieEntry,SyntheticTypeNameBuilder & NameBuilder)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
updateDieRefPatchesWithClonedOffsets()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
resolveDIEReference(const DWARFFormValue & RefValue,ResolveInterCUReferencesMode CanResolveInterCUReferences)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
resolveDIEReference(const DWARFDebugInfoEntry * DieEntry,dwarf::Attribute Attr,ResolveInterCUReferencesMode CanResolveInterCUReferences)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
addFunctionRange(uint64_t FuncLowPc,uint64_t FuncHighPc,int64_t PcOffset)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
addLabelLowPc(uint64_t LabelLowPc,int64_t PcOffset)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
cloneAndEmitDebugLocations()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
emitLocations(DebugSectionKind LocationSectionKind)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.
emitLocListHeader(SectionDescriptor & OutLocationSection)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.
emitLocListFragment(const LinkedLocationExpressionsVector & LinkedLocationExpression,SectionDescriptor & OutLocationSection)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
emitDebugAddrSection()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
cloneAndEmitRanges()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
cloneAndEmitRangeList(DebugSectionKind RngSectionKind,AddressRanges & LinkedFunctionRanges)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
emitRangeListHeader(SectionDescriptor & OutRangeSection)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
emitRangeListFragment(const AddressRanges & LinkedRanges,SectionDescriptor & OutRangeSection)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
emitAranges(AddressRanges & LinkedFunctionRanges)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
cloneAndEmitDebugMacro()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
emitMacroTableImpl(const DWARFDebugMacro * MacroTable,uint64_t OffsetToMacroTable,bool hasDWARFv5Header)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
cloneDieAttrExpression(const DWARFExpression & InputExpression,SmallVectorImpl<uint8_t> & OutputExpression,SectionDescriptor & Section,std::optional<int64_t> VarAddressAdjustment,OffsetsPtrVector & PatchesOffsets)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
cloneAndEmit(std::optional<std::reference_wrapper<const Triple>> TargetTriple,TypeUnit * ArtificialTypeUnit)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
cloneDIE(const DWARFDebugInfoEntry * InputDieEntry,TypeEntry * ClonedParentTypeDIE,uint64_t OutOffset,std::optional<int64_t> FuncAddressAdjustment,std::optional<int64_t> VarAddressAdjustment,BumpPtrAllocator & Allocator,TypeUnit * ArtificialTypeUnit)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
createPlainDIEandCloneAttributes(const DWARFDebugInfoEntry * InputDieEntry,DIEGenerator & PlainDIEGenerator,uint64_t & OutOffset,std::optional<int64_t> & FuncAddressAdjustment,std::optional<int64_t> & VarAddressAdjustment)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.
allocateTypeDie(TypeEntryBody * TypeDescriptor,DIEGenerator & TypeDIEGenerator,dwarf::Tag DieTag,bool IsDeclaration,bool IsParentDeclaration)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
createTypeDIEandCloneAttributes(const DWARFDebugInfoEntry * InputDieEntry,DIEGenerator & TypeDIEGenerator,TypeEntry * ClonedParentTypeDIE,TypeUnit * ArtificialTypeUnit)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
cloneAndEmitLineTable(const Triple & TargetTriple)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
insertLineSequence(std::vector<DWARFDebugLine::Row> & Seq,std::vector<DWARFDebugLine::Row> & Rows)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)
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>>
getDirAndFilenameFromLineTable(const DWARFFormValue & FileIdxValue)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>>
getDirAndFilenameFromLineTable(uint64_t FileIdx)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
getNamespaceOrigin()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
getParent()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
OutputUnitVariantPtr(CompileUnit * U)18001db9f3b2SDimitry Andric CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(CompileUnit *U)
18011db9f3b2SDimitry Andric : Ptr(U) {
18021db9f3b2SDimitry Andric assert(U != nullptr);
18031db9f3b2SDimitry Andric }
18041db9f3b2SDimitry Andric
OutputUnitVariantPtr(TypeUnit * U)18051db9f3b2SDimitry Andric CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(TypeUnit *U) : Ptr(U) {
18061db9f3b2SDimitry Andric assert(U != nullptr);
18071db9f3b2SDimitry Andric }
18081db9f3b2SDimitry Andric
operator ->()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
isCompileUnit()18161db9f3b2SDimitry Andric bool CompileUnit::OutputUnitVariantPtr::isCompileUnit() {
18171db9f3b2SDimitry Andric return Ptr.is<CompileUnit *>();
18181db9f3b2SDimitry Andric }
18191db9f3b2SDimitry Andric
isTypeUnit()18201db9f3b2SDimitry Andric bool CompileUnit::OutputUnitVariantPtr::isTypeUnit() {
18211db9f3b2SDimitry Andric return Ptr.is<TypeUnit *>();
18221db9f3b2SDimitry Andric }
18231db9f3b2SDimitry Andric
getAsCompileUnit()18241db9f3b2SDimitry Andric CompileUnit *CompileUnit::OutputUnitVariantPtr::getAsCompileUnit() {
18251db9f3b2SDimitry Andric return Ptr.get<CompileUnit *>();
18261db9f3b2SDimitry Andric }
18271db9f3b2SDimitry Andric
getAsTypeUnit()18281db9f3b2SDimitry Andric TypeUnit *CompileUnit::OutputUnitVariantPtr::getAsTypeUnit() {
18291db9f3b2SDimitry Andric return Ptr.get<TypeUnit *>();
18301db9f3b2SDimitry Andric }
18311db9f3b2SDimitry Andric
resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted,std::atomic<bool> & HasNewInterconnectedCUs)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
updateDependenciesCompleteness()18411db9f3b2SDimitry Andric bool CompileUnit::updateDependenciesCompleteness() {
18421db9f3b2SDimitry Andric assert(Dependencies.get());
18431db9f3b2SDimitry Andric
1844*0fca6ea1SDimitry Andric return Dependencies->updateDependenciesCompleteness();
18451db9f3b2SDimitry Andric }
18461db9f3b2SDimitry Andric
verifyDependencies()18471db9f3b2SDimitry Andric void CompileUnit::verifyDependencies() {
18481db9f3b2SDimitry Andric assert(Dependencies.get());
18491db9f3b2SDimitry Andric
1850*0fca6ea1SDimitry Andric Dependencies->verifyKeepChain();
18511db9f3b2SDimitry Andric }
18521db9f3b2SDimitry Andric
getODRAttributes()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