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