1//=== DWARFLinkerCompileUnit.cpp ------------------------------------------===// 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-exception 7//===----------------------------------------------------------------------===// 25using namespacedwarf_linker;
26using namespacedwarf_linker::parallel;
32 :
DwarfUnit(GlobalData,
ID, ClangModuleName), File(File),
33 getUnitFromOffset(UnitFromOffset),
Stage(
Stage::CreatedNotLoaded),
34 AcceleratorRecords(&GlobalData.getAllocator()) {
44 :
DwarfUnit(GlobalData,
ID, ClangModuleName), File(File),
45 OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),
47 AcceleratorRecords(&GlobalData.getAllocator()) {
55if (std::optional<DWARFFormValue> Val = CUDie.
find(dwarf::DW_AT_language)) {
76// Nothing to reset if stage is less than "Loaded". 80// Note: We need to do erasing for "Loaded" stage because 81// if live analysys failed then we will have "Loaded" stage 82// with marking from "LivenessAnalysisDone" stage partially 83// done. That marking should be cleared. 86Info.unsetFlagsWhichSetDuringLiveAnalysis();
92 Dependencies.reset(
nullptr);
99 AcceleratorRecords.
erase();
103 DebugAddrIndexMap.
clear();
119// load input dies, resize Info structures array. 128bool IsODRUnavailableFunctionScope) {
135bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;
137if (DieInfo.getIsInMouduleScope())
138 ChildInfo.setIsInMouduleScope();
140if (DieInfo.getIsInFunctionScope())
141 ChildInfo.setIsInFunctionScope();
143if (DieInfo.getIsInAnonNamespaceScope())
144 ChildInfo.setIsInAnonNamespaceScope();
146switch (CurChild->getTag()) {
147case dwarf::DW_TAG_module:
148 ChildInfo.setIsInMouduleScope();
149if (DieEntry->
getTag() == dwarf::DW_TAG_compile_unit &&
154case dwarf::DW_TAG_subprogram:
155 ChildInfo.setIsInFunctionScope();
156if (!ChildIsODRUnavailableFunctionScope &&
157 !ChildInfo.getIsInMouduleScope()) {
159 {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))
160 ChildIsODRUnavailableFunctionScope =
true;
163case dwarf::DW_TAG_namespace: {
166if (
find(CurChild, dwarf::DW_AT_extension))
169if (!NamespaceEntry.
CU->
find(NamespaceEntry.
DieEntry, dwarf::DW_AT_name))
170 ChildInfo.setIsInAnonNamespaceScope();
177 ChildInfo.setTrackLiveness();
179if ((!ChildInfo.getIsInAnonNamespaceScope() &&
180 !ChildIsODRUnavailableFunctionScope && !NoODR))
181 ChildInfo.setODRAvailable();
183if (CurChild->hasChildren())
184 analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);
192// Cache the resolved paths based on the index in the line table, 193// because calling realpath is expensive. 195if (It == ResolvedFullPaths.
end()) {
196 std::string OrigFileName;
199 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
202assert(FoundFileName &&
"Must get file name from line table");
204// Second level of caching, this time based on the file's parent 209// If the ParentPath has not yet been resolved, resolve and cache it for 212 ResolvedParentPaths.find(ParentPath);
213if (ParentIt == ResolvedParentPaths.end()) {
218 .insert({ParentPath, GlobalStrings.
insert(RealPath).first})
222// Join the file name again with the resolved path. 226 It = ResolvedFullPaths
228 FileIdx, GlobalStrings.
insert(ResolvedPath).first))
242 ResolvedParentPaths.clear();
247 Dependencies.reset(
nullptr);
251/// Collect references to parseable Swift interfaces in imported 252/// DW_TAG_module blocks. 254if (!Language || Language != dwarf::DW_LANG_Swift)
262if (!Path.ends_with(
".swiftinterface"))
264// Don't track interfaces that are part of the SDK. 271// Don't track interfaces that are part of the toolchain. 272// For example: Swift, _Concurrency, ... 274if (!DeveloperDir.
empty() && Path.starts_with(DeveloperDir))
278if (std::optional<DWARFFormValue> Val =
find(DieEntry, dwarf::DW_AT_name)) {
286// The prepend path is applied later when copying. 293if (!Entry.empty() && Entry != ResolvedPath) {
295warn(
Twine(
"conflicting parseable interfaces for Swift Module ") + *
Name +
296": " + Entry +
" and " + Path +
".",
299 Entry = std::string(ResolvedPath);
321assert(ChildInfo.getODRAvailable());
324 ChildrenIndexAssigner.getChildIndex(*
this, CurChild)))
327if (
Error Err = assignTypeNamesRec(CurChild, NameBuilder))
335if (std::optional<SectionDescriptor *> DebugInfoSection =
340 /// Replace stored DIE indexes with DIE output offsets. 347 ->ListDebugULEB128DieRefPatch.forEach(
349 /// Replace stored DIE indexes with DIE output offsets. 356if (std::optional<SectionDescriptor *> DebugLocSection =
359 ->ListDebugULEB128DieRefPatch.forEach(
361 /// Replace stored DIE indexes with DIE output offsets. 368if (std::optional<SectionDescriptor *> DebugLocListsSection =
370 (*DebugLocListsSection)
371 ->ListDebugULEB128DieRefPatch.forEach(
373 /// Replace stored DIE indexes with DIE output offsets. 390 RefCU = getUnitFromOffset(*
Offset);
397// Referenced DIE is in current compile unit. 400 }
elseif (RefCU && CanResolveInterCUReferences) {
401// Referenced DIE is in other compile unit. 403// Check whether DIEs are loaded for that compile unit. 405if (ReferredCUStage < Stage::Loaded || ReferredCUStage >
Stage::Cloned)
408if (std::optional<uint32_t> RefDieIdx =
420if (std::optional<DWARFFormValue> AttrVal =
find(DieEntry, Attr))
428 std::lock_guard<std::mutex> Guard(RangesMutex);
430 Ranges.
insert({FuncLowPc, FuncHighPc}, PcOffset);
432 LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
434 LowPc = FuncLowPc + PcOffset;
435 this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
439 std::lock_guard<std::mutex> Guard(LabelsMutex);
440 Labels.
insert({LabelLowPc, PcOffset});
460if (!DebugInfoSection.ListDebugLocPatch.empty()) {
465uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);
467 DebugInfoSection.ListDebugLocPatch.forEach([&](
DebugLocPatch &Patch) {
468// Get location expressions vector corresponding to the current 469// attribute from the source DWARF. 476if (!OriginalLocations) {
477warn(OriginalLocations.takeError());
481 LinkedLocationExpressionsVector LinkedLocationExpressions;
483 LinkedLocationExpressionsWithOffsetPatches LinkedExpression;
485if (CurExpression.Range) {
486// Relocate address range. 487 LinkedExpression.Expression.Range = {
498 LinkedExpression.Expression.Expr,
500 LinkedExpression.Patches);
502 LinkedLocationExpressions.push_back({LinkedExpression});
505// Emit locations list table fragment corresponding to the CurLocAttr. 507 OutLocationSection.
OS.
tell());
508 emitLocListFragment(LinkedLocationExpressions, OutLocationSection);
511if (OffsetAfterUnitLength > 0) {
512assert(OffsetAfterUnitLength -
514 OffsetAfterUnitLength);
515 OutLocationSection.
apply(
516 OffsetAfterUnitLength -
518 dwarf::DW_FORM_sec_offset,
519 OutLocationSection.
OS.
tell() - OffsetAfterUnitLength);
524/// Emit debug locations(.debug_loc, .debug_loclists) header. 545return OffsetAfterUnitLength;
548/// Emit debug locations(.debug_loc, .debug_loclists) fragment. 549uint64_t CompileUnit::emitLocListFragment(
550const LinkedLocationExpressionsVector &LinkedLocationExpression,
552uint64_t OffsetBeforeLocationExpression = 0;
556if (std::optional<uint64_t> LowPC =
getLowPc())
557 BaseAddress = *LowPC;
559for (
const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
560 LinkedLocationExpression) {
561if (LocExpression.Expression.Range) {
563 LocExpression.Expression.Range->LowPC - BaseAddress,
566 LocExpression.Expression.Range->HighPC - BaseAddress,
570 OutLocationSection.
emitIntVal(LocExpression.Expression.Expr.size(), 2);
571 OffsetBeforeLocationExpression = OutLocationSection.
OS.
tell();
572for (
uint64_t *OffsetPtr : LocExpression.Patches)
573 *OffsetPtr += OffsetBeforeLocationExpression;
575 OutLocationSection.
OS 576 <<
StringRef((
constchar *)LocExpression.Expression.Expr.data(),
577 LocExpression.Expression.Expr.size());
580// Emit the terminator entry. 585return OffsetBeforeLocationExpression;
588 std::optional<uint64_t> BaseAddress;
589for (
const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
590 LinkedLocationExpression) {
591if (LocExpression.Expression.Range) {
592// Check whether base address is set. If it is not set yet 593// then set current base address and emit base address selection entry. 595 BaseAddress = LocExpression.Expression.Range->LowPC;
598 OutLocationSection.
emitIntVal(dwarf::DW_LLE_base_addressx, 1);
600 OutLocationSection.
OS);
603// Emit type of entry. 604 OutLocationSection.
emitIntVal(dwarf::DW_LLE_offset_pair, 1);
606// Emit start offset relative to base address. 607encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,
608 OutLocationSection.
OS);
610// Emit end offset relative to base address. 611encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,
612 OutLocationSection.
OS);
614// Emit type of entry. 615 OutLocationSection.
emitIntVal(dwarf::DW_LLE_default_location, 1);
617encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.
OS);
618 OffsetBeforeLocationExpression = OutLocationSection.
OS.
tell();
619for (
uint64_t *OffsetPtr : LocExpression.Patches)
620 *OffsetPtr += OffsetBeforeLocationExpression;
623 (
constchar *)LocExpression.Expression.Expr.data(),
624 LocExpression.Expression.Expr.size());
627// Emit the terminator entry. 628 OutLocationSection.
emitIntVal(dwarf::DW_LLE_end_of_list, 1);
629return OffsetBeforeLocationExpression;
632Error CompileUnit::emitDebugAddrSection() {
639if (DebugAddrIndexMap.
empty())
645// Emit section header. 664// Patch section length. 665 OutAddrSection.
apply(
666 OffsetAfterSectionLength -
668 dwarf::DW_FORM_sec_offset,
669 OutAddrSection.
OS.
tell() - OffsetAfterSectionLength);
678// Build set of linked address ranges for unit function ranges. 681 LinkedFunctionRanges.
insert(
684 emitAranges(LinkedFunctionRanges);
702if (!DebugInfoSection.ListDebugRangePatch.empty()) {
703 std::optional<AddressRangeValuePair> CachedRange;
704uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);
707 DebugInfoSection.ListDebugRangePatch.forEach([&](
DebugRangePatch &Patch) {
709 CompileUnitRangePtr = &Patch;
711// Get ranges from the source DWARF corresponding to the current 713 AddressRanges LinkedRanges;
714 uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(
716 DebugInfoSection.getFormParams().getDwarfOffsetByteSize());
717 if (Expected<DWARFAddressRangesVector> InputRanges =
718 getOrigUnit().findRnglistFromOffset(
719 InputDebugRangesSectionOffset)) {
720// Apply relocation adjustment. 721 for (const auto &Range : *InputRanges) {
722 if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))
724 getFunctionRanges().getRangeThatContains(Range.LowPC);
726// All range entries should lie in the function range. 728 warn(
"inconsistent range data.");
732// Store range for emiting. 733 LinkedRanges.insert({Range.LowPC + CachedRange->Value,
734 Range.HighPC + CachedRange->Value});
737 llvm::consumeError(InputRanges.takeError());
738 warn(
"invalid range list ignored.");
741// Emit linked ranges. 743 OutRangeSection.
OS.
tell());
744 emitRangeListFragment(LinkedRanges, OutRangeSection);
748if (CompileUnitRangePtr !=
nullptr) {
749// Emit compile unit ranges last to be binary compatible with classic 752 dwarf::DW_FORM_sec_offset,
753 OutRangeSection.
OS.
tell());
754 emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);
757if (OffsetAfterUnitLength > 0) {
758assert(OffsetAfterUnitLength -
760 OffsetAfterUnitLength);
761 OutRangeSection.
apply(
762 OffsetAfterUnitLength -
764 dwarf::DW_FORM_sec_offset,
765 OutRangeSection.
OS.
tell() - OffsetAfterUnitLength);
790return OffsetAfterUnitLength;
793void CompileUnit::emitRangeListFragment(
constAddressRanges &LinkedRanges,
798if (std::optional<uint64_t> LowPC =
getLowPc())
799 BaseAddress = *LowPC;
808// Add the terminator entry. 814 std::optional<uint64_t> BaseAddress;
817 BaseAddress =
Range.start();
820 OutRangeSection.
emitIntVal(dwarf::DW_RLE_base_addressx, 1);
824// Emit type of entry. 825 OutRangeSection.
emitIntVal(dwarf::DW_RLE_offset_pair, 1);
827// Emit start offset relative to base address. 830// Emit end offset relative to base address. 834// Emit the terminator entry. 835 OutRangeSection.
emitIntVal(dwarf::DW_RLE_end_of_list, 1);
838void CompileUnit::emitAranges(
AddressRanges &LinkedFunctionRanges) {
839if (LinkedFunctionRanges.
empty())
849sizeof(int32_t) +
// Size of contents (w/o this field 850sizeof(int16_t) +
// DWARF ARange version number 851sizeof(int32_t) +
// Offset of CU in the .debug_info section 852sizeof(int8_t) +
// Pointer Size (in bytes) 853sizeof(int8_t);
// Segment Size (in bytes) 858 OutArangesSection.
emitOffset(0xBADDEF);
// Aranges length 859uint64_t OffsetAfterArangesLengthField = OutArangesSection.
OS.
tell();
862 OutArangesSection.notePatch(
864 OutArangesSection.
emitOffset(0xBADDEF);
// Corresponding unit's offset 867 OutArangesSection.
emitIntVal(0, 1);
// Segment size 872// Emit linked ranges. 886// Update Aranges lentgh. 887 OutArangesSection.
apply(
888 OffsetAfterArangesLengthField -
890 dwarf::DW_FORM_sec_offset,
891 OffsetAfterArangesEnd - OffsetAfterArangesLengthField);
901// Check for .debug_macro table. 902if (std::optional<uint64_t> MacroAttr =
906 emitMacroTableImpl(Table, *MacroAttr,
true);
910// Check for .debug_macinfo table. 911if (std::optional<uint64_t> MacroAttr =
915 emitMacroTableImpl(Table, *MacroAttr,
false);
924bool hasDWARFv5Header) {
930bool DefAttributeIsReported =
false;
931bool UndefAttributeIsReported =
false;
932bool ImportAttributeIsReported =
false;
934for (
const DWARFDebugMacro::MacroList &
List : MacroTable->MacroLists) {
935if (OffsetToMacroTable ==
List.Offset) {
936// Write DWARFv5 header. 937if (hasDWARFv5Header) {
938// Write header version. 943// Check for OPCODE_OPERANDS_TABLE. 945 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
948warn(
"opcode_operands_table is not supported yet.");
951// Check for DEBUG_LINE_OFFSET. 952 std::optional<uint64_t> StmtListOffset;
953if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
954// Get offset to the line table from the cloned compile unit. 956if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
957 StmtListOffset = V.getDIEInteger().getValue();
962if (!StmtListOffset) {
964warn(
"couldn`t find line table for macro table.");
971// Write offset to line table. 976// TODO: check that List.Header.getOffsetByteSize() and 977// DebugOffsetPatch agree on size. 982// Write macro entries. 983for (
const DWARFDebugMacro::Entry &MacroEntry :
List.Macros) {
984if (MacroEntry.Type == 0) {
989uint8_t MacroType = MacroEntry.Type;
992bool HasVendorSpecificExtension =
993 (!hasDWARFv5Header &&
998if (HasVendorSpecificExtension) {
999// Write macinfo type. 1002// Write vendor extension constant. 1005// Write vendor extension string. 1006 OutSection.
emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);
1008warn(
"unknown macro type. skip.");
1010// debug_macro and debug_macinfo share some common encodings. 1011// DW_MACRO_define == DW_MACINFO_define 1012// DW_MACRO_undef == DW_MACINFO_undef 1013// DW_MACRO_start_file == DW_MACINFO_start_file 1014// DW_MACRO_end_file == DW_MACINFO_end_file 1015// For readibility/uniformity we are using DW_MACRO_*. 1016case dwarf::DW_MACRO_define:
1017case dwarf::DW_MACRO_undef: {
1018// Write macinfo type. 1021// Write source line. 1024// Write macro string. 1025 OutSection.
emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);
1027case dwarf::DW_MACRO_define_strp:
1028case dwarf::DW_MACRO_undef_strp:
1029case dwarf::DW_MACRO_define_strx:
1030case dwarf::DW_MACRO_undef_strx: {
1031// DW_MACRO_*_strx forms are not supported currently. 1032// Convert to *_strp. 1034case dwarf::DW_MACRO_define_strx: {
1035 MacroType = dwarf::DW_MACRO_define_strp;
1036if (!DefAttributeIsReported) {
1037warn(
"DW_MACRO_define_strx unsupported yet. Convert to " 1038"DW_MACRO_define_strp.");
1039 DefAttributeIsReported =
true;
1042case dwarf::DW_MACRO_undef_strx: {
1043 MacroType = dwarf::DW_MACRO_undef_strp;
1044if (!UndefAttributeIsReported) {
1045warn(
"DW_MACRO_undef_strx unsupported yet. Convert to " 1046"DW_MACRO_undef_strp.");
1047 UndefAttributeIsReported =
true;
1055// Write macinfo type. 1058// Write source line. 1061// Write macro string. 1062 OutSection.
emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);
1065case dwarf::DW_MACRO_start_file: {
1066// Write macinfo type. 1068// Write source line. 1070// Write source file id. 1073case dwarf::DW_MACRO_end_file: {
1074// Write macinfo type. 1077case dwarf::DW_MACRO_import:
1078case dwarf::DW_MACRO_import_sup: {
1079if (!ImportAttributeIsReported) {
1080warn(
"DW_MACRO_import and DW_MACRO_import_sup are unsupported " 1082 ImportAttributeIsReported =
true;
1096 std::optional<int64_t> VarAddressAdjustment,
1104for (
auto &
Op : InputExpression) {
1106// DW_OP_const_type is variable-length and has 3 1107// operands. Thus far we only support 2. 1110Desc.
Op[0] != Encoding::Size1))
1111warn(
"unsupported DW_OP encoding.");
1115Desc.
Op[0] == Encoding::Size1)) {
1116// This code assumes that the other non-typeref operand fits into 1 byte. 1121// Copy over the operation. 1133unsigned RealSize = 0;
1134// Look up the base type. For DW_OP_convert, the operand may be 0 to 1135// instead indicate the generic type. The same holds for 1136// DW_OP_reinterpret, which is currently not supported. 1137if (RefOffset > 0 ||
Op.
getCode() != dwarf::DW_OP_convert) {
1140if (std::optional<uint32_t>
Idx =
1144// Use fixed size for ULEB128 data, since we need to update that size 1145// later with the proper offsets. Use 5 for DWARF32, 9 for DWARF64. 1150 Section.notePatchWithOffsetUpdate(
1157if (RealSize > ULEBsize) {
1158// Emit the generic type as a fallback. 1160warn(
"base type ref doesn't fit.");
1162assert(RealSize == ULEBsize &&
"padding failed");
1165 }
elseif (!
getGlobalData().getOptions().UpdateIndexTablesOnly &&
1167if (std::optional<object::SectionedAddress> SA =
1169// DWARFLinker does not use addrx forms since it generates relocated 1170// addresses. Replace DW_OP_addrx with DW_OP_addr here. 1171// Argument of DW_OP_addrx should be relocated here as it is not 1172// processed by applyValidRelocs. 1173 OutputExpression.
push_back(dwarf::DW_OP_addr);
1174uint64_t LinkedAddress = SA->Address + VarAddressAdjustment.value_or(0);
1178reinterpret_cast<constuint8_t *
>(&LinkedAddress),
1179 OrigAddressByteSize);
1180 OutputExpression.
append(AddressBytes.
begin(), AddressBytes.
end());
1182warn(
"cann't read DW_OP_addrx operand.");
1183 }
elseif (!
getGlobalData().getOptions().UpdateIndexTablesOnly &&
1185if (std::optional<object::SectionedAddress> SA =
1187// DWARFLinker does not use constx forms since it generates relocated 1188// addresses. Replace DW_OP_constx with DW_OP_const[*]u here. 1189// Argument of DW_OP_constx should be relocated here as it is not 1190// processed by applyValidRelocs. 1191 std::optional<uint8_t> OutOperandKind;
1192switch (OrigAddressByteSize) {
1194 OutOperandKind = dwarf::DW_OP_const2u;
1197 OutOperandKind = dwarf::DW_OP_const4u;
1200 OutOperandKind = dwarf::DW_OP_const8u;
1204formatv((
"unsupported address size: {0}."), OrigAddressByteSize));
1208if (OutOperandKind) {
1209 OutputExpression.
push_back(*OutOperandKind);
1211 SA->Address + VarAddressAdjustment.value_or(0);
1215reinterpret_cast<constuint8_t *
>(&LinkedAddress),
1216 OrigAddressByteSize);
1217 OutputExpression.
append(AddressBytes.
begin(), AddressBytes.
end());
1220warn(
"cann't read DW_OP_constx operand.");
1222// Copy over everything else unmodified. 1232 std::optional<std::reference_wrapper<const Triple>> TargetTriple,
1241if (ArtificialTypeUnit)
1244// Clone input DIE entry recursively. 1245 std::pair<DIE *, TypeEntry *> OutCUDie =
cloneDIE(
1247 std::nullopt, std::nullopt,
Allocator, ArtificialTypeUnit);
1250if (!TargetTriple.has_value() || (OutCUDie.first ==
nullptr))
1263// ASSUMPTION: .debug_info section should already be emitted at this point. 1264// cloneAndEmitRanges & cloneAndEmitDebugLocations use .debug_info section 1273if (
Error Err = emitDebugAddrSection())
1276// Generate Pub accelerator tables. 1289uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,
1295bool NeedToClonePlainDIE =
Info.needToKeepInPlainDwarf();
1296bool NeedToCloneTypeDIE =
1297 (InputDieEntry->
getTag() != dwarf::DW_TAG_compile_unit) &&
1298Info.needToPlaceInTypeTable();
1299 std::pair<DIE *, TypeEntry *> ClonedDIE;
1303if (NeedToClonePlainDIE)
1304// Create a cloned DIE which would be placed into the cloned version 1305// of input compile unit. 1306 ClonedDIE.first = createPlainDIEandCloneAttributes(
1307 InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,
1308 VarAddressAdjustment);
1309if (NeedToCloneTypeDIE) {
1310// Create a cloned DIE which would be placed into the artificial type 1312assert(ArtificialTypeUnit !=
nullptr);
1316 ClonedDIE.second = createTypeDIEandCloneAttributes(
1317 InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,
1318 ArtificialTypeUnit);
1321 ClonedDIE.
second ? ClonedDIE.second : ClonedParentTypeDIE;
1323bool HasPlainChildrenToClone =
1324 (ClonedDIE.first &&
Info.getKeepPlainChildren());
1326bool HasTypeChildrenToClone =
1327 ((ClonedDIE.second ||
1328 InputDieEntry->
getTag() == dwarf::DW_TAG_compile_unit) &&
1329Info.getKeepTypeChildren());
1331// Recursively clone children. 1332if (HasPlainChildrenToClone || HasTypeChildrenToClone) {
1337 std::pair<DIE *, TypeEntry *> ClonedChild =
cloneDIE(
1338 CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,
1339 VarAddressAdjustment,
Allocator, ArtificialTypeUnit);
1341if (ClonedChild.first) {
1343 ClonedChild.first->getOffset() + ClonedChild.first->getSize();
1344 PlainDIEGenerator.
addChild(ClonedChild.first);
1347assert(ClonedDIE.first ==
nullptr ||
1348 HasPlainChildrenToClone == ClonedDIE.first->hasChildren());
1350// Account for the end of children marker. 1351if (HasPlainChildrenToClone)
1352 OutOffset +=
sizeof(int8_t);
1356if (ClonedDIE.first !=
nullptr)
1357 ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());
1362DIE *CompileUnit::createPlainDIEandCloneAttributes(
1364uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
1365 std::optional<int64_t> &VarAddressAdjustment) {
1368DIE *ClonedDIE =
nullptr;
1369bool HasLocationExpressionAddress =
false;
1370if (InputDieEntry->
getTag() == dwarf::DW_TAG_subprogram) {
1371// Get relocation adjustment value for the current function. 1372 FuncAddressAdjustment =
1374getDIE(InputDieEntry),
false);
1375 }
elseif (InputDieEntry->
getTag() == dwarf::DW_TAG_label) {
1376// Get relocation adjustment value for the current label. 1377 std::optional<uint64_t> lowPC =
1381if (It != Labels.
end())
1382 FuncAddressAdjustment = It->second;
1384 }
elseif (InputDieEntry->
getTag() == dwarf::DW_TAG_variable) {
1385// Get relocation adjustment value for the current variable. 1386 std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
1388getDIE(InputDieEntry),
false);
1390 HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;
1391if (LocExprAddrAndRelocAdjustment.first &&
1392 LocExprAddrAndRelocAdjustment.second)
1393 VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;
1396 ClonedDIE = PlainDIEGenerator.
createDIE(InputDieEntry->
getTag(), OutOffset);
1398// Offset to the DIE would be used after output DIE tree is deleted. 1399// Thus we need to remember DIE offset separately. 1404 PlainDIEGenerator, FuncAddressAdjustment,
1405 VarAddressAdjustment,
1406 HasLocationExpressionAddress);
1407 AttributesCloner.clone();
1409// Remember accelerator info. 1411 AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,
1415 AttributesCloner.finalizeAbbreviations(
Info.getKeepPlainChildren());
1420/// Allocates output DIE for the specified \p TypeDescriptor. 1424bool IsParentDeclaration) {
1425DIE *DefinitionDie = TypeDescriptor->
Die;
1426// Do not allocate any new DIE if definition DIE is already met. 1433if (IsDeclaration && !DeclarationDie) {
1434// Alocate declaration DIE. 1436if (TypeDescriptor->
DeclarationDie.compare_exchange_weak(DeclarationDie,
1439 }
elseif (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
1440// Overwrite existing declaration DIE if it's parent is also an declaration 1441// while parent of current declaration DIE is a definition. 1443 OldParentIsDeclaration,
false)) {
1448 }
elseif (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {
1449// Alocate declaration DIE since parent of current DIE is marked as 1452if (TypeDescriptor->
DeclarationDie.compare_exchange_weak(DeclarationDie,
1455 }
elseif (!IsDeclaration && !IsParentDeclaration) {
1456// Allocate definition DIE. 1458if (TypeDescriptor->
Die.compare_exchange_weak(DefinitionDie, NewDie)) {
1467TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(
1470assert(ArtificialTypeUnit !=
nullptr);
1475assert(ClonedParentTypeDIE !=
nullptr);
1478 Entry, ClonedParentTypeDIE);
1484bool ParentIsDeclaration =
false;
1485if (std::optional<uint32_t> ParentIdx = InputDieEntry->
getParentIdx())
1486 ParentIsDeclaration =
1490 allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->
getTag(),
1491 IsDeclaration, ParentIsDeclaration);
1493if (OutDIE !=
nullptr) {
1494assert(ArtificialTypeUnit !=
nullptr);
1498 InputDieEntry, TypeDIEGenerator,
1499 std::nullopt, std::nullopt,
false);
1500 AttributesCloner.clone();
1502// Remember accelerator info. 1504 ArtificialTypeUnit);
1505 AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,
1508// if AttributesCloner.getOutOffset() == 0 then we need to add 1509// 1 to avoid assertion for zero size. We will subtract it back later. 1510 OutDIE->
setSize(AttributesCloner.getOutOffset() + 1);
1519if (InputLineTable ==
nullptr) {
1521warn(
"cann't load line table.");
1527// Set Line Table header. 1531// Set Line Table Rows. 1533 OutLineTable.
Rows = InputLineTable->
Rows;
1534// If all the line table contains is a DW_LNE_end_sequence, clear the line 1535// table rows, it will be inserted again in the DWARFStreamer. 1536if (OutLineTable.
Rows.size() == 1 && OutLineTable.
Rows[0].EndSequence)
1537 OutLineTable.
Rows.clear();
1541// This vector is the output line table. 1542 std::vector<DWARFDebugLine::Row> NewRows;
1543 NewRows.reserve(InputLineTable->
Rows.size());
1545// Current sequence of rows being extracted, before being inserted 1547 std::vector<DWARFDebugLine::Row> Seq;
1550 std::optional<AddressRangeValuePair> CurrRange;
1552// FIXME: This logic is meant to generate exactly the same output as 1553// Darwin's classic dsymutil. There is a nicer way to implement this 1554// by simply putting all the relocated line info in NewRows and simply 1555// sorting NewRows before passing it to emitLineTableForUnit. This 1556// should be correct as sequences for a function should stay 1557// together in the sorted output. There are a few corner cases that 1558// look suspicious though, and that required to implement the logic 1559// this way. Revisit that once initial validation is finished. 1561// Iterate over the object file line info and extract the sequences 1562// that correspond to linked functions. 1564// Check whether we stepped out of the range. The range is 1565// half-open, but consider accept the end address of the range if 1566// it is marked as end_sequence in the input (because in that 1567// case, the relocation offset is accurate and that entry won't 1568// 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_sequence 1571// corresponding to the end of the range. 1573 CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
1574 CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
1575if (StopAddress != -1ULL && !Seq.empty()) {
1576// Insert end sequence row with the computed end address, but 1577// the same line as the previous one. 1578auto NextLine = Seq.back();
1579 NextLine.Address.Address = StopAddress;
1580 NextLine.EndSequence = 1;
1581 NextLine.PrologueEnd = 0;
1582 NextLine.BasicBlock = 0;
1583 NextLine.EpilogueBegin = 0;
1584 Seq.push_back(NextLine);
1585 insertLineSequence(Seq, NewRows);
1592// Ignore empty sequences. 1593if (Row.EndSequence && Seq.empty())
1596// Relocate row address and add it to the current sequence. 1597 Row.Address.Address += CurrRange->Value;
1598 Seq.emplace_back(Row);
1601 insertLineSequence(Seq, NewRows);
1604 OutLineTable.
Rows = std::move(NewRows);
1610void CompileUnit::insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
1611 std::vector<DWARFDebugLine::Row> &Rows) {
1615if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
1625// FIXME: this only removes the unneeded end_sequence if the 1626// sequences have been inserted in order. Using a global sort like 1627// described in cloneAndEmitLineTable() and delaying the end_sequene 1628// elimination to DebugLineEmitter::emit() we can get rid of all of them. 1629if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
1630 InsertPoint->EndSequence) {
1631 *InsertPoint = Seq.front();
1632 Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
1634 Rows.insert(InsertPoint, Seq.begin(), Seq.end());
1640#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 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();
1669#endif// if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1671std::optional<std::pair<StringRef, StringRef>>
1687std::optional<std::pair<StringRef, StringRef>>
1691return std::make_pair(
StringRef(FileData->second.first),
1696if (LineTable->hasFileAtIndex(FileIdx)) {
1699 LineTable->Prologue.getFileNameEntry(FileIdx);
1707 std::string FileName = *
Name;
1713 std::make_pair(std::string(
""), std::move(FileName))))
1715return std::make_pair(
StringRef(FileData->second.first),
1721// Be defensive about the contents of Entry. 1723// DirIdx 0 is the compilation directory, so don't include it for 1725if ((Entry.DirIdx != 0) &&
1726 Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {
1728 LineTable->Prologue.IncludeDirectories[Entry.DirIdx]
1731 IncludeDir = *DirName;
1738if (0 < Entry.DirIdx &&
1739 Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {
1741 LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]
1744 IncludeDir = *DirName;
1763 std::make_pair(FileIdx, std::make_pair(std::string(FilePath),
1764 std::move(FileName))))
1766return std::make_pair(
StringRef(FileData->second.first),
1774#define MAX_REFERENCIES_DEPTH 1000 1777 std::optional<UnitEntryPairTy> RefDiePair;
1781 CUDiePair.
DieEntry, dwarf::DW_AT_extension,
1783if (!RefDiePair || !RefDiePair->DieEntry)
1786 CUDiePair = *RefDiePair;
1793if (std::optional<uint32_t> ParentIdx = DieEntry->
getParentIdx())
1810return getAsCompileUnit();
1812return getAsTypeUnit();
1816return isa<CompileUnit *>(
Ptr);
1820return isa<TypeUnit *>(
Ptr);
1824return cast<CompileUnit *>(
Ptr);
1828return cast<TypeUnit *>(
Ptr);
1832bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
1836return Dependencies->resolveDependenciesAndMarkLiveness(
1837 InterCUProcessingStarted, HasNewInterconnectedCUs);
1841assert(Dependencies.get());
1843return Dependencies->updateDependenciesCompleteness();
1847assert(Dependencies.get());
1849 Dependencies->verifyKeepChain();
1854 dwarf::DW_AT_type, dwarf::DW_AT_specification,
1855 dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};
1857return ODRAttributes;
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
Mark the given Function as meaning that it cannot be changed in any way mark any values that are used as this function s parameters or by its return values(according to Uses) live as well. void DeadArgumentEliminationPass
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define MAX_REFERENCIES_DEPTH
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A class that represents an address range.
void insert(AddressRange Range, int64_t Value)
The AddressRanges class helps normalize address range collections.
Collection::const_iterator insert(AddressRange Range)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Allocate memory in an ever growing pool, as if by bump-pointer.
std::pair< KeyDataTy *, bool > insert(const KeyTy &NewValue)
Insert new value NewValue or return already existing entry.
A structured debug information entry.
DWARFDebugInfoEntry - A DIE with only the minimum required data.
dwarf::Tag getTag() const
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
const DWARFDebugInfoEntry * getDebugInfoEntry() const
const char * getName(DINameKind Kind) const
Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.
This class represents an Operation in the Expression.
std::optional< unsigned > getSubCode() const
uint64_t getEndOffset() const
Encoding
Size and signedness of expression operations' operands.
const Description & getDescription() const
uint64_t getRawOperand(unsigned Idx) const
StringRef getData() const
std::optional< uint64_t > getAsSectionOffset() const
std::optional< int64_t > getAsSignedConstant() const
std::optional< uint64_t > getAsRelativeReference() const
getAsFoo functions below return the extracted value as Foo if only DWARFFormValue has form class is s...
std::optional< uint64_t > getAsDebugInfoReference() const
std::optional< uint64_t > getAsUnsignedConstant() const
const DWARFUnit * getUnit() const
const dwarf::FormParams & getFormParams() const
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
uint8_t getAddressByteSize() const
const char * getCompilationDir()
std::optional< uint32_t > getDIEIndexForOffset(uint64_t Offset)
Return the DIE index for a given offset Offset inside the unit's DIE vector.
Expected< DWARFLocationExpressionsVector > findLoclistFromOffset(uint64_t Offset)
bool isLittleEndian() const
std::optional< object::SectionedAddress > getAddrOffsetSectionItem(uint32_t Index) const
uint64_t getOffset() const
iterator find(const_arg_type_t< KeyT > Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
This class represents DWARF information for source file and it's address map.
std::unique_ptr< AddressesMap > Addresses
Helpful address information(list of valid address ranges, relocations).
std::unique_ptr< DWARFContext > Dwarf
Source DWARF information.
@ Pub
.debug_pubnames, .debug_pubtypes
uint64_t getValueIndex(T Value)
const SmallVector< T > & getValues() const
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName)
This class helps to store information for accelerator entries.
TypeUnit * getAsTypeUnit()
Returns TypeUnit if applicable.
DwarfUnit * operator->()
Accessor for common functionality.
CompileUnit * getAsCompileUnit()
Returns CompileUnit if applicable.
OutputUnitVariantPtr(CompileUnit *U)
Stores all information related to a compile unit, be it in its original instance of the object file o...
void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset)
Add the low_pc of a label that is relocated by applying offset PCOffset.
Error cloneAndEmitDebugLocations()
Clone and emit debug locations(.debug_loc/.debug_loclists).
void cloneDieAttrExpression(const DWARFExpression &InputExpression, SmallVectorImpl< uint8_t > &OutputExpression, SectionDescriptor &Section, std::optional< int64_t > VarAddressAdjustment, OffsetsPtrVector &PatchesOffsets)
Clone attribute location axpression.
void maybeResetToLoadedStage()
Reset compile units data(results of liveness analysis, clonning) if current stage greater than Stage:...
void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset)
Add a function range [LowPC, HighPC) that is relocated by applying offset PCOffset.
void analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry)
Collect references to parseable Swift interfaces in imported DW_TAG_module blocks.
std::pair< DIE *, TypeEntry * > cloneDIE(const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE, uint64_t OutOffset, std::optional< int64_t > FuncAddressAdjustment, std::optional< int64_t > VarAddressAdjustment, BumpPtrAllocator &Allocator, TypeUnit *ArtificialTypeUnit)
void cleanupDataAfterClonning()
Cleanup unneeded resources after compile unit is cloned.
Error assignTypeNames(TypePool &TypePoolRef)
Search for type entries and assign names.
@ Both
Corresponding DIE goes to type table and to plain dwarf.
@ TypeTable
Corresponding DIE goes to the type table only.
@ PlainDwarf
Corresponding DIE goes to the plain dwarf only.
Error cloneAndEmitLineTable(const Triple &TargetTriple)
Error cloneAndEmitRanges()
Clone and emit ranges.
void updateDieRefPatchesWithClonedOffsets()
After cloning stage the output DIEs offsets are deallocated.
uint64_t getDebugAddrIndex(uint64_t Addr)
Returns index(inside .debug_addr) of an address.
const DWARFFile & getContaingFile() const
Returns DWARFFile containing this compile unit.
bool resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted, std::atomic< bool > &HasNewInterconnectedCUs)
Search for subprograms and variables referencing live code and discover dependend DIEs.
bool updateDependenciesCompleteness()
Check dependend DIEs for incompatible placement.
bool loadInputDIEs()
Load DIEs of input compilation unit.
const RangesTy & getFunctionRanges() const
Returns function ranges of this unit.
Error cloneAndEmitDebugMacro()
Clone and emit debug macros(.debug_macinfo/.debug_macro).
Error cloneAndEmit(std::optional< std::reference_wrapper< const Triple > > TargetTriple, TypeUnit *ArtificialTypeUnit)
Clone and emit this compilation unit.
void setStage(Stage Stage)
Set stage of overall processing.
Stage getStage() const
Returns stage of overall processing.
CompileUnit(LinkingGlobalData &GlobalData, unsigned ID, StringRef ClangModuleName, DWARFFile &File, OffsetToUnitTy UnitFromOffset, dwarf::FormParams Format, llvm::endianness Endianess)
void verifyDependencies()
Check DIEs to have a consistent marking(keep marking, placement marking).
Stage
The stages of new compile unit processing.
@ Cloned
Output DWARF is generated.
@ CreatedNotLoaded
Created, linked with input DWARF file.
@ Loaded
Input DWARF is loaded.
std::optional< uint64_t > getLowPc() const
Returns value of DW_AT_low_pc attribute.
std::optional< std::pair< StringRef, StringRef > > getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue)
Returns directory and file from the line table by index.
std::optional< UnitEntryPairTy > resolveDIEReference(const DWARFFormValue &RefValue, ResolveInterCUReferencesMode CanResolveInterCUReferences)
Resolve the DIE attribute reference that has been extracted in RefValue.
void loadLineTable()
Loads unit line table.
StringEntry * getFileName(unsigned FileIdx, StringPool &GlobalStrings)
Returns name of the file for the FileIdx from the unit`s line table.
This class creates clones of input DIE attributes.
This class is a helper to create output DIE tree.
void addChild(DIE *Child)
Adds a specified Child to the current DIE.
DIE * createDIE(dwarf::Tag DieTag, uint32_t OutOffset)
Creates a DIE of specified tag DieTag and OutOffset.
This class discovers DIEs dependencies: marks "live" DIEs, marks DIE locations (whether DIE should be...
Base class for all Dwarf units(Compile unit/Type table unit).
std::string UnitName
The name of this unit.
LinkingGlobalData & getGlobalData()
Return global data.
std::vector< std::unique_ptr< DIEAbbrev > > Abbreviations
Storage for the unique Abbreviations.
DIE * OutUnitDIE
Output unit DIE.
std::string SysRoot
The DW_AT_LLVM_sysroot of this unit.
bool isClangModule() const
Return true if this compile unit is from Clang module.
const std::string & getClangModuleName() const
Return Clang module name;.
void setOutUnitDIE(DIE *UnitDie)
Set output unit DIE.
FoldingSet< DIEAbbrev > AbbreviationsSet
FoldingSet that uniques the abbreviations.
StringRef getSysRoot()
Return the DW_AT_LLVM_sysroot of the compile unit or an empty StringRef.
DIE * getOutUnitDIE()
Returns output unit DIE.
This class keeps data and services common for the whole linking process.
const DWARFLinkerOptions & getOptions() const
Returns linking options.
This class helps to assign indexes for DIE children.
LinkingGlobalData & GlobalData
dwarf::FormParams Format
Format for sections.
const dwarf::FormParams & getFormParams() const
Return size of address.
void eraseSections()
Erases data of all sections.
std::optional< const SectionDescriptor * > tryGetSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness)
Sets output format for all keeping sections.
uint16_t getVersion() const
Return DWARF version.
uint16_t getDebugInfoHeaderSize() const
Return size of header of debug_info table.
llvm::endianness getEndianness() const
Endiannes for the sections.
SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
const SectionDescriptor & getSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
The helper class to build type name based on DIE properties.
Error assignName(UnitEntryPairTy InputUnitEntryPair, std::optional< std::pair< size_t, size_t > > ChildIndex)
Create synthetic name for the specified DIE InputUnitEntryPair and assign created name to the DIE typ...
Keeps cloned data for the type DIE.
std::atomic< bool > ParentIsDeclaration
std::atomic< DIE * > DeclarationDie
std::atomic< DIE * > Die
TypeEntryBody keeps partially cloned DIEs corresponding to this type.
TypePool keeps type descriptors which contain partially cloned DIE correspinding to each type.
BumpPtrAllocator & getThreadLocalAllocator()
Return thread local allocator used by pool.
TypeEntryBody * getOrCreateTypeEntryBody(TypeEntry *Entry, TypeEntry *ParentEntry)
Create or return existing type entry body for the specified Entry.
TypeEntry * getRoot() const
Return root for all type entries.
Type Unit is used to represent an artificial compilation unit which keeps all type information.
TypePool & getTypePool()
Returns global type pool.
uint64_t tell() const
tell - Return the current offset with the file.
void rememberDieOutOffset(uint32_t Idx, uint64_t Offset)
Idx index of the DIE.
TypeEntry * getDieTypeEntry(uint32_t Idx)
Idx index of the DIE.
DIEInfo & getDIEInfo(unsigned Idx)
Idx index of the DIE.
uint64_t getDieOutOffset(uint32_t Idx)
Idx index of the DIE.
const DWARFDebugInfoEntry * getSiblingEntry(const DWARFDebugInfoEntry *Die) const
const DWARFDebugInfoEntry * getFirstChildEntry(const DWARFDebugInfoEntry *Die) const
std::optional< uint32_t > getDIEIndexForOffset(uint64_t Offset)
DWARFDie getDIE(const DWARFDebugInfoEntry *Die)
const DWARFDebugInfoEntry * getDebugInfoEntry(unsigned Index) const
DWARFUnit & getOrigUnit() const
Returns paired compile unit from input DWARF.
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const
std::optional< DWARFFormValue > find(uint32_t DieIdx, ArrayRef< dwarf::Attribute > Attrs) const
Error emitDebugInfo(const Triple &TargetTriple)
Emit .debug_info section for unit DIEs.
Error emitDebugStringOffsetSection()
Emit the .debug_str_offsets section for current unit.
void emitPubAccelerators()
Emit .debug_pubnames and .debug_pubtypes for Unit.
void warn(const Twine &Warning, const DWARFDie *DIE=nullptr)
Error emitAbbreviations()
Error emitDebugLine(const Triple &TargetTriple, const DWARFDebugLine::LineTable &OutLineTable)
Emit .debug_line section.
bool isODRLanguage(uint16_t Language)
ArrayRef< dwarf::Attribute > getODRAttributes()
ResolveInterCUReferencesMode
StringRef guessDeveloperDir(StringRef SysRoot)
Make a best effort to guess the Xcode.app/Contents/Developer path from an SDK path.
DebugSectionKind
List of tracked debug tables.
bool isInToolchainDir(StringRef Path)
Make a best effort to determine whether Path is inside a toolchain.
bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path)
std::optional< uint64_t > toAddress(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
@ DW_ARANGES_VERSION
Section version number for .debug_aranges.
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
@ Dwarf
DWARF v5 .debug_names.
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
bool isCompileUnit(const std::unique_ptr< DWARFUnit > &U)
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool hasFileAtIndex(uint64_t FileIndex) const
bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const
Extracts filename by its index in filename table in prologue.
dwarf::FormParams FormParams
Version, address size (starting in v5), and DWARF32/64 format; these parameters affect interpretation...
Standard .debug_line state machine structure.
Description of the encoding of one expression Op.
SmallVector< Encoding > Op
Encoding for Op operands.
Represents a single DWARF expression, whose value is location-dependent.
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
uint8_t getDwarfOffsetByteSize() const
The size of a reference is determined by the DWARF 32/64-bit format.
Information gathered about source DIEs.
LLVM_DUMP_METHOD void dump()
bool needToPlaceInTypeTable() const
DieOutputPlacement getPlacement() const
DWARFLinkerBase::SwiftInterfacesMapTy * ParseableSwiftInterfaces
A list of all .swiftinterface files referenced by the debug info, mapping Module name to path on disk...
SmallVector< DWARFLinkerBase::AccelTableKind, 1 > AccelTables
The accelerator table kinds.
bool NoODR
Do not unique types according to ODR.
bool UpdateIndexTablesOnly
Update index tables.
This structure is used to update reference to the DIE.
uint64_t RefDieIdxOrClonedOffset
PointerIntPair< CompileUnit *, 1 > RefCU
This structure is used to update location list offset into .debug_loc/.debug_loclists.
int64_t AddrAdjustmentValue
This structure is used to update range list offset into .debug_ranges/.debug_rnglists.
bool IsCompileUnitRanges
Indicates patch which points to immediate compile unit's attribute.
This structure is used to update reference to the DIE of ULEB128 form.
uint64_t RefDieIdxOrClonedOffset
PointerIntPair< CompileUnit *, 1 > RefCU
dwarf::FormParams getFormParams() const
Returns FormParams used by section.
This structure is used to keep data of the concrete section.
raw_svector_ostream OS
Stream which stores data to the Contents.
void emitUnitLength(uint64_t Length)
Emit unit length into the current section contents.
void emitOffset(uint64_t Val)
Emit specified offset value into the current section contents.
void emitString(dwarf::Form StringForm, const char *StringVal)
void emitIntVal(uint64_t Val, unsigned Size)
Emit specified integer value into the current section contents.
void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val)
Write specified Value of AttrForm to the PatchOffset.
uint64_t getIntVal(uint64_t PatchOffset, unsigned Size)
Returns integer value of Size located by specified PatchOffset.
This is a helper structure which keeps a debug info entry with it's containing compilation unit.
std::optional< UnitEntryPairTy > getParent()
UnitEntryPairTy getNamespaceOrigin()
const DWARFDebugInfoEntry * DieEntry