Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
35291 views
//=== DWARFLinkerCompileUnit.cpp ------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "DWARFLinkerCompileUnit.h"9#include "AcceleratorRecordsSaver.h"10#include "DIEAttributeCloner.h"11#include "DIEGenerator.h"12#include "DependencyTracker.h"13#include "SyntheticTypeNameBuilder.h"14#include "llvm/DWARFLinker/Utils.h"15#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"16#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"17#include "llvm/Support/DJB.h"18#include "llvm/Support/FileSystem.h"19#include "llvm/Support/FormatVariadic.h"20#include "llvm/Support/Path.h"21#include <utility>2223using namespace llvm;24using namespace dwarf_linker;25using namespace dwarf_linker::parallel;2627CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,28StringRef ClangModuleName, DWARFFile &File,29OffsetToUnitTy UnitFromOffset,30dwarf::FormParams Format, llvm::endianness Endianess)31: DwarfUnit(GlobalData, ID, ClangModuleName), File(File),32getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded),33AcceleratorRecords(&GlobalData.getAllocator()) {34UnitName = File.FileName;35setOutputFormat(Format, Endianess);36getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);37}3839CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit,40unsigned ID, StringRef ClangModuleName,41DWARFFile &File, OffsetToUnitTy UnitFromOffset,42dwarf::FormParams Format, llvm::endianness Endianess)43: DwarfUnit(GlobalData, ID, ClangModuleName), File(File),44OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),45Stage(Stage::CreatedNotLoaded),46AcceleratorRecords(&GlobalData.getAllocator()) {47setOutputFormat(Format, Endianess);48getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);4950DWARFDie CUDie = OrigUnit.getUnitDIE();51if (!CUDie)52return;5354if (std::optional<DWARFFormValue> Val = CUDie.find(dwarf::DW_AT_language)) {55uint16_t LangVal = dwarf::toUnsigned(Val, 0);56if (isODRLanguage(LangVal))57Language = LangVal;58}5960if (!GlobalData.getOptions().NoODR && Language.has_value())61NoODR = false;6263if (const char *CUName = CUDie.getName(DINameKind::ShortName))64UnitName = CUName;65else66UnitName = File.FileName;67SysRoot = dwarf::toStringRef(CUDie.find(dwarf::DW_AT_LLVM_sysroot)).str();68}6970void CompileUnit::loadLineTable() {71LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());72}7374void CompileUnit::maybeResetToLoadedStage() {75// Nothing to reset if stage is less than "Loaded".76if (getStage() < Stage::Loaded)77return;7879// Note: We need to do erasing for "Loaded" stage because80// if live analysys failed then we will have "Loaded" stage81// with marking from "LivenessAnalysisDone" stage partially82// done. That marking should be cleared.8384for (DIEInfo &Info : DieInfoArray)85Info.unsetFlagsWhichSetDuringLiveAnalysis();8687LowPc = std::nullopt;88HighPc = 0;89Labels.clear();90Ranges.clear();91Dependencies.reset(nullptr);9293if (getStage() < Stage::Cloned) {94setStage(Stage::Loaded);95return;96}9798AcceleratorRecords.erase();99AbbreviationsSet.clear();100Abbreviations.clear();101OutUnitDIE = nullptr;102DebugAddrIndexMap.clear();103104for (uint64_t &Offset : OutDieOffsetArray)105Offset = 0;106for (TypeEntry *&Name : TypeEntries)107Name = nullptr;108eraseSections();109110setStage(Stage::CreatedNotLoaded);111}112113bool CompileUnit::loadInputDIEs() {114DWARFDie InputUnitDIE = getUnitDIE(false);115if (!InputUnitDIE)116return false;117118// load input dies, resize Info structures array.119DieInfoArray.resize(getOrigUnit().getNumDIEs());120OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);121if (!NoODR)122TypeEntries.resize(getOrigUnit().getNumDIEs());123return true;124}125126void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,127bool IsODRUnavailableFunctionScope) {128CompileUnit::DIEInfo &DieInfo = getDIEInfo(DieEntry);129130for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);131CurChild && CurChild->getAbbreviationDeclarationPtr();132CurChild = getSiblingEntry(CurChild)) {133CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);134bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;135136if (DieInfo.getIsInMouduleScope())137ChildInfo.setIsInMouduleScope();138139if (DieInfo.getIsInFunctionScope())140ChildInfo.setIsInFunctionScope();141142if (DieInfo.getIsInAnonNamespaceScope())143ChildInfo.setIsInAnonNamespaceScope();144145switch (CurChild->getTag()) {146case dwarf::DW_TAG_module:147ChildInfo.setIsInMouduleScope();148if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit &&149dwarf::toString(find(CurChild, dwarf::DW_AT_name), "") !=150getClangModuleName())151analyzeImportedModule(CurChild);152break;153case dwarf::DW_TAG_subprogram:154ChildInfo.setIsInFunctionScope();155if (!ChildIsODRUnavailableFunctionScope &&156!ChildInfo.getIsInMouduleScope()) {157if (find(CurChild,158{dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))159ChildIsODRUnavailableFunctionScope = true;160}161break;162case dwarf::DW_TAG_namespace: {163UnitEntryPairTy NamespaceEntry = {this, CurChild};164165if (find(CurChild, dwarf::DW_AT_extension))166NamespaceEntry = NamespaceEntry.getNamespaceOrigin();167168if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))169ChildInfo.setIsInAnonNamespaceScope();170} break;171default:172break;173}174175if (!isClangModule() && !getGlobalData().getOptions().UpdateIndexTablesOnly)176ChildInfo.setTrackLiveness();177178if ((!ChildInfo.getIsInAnonNamespaceScope() &&179!ChildIsODRUnavailableFunctionScope && !NoODR))180ChildInfo.setODRAvailable();181182if (CurChild->hasChildren())183analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);184}185}186187StringEntry *CompileUnit::getFileName(unsigned FileIdx,188StringPool &GlobalStrings) {189if (LineTablePtr) {190if (LineTablePtr->hasFileAtIndex(FileIdx)) {191// Cache the resolved paths based on the index in the line table,192// because calling realpath is expensive.193ResolvedPathsMap::const_iterator It = ResolvedFullPaths.find(FileIdx);194if (It == ResolvedFullPaths.end()) {195std::string OrigFileName;196bool FoundFileName = LineTablePtr->getFileNameByIndex(197FileIdx, getOrigUnit().getCompilationDir(),198DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,199OrigFileName);200(void)FoundFileName;201assert(FoundFileName && "Must get file name from line table");202203// Second level of caching, this time based on the file's parent204// path.205StringRef FileName = sys::path::filename(OrigFileName);206StringRef ParentPath = sys::path::parent_path(OrigFileName);207208// If the ParentPath has not yet been resolved, resolve and cache it for209// future look-ups.210StringMap<StringEntry *>::iterator ParentIt =211ResolvedParentPaths.find(ParentPath);212if (ParentIt == ResolvedParentPaths.end()) {213SmallString<256> RealPath;214sys::fs::real_path(ParentPath, RealPath);215ParentIt =216ResolvedParentPaths217.insert({ParentPath, GlobalStrings.insert(RealPath).first})218.first;219}220221// Join the file name again with the resolved path.222SmallString<256> ResolvedPath(ParentIt->second->first());223sys::path::append(ResolvedPath, FileName);224225It = ResolvedFullPaths226.insert(std::make_pair(227FileIdx, GlobalStrings.insert(ResolvedPath).first))228.first;229}230231return It->second;232}233}234235return nullptr;236}237238void CompileUnit::cleanupDataAfterClonning() {239AbbreviationsSet.clear();240ResolvedFullPaths.shrink_and_clear();241ResolvedParentPaths.clear();242FileNames.shrink_and_clear();243DieInfoArray = SmallVector<DIEInfo>();244OutDieOffsetArray = SmallVector<uint64_t>();245TypeEntries = SmallVector<TypeEntry *>();246Dependencies.reset(nullptr);247getOrigUnit().clear();248}249250/// Collect references to parseable Swift interfaces in imported251/// DW_TAG_module blocks.252void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) {253if (!Language || Language != dwarf::DW_LANG_Swift)254return;255256if (!GlobalData.getOptions().ParseableSwiftInterfaces)257return;258259StringRef Path =260dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_include_path));261if (!Path.ends_with(".swiftinterface"))262return;263// Don't track interfaces that are part of the SDK.264StringRef SysRoot =265dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_sysroot));266if (SysRoot.empty())267SysRoot = getSysRoot();268if (!SysRoot.empty() && Path.starts_with(SysRoot))269return;270// Don't track interfaces that are part of the toolchain.271// For example: Swift, _Concurrency, ...272StringRef DeveloperDir = guessDeveloperDir(SysRoot);273if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))274return;275if (isInToolchainDir(Path))276return;277if (std::optional<DWARFFormValue> Val = find(DieEntry, dwarf::DW_AT_name)) {278Expected<const char *> Name = Val->getAsCString();279if (!Name) {280warn(Name.takeError());281return;282}283284auto &Entry = (*GlobalData.getOptions().ParseableSwiftInterfaces)[*Name];285// The prepend path is applied later when copying.286SmallString<128> ResolvedPath;287if (sys::path::is_relative(Path))288sys::path::append(289ResolvedPath,290dwarf::toString(getUnitDIE().find(dwarf::DW_AT_comp_dir), ""));291sys::path::append(ResolvedPath, Path);292if (!Entry.empty() && Entry != ResolvedPath) {293DWARFDie Die = getDIE(DieEntry);294warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name +295": " + Entry + " and " + Path + ".",296&Die);297}298Entry = std::string(ResolvedPath);299}300}301302Error CompileUnit::assignTypeNames(TypePool &TypePoolRef) {303if (!getUnitDIE().isValid())304return Error::success();305306SyntheticTypeNameBuilder NameBuilder(TypePoolRef);307return assignTypeNamesRec(getDebugInfoEntry(0), NameBuilder);308}309310Error CompileUnit::assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,311SyntheticTypeNameBuilder &NameBuilder) {312OrderedChildrenIndexAssigner ChildrenIndexAssigner(*this, DieEntry);313for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);314CurChild && CurChild->getAbbreviationDeclarationPtr();315CurChild = getSiblingEntry(CurChild)) {316CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);317if (!ChildInfo.needToPlaceInTypeTable())318continue;319320assert(ChildInfo.getODRAvailable());321if (Error Err = NameBuilder.assignName(322{this, CurChild},323ChildrenIndexAssigner.getChildIndex(*this, CurChild)))324return Err;325326if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))327return Err;328}329330return Error::success();331}332333void CompileUnit::updateDieRefPatchesWithClonedOffsets() {334if (std::optional<SectionDescriptor *> DebugInfoSection =335tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) {336337(*DebugInfoSection)338->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {339/// Replace stored DIE indexes with DIE output offsets.340Patch.RefDieIdxOrClonedOffset =341Patch.RefCU.getPointer()->getDieOutOffset(342Patch.RefDieIdxOrClonedOffset);343});344345(*DebugInfoSection)346->ListDebugULEB128DieRefPatch.forEach(347[&](DebugULEB128DieRefPatch &Patch) {348/// Replace stored DIE indexes with DIE output offsets.349Patch.RefDieIdxOrClonedOffset =350Patch.RefCU.getPointer()->getDieOutOffset(351Patch.RefDieIdxOrClonedOffset);352});353}354355if (std::optional<SectionDescriptor *> DebugLocSection =356tryGetSectionDescriptor(DebugSectionKind::DebugLoc)) {357(*DebugLocSection)358->ListDebugULEB128DieRefPatch.forEach(359[](DebugULEB128DieRefPatch &Patch) {360/// Replace stored DIE indexes with DIE output offsets.361Patch.RefDieIdxOrClonedOffset =362Patch.RefCU.getPointer()->getDieOutOffset(363Patch.RefDieIdxOrClonedOffset);364});365}366367if (std::optional<SectionDescriptor *> DebugLocListsSection =368tryGetSectionDescriptor(DebugSectionKind::DebugLocLists)) {369(*DebugLocListsSection)370->ListDebugULEB128DieRefPatch.forEach(371[](DebugULEB128DieRefPatch &Patch) {372/// Replace stored DIE indexes with DIE output offsets.373Patch.RefDieIdxOrClonedOffset =374Patch.RefCU.getPointer()->getDieOutOffset(375Patch.RefDieIdxOrClonedOffset);376});377}378}379380std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(381const DWARFFormValue &RefValue,382ResolveInterCUReferencesMode CanResolveInterCUReferences) {383CompileUnit *RefCU;384uint64_t RefDIEOffset;385if (std::optional<uint64_t> Offset = RefValue.getAsRelativeReference()) {386RefCU = this;387RefDIEOffset = RefValue.getUnit()->getOffset() + *Offset;388} else if (Offset = RefValue.getAsDebugInfoReference(); Offset) {389RefCU = getUnitFromOffset(*Offset);390RefDIEOffset = *Offset;391} else {392return std::nullopt;393}394395if (RefCU == this) {396// Referenced DIE is in current compile unit.397if (std::optional<uint32_t> RefDieIdx = getDIEIndexForOffset(RefDIEOffset))398return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)};399} else if (RefCU && CanResolveInterCUReferences) {400// Referenced DIE is in other compile unit.401402// Check whether DIEs are loaded for that compile unit.403enum Stage ReferredCUStage = RefCU->getStage();404if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)405return UnitEntryPairTy{RefCU, nullptr};406407if (std::optional<uint32_t> RefDieIdx =408RefCU->getDIEIndexForOffset(RefDIEOffset))409return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)};410} else {411return UnitEntryPairTy{RefCU, nullptr};412}413return std::nullopt;414}415416std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(417const DWARFDebugInfoEntry *DieEntry, dwarf::Attribute Attr,418ResolveInterCUReferencesMode CanResolveInterCUReferences) {419if (std::optional<DWARFFormValue> AttrVal = find(DieEntry, Attr))420return resolveDIEReference(*AttrVal, CanResolveInterCUReferences);421422return std::nullopt;423}424425void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,426int64_t PcOffset) {427std::lock_guard<std::mutex> Guard(RangesMutex);428429Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);430if (LowPc)431LowPc = std::min(*LowPc, FuncLowPc + PcOffset);432else433LowPc = FuncLowPc + PcOffset;434this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);435}436437void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {438std::lock_guard<std::mutex> Guard(LabelsMutex);439Labels.insert({LabelLowPc, PcOffset});440}441442Error CompileUnit::cloneAndEmitDebugLocations() {443if (getGlobalData().getOptions().UpdateIndexTablesOnly)444return Error::success();445446if (getOrigUnit().getVersion() < 5) {447emitLocations(DebugSectionKind::DebugLoc);448return Error::success();449}450451emitLocations(DebugSectionKind::DebugLocLists);452return Error::success();453}454455void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {456SectionDescriptor &DebugInfoSection =457getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);458459if (!DebugInfoSection.ListDebugLocPatch.empty()) {460SectionDescriptor &OutLocationSection =461getOrCreateSectionDescriptor(LocationSectionKind);462DWARFUnit &OrigUnit = getOrigUnit();463464uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);465466DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {467// Get location expressions vector corresponding to the current468// attribute from the source DWARF.469uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(470Patch.PatchOffset,471DebugInfoSection.getFormParams().getDwarfOffsetByteSize());472Expected<DWARFLocationExpressionsVector> OriginalLocations =473OrigUnit.findLoclistFromOffset(InputDebugLocSectionOffset);474475if (!OriginalLocations) {476warn(OriginalLocations.takeError());477return;478}479480LinkedLocationExpressionsVector LinkedLocationExpressions;481for (DWARFLocationExpression &CurExpression : *OriginalLocations) {482LinkedLocationExpressionsWithOffsetPatches LinkedExpression;483484if (CurExpression.Range) {485// Relocate address range.486LinkedExpression.Expression.Range = {487CurExpression.Range->LowPC + Patch.AddrAdjustmentValue,488CurExpression.Range->HighPC + Patch.AddrAdjustmentValue};489}490491DataExtractor Data(CurExpression.Expr, OrigUnit.isLittleEndian(),492OrigUnit.getAddressByteSize());493494DWARFExpression InputExpression(Data, OrigUnit.getAddressByteSize(),495OrigUnit.getFormParams().Format);496cloneDieAttrExpression(InputExpression,497LinkedExpression.Expression.Expr,498OutLocationSection, Patch.AddrAdjustmentValue,499LinkedExpression.Patches);500501LinkedLocationExpressions.push_back({LinkedExpression});502}503504// Emit locations list table fragment corresponding to the CurLocAttr.505DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,506OutLocationSection.OS.tell());507emitLocListFragment(LinkedLocationExpressions, OutLocationSection);508});509510if (OffsetAfterUnitLength > 0) {511assert(OffsetAfterUnitLength -512OutLocationSection.getFormParams().getDwarfOffsetByteSize() <513OffsetAfterUnitLength);514OutLocationSection.apply(515OffsetAfterUnitLength -516OutLocationSection.getFormParams().getDwarfOffsetByteSize(),517dwarf::DW_FORM_sec_offset,518OutLocationSection.OS.tell() - OffsetAfterUnitLength);519}520}521}522523/// Emit debug locations(.debug_loc, .debug_loclists) header.524uint64_t CompileUnit::emitLocListHeader(SectionDescriptor &OutLocationSection) {525if (getOrigUnit().getVersion() < 5)526return 0;527528// unit_length.529OutLocationSection.emitUnitLength(0xBADDEF);530uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell();531532// Version.533OutLocationSection.emitIntVal(5, 2);534535// Address size.536OutLocationSection.emitIntVal(OutLocationSection.getFormParams().AddrSize, 1);537538// Seg_size539OutLocationSection.emitIntVal(0, 1);540541// Offset entry count542OutLocationSection.emitIntVal(0, 4);543544return OffsetAfterUnitLength;545}546547/// Emit debug locations(.debug_loc, .debug_loclists) fragment.548uint64_t CompileUnit::emitLocListFragment(549const LinkedLocationExpressionsVector &LinkedLocationExpression,550SectionDescriptor &OutLocationSection) {551uint64_t OffsetBeforeLocationExpression = 0;552553if (getOrigUnit().getVersion() < 5) {554uint64_t BaseAddress = 0;555if (std::optional<uint64_t> LowPC = getLowPc())556BaseAddress = *LowPC;557558for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :559LinkedLocationExpression) {560if (LocExpression.Expression.Range) {561OutLocationSection.emitIntVal(562LocExpression.Expression.Range->LowPC - BaseAddress,563OutLocationSection.getFormParams().AddrSize);564OutLocationSection.emitIntVal(565LocExpression.Expression.Range->HighPC - BaseAddress,566OutLocationSection.getFormParams().AddrSize);567}568569OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2);570OffsetBeforeLocationExpression = OutLocationSection.OS.tell();571for (uint64_t *OffsetPtr : LocExpression.Patches)572*OffsetPtr += OffsetBeforeLocationExpression;573574OutLocationSection.OS575<< StringRef((const char *)LocExpression.Expression.Expr.data(),576LocExpression.Expression.Expr.size());577}578579// Emit the terminator entry.580OutLocationSection.emitIntVal(0,581OutLocationSection.getFormParams().AddrSize);582OutLocationSection.emitIntVal(0,583OutLocationSection.getFormParams().AddrSize);584return OffsetBeforeLocationExpression;585}586587std::optional<uint64_t> BaseAddress;588for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :589LinkedLocationExpression) {590if (LocExpression.Expression.Range) {591// Check whether base address is set. If it is not set yet592// then set current base address and emit base address selection entry.593if (!BaseAddress) {594BaseAddress = LocExpression.Expression.Range->LowPC;595596// Emit base address.597OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1);598encodeULEB128(DebugAddrIndexMap.getValueIndex(*BaseAddress),599OutLocationSection.OS);600}601602// Emit type of entry.603OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1);604605// Emit start offset relative to base address.606encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,607OutLocationSection.OS);608609// Emit end offset relative to base address.610encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,611OutLocationSection.OS);612} else613// Emit type of entry.614OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1);615616encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS);617OffsetBeforeLocationExpression = OutLocationSection.OS.tell();618for (uint64_t *OffsetPtr : LocExpression.Patches)619*OffsetPtr += OffsetBeforeLocationExpression;620621OutLocationSection.OS << StringRef(622(const char *)LocExpression.Expression.Expr.data(),623LocExpression.Expression.Expr.size());624}625626// Emit the terminator entry.627OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1);628return OffsetBeforeLocationExpression;629}630631Error CompileUnit::emitDebugAddrSection() {632if (GlobalData.getOptions().UpdateIndexTablesOnly)633return Error::success();634635if (getVersion() < 5)636return Error::success();637638if (DebugAddrIndexMap.empty())639return Error::success();640641SectionDescriptor &OutAddrSection =642getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr);643644// Emit section header.645646// Emit length.647OutAddrSection.emitUnitLength(0xBADDEF);648uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell();649650// Emit version.651OutAddrSection.emitIntVal(5, 2);652653// Emit address size.654OutAddrSection.emitIntVal(getFormParams().AddrSize, 1);655656// Emit segment size.657OutAddrSection.emitIntVal(0, 1);658659// Emit addresses.660for (uint64_t AddrValue : DebugAddrIndexMap.getValues())661OutAddrSection.emitIntVal(AddrValue, getFormParams().AddrSize);662663// Patch section length.664OutAddrSection.apply(665OffsetAfterSectionLength -666OutAddrSection.getFormParams().getDwarfOffsetByteSize(),667dwarf::DW_FORM_sec_offset,668OutAddrSection.OS.tell() - OffsetAfterSectionLength);669670return Error::success();671}672673Error CompileUnit::cloneAndEmitRanges() {674if (getGlobalData().getOptions().UpdateIndexTablesOnly)675return Error::success();676677// Build set of linked address ranges for unit function ranges.678AddressRanges LinkedFunctionRanges;679for (const AddressRangeValuePair &Range : getFunctionRanges())680LinkedFunctionRanges.insert(681{Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});682683emitAranges(LinkedFunctionRanges);684685if (getOrigUnit().getVersion() < 5) {686cloneAndEmitRangeList(DebugSectionKind::DebugRange, LinkedFunctionRanges);687return Error::success();688}689690cloneAndEmitRangeList(DebugSectionKind::DebugRngLists, LinkedFunctionRanges);691return Error::success();692}693694void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,695AddressRanges &LinkedFunctionRanges) {696SectionDescriptor &DebugInfoSection =697getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);698SectionDescriptor &OutRangeSection =699getOrCreateSectionDescriptor(RngSectionKind);700701if (!DebugInfoSection.ListDebugRangePatch.empty()) {702std::optional<AddressRangeValuePair> CachedRange;703uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);704705DebugRangePatch *CompileUnitRangePtr = nullptr;706DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {707if (Patch.IsCompileUnitRanges) {708CompileUnitRangePtr = &Patch;709} else {710// Get ranges from the source DWARF corresponding to the current711// attribute.712AddressRanges LinkedRanges;713uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(714Patch.PatchOffset,715DebugInfoSection.getFormParams().getDwarfOffsetByteSize());716if (Expected<DWARFAddressRangesVector> InputRanges =717getOrigUnit().findRnglistFromOffset(718InputDebugRangesSectionOffset)) {719// Apply relocation adjustment.720for (const auto &Range : *InputRanges) {721if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))722CachedRange =723getFunctionRanges().getRangeThatContains(Range.LowPC);724725// All range entries should lie in the function range.726if (!CachedRange) {727warn("inconsistent range data.");728continue;729}730731// Store range for emiting.732LinkedRanges.insert({Range.LowPC + CachedRange->Value,733Range.HighPC + CachedRange->Value});734}735} else {736llvm::consumeError(InputRanges.takeError());737warn("invalid range list ignored.");738}739740// Emit linked ranges.741DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,742OutRangeSection.OS.tell());743emitRangeListFragment(LinkedRanges, OutRangeSection);744}745});746747if (CompileUnitRangePtr != nullptr) {748// Emit compile unit ranges last to be binary compatible with classic749// dsymutil.750DebugInfoSection.apply(CompileUnitRangePtr->PatchOffset,751dwarf::DW_FORM_sec_offset,752OutRangeSection.OS.tell());753emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);754}755756if (OffsetAfterUnitLength > 0) {757assert(OffsetAfterUnitLength -758OutRangeSection.getFormParams().getDwarfOffsetByteSize() <759OffsetAfterUnitLength);760OutRangeSection.apply(761OffsetAfterUnitLength -762OutRangeSection.getFormParams().getDwarfOffsetByteSize(),763dwarf::DW_FORM_sec_offset,764OutRangeSection.OS.tell() - OffsetAfterUnitLength);765}766}767}768769uint64_t CompileUnit::emitRangeListHeader(SectionDescriptor &OutRangeSection) {770if (OutRangeSection.getFormParams().Version < 5)771return 0;772773// unit_length.774OutRangeSection.emitUnitLength(0xBADDEF);775uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell();776777// Version.778OutRangeSection.emitIntVal(5, 2);779780// Address size.781OutRangeSection.emitIntVal(OutRangeSection.getFormParams().AddrSize, 1);782783// Seg_size784OutRangeSection.emitIntVal(0, 1);785786// Offset entry count787OutRangeSection.emitIntVal(0, 4);788789return OffsetAfterUnitLength;790}791792void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges,793SectionDescriptor &OutRangeSection) {794if (OutRangeSection.getFormParams().Version < 5) {795// Emit ranges.796uint64_t BaseAddress = 0;797if (std::optional<uint64_t> LowPC = getLowPc())798BaseAddress = *LowPC;799800for (const AddressRange &Range : LinkedRanges) {801OutRangeSection.emitIntVal(Range.start() - BaseAddress,802OutRangeSection.getFormParams().AddrSize);803OutRangeSection.emitIntVal(Range.end() - BaseAddress,804OutRangeSection.getFormParams().AddrSize);805}806807// Add the terminator entry.808OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);809OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);810return;811}812813std::optional<uint64_t> BaseAddress;814for (const AddressRange &Range : LinkedRanges) {815if (!BaseAddress) {816BaseAddress = Range.start();817818// Emit base address.819OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1);820encodeULEB128(getDebugAddrIndex(*BaseAddress), OutRangeSection.OS);821}822823// Emit type of entry.824OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1);825826// Emit start offset relative to base address.827encodeULEB128(Range.start() - *BaseAddress, OutRangeSection.OS);828829// Emit end offset relative to base address.830encodeULEB128(Range.end() - *BaseAddress, OutRangeSection.OS);831}832833// Emit the terminator entry.834OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1);835}836837void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) {838if (LinkedFunctionRanges.empty())839return;840841SectionDescriptor &DebugInfoSection =842getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);843SectionDescriptor &OutArangesSection =844getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges);845846// Emit Header.847unsigned HeaderSize =848sizeof(int32_t) + // Size of contents (w/o this field849sizeof(int16_t) + // DWARF ARange version number850sizeof(int32_t) + // Offset of CU in the .debug_info section851sizeof(int8_t) + // Pointer Size (in bytes)852sizeof(int8_t); // Segment Size (in bytes)853854unsigned TupleSize = OutArangesSection.getFormParams().AddrSize * 2;855unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));856857OutArangesSection.emitOffset(0xBADDEF); // Aranges length858uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell();859860OutArangesSection.emitIntVal(dwarf::DW_ARANGES_VERSION, 2); // Version number861OutArangesSection.notePatch(862DebugOffsetPatch{OutArangesSection.OS.tell(), &DebugInfoSection});863OutArangesSection.emitOffset(0xBADDEF); // Corresponding unit's offset864OutArangesSection.emitIntVal(OutArangesSection.getFormParams().AddrSize,8651); // Address size866OutArangesSection.emitIntVal(0, 1); // Segment size867868for (size_t Idx = 0; Idx < Padding; Idx++)869OutArangesSection.emitIntVal(0, 1); // Padding870871// Emit linked ranges.872for (const AddressRange &Range : LinkedFunctionRanges) {873OutArangesSection.emitIntVal(Range.start(),874OutArangesSection.getFormParams().AddrSize);875OutArangesSection.emitIntVal(Range.end() - Range.start(),876OutArangesSection.getFormParams().AddrSize);877}878879// Emit terminator.880OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);881OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);882883uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell();884885// Update Aranges lentgh.886OutArangesSection.apply(887OffsetAfterArangesLengthField -888OutArangesSection.getFormParams().getDwarfOffsetByteSize(),889dwarf::DW_FORM_sec_offset,890OffsetAfterArangesEnd - OffsetAfterArangesLengthField);891}892893Error CompileUnit::cloneAndEmitDebugMacro() {894if (getOutUnitDIE() == nullptr)895return Error::success();896897DWARFUnit &OrigUnit = getOrigUnit();898DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();899900// Check for .debug_macro table.901if (std::optional<uint64_t> MacroAttr =902dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macros))) {903if (const DWARFDebugMacro *Table =904getContaingFile().Dwarf->getDebugMacro()) {905emitMacroTableImpl(Table, *MacroAttr, true);906}907}908909// Check for .debug_macinfo table.910if (std::optional<uint64_t> MacroAttr =911dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macro_info))) {912if (const DWARFDebugMacro *Table =913getContaingFile().Dwarf->getDebugMacinfo()) {914emitMacroTableImpl(Table, *MacroAttr, false);915}916}917918return Error::success();919}920921void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,922uint64_t OffsetToMacroTable,923bool hasDWARFv5Header) {924SectionDescriptor &OutSection =925hasDWARFv5Header926? getOrCreateSectionDescriptor(DebugSectionKind::DebugMacro)927: getOrCreateSectionDescriptor(DebugSectionKind::DebugMacinfo);928929bool DefAttributeIsReported = false;930bool UndefAttributeIsReported = false;931bool ImportAttributeIsReported = false;932933for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {934if (OffsetToMacroTable == List.Offset) {935// Write DWARFv5 header.936if (hasDWARFv5Header) {937// Write header version.938OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version));939940uint8_t Flags = List.Header.Flags;941942// Check for OPCODE_OPERANDS_TABLE.943if (Flags &944DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {945Flags &=946~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;947warn("opcode_operands_table is not supported yet.");948}949950// Check for DEBUG_LINE_OFFSET.951std::optional<uint64_t> StmtListOffset;952if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {953// Get offset to the line table from the cloned compile unit.954for (auto &V : getOutUnitDIE()->values()) {955if (V.getAttribute() == dwarf::DW_AT_stmt_list) {956StmtListOffset = V.getDIEInteger().getValue();957break;958}959}960961if (!StmtListOffset) {962Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;963warn("couldn`t find line table for macro table.");964}965}966967// Write flags.968OutSection.emitIntVal(Flags, sizeof(Flags));969970// Write offset to line table.971if (StmtListOffset) {972OutSection.notePatch(DebugOffsetPatch{973OutSection.OS.tell(),974&getOrCreateSectionDescriptor(DebugSectionKind::DebugLine)});975// TODO: check that List.Header.getOffsetByteSize() and976// DebugOffsetPatch agree on size.977OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize());978}979}980981// Write macro entries.982for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {983if (MacroEntry.Type == 0) {984encodeULEB128(MacroEntry.Type, OutSection.OS);985continue;986}987988uint8_t MacroType = MacroEntry.Type;989switch (MacroType) {990default: {991bool HasVendorSpecificExtension =992(!hasDWARFv5Header &&993MacroType == dwarf::DW_MACINFO_vendor_ext) ||994(hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&995MacroType <= dwarf::DW_MACRO_hi_user));996997if (HasVendorSpecificExtension) {998// Write macinfo type.999OutSection.emitIntVal(MacroType, 1);10001001// Write vendor extension constant.1002encodeULEB128(MacroEntry.ExtConstant, OutSection.OS);10031004// Write vendor extension string.1005OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);1006} else1007warn("unknown macro type. skip.");1008} break;1009// debug_macro and debug_macinfo share some common encodings.1010// DW_MACRO_define == DW_MACINFO_define1011// DW_MACRO_undef == DW_MACINFO_undef1012// DW_MACRO_start_file == DW_MACINFO_start_file1013// DW_MACRO_end_file == DW_MACINFO_end_file1014// For readibility/uniformity we are using DW_MACRO_*.1015case dwarf::DW_MACRO_define:1016case dwarf::DW_MACRO_undef: {1017// Write macinfo type.1018OutSection.emitIntVal(MacroType, 1);10191020// Write source line.1021encodeULEB128(MacroEntry.Line, OutSection.OS);10221023// Write macro string.1024OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);1025} break;1026case dwarf::DW_MACRO_define_strp:1027case dwarf::DW_MACRO_undef_strp:1028case dwarf::DW_MACRO_define_strx:1029case dwarf::DW_MACRO_undef_strx: {1030// DW_MACRO_*_strx forms are not supported currently.1031// Convert to *_strp.1032switch (MacroType) {1033case dwarf::DW_MACRO_define_strx: {1034MacroType = dwarf::DW_MACRO_define_strp;1035if (!DefAttributeIsReported) {1036warn("DW_MACRO_define_strx unsupported yet. Convert to "1037"DW_MACRO_define_strp.");1038DefAttributeIsReported = true;1039}1040} break;1041case dwarf::DW_MACRO_undef_strx: {1042MacroType = dwarf::DW_MACRO_undef_strp;1043if (!UndefAttributeIsReported) {1044warn("DW_MACRO_undef_strx unsupported yet. Convert to "1045"DW_MACRO_undef_strp.");1046UndefAttributeIsReported = true;1047}1048} break;1049default:1050// Nothing to do.1051break;1052}10531054// Write macinfo type.1055OutSection.emitIntVal(MacroType, 1);10561057// Write source line.1058encodeULEB128(MacroEntry.Line, OutSection.OS);10591060// Write macro string.1061OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);1062break;1063}1064case dwarf::DW_MACRO_start_file: {1065// Write macinfo type.1066OutSection.emitIntVal(MacroType, 1);1067// Write source line.1068encodeULEB128(MacroEntry.Line, OutSection.OS);1069// Write source file id.1070encodeULEB128(MacroEntry.File, OutSection.OS);1071} break;1072case dwarf::DW_MACRO_end_file: {1073// Write macinfo type.1074OutSection.emitIntVal(MacroType, 1);1075} break;1076case dwarf::DW_MACRO_import:1077case dwarf::DW_MACRO_import_sup: {1078if (!ImportAttributeIsReported) {1079warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported "1080"yet. remove.");1081ImportAttributeIsReported = true;1082}1083} break;1084}1085}10861087return;1088}1089}1090}10911092void CompileUnit::cloneDieAttrExpression(1093const DWARFExpression &InputExpression,1094SmallVectorImpl<uint8_t> &OutputExpression, SectionDescriptor &Section,1095std::optional<int64_t> VarAddressAdjustment,1096OffsetsPtrVector &PatchesOffsets) {1097using Encoding = DWARFExpression::Operation::Encoding;10981099DWARFUnit &OrigUnit = getOrigUnit();1100uint8_t OrigAddressByteSize = OrigUnit.getAddressByteSize();11011102uint64_t OpOffset = 0;1103for (auto &Op : InputExpression) {1104auto Desc = Op.getDescription();1105// DW_OP_const_type is variable-length and has 31106// operands. Thus far we only support 2.1107if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||1108(Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&1109Desc.Op[0] != Encoding::Size1))1110warn("unsupported DW_OP encoding.");11111112if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||1113(Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&1114Desc.Op[0] == Encoding::Size1)) {1115// This code assumes that the other non-typeref operand fits into 1 byte.1116assert(OpOffset < Op.getEndOffset());1117uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;1118assert(ULEBsize <= 16);11191120// Copy over the operation.1121assert(!Op.getSubCode() && "SubOps not yet supported");1122OutputExpression.push_back(Op.getCode());1123uint64_t RefOffset;1124if (Desc.Op.size() == 1) {1125RefOffset = Op.getRawOperand(0);1126} else {1127OutputExpression.push_back(Op.getRawOperand(0));1128RefOffset = Op.getRawOperand(1);1129}1130uint8_t ULEB[16];1131uint32_t Offset = 0;1132unsigned RealSize = 0;1133// Look up the base type. For DW_OP_convert, the operand may be 0 to1134// instead indicate the generic type. The same holds for1135// DW_OP_reinterpret, which is currently not supported.1136if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {1137RefOffset += OrigUnit.getOffset();1138uint32_t RefDieIdx = 0;1139if (std::optional<uint32_t> Idx =1140OrigUnit.getDIEIndexForOffset(RefOffset))1141RefDieIdx = *Idx;11421143// Use fixed size for ULEB128 data, since we need to update that size1144// later with the proper offsets. Use 5 for DWARF32, 9 for DWARF64.1145ULEBsize = getFormParams().getDwarfOffsetByteSize() + 1;11461147RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize);11481149Section.notePatchWithOffsetUpdate(1150DebugULEB128DieRefPatch(OutputExpression.size(), this, this,1151RefDieIdx),1152PatchesOffsets);1153} else1154RealSize = encodeULEB128(Offset, ULEB, ULEBsize);11551156if (RealSize > ULEBsize) {1157// Emit the generic type as a fallback.1158RealSize = encodeULEB128(0, ULEB, ULEBsize);1159warn("base type ref doesn't fit.");1160}1161assert(RealSize == ULEBsize && "padding failed");1162ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);1163OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());1164} else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&1165Op.getCode() == dwarf::DW_OP_addrx) {1166if (std::optional<object::SectionedAddress> SA =1167OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {1168// DWARFLinker does not use addrx forms since it generates relocated1169// addresses. Replace DW_OP_addrx with DW_OP_addr here.1170// Argument of DW_OP_addrx should be relocated here as it is not1171// processed by applyValidRelocs.1172OutputExpression.push_back(dwarf::DW_OP_addr);1173uint64_t LinkedAddress =1174SA->Address + (VarAddressAdjustment ? *VarAddressAdjustment : 0);1175if (getEndianness() != llvm::endianness::native)1176sys::swapByteOrder(LinkedAddress);1177ArrayRef<uint8_t> AddressBytes(1178reinterpret_cast<const uint8_t *>(&LinkedAddress),1179OrigAddressByteSize);1180OutputExpression.append(AddressBytes.begin(), AddressBytes.end());1181} else1182warn("cann't read DW_OP_addrx operand.");1183} else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&1184Op.getCode() == dwarf::DW_OP_constx) {1185if (std::optional<object::SectionedAddress> SA =1186OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {1187// DWARFLinker does not use constx forms since it generates relocated1188// addresses. Replace DW_OP_constx with DW_OP_const[*]u here.1189// Argument of DW_OP_constx should be relocated here as it is not1190// processed by applyValidRelocs.1191std::optional<uint8_t> OutOperandKind;1192switch (OrigAddressByteSize) {1193case 2:1194OutOperandKind = dwarf::DW_OP_const2u;1195break;1196case 4:1197OutOperandKind = dwarf::DW_OP_const4u;1198break;1199case 8:1200OutOperandKind = dwarf::DW_OP_const8u;1201break;1202default:1203warn(1204formatv(("unsupported address size: {0}."), OrigAddressByteSize));1205break;1206}12071208if (OutOperandKind) {1209OutputExpression.push_back(*OutOperandKind);1210uint64_t LinkedAddress =1211SA->Address + (VarAddressAdjustment ? *VarAddressAdjustment : 0);1212if (getEndianness() != llvm::endianness::native)1213sys::swapByteOrder(LinkedAddress);1214ArrayRef<uint8_t> AddressBytes(1215reinterpret_cast<const uint8_t *>(&LinkedAddress),1216OrigAddressByteSize);1217OutputExpression.append(AddressBytes.begin(), AddressBytes.end());1218}1219} else1220warn("cann't read DW_OP_constx operand.");1221} else {1222// Copy over everything else unmodified.1223StringRef Bytes =1224InputExpression.getData().slice(OpOffset, Op.getEndOffset());1225OutputExpression.append(Bytes.begin(), Bytes.end());1226}1227OpOffset = Op.getEndOffset();1228}1229}12301231Error CompileUnit::cloneAndEmit(1232std::optional<std::reference_wrapper<const Triple>> TargetTriple,1233TypeUnit *ArtificialTypeUnit) {1234BumpPtrAllocator Allocator;12351236DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE();1237if (!OrigUnitDIE.isValid())1238return Error::success();12391240TypeEntry *RootEntry = nullptr;1241if (ArtificialTypeUnit)1242RootEntry = ArtificialTypeUnit->getTypePool().getRoot();12431244// Clone input DIE entry recursively.1245std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(1246OrigUnitDIE.getDebugInfoEntry(), RootEntry, getDebugInfoHeaderSize(),1247std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);1248setOutUnitDIE(OutCUDie.first);12491250if (!TargetTriple.has_value() || (OutCUDie.first == nullptr))1251return Error::success();12521253if (Error Err = cloneAndEmitLineTable((*TargetTriple).get()))1254return Err;12551256if (Error Err = cloneAndEmitDebugMacro())1257return Err;12581259getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);1260if (Error Err = emitDebugInfo((*TargetTriple).get()))1261return Err;12621263// ASSUMPTION: .debug_info section should already be emitted at this point.1264// cloneAndEmitRanges & cloneAndEmitDebugLocations use .debug_info section1265// data.12661267if (Error Err = cloneAndEmitRanges())1268return Err;12691270if (Error Err = cloneAndEmitDebugLocations())1271return Err;12721273if (Error Err = emitDebugAddrSection())1274return Err;12751276// Generate Pub accelerator tables.1277if (llvm::is_contained(GlobalData.getOptions().AccelTables,1278DWARFLinker::AccelTableKind::Pub))1279emitPubAccelerators();12801281if (Error Err = emitDebugStringOffsetSection())1282return Err;12831284return emitAbbreviations();1285}12861287std::pair<DIE *, TypeEntry *> CompileUnit::cloneDIE(1288const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE,1289uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,1290std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,1291TypeUnit *ArtificialTypeUnit) {1292uint32_t InputDieIdx = getDIEIndex(InputDieEntry);1293CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);12941295bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();1296bool NeedToCloneTypeDIE =1297(InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&1298Info.needToPlaceInTypeTable();1299std::pair<DIE *, TypeEntry *> ClonedDIE;13001301DIEGenerator PlainDIEGenerator(Allocator, *this);13021303if (NeedToClonePlainDIE)1304// Create a cloned DIE which would be placed into the cloned version1305// of input compile unit.1306ClonedDIE.first = createPlainDIEandCloneAttributes(1307InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,1308VarAddressAdjustment);1309if (NeedToCloneTypeDIE) {1310// Create a cloned DIE which would be placed into the artificial type1311// unit.1312assert(ArtificialTypeUnit != nullptr);1313DIEGenerator TypeDIEGenerator(1314ArtificialTypeUnit->getTypePool().getThreadLocalAllocator(), *this);13151316ClonedDIE.second = createTypeDIEandCloneAttributes(1317InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,1318ArtificialTypeUnit);1319}1320TypeEntry *TypeParentForChild =1321ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;13221323bool HasPlainChildrenToClone =1324(ClonedDIE.first && Info.getKeepPlainChildren());13251326bool HasTypeChildrenToClone =1327((ClonedDIE.second ||1328InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&1329Info.getKeepTypeChildren());13301331// Recursively clone children.1332if (HasPlainChildrenToClone || HasTypeChildrenToClone) {1333for (const DWARFDebugInfoEntry *CurChild =1334getFirstChildEntry(InputDieEntry);1335CurChild && CurChild->getAbbreviationDeclarationPtr();1336CurChild = getSiblingEntry(CurChild)) {1337std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(1338CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,1339VarAddressAdjustment, Allocator, ArtificialTypeUnit);13401341if (ClonedChild.first) {1342OutOffset =1343ClonedChild.first->getOffset() + ClonedChild.first->getSize();1344PlainDIEGenerator.addChild(ClonedChild.first);1345}1346}1347assert(ClonedDIE.first == nullptr ||1348HasPlainChildrenToClone == ClonedDIE.first->hasChildren());13491350// Account for the end of children marker.1351if (HasPlainChildrenToClone)1352OutOffset += sizeof(int8_t);1353}13541355// Update our size.1356if (ClonedDIE.first != nullptr)1357ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());13581359return ClonedDIE;1360}13611362DIE *CompileUnit::createPlainDIEandCloneAttributes(1363const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,1364uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,1365std::optional<int64_t> &VarAddressAdjustment) {1366uint32_t InputDieIdx = getDIEIndex(InputDieEntry);1367CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);1368DIE *ClonedDIE = nullptr;1369bool HasLocationExpressionAddress = false;1370if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {1371// Get relocation adjustment value for the current function.1372FuncAddressAdjustment =1373getContaingFile().Addresses->getSubprogramRelocAdjustment(1374getDIE(InputDieEntry), false);1375} else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {1376// Get relocation adjustment value for the current label.1377std::optional<uint64_t> lowPC =1378dwarf::toAddress(find(InputDieEntry, dwarf::DW_AT_low_pc));1379if (lowPC) {1380LabelMapTy::iterator It = Labels.find(*lowPC);1381if (It != Labels.end())1382FuncAddressAdjustment = It->second;1383}1384} else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {1385// Get relocation adjustment value for the current variable.1386std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =1387getContaingFile().Addresses->getVariableRelocAdjustment(1388getDIE(InputDieEntry), false);13891390HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;1391if (LocExprAddrAndRelocAdjustment.first &&1392LocExprAddrAndRelocAdjustment.second)1393VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;1394}13951396ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);13971398// Offset to the DIE would be used after output DIE tree is deleted.1399// Thus we need to remember DIE offset separately.1400rememberDieOutOffset(InputDieIdx, OutOffset);14011402// Clone Attributes.1403DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,1404PlainDIEGenerator, FuncAddressAdjustment,1405VarAddressAdjustment,1406HasLocationExpressionAddress);1407AttributesCloner.clone();14081409// Remember accelerator info.1410AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this);1411AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,1412nullptr);14131414OutOffset =1415AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());14161417return ClonedDIE;1418}14191420/// Allocates output DIE for the specified \p TypeDescriptor.1421DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,1422DIEGenerator &TypeDIEGenerator,1423dwarf::Tag DieTag, bool IsDeclaration,1424bool IsParentDeclaration) {1425DIE *DefinitionDie = TypeDescriptor->Die;1426// Do not allocate any new DIE if definition DIE is already met.1427if (DefinitionDie)1428return nullptr;14291430DIE *DeclarationDie = TypeDescriptor->DeclarationDie;1431bool OldParentIsDeclaration = TypeDescriptor->ParentIsDeclaration;14321433if (IsDeclaration && !DeclarationDie) {1434// Alocate declaration DIE.1435DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);1436if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,1437NewDie))1438return NewDie;1439} else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {1440// Overwrite existing declaration DIE if it's parent is also an declaration1441// while parent of current declaration DIE is a definition.1442if (TypeDescriptor->ParentIsDeclaration.compare_exchange_weak(1443OldParentIsDeclaration, false)) {1444DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);1445TypeDescriptor->DeclarationDie = NewDie;1446return NewDie;1447}1448} else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {1449// Alocate declaration DIE since parent of current DIE is marked as1450// declaration.1451DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);1452if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,1453NewDie))1454return NewDie;1455} else if (!IsDeclaration && !IsParentDeclaration) {1456// Allocate definition DIE.1457DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);1458if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) {1459TypeDescriptor->ParentIsDeclaration = false;1460return NewDie;1461}1462}14631464return nullptr;1465}14661467TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(1468const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,1469TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit) {1470assert(ArtificialTypeUnit != nullptr);1471uint32_t InputDieIdx = getDIEIndex(InputDieEntry);14721473TypeEntry *Entry = getDieTypeEntry(InputDieIdx);1474assert(Entry != nullptr);1475assert(ClonedParentTypeDIE != nullptr);1476TypeEntryBody *EntryBody =1477ArtificialTypeUnit->getTypePool().getOrCreateTypeEntryBody(1478Entry, ClonedParentTypeDIE);1479assert(EntryBody);14801481bool IsDeclaration =1482dwarf::toUnsigned(find(InputDieEntry, dwarf::DW_AT_declaration), 0);14831484bool ParentIsDeclaration = false;1485if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())1486ParentIsDeclaration =1487dwarf::toUnsigned(find(*ParentIdx, dwarf::DW_AT_declaration), 0);14881489DIE *OutDIE =1490allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),1491IsDeclaration, ParentIsDeclaration);14921493if (OutDIE != nullptr) {1494assert(ArtificialTypeUnit != nullptr);1495ArtificialTypeUnit->getSectionDescriptor(DebugSectionKind::DebugInfo);14961497DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,1498InputDieEntry, TypeDIEGenerator,1499std::nullopt, std::nullopt, false);1500AttributesCloner.clone();15011502// Remember accelerator info.1503AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this,1504ArtificialTypeUnit);1505AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,1506Entry);15071508// if AttributesCloner.getOutOffset() == 0 then we need to add1509// 1 to avoid assertion for zero size. We will subtract it back later.1510OutDIE->setSize(AttributesCloner.getOutOffset() + 1);1511}15121513return Entry;1514}15151516Error CompileUnit::cloneAndEmitLineTable(const Triple &TargetTriple) {1517const DWARFDebugLine::LineTable *InputLineTable =1518getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit());1519if (InputLineTable == nullptr) {1520if (getOrigUnit().getUnitDIE().find(dwarf::DW_AT_stmt_list))1521warn("cann't load line table.");1522return Error::success();1523}15241525DWARFDebugLine::LineTable OutLineTable;15261527// Set Line Table header.1528OutLineTable.Prologue = InputLineTable->Prologue;1529OutLineTable.Prologue.FormParams.AddrSize = getFormParams().AddrSize;15301531// Set Line Table Rows.1532if (getGlobalData().getOptions().UpdateIndexTablesOnly) {1533OutLineTable.Rows = InputLineTable->Rows;1534// If all the line table contains is a DW_LNE_end_sequence, clear the line1535// table rows, it will be inserted again in the DWARFStreamer.1536if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence)1537OutLineTable.Rows.clear();15381539OutLineTable.Sequences = InputLineTable->Sequences;1540} else {1541// This vector is the output line table.1542std::vector<DWARFDebugLine::Row> NewRows;1543NewRows.reserve(InputLineTable->Rows.size());15441545// Current sequence of rows being extracted, before being inserted1546// in NewRows.1547std::vector<DWARFDebugLine::Row> Seq;15481549const auto &FunctionRanges = getFunctionRanges();1550std::optional<AddressRangeValuePair> CurrRange;15511552// FIXME: This logic is meant to generate exactly the same output as1553// Darwin's classic dsymutil. There is a nicer way to implement this1554// by simply putting all the relocated line info in NewRows and simply1555// sorting NewRows before passing it to emitLineTableForUnit. This1556// should be correct as sequences for a function should stay1557// together in the sorted output. There are a few corner cases that1558// look suspicious though, and that required to implement the logic1559// this way. Revisit that once initial validation is finished.15601561// Iterate over the object file line info and extract the sequences1562// that correspond to linked functions.1563for (DWARFDebugLine::Row Row : InputLineTable->Rows) {1564// Check whether we stepped out of the range. The range is1565// half-open, but consider accept the end address of the range if1566// it is marked as end_sequence in the input (because in that1567// case, the relocation offset is accurate and that entry won't1568// serve as the start of another function).1569if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {1570// We just stepped out of a known range. Insert a end_sequence1571// corresponding to the end of the range.1572uint64_t StopAddress =1573CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;1574CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);1575if (StopAddress != -1ULL && !Seq.empty()) {1576// Insert end sequence row with the computed end address, but1577// the same line as the previous one.1578auto NextLine = Seq.back();1579NextLine.Address.Address = StopAddress;1580NextLine.EndSequence = 1;1581NextLine.PrologueEnd = 0;1582NextLine.BasicBlock = 0;1583NextLine.EpilogueBegin = 0;1584Seq.push_back(NextLine);1585insertLineSequence(Seq, NewRows);1586}15871588if (!CurrRange)1589continue;1590}15911592// Ignore empty sequences.1593if (Row.EndSequence && Seq.empty())1594continue;15951596// Relocate row address and add it to the current sequence.1597Row.Address.Address += CurrRange->Value;1598Seq.emplace_back(Row);15991600if (Row.EndSequence)1601insertLineSequence(Seq, NewRows);1602}16031604OutLineTable.Rows = std::move(NewRows);1605}16061607return emitDebugLine(TargetTriple, OutLineTable);1608}16091610void CompileUnit::insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,1611std::vector<DWARFDebugLine::Row> &Rows) {1612if (Seq.empty())1613return;16141615if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {1616llvm::append_range(Rows, Seq);1617Seq.clear();1618return;1619}16201621object::SectionedAddress Front = Seq.front().Address;1622auto InsertPoint = partition_point(1623Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; });16241625// FIXME: this only removes the unneeded end_sequence if the1626// sequences have been inserted in order. Using a global sort like1627// described in cloneAndEmitLineTable() and delaying the end_sequene1628// elimination to DebugLineEmitter::emit() we can get rid of all of them.1629if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&1630InsertPoint->EndSequence) {1631*InsertPoint = Seq.front();1632Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());1633} else {1634Rows.insert(InsertPoint, Seq.begin(), Seq.end());1635}16361637Seq.clear();1638}16391640#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)1641LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {1642llvm::errs() << "{";1643llvm::errs() << " Placement: ";1644switch (getPlacement()) {1645case NotSet:1646llvm::errs() << "NotSet";1647break;1648case TypeTable:1649llvm::errs() << "TypeTable";1650break;1651case PlainDwarf:1652llvm::errs() << "PlainDwarf";1653break;1654case Both:1655llvm::errs() << "Both";1656break;1657}16581659llvm::errs() << " Keep: " << getKeep();1660llvm::errs() << " KeepPlainChildren: " << getKeepPlainChildren();1661llvm::errs() << " KeepTypeChildren: " << getKeepTypeChildren();1662llvm::errs() << " IsInMouduleScope: " << getIsInMouduleScope();1663llvm::errs() << " IsInFunctionScope: " << getIsInFunctionScope();1664llvm::errs() << " IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();1665llvm::errs() << " ODRAvailable: " << getODRAvailable();1666llvm::errs() << " TrackLiveness: " << getTrackLiveness();1667llvm::errs() << "}\n";1668}1669#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)16701671std::optional<std::pair<StringRef, StringRef>>1672CompileUnit::getDirAndFilenameFromLineTable(1673const DWARFFormValue &FileIdxValue) {1674uint64_t FileIdx;1675if (std::optional<uint64_t> Val = FileIdxValue.getAsUnsignedConstant())1676FileIdx = *Val;1677else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())1678FileIdx = *Val;1679else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())1680FileIdx = *Val;1681else1682return std::nullopt;16831684return getDirAndFilenameFromLineTable(FileIdx);1685}16861687std::optional<std::pair<StringRef, StringRef>>1688CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {1689FileNamesCache::iterator FileData = FileNames.find(FileIdx);1690if (FileData != FileNames.end())1691return std::make_pair(StringRef(FileData->second.first),1692StringRef(FileData->second.second));16931694if (const DWARFDebugLine::LineTable *LineTable =1695getOrigUnit().getContext().getLineTableForUnit(&getOrigUnit())) {1696if (LineTable->hasFileAtIndex(FileIdx)) {16971698const llvm::DWARFDebugLine::FileNameEntry &Entry =1699LineTable->Prologue.getFileNameEntry(FileIdx);17001701Expected<const char *> Name = Entry.Name.getAsCString();1702if (!Name) {1703warn(Name.takeError());1704return std::nullopt;1705}17061707std::string FileName = *Name;1708if (isPathAbsoluteOnWindowsOrPosix(FileName)) {1709FileNamesCache::iterator FileData =1710FileNames1711.insert(std::make_pair(1712FileIdx,1713std::make_pair(std::string(""), std::move(FileName))))1714.first;1715return std::make_pair(StringRef(FileData->second.first),1716StringRef(FileData->second.second));1717}17181719SmallString<256> FilePath;1720StringRef IncludeDir;1721// Be defensive about the contents of Entry.1722if (getVersion() >= 5) {1723// DirIdx 0 is the compilation directory, so don't include it for1724// relative names.1725if ((Entry.DirIdx != 0) &&1726Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {1727Expected<const char *> DirName =1728LineTable->Prologue.IncludeDirectories[Entry.DirIdx]1729.getAsCString();1730if (DirName)1731IncludeDir = *DirName;1732else {1733warn(DirName.takeError());1734return std::nullopt;1735}1736}1737} else {1738if (0 < Entry.DirIdx &&1739Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {1740Expected<const char *> DirName =1741LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]1742.getAsCString();1743if (DirName)1744IncludeDir = *DirName;1745else {1746warn(DirName.takeError());1747return std::nullopt;1748}1749}1750}17511752StringRef CompDir = getOrigUnit().getCompilationDir();17531754if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) {1755sys::path::append(FilePath, sys::path::Style::native, CompDir);1756}17571758sys::path::append(FilePath, sys::path::Style::native, IncludeDir);17591760FileNamesCache::iterator FileData =1761FileNames1762.insert(1763std::make_pair(FileIdx, std::make_pair(std::string(FilePath),1764std::move(FileName))))1765.first;1766return std::make_pair(StringRef(FileData->second.first),1767StringRef(FileData->second.second));1768}1769}17701771return std::nullopt;1772}17731774#define MAX_REFERENCIES_DEPTH 10001775UnitEntryPairTy UnitEntryPairTy::getNamespaceOrigin() {1776UnitEntryPairTy CUDiePair(*this);1777std::optional<UnitEntryPairTy> RefDiePair;1778int refDepth = 0;1779do {1780RefDiePair = CUDiePair.CU->resolveDIEReference(1781CUDiePair.DieEntry, dwarf::DW_AT_extension,1782ResolveInterCUReferencesMode::Resolve);1783if (!RefDiePair || !RefDiePair->DieEntry)1784return CUDiePair;17851786CUDiePair = *RefDiePair;1787} while (refDepth++ < MAX_REFERENCIES_DEPTH);17881789return CUDiePair;1790}17911792std::optional<UnitEntryPairTy> UnitEntryPairTy::getParent() {1793if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())1794return UnitEntryPairTy{CU, CU->getDebugInfoEntry(*ParentIdx)};17951796return std::nullopt;1797}17981799CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(CompileUnit *U)1800: Ptr(U) {1801assert(U != nullptr);1802}18031804CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(TypeUnit *U) : Ptr(U) {1805assert(U != nullptr);1806}18071808DwarfUnit *CompileUnit::OutputUnitVariantPtr::operator->() {1809if (isCompileUnit())1810return getAsCompileUnit();1811else1812return getAsTypeUnit();1813}18141815bool CompileUnit::OutputUnitVariantPtr::isCompileUnit() {1816return Ptr.is<CompileUnit *>();1817}18181819bool CompileUnit::OutputUnitVariantPtr::isTypeUnit() {1820return Ptr.is<TypeUnit *>();1821}18221823CompileUnit *CompileUnit::OutputUnitVariantPtr::getAsCompileUnit() {1824return Ptr.get<CompileUnit *>();1825}18261827TypeUnit *CompileUnit::OutputUnitVariantPtr::getAsTypeUnit() {1828return Ptr.get<TypeUnit *>();1829}18301831bool CompileUnit::resolveDependenciesAndMarkLiveness(1832bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {1833if (!Dependencies)1834Dependencies.reset(new DependencyTracker(*this));18351836return Dependencies->resolveDependenciesAndMarkLiveness(1837InterCUProcessingStarted, HasNewInterconnectedCUs);1838}18391840bool CompileUnit::updateDependenciesCompleteness() {1841assert(Dependencies.get());18421843return Dependencies->updateDependenciesCompleteness();1844}18451846void CompileUnit::verifyDependencies() {1847assert(Dependencies.get());18481849Dependencies->verifyKeepChain();1850}18511852ArrayRef<dwarf::Attribute> dwarf_linker::parallel::getODRAttributes() {1853static dwarf::Attribute ODRAttributes[] = {1854dwarf::DW_AT_type, dwarf::DW_AT_specification,1855dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};18561857return ODRAttributes;1858}185918601861