1856 lines · cpp
1//=== DWARFLinkerCompileUnit.cpp ------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DWARFLinkerCompileUnit.h"10#include "AcceleratorRecordsSaver.h"11#include "DIEAttributeCloner.h"12#include "DIEGenerator.h"13#include "DependencyTracker.h"14#include "SyntheticTypeNameBuilder.h"15#include "llvm/DWARFLinker/Utils.h"16#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"17#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"18#include "llvm/Support/FileSystem.h"19#include "llvm/Support/FormatVariadic.h"20#include "llvm/Support/Path.h"21#include <utility>22 23using namespace llvm;24using namespace dwarf_linker;25using namespace dwarf_linker::parallel;26 27CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,28 StringRef ClangModuleName, DWARFFile &File,29 OffsetToUnitTy UnitFromOffset,30 dwarf::FormParams Format, llvm::endianness Endianess)31 : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),32 getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded),33 AcceleratorRecords(&GlobalData.getAllocator()) {34 UnitName = File.FileName;35 setOutputFormat(Format, Endianess);36 getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);37}38 39CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit,40 unsigned ID, StringRef ClangModuleName,41 DWARFFile &File, OffsetToUnitTy UnitFromOffset,42 dwarf::FormParams Format, llvm::endianness Endianess)43 : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),44 OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),45 Stage(Stage::CreatedNotLoaded),46 AcceleratorRecords(&GlobalData.getAllocator()) {47 setOutputFormat(Format, Endianess);48 getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);49 50 DWARFDie CUDie = OrigUnit.getUnitDIE();51 if (!CUDie)52 return;53 54 if (std::optional<DWARFFormValue> Val = CUDie.find(dwarf::DW_AT_language)) {55 uint16_t LangVal = dwarf::toUnsigned(Val, 0);56 if (isODRLanguage(LangVal))57 Language = LangVal;58 }59 60 if (!GlobalData.getOptions().NoODR && Language.has_value())61 NoODR = false;62 63 if (const char *CUName = CUDie.getName(DINameKind::ShortName))64 UnitName = CUName;65 else66 UnitName = File.FileName;67 SysRoot = dwarf::toStringRef(CUDie.find(dwarf::DW_AT_LLVM_sysroot)).str();68}69 70void CompileUnit::loadLineTable() {71 LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());72}73 74void CompileUnit::maybeResetToLoadedStage() {75 // Nothing to reset if stage is less than "Loaded".76 if (getStage() < Stage::Loaded)77 return;78 79 // 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.83 84 for (DIEInfo &Info : DieInfoArray)85 Info.unsetFlagsWhichSetDuringLiveAnalysis();86 87 LowPc = std::nullopt;88 HighPc = 0;89 Labels.clear();90 Ranges.clear();91 Dependencies.reset(nullptr);92 93 if (getStage() < Stage::Cloned) {94 setStage(Stage::Loaded);95 return;96 }97 98 AcceleratorRecords.erase();99 AbbreviationsSet.clear();100 Abbreviations.clear();101 OutUnitDIE = nullptr;102 DebugAddrIndexMap.clear();103 104 llvm::fill(OutDieOffsetArray, 0);105 llvm::fill(TypeEntries, nullptr);106 eraseSections();107 108 setStage(Stage::CreatedNotLoaded);109}110 111bool CompileUnit::loadInputDIEs() {112 DWARFDie InputUnitDIE = getUnitDIE(false);113 if (!InputUnitDIE)114 return false;115 116 // load input dies, resize Info structures array.117 DieInfoArray.resize(getOrigUnit().getNumDIEs());118 OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);119 if (!NoODR)120 TypeEntries.resize(getOrigUnit().getNumDIEs());121 return true;122}123 124void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,125 bool IsODRUnavailableFunctionScope) {126 CompileUnit::DIEInfo &DieInfo = getDIEInfo(DieEntry);127 128 for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);129 CurChild && CurChild->getAbbreviationDeclarationPtr();130 CurChild = getSiblingEntry(CurChild)) {131 CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);132 bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;133 134 if (DieInfo.getIsInMouduleScope())135 ChildInfo.setIsInMouduleScope();136 137 if (DieInfo.getIsInFunctionScope())138 ChildInfo.setIsInFunctionScope();139 140 if (DieInfo.getIsInAnonNamespaceScope())141 ChildInfo.setIsInAnonNamespaceScope();142 143 switch (CurChild->getTag()) {144 case dwarf::DW_TAG_module:145 ChildInfo.setIsInMouduleScope();146 if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit &&147 dwarf::toString(find(CurChild, dwarf::DW_AT_name), "") !=148 getClangModuleName())149 analyzeImportedModule(CurChild);150 break;151 case dwarf::DW_TAG_subprogram:152 ChildInfo.setIsInFunctionScope();153 if (!ChildIsODRUnavailableFunctionScope &&154 !ChildInfo.getIsInMouduleScope()) {155 if (find(CurChild,156 {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))157 ChildIsODRUnavailableFunctionScope = true;158 }159 break;160 case dwarf::DW_TAG_namespace: {161 UnitEntryPairTy NamespaceEntry = {this, CurChild};162 163 if (find(CurChild, dwarf::DW_AT_extension))164 NamespaceEntry = NamespaceEntry.getNamespaceOrigin();165 166 if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))167 ChildInfo.setIsInAnonNamespaceScope();168 } break;169 default:170 break;171 }172 173 if (!isClangModule() && !getGlobalData().getOptions().UpdateIndexTablesOnly)174 ChildInfo.setTrackLiveness();175 176 if ((!ChildInfo.getIsInAnonNamespaceScope() &&177 !ChildIsODRUnavailableFunctionScope && !NoODR))178 ChildInfo.setODRAvailable();179 180 if (CurChild->hasChildren())181 analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);182 }183}184 185StringEntry *CompileUnit::getFileName(unsigned FileIdx,186 StringPool &GlobalStrings) {187 if (LineTablePtr) {188 if (LineTablePtr->hasFileAtIndex(FileIdx)) {189 // Cache the resolved paths based on the index in the line table,190 // because calling realpath is expensive.191 ResolvedPathsMap::const_iterator It = ResolvedFullPaths.find(FileIdx);192 if (It == ResolvedFullPaths.end()) {193 std::string OrigFileName;194 bool FoundFileName = LineTablePtr->getFileNameByIndex(195 FileIdx, getOrigUnit().getCompilationDir(),196 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,197 OrigFileName);198 (void)FoundFileName;199 assert(FoundFileName && "Must get file name from line table");200 201 // Second level of caching, this time based on the file's parent202 // path.203 StringRef FileName = sys::path::filename(OrigFileName);204 StringRef ParentPath = sys::path::parent_path(OrigFileName);205 206 // If the ParentPath has not yet been resolved, resolve and cache it for207 // future look-ups.208 StringMap<StringEntry *>::iterator ParentIt =209 ResolvedParentPaths.find(ParentPath);210 if (ParentIt == ResolvedParentPaths.end()) {211 SmallString<256> RealPath;212 sys::fs::real_path(ParentPath, RealPath);213 ParentIt =214 ResolvedParentPaths215 .insert({ParentPath, GlobalStrings.insert(RealPath).first})216 .first;217 }218 219 // Join the file name again with the resolved path.220 SmallString<256> ResolvedPath(ParentIt->second->first());221 sys::path::append(ResolvedPath, FileName);222 223 It = ResolvedFullPaths224 .insert(std::make_pair(225 FileIdx, GlobalStrings.insert(ResolvedPath).first))226 .first;227 }228 229 return It->second;230 }231 }232 233 return nullptr;234}235 236void CompileUnit::cleanupDataAfterClonning() {237 AbbreviationsSet.clear();238 ResolvedFullPaths.shrink_and_clear();239 ResolvedParentPaths.clear();240 FileNames.shrink_and_clear();241 DieInfoArray = SmallVector<DIEInfo>();242 OutDieOffsetArray = SmallVector<uint64_t>();243 TypeEntries = SmallVector<TypeEntry *>();244 Dependencies.reset(nullptr);245 getOrigUnit().clear();246}247 248/// Collect references to parseable Swift interfaces in imported249/// DW_TAG_module blocks.250void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) {251 if (!Language || Language != dwarf::DW_LANG_Swift)252 return;253 254 if (!GlobalData.getOptions().ParseableSwiftInterfaces)255 return;256 257 StringRef Path =258 dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_include_path));259 if (!Path.ends_with(".swiftinterface"))260 return;261 // Don't track interfaces that are part of the SDK.262 StringRef SysRoot =263 dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_sysroot));264 if (SysRoot.empty())265 SysRoot = getSysRoot();266 if (!SysRoot.empty() && Path.starts_with(SysRoot))267 return;268 // Don't track interfaces that are part of the toolchain.269 // For example: Swift, _Concurrency, ...270 StringRef DeveloperDir = guessDeveloperDir(SysRoot);271 if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))272 return;273 if (isInToolchainDir(Path))274 return;275 if (std::optional<DWARFFormValue> Val = find(DieEntry, dwarf::DW_AT_name)) {276 Expected<const char *> Name = Val->getAsCString();277 if (!Name) {278 warn(Name.takeError());279 return;280 }281 282 auto &Entry = (*GlobalData.getOptions().ParseableSwiftInterfaces)[*Name];283 // The prepend path is applied later when copying.284 SmallString<128> ResolvedPath;285 if (sys::path::is_relative(Path))286 sys::path::append(287 ResolvedPath,288 dwarf::toString(getUnitDIE().find(dwarf::DW_AT_comp_dir), ""));289 sys::path::append(ResolvedPath, Path);290 if (!Entry.empty() && Entry != ResolvedPath) {291 DWARFDie Die = getDIE(DieEntry);292 warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name +293 ": " + Entry + " and " + Path + ".",294 &Die);295 }296 Entry = std::string(ResolvedPath);297 }298}299 300Error CompileUnit::assignTypeNames(TypePool &TypePoolRef) {301 if (!getUnitDIE().isValid())302 return Error::success();303 304 SyntheticTypeNameBuilder NameBuilder(TypePoolRef);305 return assignTypeNamesRec(getDebugInfoEntry(0), NameBuilder);306}307 308Error CompileUnit::assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,309 SyntheticTypeNameBuilder &NameBuilder) {310 OrderedChildrenIndexAssigner ChildrenIndexAssigner(*this, DieEntry);311 for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);312 CurChild && CurChild->getAbbreviationDeclarationPtr();313 CurChild = getSiblingEntry(CurChild)) {314 CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);315 if (!ChildInfo.needToPlaceInTypeTable())316 continue;317 318 assert(ChildInfo.getODRAvailable());319 if (Error Err = NameBuilder.assignName(320 {this, CurChild},321 ChildrenIndexAssigner.getChildIndex(*this, CurChild)))322 return Err;323 324 if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))325 return Err;326 }327 328 return Error::success();329}330 331void CompileUnit::updateDieRefPatchesWithClonedOffsets() {332 if (std::optional<SectionDescriptor *> DebugInfoSection =333 tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) {334 335 (*DebugInfoSection)336 ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {337 /// Replace stored DIE indexes with DIE output offsets.338 Patch.RefDieIdxOrClonedOffset =339 Patch.RefCU.getPointer()->getDieOutOffset(340 Patch.RefDieIdxOrClonedOffset);341 });342 343 (*DebugInfoSection)344 ->ListDebugULEB128DieRefPatch.forEach(345 [&](DebugULEB128DieRefPatch &Patch) {346 /// Replace stored DIE indexes with DIE output offsets.347 Patch.RefDieIdxOrClonedOffset =348 Patch.RefCU.getPointer()->getDieOutOffset(349 Patch.RefDieIdxOrClonedOffset);350 });351 }352 353 if (std::optional<SectionDescriptor *> DebugLocSection =354 tryGetSectionDescriptor(DebugSectionKind::DebugLoc)) {355 (*DebugLocSection)356 ->ListDebugULEB128DieRefPatch.forEach(357 [](DebugULEB128DieRefPatch &Patch) {358 /// Replace stored DIE indexes with DIE output offsets.359 Patch.RefDieIdxOrClonedOffset =360 Patch.RefCU.getPointer()->getDieOutOffset(361 Patch.RefDieIdxOrClonedOffset);362 });363 }364 365 if (std::optional<SectionDescriptor *> DebugLocListsSection =366 tryGetSectionDescriptor(DebugSectionKind::DebugLocLists)) {367 (*DebugLocListsSection)368 ->ListDebugULEB128DieRefPatch.forEach(369 [](DebugULEB128DieRefPatch &Patch) {370 /// Replace stored DIE indexes with DIE output offsets.371 Patch.RefDieIdxOrClonedOffset =372 Patch.RefCU.getPointer()->getDieOutOffset(373 Patch.RefDieIdxOrClonedOffset);374 });375 }376}377 378std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(379 const DWARFFormValue &RefValue,380 ResolveInterCUReferencesMode CanResolveInterCUReferences) {381 CompileUnit *RefCU;382 uint64_t RefDIEOffset;383 if (std::optional<uint64_t> Offset = RefValue.getAsRelativeReference()) {384 RefCU = this;385 RefDIEOffset = RefValue.getUnit()->getOffset() + *Offset;386 } else if (Offset = RefValue.getAsDebugInfoReference(); Offset) {387 RefCU = getUnitFromOffset(*Offset);388 RefDIEOffset = *Offset;389 } else {390 return std::nullopt;391 }392 393 if (RefCU == this) {394 // Referenced DIE is in current compile unit.395 if (std::optional<uint32_t> RefDieIdx = getDIEIndexForOffset(RefDIEOffset))396 return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)};397 } else if (RefCU && CanResolveInterCUReferences) {398 // Referenced DIE is in other compile unit.399 400 // Check whether DIEs are loaded for that compile unit.401 enum Stage ReferredCUStage = RefCU->getStage();402 if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)403 return UnitEntryPairTy{RefCU, nullptr};404 405 if (std::optional<uint32_t> RefDieIdx =406 RefCU->getDIEIndexForOffset(RefDIEOffset))407 return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)};408 } else {409 return UnitEntryPairTy{RefCU, nullptr};410 }411 return std::nullopt;412}413 414std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(415 const DWARFDebugInfoEntry *DieEntry, dwarf::Attribute Attr,416 ResolveInterCUReferencesMode CanResolveInterCUReferences) {417 if (std::optional<DWARFFormValue> AttrVal = find(DieEntry, Attr))418 return resolveDIEReference(*AttrVal, CanResolveInterCUReferences);419 420 return std::nullopt;421}422 423void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,424 int64_t PcOffset) {425 std::lock_guard<std::mutex> Guard(RangesMutex);426 427 Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);428 if (LowPc)429 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);430 else431 LowPc = FuncLowPc + PcOffset;432 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);433}434 435void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {436 std::lock_guard<std::mutex> Guard(LabelsMutex);437 Labels.insert({LabelLowPc, PcOffset});438}439 440Error CompileUnit::cloneAndEmitDebugLocations() {441 if (getGlobalData().getOptions().UpdateIndexTablesOnly)442 return Error::success();443 444 if (getOrigUnit().getVersion() < 5) {445 emitLocations(DebugSectionKind::DebugLoc);446 return Error::success();447 }448 449 emitLocations(DebugSectionKind::DebugLocLists);450 return Error::success();451}452 453void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {454 SectionDescriptor &DebugInfoSection =455 getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);456 457 if (!DebugInfoSection.ListDebugLocPatch.empty()) {458 SectionDescriptor &OutLocationSection =459 getOrCreateSectionDescriptor(LocationSectionKind);460 DWARFUnit &OrigUnit = getOrigUnit();461 462 uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);463 464 DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {465 // Get location expressions vector corresponding to the current466 // attribute from the source DWARF.467 uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(468 Patch.PatchOffset,469 DebugInfoSection.getFormParams().getDwarfOffsetByteSize());470 Expected<DWARFLocationExpressionsVector> OriginalLocations =471 OrigUnit.findLoclistFromOffset(InputDebugLocSectionOffset);472 473 if (!OriginalLocations) {474 warn(OriginalLocations.takeError());475 return;476 }477 478 LinkedLocationExpressionsVector LinkedLocationExpressions;479 for (DWARFLocationExpression &CurExpression : *OriginalLocations) {480 LinkedLocationExpressionsWithOffsetPatches LinkedExpression;481 482 if (CurExpression.Range) {483 // Relocate address range.484 LinkedExpression.Expression.Range = {485 CurExpression.Range->LowPC + Patch.AddrAdjustmentValue,486 CurExpression.Range->HighPC + Patch.AddrAdjustmentValue};487 }488 489 DataExtractor Data(CurExpression.Expr, OrigUnit.isLittleEndian(),490 OrigUnit.getAddressByteSize());491 492 DWARFExpression InputExpression(Data, OrigUnit.getAddressByteSize(),493 OrigUnit.getFormParams().Format);494 cloneDieAttrExpression(InputExpression,495 LinkedExpression.Expression.Expr,496 OutLocationSection, Patch.AddrAdjustmentValue,497 LinkedExpression.Patches);498 499 LinkedLocationExpressions.push_back({LinkedExpression});500 }501 502 // Emit locations list table fragment corresponding to the CurLocAttr.503 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,504 OutLocationSection.OS.tell());505 emitLocListFragment(LinkedLocationExpressions, OutLocationSection);506 });507 508 if (OffsetAfterUnitLength > 0) {509 assert(OffsetAfterUnitLength -510 OutLocationSection.getFormParams().getDwarfOffsetByteSize() <511 OffsetAfterUnitLength);512 OutLocationSection.apply(513 OffsetAfterUnitLength -514 OutLocationSection.getFormParams().getDwarfOffsetByteSize(),515 dwarf::DW_FORM_sec_offset,516 OutLocationSection.OS.tell() - OffsetAfterUnitLength);517 }518 }519}520 521/// Emit debug locations(.debug_loc, .debug_loclists) header.522uint64_t CompileUnit::emitLocListHeader(SectionDescriptor &OutLocationSection) {523 if (getOrigUnit().getVersion() < 5)524 return 0;525 526 // unit_length.527 OutLocationSection.emitUnitLength(0xBADDEF);528 uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell();529 530 // Version.531 OutLocationSection.emitIntVal(5, 2);532 533 // Address size.534 OutLocationSection.emitIntVal(OutLocationSection.getFormParams().AddrSize, 1);535 536 // Seg_size537 OutLocationSection.emitIntVal(0, 1);538 539 // Offset entry count540 OutLocationSection.emitIntVal(0, 4);541 542 return OffsetAfterUnitLength;543}544 545/// Emit debug locations(.debug_loc, .debug_loclists) fragment.546uint64_t CompileUnit::emitLocListFragment(547 const LinkedLocationExpressionsVector &LinkedLocationExpression,548 SectionDescriptor &OutLocationSection) {549 uint64_t OffsetBeforeLocationExpression = 0;550 551 if (getOrigUnit().getVersion() < 5) {552 uint64_t BaseAddress = 0;553 if (std::optional<uint64_t> LowPC = getLowPc())554 BaseAddress = *LowPC;555 556 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :557 LinkedLocationExpression) {558 if (LocExpression.Expression.Range) {559 OutLocationSection.emitIntVal(560 LocExpression.Expression.Range->LowPC - BaseAddress,561 OutLocationSection.getFormParams().AddrSize);562 OutLocationSection.emitIntVal(563 LocExpression.Expression.Range->HighPC - BaseAddress,564 OutLocationSection.getFormParams().AddrSize);565 }566 567 OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2);568 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();569 for (uint64_t *OffsetPtr : LocExpression.Patches)570 *OffsetPtr += OffsetBeforeLocationExpression;571 572 OutLocationSection.OS573 << StringRef((const char *)LocExpression.Expression.Expr.data(),574 LocExpression.Expression.Expr.size());575 }576 577 // Emit the terminator entry.578 OutLocationSection.emitIntVal(0,579 OutLocationSection.getFormParams().AddrSize);580 OutLocationSection.emitIntVal(0,581 OutLocationSection.getFormParams().AddrSize);582 return OffsetBeforeLocationExpression;583 }584 585 std::optional<uint64_t> BaseAddress;586 for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :587 LinkedLocationExpression) {588 if (LocExpression.Expression.Range) {589 // Check whether base address is set. If it is not set yet590 // then set current base address and emit base address selection entry.591 if (!BaseAddress) {592 BaseAddress = LocExpression.Expression.Range->LowPC;593 594 // Emit base address.595 OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1);596 encodeULEB128(DebugAddrIndexMap.getValueIndex(*BaseAddress),597 OutLocationSection.OS);598 }599 600 // Emit type of entry.601 OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1);602 603 // Emit start offset relative to base address.604 encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,605 OutLocationSection.OS);606 607 // Emit end offset relative to base address.608 encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,609 OutLocationSection.OS);610 } else611 // Emit type of entry.612 OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1);613 614 encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS);615 OffsetBeforeLocationExpression = OutLocationSection.OS.tell();616 for (uint64_t *OffsetPtr : LocExpression.Patches)617 *OffsetPtr += OffsetBeforeLocationExpression;618 619 OutLocationSection.OS << StringRef(620 (const char *)LocExpression.Expression.Expr.data(),621 LocExpression.Expression.Expr.size());622 }623 624 // Emit the terminator entry.625 OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1);626 return OffsetBeforeLocationExpression;627}628 629Error CompileUnit::emitDebugAddrSection() {630 if (GlobalData.getOptions().UpdateIndexTablesOnly)631 return Error::success();632 633 if (getVersion() < 5)634 return Error::success();635 636 if (DebugAddrIndexMap.empty())637 return Error::success();638 639 SectionDescriptor &OutAddrSection =640 getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr);641 642 // Emit section header.643 644 // Emit length.645 OutAddrSection.emitUnitLength(0xBADDEF);646 uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell();647 648 // Emit version.649 OutAddrSection.emitIntVal(5, 2);650 651 // Emit address size.652 OutAddrSection.emitIntVal(getFormParams().AddrSize, 1);653 654 // Emit segment size.655 OutAddrSection.emitIntVal(0, 1);656 657 // Emit addresses.658 for (uint64_t AddrValue : DebugAddrIndexMap.getValues())659 OutAddrSection.emitIntVal(AddrValue, getFormParams().AddrSize);660 661 // Patch section length.662 OutAddrSection.apply(663 OffsetAfterSectionLength -664 OutAddrSection.getFormParams().getDwarfOffsetByteSize(),665 dwarf::DW_FORM_sec_offset,666 OutAddrSection.OS.tell() - OffsetAfterSectionLength);667 668 return Error::success();669}670 671Error CompileUnit::cloneAndEmitRanges() {672 if (getGlobalData().getOptions().UpdateIndexTablesOnly)673 return Error::success();674 675 // Build set of linked address ranges for unit function ranges.676 AddressRanges LinkedFunctionRanges;677 for (const AddressRangeValuePair &Range : getFunctionRanges())678 LinkedFunctionRanges.insert(679 {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});680 681 emitAranges(LinkedFunctionRanges);682 683 if (getOrigUnit().getVersion() < 5) {684 cloneAndEmitRangeList(DebugSectionKind::DebugRange, LinkedFunctionRanges);685 return Error::success();686 }687 688 cloneAndEmitRangeList(DebugSectionKind::DebugRngLists, LinkedFunctionRanges);689 return Error::success();690}691 692void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,693 AddressRanges &LinkedFunctionRanges) {694 SectionDescriptor &DebugInfoSection =695 getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);696 SectionDescriptor &OutRangeSection =697 getOrCreateSectionDescriptor(RngSectionKind);698 699 if (!DebugInfoSection.ListDebugRangePatch.empty()) {700 std::optional<AddressRangeValuePair> CachedRange;701 uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);702 703 DebugRangePatch *CompileUnitRangePtr = nullptr;704 DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {705 if (Patch.IsCompileUnitRanges) {706 CompileUnitRangePtr = &Patch;707 } else {708 // Get ranges from the source DWARF corresponding to the current709 // attribute.710 AddressRanges LinkedRanges;711 uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(712 Patch.PatchOffset,713 DebugInfoSection.getFormParams().getDwarfOffsetByteSize());714 if (Expected<DWARFAddressRangesVector> InputRanges =715 getOrigUnit().findRnglistFromOffset(716 InputDebugRangesSectionOffset)) {717 // Apply relocation adjustment.718 for (const auto &Range : *InputRanges) {719 if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))720 CachedRange =721 getFunctionRanges().getRangeThatContains(Range.LowPC);722 723 // All range entries should lie in the function range.724 if (!CachedRange) {725 warn("inconsistent range data.");726 continue;727 }728 729 // Store range for emiting.730 LinkedRanges.insert({Range.LowPC + CachedRange->Value,731 Range.HighPC + CachedRange->Value});732 }733 } else {734 llvm::consumeError(InputRanges.takeError());735 warn("invalid range list ignored.");736 }737 738 // Emit linked ranges.739 DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,740 OutRangeSection.OS.tell());741 emitRangeListFragment(LinkedRanges, OutRangeSection);742 }743 });744 745 if (CompileUnitRangePtr != nullptr) {746 // Emit compile unit ranges last to be binary compatible with classic747 // dsymutil.748 DebugInfoSection.apply(CompileUnitRangePtr->PatchOffset,749 dwarf::DW_FORM_sec_offset,750 OutRangeSection.OS.tell());751 emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);752 }753 754 if (OffsetAfterUnitLength > 0) {755 assert(OffsetAfterUnitLength -756 OutRangeSection.getFormParams().getDwarfOffsetByteSize() <757 OffsetAfterUnitLength);758 OutRangeSection.apply(759 OffsetAfterUnitLength -760 OutRangeSection.getFormParams().getDwarfOffsetByteSize(),761 dwarf::DW_FORM_sec_offset,762 OutRangeSection.OS.tell() - OffsetAfterUnitLength);763 }764 }765}766 767uint64_t CompileUnit::emitRangeListHeader(SectionDescriptor &OutRangeSection) {768 if (OutRangeSection.getFormParams().Version < 5)769 return 0;770 771 // unit_length.772 OutRangeSection.emitUnitLength(0xBADDEF);773 uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell();774 775 // Version.776 OutRangeSection.emitIntVal(5, 2);777 778 // Address size.779 OutRangeSection.emitIntVal(OutRangeSection.getFormParams().AddrSize, 1);780 781 // Seg_size782 OutRangeSection.emitIntVal(0, 1);783 784 // Offset entry count785 OutRangeSection.emitIntVal(0, 4);786 787 return OffsetAfterUnitLength;788}789 790void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges,791 SectionDescriptor &OutRangeSection) {792 if (OutRangeSection.getFormParams().Version < 5) {793 // Emit ranges.794 uint64_t BaseAddress = 0;795 if (std::optional<uint64_t> LowPC = getLowPc())796 BaseAddress = *LowPC;797 798 for (const AddressRange &Range : LinkedRanges) {799 OutRangeSection.emitIntVal(Range.start() - BaseAddress,800 OutRangeSection.getFormParams().AddrSize);801 OutRangeSection.emitIntVal(Range.end() - BaseAddress,802 OutRangeSection.getFormParams().AddrSize);803 }804 805 // Add the terminator entry.806 OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);807 OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);808 return;809 }810 811 std::optional<uint64_t> BaseAddress;812 for (const AddressRange &Range : LinkedRanges) {813 if (!BaseAddress) {814 BaseAddress = Range.start();815 816 // Emit base address.817 OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1);818 encodeULEB128(getDebugAddrIndex(*BaseAddress), OutRangeSection.OS);819 }820 821 // Emit type of entry.822 OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1);823 824 // Emit start offset relative to base address.825 encodeULEB128(Range.start() - *BaseAddress, OutRangeSection.OS);826 827 // Emit end offset relative to base address.828 encodeULEB128(Range.end() - *BaseAddress, OutRangeSection.OS);829 }830 831 // Emit the terminator entry.832 OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1);833}834 835void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) {836 if (LinkedFunctionRanges.empty())837 return;838 839 SectionDescriptor &DebugInfoSection =840 getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);841 SectionDescriptor &OutArangesSection =842 getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges);843 844 // Emit Header.845 unsigned HeaderSize =846 sizeof(int32_t) + // Size of contents (w/o this field847 sizeof(int16_t) + // DWARF ARange version number848 sizeof(int32_t) + // Offset of CU in the .debug_info section849 sizeof(int8_t) + // Pointer Size (in bytes)850 sizeof(int8_t); // Segment Size (in bytes)851 852 unsigned TupleSize = OutArangesSection.getFormParams().AddrSize * 2;853 unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));854 855 OutArangesSection.emitOffset(0xBADDEF); // Aranges length856 uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell();857 858 OutArangesSection.emitIntVal(dwarf::DW_ARANGES_VERSION, 2); // Version number859 OutArangesSection.notePatch(860 DebugOffsetPatch{OutArangesSection.OS.tell(), &DebugInfoSection});861 OutArangesSection.emitOffset(0xBADDEF); // Corresponding unit's offset862 OutArangesSection.emitIntVal(OutArangesSection.getFormParams().AddrSize,863 1); // Address size864 OutArangesSection.emitIntVal(0, 1); // Segment size865 866 for (size_t Idx = 0; Idx < Padding; Idx++)867 OutArangesSection.emitIntVal(0, 1); // Padding868 869 // Emit linked ranges.870 for (const AddressRange &Range : LinkedFunctionRanges) {871 OutArangesSection.emitIntVal(Range.start(),872 OutArangesSection.getFormParams().AddrSize);873 OutArangesSection.emitIntVal(Range.end() - Range.start(),874 OutArangesSection.getFormParams().AddrSize);875 }876 877 // Emit terminator.878 OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);879 OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);880 881 uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell();882 883 // Update Aranges lentgh.884 OutArangesSection.apply(885 OffsetAfterArangesLengthField -886 OutArangesSection.getFormParams().getDwarfOffsetByteSize(),887 dwarf::DW_FORM_sec_offset,888 OffsetAfterArangesEnd - OffsetAfterArangesLengthField);889}890 891Error CompileUnit::cloneAndEmitDebugMacro() {892 if (getOutUnitDIE() == nullptr)893 return Error::success();894 895 DWARFUnit &OrigUnit = getOrigUnit();896 DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();897 898 // Check for .debug_macro table.899 if (std::optional<uint64_t> MacroAttr =900 dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macros))) {901 if (const DWARFDebugMacro *Table =902 getContaingFile().Dwarf->getDebugMacro()) {903 emitMacroTableImpl(Table, *MacroAttr, true);904 }905 }906 907 // Check for .debug_macinfo table.908 if (std::optional<uint64_t> MacroAttr =909 dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macro_info))) {910 if (const DWARFDebugMacro *Table =911 getContaingFile().Dwarf->getDebugMacinfo()) {912 emitMacroTableImpl(Table, *MacroAttr, false);913 }914 }915 916 return Error::success();917}918 919void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,920 uint64_t OffsetToMacroTable,921 bool hasDWARFv5Header) {922 SectionDescriptor &OutSection =923 hasDWARFv5Header924 ? getOrCreateSectionDescriptor(DebugSectionKind::DebugMacro)925 : getOrCreateSectionDescriptor(DebugSectionKind::DebugMacinfo);926 927 bool DefAttributeIsReported = false;928 bool UndefAttributeIsReported = false;929 bool ImportAttributeIsReported = false;930 931 for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {932 if (OffsetToMacroTable == List.Offset) {933 // Write DWARFv5 header.934 if (hasDWARFv5Header) {935 // Write header version.936 OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version));937 938 uint8_t Flags = List.Header.Flags;939 940 // Check for OPCODE_OPERANDS_TABLE.941 if (Flags &942 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {943 Flags &=944 ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;945 warn("opcode_operands_table is not supported yet.");946 }947 948 // Check for DEBUG_LINE_OFFSET.949 std::optional<uint64_t> StmtListOffset;950 if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {951 // Get offset to the line table from the cloned compile unit.952 for (auto &V : getOutUnitDIE()->values()) {953 if (V.getAttribute() == dwarf::DW_AT_stmt_list) {954 StmtListOffset = V.getDIEInteger().getValue();955 break;956 }957 }958 959 if (!StmtListOffset) {960 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;961 warn("couldn`t find line table for macro table.");962 }963 }964 965 // Write flags.966 OutSection.emitIntVal(Flags, sizeof(Flags));967 968 // Write offset to line table.969 if (StmtListOffset) {970 OutSection.notePatch(DebugOffsetPatch{971 OutSection.OS.tell(),972 &getOrCreateSectionDescriptor(DebugSectionKind::DebugLine)});973 // TODO: check that List.Header.getOffsetByteSize() and974 // DebugOffsetPatch agree on size.975 OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize());976 }977 }978 979 // Write macro entries.980 for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {981 if (MacroEntry.Type == 0) {982 encodeULEB128(MacroEntry.Type, OutSection.OS);983 continue;984 }985 986 uint8_t MacroType = MacroEntry.Type;987 switch (MacroType) {988 default: {989 bool HasVendorSpecificExtension =990 (!hasDWARFv5Header &&991 MacroType == dwarf::DW_MACINFO_vendor_ext) ||992 (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&993 MacroType <= dwarf::DW_MACRO_hi_user));994 995 if (HasVendorSpecificExtension) {996 // Write macinfo type.997 OutSection.emitIntVal(MacroType, 1);998 999 // Write vendor extension constant.1000 encodeULEB128(MacroEntry.ExtConstant, OutSection.OS);1001 1002 // Write vendor extension string.1003 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);1004 } else1005 warn("unknown macro type. skip.");1006 } break;1007 // debug_macro and debug_macinfo share some common encodings.1008 // DW_MACRO_define == DW_MACINFO_define1009 // DW_MACRO_undef == DW_MACINFO_undef1010 // DW_MACRO_start_file == DW_MACINFO_start_file1011 // DW_MACRO_end_file == DW_MACINFO_end_file1012 // For readibility/uniformity we are using DW_MACRO_*.1013 case dwarf::DW_MACRO_define:1014 case dwarf::DW_MACRO_undef: {1015 // Write macinfo type.1016 OutSection.emitIntVal(MacroType, 1);1017 1018 // Write source line.1019 encodeULEB128(MacroEntry.Line, OutSection.OS);1020 1021 // Write macro string.1022 OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);1023 } break;1024 case dwarf::DW_MACRO_define_strp:1025 case dwarf::DW_MACRO_undef_strp:1026 case dwarf::DW_MACRO_define_strx:1027 case dwarf::DW_MACRO_undef_strx: {1028 // DW_MACRO_*_strx forms are not supported currently.1029 // Convert to *_strp.1030 switch (MacroType) {1031 case dwarf::DW_MACRO_define_strx: {1032 MacroType = dwarf::DW_MACRO_define_strp;1033 if (!DefAttributeIsReported) {1034 warn("DW_MACRO_define_strx unsupported yet. Convert to "1035 "DW_MACRO_define_strp.");1036 DefAttributeIsReported = true;1037 }1038 } break;1039 case dwarf::DW_MACRO_undef_strx: {1040 MacroType = dwarf::DW_MACRO_undef_strp;1041 if (!UndefAttributeIsReported) {1042 warn("DW_MACRO_undef_strx unsupported yet. Convert to "1043 "DW_MACRO_undef_strp.");1044 UndefAttributeIsReported = true;1045 }1046 } break;1047 default:1048 // Nothing to do.1049 break;1050 }1051 1052 // Write macinfo type.1053 OutSection.emitIntVal(MacroType, 1);1054 1055 // Write source line.1056 encodeULEB128(MacroEntry.Line, OutSection.OS);1057 1058 // Write macro string.1059 OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);1060 break;1061 }1062 case dwarf::DW_MACRO_start_file: {1063 // Write macinfo type.1064 OutSection.emitIntVal(MacroType, 1);1065 // Write source line.1066 encodeULEB128(MacroEntry.Line, OutSection.OS);1067 // Write source file id.1068 encodeULEB128(MacroEntry.File, OutSection.OS);1069 } break;1070 case dwarf::DW_MACRO_end_file: {1071 // Write macinfo type.1072 OutSection.emitIntVal(MacroType, 1);1073 } break;1074 case dwarf::DW_MACRO_import:1075 case dwarf::DW_MACRO_import_sup: {1076 if (!ImportAttributeIsReported) {1077 warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported "1078 "yet. remove.");1079 ImportAttributeIsReported = true;1080 }1081 } break;1082 }1083 }1084 1085 return;1086 }1087 }1088}1089 1090void CompileUnit::cloneDieAttrExpression(1091 const DWARFExpression &InputExpression,1092 SmallVectorImpl<uint8_t> &OutputExpression, SectionDescriptor &Section,1093 std::optional<int64_t> VarAddressAdjustment,1094 OffsetsPtrVector &PatchesOffsets) {1095 using Encoding = DWARFExpression::Operation::Encoding;1096 1097 DWARFUnit &OrigUnit = getOrigUnit();1098 uint8_t OrigAddressByteSize = OrigUnit.getAddressByteSize();1099 1100 uint64_t OpOffset = 0;1101 for (auto &Op : InputExpression) {1102 auto Desc = Op.getDescription();1103 // DW_OP_const_type is variable-length and has 31104 // operands. Thus far we only support 2.1105 if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||1106 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&1107 Desc.Op[0] != Encoding::Size1))1108 warn("unsupported DW_OP encoding.");1109 1110 if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||1111 (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&1112 Desc.Op[0] == Encoding::Size1)) {1113 // This code assumes that the other non-typeref operand fits into 1 byte.1114 assert(OpOffset < Op.getEndOffset());1115 uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;1116 assert(ULEBsize <= 16);1117 1118 // Copy over the operation.1119 assert(!Op.getSubCode() && "SubOps not yet supported");1120 OutputExpression.push_back(Op.getCode());1121 uint64_t RefOffset;1122 if (Desc.Op.size() == 1) {1123 RefOffset = Op.getRawOperand(0);1124 } else {1125 OutputExpression.push_back(Op.getRawOperand(0));1126 RefOffset = Op.getRawOperand(1);1127 }1128 uint8_t ULEB[16];1129 uint32_t Offset = 0;1130 unsigned RealSize = 0;1131 // Look up the base type. For DW_OP_convert, the operand may be 0 to1132 // instead indicate the generic type. The same holds for1133 // DW_OP_reinterpret, which is currently not supported.1134 if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {1135 RefOffset += OrigUnit.getOffset();1136 uint32_t RefDieIdx = 0;1137 if (std::optional<uint32_t> Idx =1138 OrigUnit.getDIEIndexForOffset(RefOffset))1139 RefDieIdx = *Idx;1140 1141 // Use fixed size for ULEB128 data, since we need to update that size1142 // later with the proper offsets. Use 5 for DWARF32, 9 for DWARF64.1143 ULEBsize = getFormParams().getDwarfOffsetByteSize() + 1;1144 1145 RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize);1146 1147 Section.notePatchWithOffsetUpdate(1148 DebugULEB128DieRefPatch(OutputExpression.size(), this, this,1149 RefDieIdx),1150 PatchesOffsets);1151 } else1152 RealSize = encodeULEB128(Offset, ULEB, ULEBsize);1153 1154 if (RealSize > ULEBsize) {1155 // Emit the generic type as a fallback.1156 RealSize = encodeULEB128(0, ULEB, ULEBsize);1157 warn("base type ref doesn't fit.");1158 }1159 assert(RealSize == ULEBsize && "padding failed");1160 ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);1161 OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());1162 } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&1163 Op.getCode() == dwarf::DW_OP_addrx) {1164 if (std::optional<object::SectionedAddress> SA =1165 OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {1166 // DWARFLinker does not use addrx forms since it generates relocated1167 // addresses. Replace DW_OP_addrx with DW_OP_addr here.1168 // Argument of DW_OP_addrx should be relocated here as it is not1169 // processed by applyValidRelocs.1170 OutputExpression.push_back(dwarf::DW_OP_addr);1171 uint64_t LinkedAddress = SA->Address + VarAddressAdjustment.value_or(0);1172 if (getEndianness() != llvm::endianness::native)1173 sys::swapByteOrder(LinkedAddress);1174 ArrayRef<uint8_t> AddressBytes(1175 reinterpret_cast<const uint8_t *>(&LinkedAddress),1176 OrigAddressByteSize);1177 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());1178 } else1179 warn("cann't read DW_OP_addrx operand.");1180 } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&1181 Op.getCode() == dwarf::DW_OP_constx) {1182 if (std::optional<object::SectionedAddress> SA =1183 OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {1184 // DWARFLinker does not use constx forms since it generates relocated1185 // addresses. Replace DW_OP_constx with DW_OP_const[*]u here.1186 // Argument of DW_OP_constx should be relocated here as it is not1187 // processed by applyValidRelocs.1188 std::optional<uint8_t> OutOperandKind;1189 switch (OrigAddressByteSize) {1190 case 2:1191 OutOperandKind = dwarf::DW_OP_const2u;1192 break;1193 case 4:1194 OutOperandKind = dwarf::DW_OP_const4u;1195 break;1196 case 8:1197 OutOperandKind = dwarf::DW_OP_const8u;1198 break;1199 default:1200 warn(1201 formatv(("unsupported address size: {0}."), OrigAddressByteSize));1202 break;1203 }1204 1205 if (OutOperandKind) {1206 OutputExpression.push_back(*OutOperandKind);1207 uint64_t LinkedAddress =1208 SA->Address + VarAddressAdjustment.value_or(0);1209 if (getEndianness() != llvm::endianness::native)1210 sys::swapByteOrder(LinkedAddress);1211 ArrayRef<uint8_t> AddressBytes(1212 reinterpret_cast<const uint8_t *>(&LinkedAddress),1213 OrigAddressByteSize);1214 OutputExpression.append(AddressBytes.begin(), AddressBytes.end());1215 }1216 } else1217 warn("cann't read DW_OP_constx operand.");1218 } else {1219 // Copy over everything else unmodified.1220 StringRef Bytes =1221 InputExpression.getData().slice(OpOffset, Op.getEndOffset());1222 OutputExpression.append(Bytes.begin(), Bytes.end());1223 }1224 OpOffset = Op.getEndOffset();1225 }1226}1227 1228Error CompileUnit::cloneAndEmit(1229 std::optional<std::reference_wrapper<const Triple>> TargetTriple,1230 TypeUnit *ArtificialTypeUnit) {1231 BumpPtrAllocator Allocator;1232 1233 DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE();1234 if (!OrigUnitDIE.isValid())1235 return Error::success();1236 1237 TypeEntry *RootEntry = nullptr;1238 if (ArtificialTypeUnit)1239 RootEntry = ArtificialTypeUnit->getTypePool().getRoot();1240 1241 // Clone input DIE entry recursively.1242 std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(1243 OrigUnitDIE.getDebugInfoEntry(), RootEntry, getDebugInfoHeaderSize(),1244 std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);1245 setOutUnitDIE(OutCUDie.first);1246 1247 if (!TargetTriple.has_value() || (OutCUDie.first == nullptr))1248 return Error::success();1249 1250 if (Error Err = cloneAndEmitLineTable((*TargetTriple).get()))1251 return Err;1252 1253 if (Error Err = cloneAndEmitDebugMacro())1254 return Err;1255 1256 getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);1257 if (Error Err = emitDebugInfo((*TargetTriple).get()))1258 return Err;1259 1260 // ASSUMPTION: .debug_info section should already be emitted at this point.1261 // cloneAndEmitRanges & cloneAndEmitDebugLocations use .debug_info section1262 // data.1263 1264 if (Error Err = cloneAndEmitRanges())1265 return Err;1266 1267 if (Error Err = cloneAndEmitDebugLocations())1268 return Err;1269 1270 if (Error Err = emitDebugAddrSection())1271 return Err;1272 1273 // Generate Pub accelerator tables.1274 if (llvm::is_contained(GlobalData.getOptions().AccelTables,1275 DWARFLinker::AccelTableKind::Pub))1276 emitPubAccelerators();1277 1278 if (Error Err = emitDebugStringOffsetSection())1279 return Err;1280 1281 return emitAbbreviations();1282}1283 1284std::pair<DIE *, TypeEntry *> CompileUnit::cloneDIE(1285 const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE,1286 uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,1287 std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,1288 TypeUnit *ArtificialTypeUnit) {1289 uint32_t InputDieIdx = getDIEIndex(InputDieEntry);1290 CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);1291 1292 bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();1293 bool NeedToCloneTypeDIE =1294 (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&1295 Info.needToPlaceInTypeTable();1296 std::pair<DIE *, TypeEntry *> ClonedDIE;1297 1298 DIEGenerator PlainDIEGenerator(Allocator, *this);1299 1300 if (NeedToClonePlainDIE)1301 // Create a cloned DIE which would be placed into the cloned version1302 // of input compile unit.1303 ClonedDIE.first = createPlainDIEandCloneAttributes(1304 InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,1305 VarAddressAdjustment);1306 if (NeedToCloneTypeDIE) {1307 // Create a cloned DIE which would be placed into the artificial type1308 // unit.1309 assert(ArtificialTypeUnit != nullptr);1310 DIEGenerator TypeDIEGenerator(1311 ArtificialTypeUnit->getTypePool().getThreadLocalAllocator(), *this);1312 1313 ClonedDIE.second = createTypeDIEandCloneAttributes(1314 InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,1315 ArtificialTypeUnit);1316 }1317 TypeEntry *TypeParentForChild =1318 ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;1319 1320 bool HasPlainChildrenToClone =1321 (ClonedDIE.first && Info.getKeepPlainChildren());1322 1323 bool HasTypeChildrenToClone =1324 ((ClonedDIE.second ||1325 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&1326 Info.getKeepTypeChildren());1327 1328 // Recursively clone children.1329 if (HasPlainChildrenToClone || HasTypeChildrenToClone) {1330 for (const DWARFDebugInfoEntry *CurChild =1331 getFirstChildEntry(InputDieEntry);1332 CurChild && CurChild->getAbbreviationDeclarationPtr();1333 CurChild = getSiblingEntry(CurChild)) {1334 std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(1335 CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,1336 VarAddressAdjustment, Allocator, ArtificialTypeUnit);1337 1338 if (ClonedChild.first) {1339 OutOffset =1340 ClonedChild.first->getOffset() + ClonedChild.first->getSize();1341 PlainDIEGenerator.addChild(ClonedChild.first);1342 }1343 }1344 assert(ClonedDIE.first == nullptr ||1345 HasPlainChildrenToClone == ClonedDIE.first->hasChildren());1346 1347 // Account for the end of children marker.1348 if (HasPlainChildrenToClone)1349 OutOffset += sizeof(int8_t);1350 }1351 1352 // Update our size.1353 if (ClonedDIE.first != nullptr)1354 ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());1355 1356 return ClonedDIE;1357}1358 1359DIE *CompileUnit::createPlainDIEandCloneAttributes(1360 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,1361 uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,1362 std::optional<int64_t> &VarAddressAdjustment) {1363 uint32_t InputDieIdx = getDIEIndex(InputDieEntry);1364 CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);1365 DIE *ClonedDIE = nullptr;1366 bool HasLocationExpressionAddress = false;1367 if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {1368 // Get relocation adjustment value for the current function.1369 FuncAddressAdjustment =1370 getContaingFile().Addresses->getSubprogramRelocAdjustment(1371 getDIE(InputDieEntry), false);1372 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {1373 // Get relocation adjustment value for the current label.1374 std::optional<uint64_t> lowPC =1375 dwarf::toAddress(find(InputDieEntry, dwarf::DW_AT_low_pc));1376 if (lowPC) {1377 LabelMapTy::iterator It = Labels.find(*lowPC);1378 if (It != Labels.end())1379 FuncAddressAdjustment = It->second;1380 }1381 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {1382 // Get relocation adjustment value for the current variable.1383 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =1384 getContaingFile().Addresses->getVariableRelocAdjustment(1385 getDIE(InputDieEntry), false);1386 1387 HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;1388 if (LocExprAddrAndRelocAdjustment.first &&1389 LocExprAddrAndRelocAdjustment.second)1390 VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;1391 }1392 1393 ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);1394 1395 // Offset to the DIE would be used after output DIE tree is deleted.1396 // Thus we need to remember DIE offset separately.1397 rememberDieOutOffset(InputDieIdx, OutOffset);1398 1399 // Clone Attributes.1400 DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,1401 PlainDIEGenerator, FuncAddressAdjustment,1402 VarAddressAdjustment,1403 HasLocationExpressionAddress);1404 AttributesCloner.clone();1405 1406 // Remember accelerator info.1407 AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this);1408 AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,1409 nullptr);1410 1411 OutOffset =1412 AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());1413 1414 return ClonedDIE;1415}1416 1417/// Allocates output DIE for the specified \p TypeDescriptor.1418DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,1419 DIEGenerator &TypeDIEGenerator,1420 dwarf::Tag DieTag, bool IsDeclaration,1421 bool IsParentDeclaration) {1422 DIE *DefinitionDie = TypeDescriptor->Die;1423 // Do not allocate any new DIE if definition DIE is already met.1424 if (DefinitionDie)1425 return nullptr;1426 1427 DIE *DeclarationDie = TypeDescriptor->DeclarationDie;1428 bool OldParentIsDeclaration = TypeDescriptor->ParentIsDeclaration;1429 1430 if (IsDeclaration && !DeclarationDie) {1431 // Alocate declaration DIE.1432 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);1433 if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,1434 NewDie))1435 return NewDie;1436 } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {1437 // Overwrite existing declaration DIE if it's parent is also an declaration1438 // while parent of current declaration DIE is a definition.1439 if (TypeDescriptor->ParentIsDeclaration.compare_exchange_strong(1440 OldParentIsDeclaration, false)) {1441 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);1442 TypeDescriptor->DeclarationDie = NewDie;1443 return NewDie;1444 }1445 } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {1446 // Alocate declaration DIE since parent of current DIE is marked as1447 // declaration.1448 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);1449 if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,1450 NewDie))1451 return NewDie;1452 } else if (!IsDeclaration && !IsParentDeclaration) {1453 // Allocate definition DIE.1454 DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);1455 if (TypeDescriptor->Die.compare_exchange_strong(DefinitionDie, NewDie)) {1456 TypeDescriptor->ParentIsDeclaration = false;1457 return NewDie;1458 }1459 }1460 1461 return nullptr;1462}1463 1464TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(1465 const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,1466 TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit) {1467 assert(ArtificialTypeUnit != nullptr);1468 uint32_t InputDieIdx = getDIEIndex(InputDieEntry);1469 1470 TypeEntry *Entry = getDieTypeEntry(InputDieIdx);1471 assert(Entry != nullptr);1472 assert(ClonedParentTypeDIE != nullptr);1473 TypeEntryBody *EntryBody =1474 ArtificialTypeUnit->getTypePool().getOrCreateTypeEntryBody(1475 Entry, ClonedParentTypeDIE);1476 assert(EntryBody);1477 1478 bool IsDeclaration =1479 dwarf::toUnsigned(find(InputDieEntry, dwarf::DW_AT_declaration), 0);1480 1481 bool ParentIsDeclaration = false;1482 if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())1483 ParentIsDeclaration =1484 dwarf::toUnsigned(find(*ParentIdx, dwarf::DW_AT_declaration), 0);1485 1486 DIE *OutDIE =1487 allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),1488 IsDeclaration, ParentIsDeclaration);1489 1490 if (OutDIE != nullptr) {1491 assert(ArtificialTypeUnit != nullptr);1492 ArtificialTypeUnit->getSectionDescriptor(DebugSectionKind::DebugInfo);1493 1494 DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,1495 InputDieEntry, TypeDIEGenerator,1496 std::nullopt, std::nullopt, false);1497 AttributesCloner.clone();1498 1499 // Remember accelerator info.1500 AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this,1501 ArtificialTypeUnit);1502 AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,1503 Entry);1504 1505 // if AttributesCloner.getOutOffset() == 0 then we need to add1506 // 1 to avoid assertion for zero size. We will subtract it back later.1507 OutDIE->setSize(AttributesCloner.getOutOffset() + 1);1508 }1509 1510 return Entry;1511}1512 1513Error CompileUnit::cloneAndEmitLineTable(const Triple &TargetTriple) {1514 const DWARFDebugLine::LineTable *InputLineTable =1515 getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit());1516 if (InputLineTable == nullptr) {1517 if (getOrigUnit().getUnitDIE().find(dwarf::DW_AT_stmt_list))1518 warn("cann't load line table.");1519 return Error::success();1520 }1521 1522 DWARFDebugLine::LineTable OutLineTable;1523 1524 // Set Line Table header.1525 OutLineTable.Prologue = InputLineTable->Prologue;1526 OutLineTable.Prologue.FormParams.AddrSize = getFormParams().AddrSize;1527 1528 // Set Line Table Rows.1529 if (getGlobalData().getOptions().UpdateIndexTablesOnly) {1530 OutLineTable.Rows = InputLineTable->Rows;1531 // If all the line table contains is a DW_LNE_end_sequence, clear the line1532 // table rows, it will be inserted again in the DWARFStreamer.1533 if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence)1534 OutLineTable.Rows.clear();1535 1536 OutLineTable.Sequences = InputLineTable->Sequences;1537 } else {1538 // This vector is the output line table.1539 std::vector<DWARFDebugLine::Row> NewRows;1540 NewRows.reserve(InputLineTable->Rows.size());1541 1542 // Current sequence of rows being extracted, before being inserted1543 // in NewRows.1544 std::vector<DWARFDebugLine::Row> Seq;1545 1546 const auto &FunctionRanges = getFunctionRanges();1547 std::optional<AddressRangeValuePair> CurrRange;1548 1549 // FIXME: This logic is meant to generate exactly the same output as1550 // Darwin's classic dsymutil. There is a nicer way to implement this1551 // by simply putting all the relocated line info in NewRows and simply1552 // sorting NewRows before passing it to emitLineTableForUnit. This1553 // should be correct as sequences for a function should stay1554 // together in the sorted output. There are a few corner cases that1555 // look suspicious though, and that required to implement the logic1556 // this way. Revisit that once initial validation is finished.1557 1558 // Iterate over the object file line info and extract the sequences1559 // that correspond to linked functions.1560 for (DWARFDebugLine::Row Row : InputLineTable->Rows) {1561 // Check whether we stepped out of the range. The range is1562 // half-open, but consider accept the end address of the range if1563 // it is marked as end_sequence in the input (because in that1564 // case, the relocation offset is accurate and that entry won't1565 // serve as the start of another function).1566 if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {1567 // We just stepped out of a known range. Insert a end_sequence1568 // corresponding to the end of the range.1569 uint64_t StopAddress =1570 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;1571 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);1572 if (StopAddress != -1ULL && !Seq.empty()) {1573 // Insert end sequence row with the computed end address, but1574 // the same line as the previous one.1575 auto NextLine = Seq.back();1576 NextLine.Address.Address = StopAddress;1577 NextLine.EndSequence = 1;1578 NextLine.PrologueEnd = 0;1579 NextLine.BasicBlock = 0;1580 NextLine.EpilogueBegin = 0;1581 Seq.push_back(NextLine);1582 insertLineSequence(Seq, NewRows);1583 }1584 1585 if (!CurrRange)1586 continue;1587 }1588 1589 // Ignore empty sequences.1590 if (Row.EndSequence && Seq.empty())1591 continue;1592 1593 // Relocate row address and add it to the current sequence.1594 Row.Address.Address += CurrRange->Value;1595 Seq.emplace_back(Row);1596 1597 if (Row.EndSequence)1598 insertLineSequence(Seq, NewRows);1599 }1600 1601 OutLineTable.Rows = std::move(NewRows);1602 }1603 1604 return emitDebugLine(TargetTriple, OutLineTable);1605}1606 1607void CompileUnit::insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,1608 std::vector<DWARFDebugLine::Row> &Rows) {1609 if (Seq.empty())1610 return;1611 1612 if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {1613 llvm::append_range(Rows, Seq);1614 Seq.clear();1615 return;1616 }1617 1618 object::SectionedAddress Front = Seq.front().Address;1619 auto InsertPoint = partition_point(1620 Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; });1621 1622 // FIXME: this only removes the unneeded end_sequence if the1623 // sequences have been inserted in order. Using a global sort like1624 // described in cloneAndEmitLineTable() and delaying the end_sequene1625 // elimination to DebugLineEmitter::emit() we can get rid of all of them.1626 if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&1627 InsertPoint->EndSequence) {1628 *InsertPoint = Seq.front();1629 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());1630 } else {1631 Rows.insert(InsertPoint, Seq.begin(), Seq.end());1632 }1633 1634 Seq.clear();1635}1636 1637#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)1638LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {1639 llvm::errs() << "{";1640 llvm::errs() << " Placement: ";1641 switch (getPlacement()) {1642 case NotSet:1643 llvm::errs() << "NotSet";1644 break;1645 case TypeTable:1646 llvm::errs() << "TypeTable";1647 break;1648 case PlainDwarf:1649 llvm::errs() << "PlainDwarf";1650 break;1651 case Both:1652 llvm::errs() << "Both";1653 break;1654 }1655 1656 llvm::errs() << " Keep: " << getKeep();1657 llvm::errs() << " KeepPlainChildren: " << getKeepPlainChildren();1658 llvm::errs() << " KeepTypeChildren: " << getKeepTypeChildren();1659 llvm::errs() << " IsInMouduleScope: " << getIsInMouduleScope();1660 llvm::errs() << " IsInFunctionScope: " << getIsInFunctionScope();1661 llvm::errs() << " IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();1662 llvm::errs() << " ODRAvailable: " << getODRAvailable();1663 llvm::errs() << " TrackLiveness: " << getTrackLiveness();1664 llvm::errs() << "}\n";1665}1666#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)1667 1668std::optional<std::pair<StringRef, StringRef>>1669CompileUnit::getDirAndFilenameFromLineTable(1670 const DWARFFormValue &FileIdxValue) {1671 uint64_t FileIdx;1672 if (std::optional<uint64_t> Val = FileIdxValue.getAsUnsignedConstant())1673 FileIdx = *Val;1674 else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())1675 FileIdx = *Val;1676 else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())1677 FileIdx = *Val;1678 else1679 return std::nullopt;1680 1681 return getDirAndFilenameFromLineTable(FileIdx);1682}1683 1684std::optional<std::pair<StringRef, StringRef>>1685CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {1686 FileNamesCache::iterator FileData = FileNames.find(FileIdx);1687 if (FileData != FileNames.end())1688 return std::make_pair(StringRef(FileData->second.first),1689 StringRef(FileData->second.second));1690 1691 if (const DWARFDebugLine::LineTable *LineTable =1692 getOrigUnit().getContext().getLineTableForUnit(&getOrigUnit())) {1693 if (LineTable->hasFileAtIndex(FileIdx)) {1694 1695 const llvm::DWARFDebugLine::FileNameEntry &Entry =1696 LineTable->Prologue.getFileNameEntry(FileIdx);1697 1698 Expected<const char *> Name = Entry.Name.getAsCString();1699 if (!Name) {1700 warn(Name.takeError());1701 return std::nullopt;1702 }1703 1704 std::string FileName = *Name;1705 if (isPathAbsoluteOnWindowsOrPosix(FileName)) {1706 FileNamesCache::iterator FileData =1707 FileNames1708 .insert(std::make_pair(1709 FileIdx,1710 std::make_pair(std::string(""), std::move(FileName))))1711 .first;1712 return std::make_pair(StringRef(FileData->second.first),1713 StringRef(FileData->second.second));1714 }1715 1716 SmallString<256> FilePath;1717 StringRef IncludeDir;1718 // Be defensive about the contents of Entry.1719 if (getVersion() >= 5) {1720 // DirIdx 0 is the compilation directory, so don't include it for1721 // relative names.1722 if ((Entry.DirIdx != 0) &&1723 Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {1724 Expected<const char *> DirName =1725 LineTable->Prologue.IncludeDirectories[Entry.DirIdx]1726 .getAsCString();1727 if (DirName)1728 IncludeDir = *DirName;1729 else {1730 warn(DirName.takeError());1731 return std::nullopt;1732 }1733 }1734 } else {1735 if (0 < Entry.DirIdx &&1736 Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {1737 Expected<const char *> DirName =1738 LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]1739 .getAsCString();1740 if (DirName)1741 IncludeDir = *DirName;1742 else {1743 warn(DirName.takeError());1744 return std::nullopt;1745 }1746 }1747 }1748 1749 StringRef CompDir = getOrigUnit().getCompilationDir();1750 1751 if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) {1752 sys::path::append(FilePath, sys::path::Style::native, CompDir);1753 }1754 1755 sys::path::append(FilePath, sys::path::Style::native, IncludeDir);1756 1757 FileNamesCache::iterator FileData =1758 FileNames1759 .insert(1760 std::make_pair(FileIdx, std::make_pair(std::string(FilePath),1761 std::move(FileName))))1762 .first;1763 return std::make_pair(StringRef(FileData->second.first),1764 StringRef(FileData->second.second));1765 }1766 }1767 1768 return std::nullopt;1769}1770 1771#define MAX_REFERENCIES_DEPTH 10001772UnitEntryPairTy UnitEntryPairTy::getNamespaceOrigin() {1773 UnitEntryPairTy CUDiePair(*this);1774 std::optional<UnitEntryPairTy> RefDiePair;1775 int refDepth = 0;1776 do {1777 RefDiePair = CUDiePair.CU->resolveDIEReference(1778 CUDiePair.DieEntry, dwarf::DW_AT_extension,1779 ResolveInterCUReferencesMode::Resolve);1780 if (!RefDiePair || !RefDiePair->DieEntry)1781 return CUDiePair;1782 1783 CUDiePair = *RefDiePair;1784 } while (refDepth++ < MAX_REFERENCIES_DEPTH);1785 1786 return CUDiePair;1787}1788 1789std::optional<UnitEntryPairTy> UnitEntryPairTy::getParent() {1790 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())1791 return UnitEntryPairTy{CU, CU->getDebugInfoEntry(*ParentIdx)};1792 1793 return std::nullopt;1794}1795 1796CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(CompileUnit *U)1797 : Ptr(U) {1798 assert(U != nullptr);1799}1800 1801CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(TypeUnit *U) : Ptr(U) {1802 assert(U != nullptr);1803}1804 1805DwarfUnit *CompileUnit::OutputUnitVariantPtr::operator->() {1806 if (isCompileUnit())1807 return getAsCompileUnit();1808 else1809 return getAsTypeUnit();1810}1811 1812bool CompileUnit::OutputUnitVariantPtr::isCompileUnit() {1813 return isa<CompileUnit *>(Ptr);1814}1815 1816bool CompileUnit::OutputUnitVariantPtr::isTypeUnit() {1817 return isa<TypeUnit *>(Ptr);1818}1819 1820CompileUnit *CompileUnit::OutputUnitVariantPtr::getAsCompileUnit() {1821 return cast<CompileUnit *>(Ptr);1822}1823 1824TypeUnit *CompileUnit::OutputUnitVariantPtr::getAsTypeUnit() {1825 return cast<TypeUnit *>(Ptr);1826}1827 1828bool CompileUnit::resolveDependenciesAndMarkLiveness(1829 bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {1830 if (!Dependencies)1831 Dependencies.reset(new DependencyTracker(*this));1832 1833 return Dependencies->resolveDependenciesAndMarkLiveness(1834 InterCUProcessingStarted, HasNewInterconnectedCUs);1835}1836 1837bool CompileUnit::updateDependenciesCompleteness() {1838 assert(Dependencies.get());1839 1840 return Dependencies->updateDependenciesCompleteness();1841}1842 1843void CompileUnit::verifyDependencies() {1844 assert(Dependencies.get());1845 1846 Dependencies->verifyKeepChain();1847}1848 1849ArrayRef<dwarf::Attribute> dwarf_linker::parallel::getODRAttributes() {1850 static dwarf::Attribute ODRAttributes[] = {1851 dwarf::DW_AT_type, dwarf::DW_AT_specification,1852 dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};1853 1854 return ODRAttributes;1855}1856