1 | //===- DWARFLinker.h --------------------------------------------*- C++ -*-===// |
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 | #ifndef LLVM_DWARFLINKER_CLASSIC_DWARFLINKER_H |
10 | #define LLVM_DWARFLINKER_CLASSIC_DWARFLINKER_H |
11 | |
12 | #include "llvm/ADT/AddressRanges.h" |
13 | #include "llvm/ADT/DenseMap.h" |
14 | #include "llvm/CodeGen/AccelTable.h" |
15 | #include "llvm/CodeGen/NonRelocatableStringpool.h" |
16 | #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h" |
17 | #include "llvm/DWARFLinker/DWARFLinkerBase.h" |
18 | #include "llvm/DWARFLinker/IndexedValuesMap.h" |
19 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
20 | #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" |
21 | #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" |
22 | #include "llvm/DebugInfo/DWARF/DWARFDie.h" |
23 | #include "llvm/DebugInfo/DWARF/DWARFExpression.h" |
24 | #include <map> |
25 | |
26 | namespace llvm { |
27 | class DWARFExpression; |
28 | class DWARFUnit; |
29 | class ; |
30 | template <typename T> class SmallVectorImpl; |
31 | |
32 | namespace dwarf_linker { |
33 | namespace classic { |
34 | class DeclContextTree; |
35 | |
36 | using Offset2UnitMap = DenseMap<uint64_t, CompileUnit *>; |
37 | using DebugDieValuePool = IndexedValuesMap<uint64_t>; |
38 | |
39 | /// DwarfEmitter presents interface to generate all debug info tables. |
40 | class DwarfEmitter { |
41 | public: |
42 | virtual ~DwarfEmitter() = default; |
43 | |
44 | /// Emit section named SecName with data SecData. |
45 | virtual void emitSectionContents(StringRef SecData, |
46 | DebugSectionKind SecKind) = 0; |
47 | |
48 | /// Emit the abbreviation table \p Abbrevs to the .debug_abbrev section. |
49 | virtual void |
50 | emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs, |
51 | unsigned DwarfVersion) = 0; |
52 | |
53 | /// Emit the string table described by \p Pool into .debug_str table. |
54 | virtual void emitStrings(const NonRelocatableStringpool &Pool) = 0; |
55 | |
56 | /// Emit the debug string offset table described by \p StringOffsets into the |
57 | /// .debug_str_offsets table. |
58 | virtual void emitStringOffsets(const SmallVector<uint64_t> &StringOffsets, |
59 | uint16_t TargetDWARFVersion) = 0; |
60 | |
61 | /// Emit the string table described by \p Pool into .debug_line_str table. |
62 | virtual void emitLineStrings(const NonRelocatableStringpool &Pool) = 0; |
63 | |
64 | /// Emit DWARF debug names. |
65 | virtual void emitDebugNames(DWARF5AccelTable &Table) = 0; |
66 | |
67 | /// Emit Apple namespaces accelerator table. |
68 | virtual void |
69 | emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0; |
70 | |
71 | /// Emit Apple names accelerator table. |
72 | virtual void |
73 | emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0; |
74 | |
75 | /// Emit Apple Objective-C accelerator table. |
76 | virtual void |
77 | emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0; |
78 | |
79 | /// Emit Apple type accelerator table. |
80 | virtual void |
81 | emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) = 0; |
82 | |
83 | /// Emit debug ranges (.debug_ranges, .debug_rnglists) header. |
84 | virtual MCSymbol *(const CompileUnit &Unit) = 0; |
85 | |
86 | /// Emit debug ranges (.debug_ranges, .debug_rnglists) fragment. |
87 | virtual void emitDwarfDebugRangeListFragment( |
88 | const CompileUnit &Unit, const AddressRanges &LinkedRanges, |
89 | PatchLocation Patch, DebugDieValuePool &AddrPool) = 0; |
90 | |
91 | /// Emit debug ranges (.debug_ranges, .debug_rnglists) footer. |
92 | virtual void (const CompileUnit &Unit, |
93 | MCSymbol *EndLabel) = 0; |
94 | |
95 | /// Emit debug locations (.debug_loc, .debug_loclists) header. |
96 | virtual MCSymbol *(const CompileUnit &Unit) = 0; |
97 | |
98 | /// Emit debug locations (.debug_loc, .debug_loclists) fragment. |
99 | virtual void emitDwarfDebugLocListFragment( |
100 | const CompileUnit &Unit, |
101 | const DWARFLocationExpressionsVector &LinkedLocationExpression, |
102 | PatchLocation Patch, DebugDieValuePool &AddrPool) = 0; |
103 | |
104 | /// Emit debug locations (.debug_loc, .debug_loclists) footer. |
105 | virtual void (const CompileUnit &Unit, |
106 | MCSymbol *EndLabel) = 0; |
107 | |
108 | /// Emit .debug_addr header. |
109 | virtual MCSymbol *(const CompileUnit &Unit) = 0; |
110 | |
111 | /// Emit the addresses described by \p Addrs into the .debug_addr section. |
112 | virtual void emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs, |
113 | uint8_t AddrSize) = 0; |
114 | |
115 | /// Emit .debug_addr footer. |
116 | virtual void (const CompileUnit &Unit, |
117 | MCSymbol *EndLabel) = 0; |
118 | |
119 | /// Emit .debug_aranges entries for \p Unit |
120 | virtual void |
121 | emitDwarfDebugArangesTable(const CompileUnit &Unit, |
122 | const AddressRanges &LinkedRanges) = 0; |
123 | |
124 | /// Emit specified \p LineTable into .debug_line table. |
125 | virtual void emitLineTableForUnit(const DWARFDebugLine::LineTable &LineTable, |
126 | const CompileUnit &Unit, |
127 | OffsetsStringPool &DebugStrPool, |
128 | OffsetsStringPool &DebugLineStrPool) = 0; |
129 | |
130 | /// Emit the .debug_pubnames contribution for \p Unit. |
131 | virtual void emitPubNamesForUnit(const CompileUnit &Unit) = 0; |
132 | |
133 | /// Emit the .debug_pubtypes contribution for \p Unit. |
134 | virtual void emitPubTypesForUnit(const CompileUnit &Unit) = 0; |
135 | |
136 | /// Emit a CIE. |
137 | virtual void emitCIE(StringRef CIEBytes) = 0; |
138 | |
139 | /// Emit an FDE with data \p Bytes. |
140 | virtual void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address, |
141 | StringRef Bytes) = 0; |
142 | |
143 | /// Emit the compilation unit header for \p Unit in the |
144 | /// .debug_info section. |
145 | /// |
146 | /// As a side effect, this also switches the current Dwarf version |
147 | /// of the MC layer to the one of U.getOrigUnit(). |
148 | virtual void (CompileUnit &Unit, |
149 | unsigned DwarfVersion) = 0; |
150 | |
151 | /// Recursively emit the DIE tree rooted at \p Die. |
152 | virtual void emitDIE(DIE &Die) = 0; |
153 | |
154 | /// Emit all available macro tables(DWARFv4 and DWARFv5). |
155 | /// Use \p UnitMacroMap to get compilation unit by macro table offset. |
156 | /// Side effects: Fill \p StringPool with macro strings, update |
157 | /// DW_AT_macro_info, DW_AT_macros attributes for corresponding compile |
158 | /// units. |
159 | virtual void emitMacroTables(DWARFContext *Context, |
160 | const Offset2UnitMap &UnitMacroMap, |
161 | OffsetsStringPool &StringPool) = 0; |
162 | |
163 | /// Returns size of generated .debug_line section. |
164 | virtual uint64_t getLineSectionSize() const = 0; |
165 | |
166 | /// Returns size of generated .debug_frame section. |
167 | virtual uint64_t getFrameSectionSize() const = 0; |
168 | |
169 | /// Returns size of generated .debug_ranges section. |
170 | virtual uint64_t getRangesSectionSize() const = 0; |
171 | |
172 | /// Returns size of generated .debug_rnglists section. |
173 | virtual uint64_t getRngListsSectionSize() const = 0; |
174 | |
175 | /// Returns size of generated .debug_info section. |
176 | virtual uint64_t getDebugInfoSectionSize() const = 0; |
177 | |
178 | /// Returns size of generated .debug_macinfo section. |
179 | virtual uint64_t getDebugMacInfoSectionSize() const = 0; |
180 | |
181 | /// Returns size of generated .debug_macro section. |
182 | virtual uint64_t getDebugMacroSectionSize() const = 0; |
183 | |
184 | /// Returns size of generated .debug_loclists section. |
185 | virtual uint64_t getLocListsSectionSize() const = 0; |
186 | |
187 | /// Returns size of generated .debug_addr section. |
188 | virtual uint64_t getDebugAddrSectionSize() const = 0; |
189 | |
190 | /// Dump the file to the disk. |
191 | virtual void finish() = 0; |
192 | }; |
193 | |
194 | class DwarfStreamer; |
195 | using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>; |
196 | |
197 | /// The core of the Dwarf linking logic. |
198 | /// |
199 | /// The generation of the dwarf information from the object files will be |
200 | /// driven by the selection of 'root DIEs', which are DIEs that |
201 | /// describe variables or functions that resolves to the corresponding |
202 | /// code section(and thus have entries in the Addresses map). All the debug |
203 | /// information that will be generated(the DIEs, but also the line |
204 | /// tables, ranges, ...) is derived from that set of root DIEs. |
205 | /// |
206 | /// The root DIEs are identified because they contain relocations that |
207 | /// points to code section(the low_pc for a function, the location for |
208 | /// a variable). These relocations are called ValidRelocs in the |
209 | /// AddressesInfo and are gathered as a very first step when we start |
210 | /// processing a object file. |
211 | class DWARFLinker : public DWARFLinkerBase { |
212 | public: |
213 | DWARFLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler, |
214 | std::function<StringRef(StringRef)> StringsTranslator) |
215 | : StringsTranslator(StringsTranslator), ErrorHandler(ErrorHandler), |
216 | WarningHandler(WarningHandler) {} |
217 | |
218 | static std::unique_ptr<DWARFLinker> createLinker( |
219 | MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler, |
220 | std::function<StringRef(StringRef)> StringsTranslator = nullptr) { |
221 | return std::make_unique<DWARFLinker>(args&: ErrorHandler, args&: WarningHandler, |
222 | args&: StringsTranslator); |
223 | } |
224 | |
225 | /// Set output DWARF emitter. |
226 | void setOutputDWARFEmitter(DwarfEmitter *Emitter) { |
227 | TheDwarfEmitter = Emitter; |
228 | } |
229 | |
230 | /// Add object file to be linked. Pre-load compile unit die. Call |
231 | /// \p OnCUDieLoaded for each compile unit die. If specified \p File |
232 | /// has reference to the Clang module then such module would be |
233 | /// pre-loaded by \p Loader for !Update case. |
234 | /// |
235 | /// \pre NoODR, Update options should be set before call to addObjectFile. |
236 | void addObjectFile( |
237 | DWARFFile &File, ObjFileLoaderTy Loader = nullptr, |
238 | CompileUnitHandlerTy OnCUDieLoaded = [](const DWARFUnit &) {}) override; |
239 | |
240 | /// Link debug info for added objFiles. Object files are linked all together. |
241 | Error link() override; |
242 | |
243 | /// A number of methods setting various linking options: |
244 | |
245 | /// Allows to generate log of linking process to the standard output. |
246 | void setVerbosity(bool Verbose) override { Options.Verbose = Verbose; } |
247 | |
248 | /// Print statistics to standard output. |
249 | void setStatistics(bool Statistics) override { |
250 | Options.Statistics = Statistics; |
251 | } |
252 | |
253 | /// Verify the input DWARF. |
254 | void setVerifyInputDWARF(bool Verify) override { |
255 | Options.VerifyInputDWARF = Verify; |
256 | } |
257 | |
258 | /// Do not unique types according to ODR. |
259 | void setNoODR(bool NoODR) override { Options.NoODR = NoODR; } |
260 | |
261 | /// Update index tables only(do not modify rest of DWARF). |
262 | void setUpdateIndexTablesOnly(bool Update) override { |
263 | Options.Update = Update; |
264 | } |
265 | |
266 | /// Allow generating valid, but non-deterministic output. |
267 | void setAllowNonDeterministicOutput(bool) override { /* Nothing to do. */ |
268 | } |
269 | |
270 | /// Set whether to keep the enclosing function for a static variable. |
271 | void setKeepFunctionForStatic(bool KeepFunctionForStatic) override { |
272 | Options.KeepFunctionForStatic = KeepFunctionForStatic; |
273 | } |
274 | |
275 | /// Use specified number of threads for parallel files linking. |
276 | void setNumThreads(unsigned NumThreads) override { |
277 | Options.Threads = NumThreads; |
278 | } |
279 | |
280 | /// Add kind of accelerator tables to be generated. |
281 | void addAccelTableKind(AccelTableKind Kind) override { |
282 | assert(!llvm::is_contained(Options.AccelTables, Kind)); |
283 | Options.AccelTables.emplace_back(Args&: Kind); |
284 | } |
285 | |
286 | /// Set prepend path for clang modules. |
287 | void setPrependPath(StringRef Ppath) override { Options.PrependPath = Ppath; } |
288 | |
289 | /// Set estimated objects files amount, for preliminary data allocation. |
290 | void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override { |
291 | ObjectContexts.reserve(n: ObjFilesNum); |
292 | } |
293 | |
294 | /// Set verification handler which would be used to report verification |
295 | /// errors. |
296 | void |
297 | setInputVerificationHandler(InputVerificationHandlerTy Handler) override { |
298 | Options.InputVerificationHandler = Handler; |
299 | } |
300 | |
301 | /// Set map for Swift interfaces. |
302 | void setSwiftInterfacesMap(SwiftInterfacesMapTy *Map) override { |
303 | Options.ParseableSwiftInterfaces = Map; |
304 | } |
305 | |
306 | /// Set prefix map for objects. |
307 | void setObjectPrefixMap(ObjectPrefixMapTy *Map) override { |
308 | Options.ObjectPrefixMap = Map; |
309 | } |
310 | |
311 | /// Set target DWARF version. |
312 | Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) override { |
313 | if ((TargetDWARFVersion < 1) || (TargetDWARFVersion > 5)) |
314 | return createStringError(EC: std::errc::invalid_argument, |
315 | Fmt: "unsupported DWARF version: %d" , |
316 | Vals: TargetDWARFVersion); |
317 | |
318 | Options.TargetDWARFVersion = TargetDWARFVersion; |
319 | return Error::success(); |
320 | } |
321 | |
322 | private: |
323 | /// Flags passed to DwarfLinker::lookForDIEsToKeep |
324 | enum TraversalFlags { |
325 | TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept. |
326 | TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope. |
327 | TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE. |
328 | TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE. |
329 | TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents. |
330 | TF_SkipPC = 1 << 5, ///< Skip all location attributes. |
331 | }; |
332 | |
333 | /// The distinct types of work performed by the work loop. |
334 | enum class WorklistItemType { |
335 | /// Given a DIE, look for DIEs to be kept. |
336 | LookForDIEsToKeep, |
337 | /// Given a DIE, look for children of this DIE to be kept. |
338 | LookForChildDIEsToKeep, |
339 | /// Given a DIE, look for DIEs referencing this DIE to be kept. |
340 | LookForRefDIEsToKeep, |
341 | /// Given a DIE, look for parent DIEs to be kept. |
342 | LookForParentDIEsToKeep, |
343 | /// Given a DIE, update its incompleteness based on whether its children are |
344 | /// incomplete. |
345 | UpdateChildIncompleteness, |
346 | /// Given a DIE, update its incompleteness based on whether the DIEs it |
347 | /// references are incomplete. |
348 | UpdateRefIncompleteness, |
349 | /// Given a DIE, mark it as ODR Canonical if applicable. |
350 | MarkODRCanonicalDie, |
351 | }; |
352 | |
353 | /// This class represents an item in the work list. The type defines what kind |
354 | /// of work needs to be performed when processing the current item. The flags |
355 | /// and info fields are optional based on the type. |
356 | struct WorklistItem { |
357 | DWARFDie Die; |
358 | WorklistItemType Type; |
359 | CompileUnit &CU; |
360 | unsigned Flags; |
361 | union { |
362 | const unsigned AncestorIdx; |
363 | CompileUnit::DIEInfo *OtherInfo; |
364 | }; |
365 | |
366 | WorklistItem(DWARFDie Die, CompileUnit &CU, unsigned Flags, |
367 | WorklistItemType T = WorklistItemType::LookForDIEsToKeep) |
368 | : Die(Die), Type(T), CU(CU), Flags(Flags), AncestorIdx(0) {} |
369 | |
370 | WorklistItem(DWARFDie Die, CompileUnit &CU, WorklistItemType T, |
371 | CompileUnit::DIEInfo *OtherInfo = nullptr) |
372 | : Die(Die), Type(T), CU(CU), Flags(0), OtherInfo(OtherInfo) {} |
373 | |
374 | WorklistItem(unsigned AncestorIdx, CompileUnit &CU, unsigned Flags) |
375 | : Type(WorklistItemType::LookForParentDIEsToKeep), CU(CU), Flags(Flags), |
376 | AncestorIdx(AncestorIdx) {} |
377 | }; |
378 | |
379 | /// Verify the given DWARF file. |
380 | void verifyInput(const DWARFFile &File); |
381 | |
382 | /// returns true if we need to translate strings. |
383 | bool needToTranslateStrings() { return StringsTranslator != nullptr; } |
384 | |
385 | void reportWarning(const Twine &Warning, const DWARFFile &File, |
386 | const DWARFDie *DIE = nullptr) const { |
387 | if (WarningHandler != nullptr) |
388 | WarningHandler(Warning, File.FileName, DIE); |
389 | } |
390 | |
391 | void reportError(const Twine &Warning, const DWARFFile &File, |
392 | const DWARFDie *DIE = nullptr) const { |
393 | if (ErrorHandler != nullptr) |
394 | ErrorHandler(Warning, File.FileName, DIE); |
395 | } |
396 | |
397 | void copyInvariantDebugSection(DWARFContext &Dwarf); |
398 | |
399 | /// Keep information for referenced clang module: already loaded DWARF info |
400 | /// of the clang module and a CompileUnit of the module. |
401 | struct RefModuleUnit { |
402 | RefModuleUnit(DWARFFile &File, std::unique_ptr<CompileUnit> Unit) |
403 | : File(File), Unit(std::move(Unit)) {} |
404 | RefModuleUnit(RefModuleUnit &&Other) |
405 | : File(Other.File), Unit(std::move(Other.Unit)) {} |
406 | RefModuleUnit(const RefModuleUnit &) = delete; |
407 | |
408 | DWARFFile &File; |
409 | std::unique_ptr<CompileUnit> Unit; |
410 | }; |
411 | using ModuleUnitListTy = std::vector<RefModuleUnit>; |
412 | |
413 | /// Keeps track of data associated with one object during linking. |
414 | struct LinkContext { |
415 | DWARFFile &File; |
416 | UnitListTy CompileUnits; |
417 | ModuleUnitListTy ModuleUnits; |
418 | bool Skip = false; |
419 | |
420 | LinkContext(DWARFFile &File) : File(File) {} |
421 | |
422 | /// Clear part of the context that's no longer needed when we're done with |
423 | /// the debug object. |
424 | void clear() { |
425 | CompileUnits.clear(); |
426 | ModuleUnits.clear(); |
427 | File.unload(); |
428 | } |
429 | }; |
430 | |
431 | /// Called before emitting object data |
432 | void cleanupAuxiliarryData(LinkContext &Context); |
433 | |
434 | /// Look at the parent of the given DIE and decide whether they should be |
435 | /// kept. |
436 | void lookForParentDIEsToKeep(unsigned AncestorIdx, CompileUnit &CU, |
437 | unsigned Flags, |
438 | SmallVectorImpl<WorklistItem> &Worklist); |
439 | |
440 | /// Look at the children of the given DIE and decide whether they should be |
441 | /// kept. |
442 | void lookForChildDIEsToKeep(const DWARFDie &Die, CompileUnit &CU, |
443 | unsigned Flags, |
444 | SmallVectorImpl<WorklistItem> &Worklist); |
445 | |
446 | /// Look at DIEs referenced by the given DIE and decide whether they should be |
447 | /// kept. All DIEs referenced though attributes should be kept. |
448 | void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU, |
449 | unsigned Flags, const UnitListTy &Units, |
450 | const DWARFFile &File, |
451 | SmallVectorImpl<WorklistItem> &Worklist); |
452 | |
453 | /// Mark context corresponding to the specified \p Die as having canonical |
454 | /// die, if applicable. |
455 | void markODRCanonicalDie(const DWARFDie &Die, CompileUnit &CU); |
456 | |
457 | /// \defgroup FindRootDIEs Find DIEs corresponding to Address map entries. |
458 | /// |
459 | /// @{ |
460 | /// Recursively walk the \p DIE tree and look for DIEs to |
461 | /// keep. Store that information in \p CU's DIEInfo. |
462 | /// |
463 | /// The return value indicates whether the DIE is incomplete. |
464 | void lookForDIEsToKeep(AddressesMap &RelocMgr, const UnitListTy &Units, |
465 | const DWARFDie &DIE, const DWARFFile &File, |
466 | CompileUnit &CU, unsigned Flags); |
467 | |
468 | /// Check whether specified \p CUDie is a Clang module reference. |
469 | /// if \p Quiet is false then display error messages. |
470 | /// \return first == true if CUDie is a Clang module reference. |
471 | /// second == true if module is already loaded. |
472 | std::pair<bool, bool> isClangModuleRef(const DWARFDie &CUDie, |
473 | std::string &PCMFile, |
474 | LinkContext &Context, unsigned Indent, |
475 | bool Quiet); |
476 | |
477 | /// If this compile unit is really a skeleton CU that points to a |
478 | /// clang module, register it in ClangModules and return true. |
479 | /// |
480 | /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name |
481 | /// pointing to the module, and a DW_AT_gnu_dwo_id with the module |
482 | /// hash. |
483 | bool registerModuleReference(const DWARFDie &CUDie, LinkContext &Context, |
484 | ObjFileLoaderTy Loader, |
485 | CompileUnitHandlerTy OnCUDieLoaded, |
486 | unsigned Indent = 0); |
487 | |
488 | /// Recursively add the debug info in this clang module .pcm |
489 | /// file (and all the modules imported by it in a bottom-up fashion) |
490 | /// to ModuleUnits. |
491 | Error loadClangModule(ObjFileLoaderTy Loader, const DWARFDie &CUDie, |
492 | const std::string &PCMFile, LinkContext &Context, |
493 | CompileUnitHandlerTy OnCUDieLoaded, |
494 | unsigned Indent = 0); |
495 | |
496 | /// Clone specified Clang module unit \p Unit. |
497 | Error cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit, |
498 | DeclContextTree &ODRContexts, |
499 | OffsetsStringPool &DebugStrPool, |
500 | OffsetsStringPool &DebugLineStrPool, |
501 | DebugDieValuePool &StringOffsetPool, |
502 | unsigned Indent = 0); |
503 | |
504 | unsigned shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE, |
505 | const DWARFFile &File, CompileUnit &Unit, |
506 | CompileUnit::DIEInfo &MyInfo, unsigned Flags); |
507 | |
508 | /// This function checks whether variable has DWARF expression containing |
509 | /// operation referencing live address(f.e. DW_OP_addr, DW_OP_addrx...). |
510 | /// \returns first is true if the expression has an operation referencing an |
511 | /// address. |
512 | /// second is the relocation adjustment value if the live address is |
513 | /// referenced. |
514 | std::pair<bool, std::optional<int64_t>> |
515 | getVariableRelocAdjustment(AddressesMap &RelocMgr, const DWARFDie &DIE); |
516 | |
517 | /// Check if a variable describing DIE should be kept. |
518 | /// \returns updated TraversalFlags. |
519 | unsigned shouldKeepVariableDIE(AddressesMap &RelocMgr, const DWARFDie &DIE, |
520 | CompileUnit::DIEInfo &MyInfo, unsigned Flags); |
521 | |
522 | unsigned shouldKeepSubprogramDIE(AddressesMap &RelocMgr, const DWARFDie &DIE, |
523 | const DWARFFile &File, CompileUnit &Unit, |
524 | CompileUnit::DIEInfo &MyInfo, |
525 | unsigned Flags); |
526 | |
527 | /// Resolve the DIE attribute reference that has been extracted in \p |
528 | /// RefValue. The resulting DIE might be in another CompileUnit which is |
529 | /// stored into \p ReferencedCU. \returns null if resolving fails for any |
530 | /// reason. |
531 | DWARFDie resolveDIEReference(const DWARFFile &File, const UnitListTy &Units, |
532 | const DWARFFormValue &RefValue, |
533 | const DWARFDie &DIE, CompileUnit *&RefCU); |
534 | |
535 | /// @} |
536 | |
537 | /// \defgroup Methods used to link the debug information |
538 | /// |
539 | /// @{ |
540 | |
541 | struct DWARFLinkerOptions; |
542 | |
543 | class DIECloner { |
544 | DWARFLinker &Linker; |
545 | DwarfEmitter *Emitter; |
546 | DWARFFile &ObjFile; |
547 | OffsetsStringPool &DebugStrPool; |
548 | OffsetsStringPool &DebugLineStrPool; |
549 | DebugDieValuePool &StringOffsetPool; |
550 | DebugDieValuePool AddrPool; |
551 | |
552 | /// Allocator used for all the DIEValue objects. |
553 | BumpPtrAllocator &DIEAlloc; |
554 | |
555 | std::vector<std::unique_ptr<CompileUnit>> &CompileUnits; |
556 | |
557 | /// Keeps mapping from offset of the macro table to corresponding |
558 | /// compile unit. |
559 | Offset2UnitMap UnitMacroMap; |
560 | |
561 | bool Update; |
562 | |
563 | public: |
564 | DIECloner(DWARFLinker &Linker, DwarfEmitter *Emitter, DWARFFile &ObjFile, |
565 | BumpPtrAllocator &DIEAlloc, |
566 | std::vector<std::unique_ptr<CompileUnit>> &CompileUnits, |
567 | bool Update, OffsetsStringPool &DebugStrPool, |
568 | OffsetsStringPool &DebugLineStrPool, |
569 | DebugDieValuePool &StringOffsetPool) |
570 | : Linker(Linker), Emitter(Emitter), ObjFile(ObjFile), |
571 | DebugStrPool(DebugStrPool), DebugLineStrPool(DebugLineStrPool), |
572 | StringOffsetPool(StringOffsetPool), DIEAlloc(DIEAlloc), |
573 | CompileUnits(CompileUnits), Update(Update) {} |
574 | |
575 | /// Recursively clone \p InputDIE into an tree of DIE objects |
576 | /// where useless (as decided by lookForDIEsToKeep()) bits have been |
577 | /// stripped out and addresses have been rewritten according to the |
578 | /// address map. |
579 | /// |
580 | /// \param OutOffset is the offset the cloned DIE in the output |
581 | /// compile unit. |
582 | /// \param PCOffset (while cloning a function scope) is the offset |
583 | /// applied to the entry point of the function to get the linked address. |
584 | /// \param Die the output DIE to use, pass NULL to create one. |
585 | /// \returns the root of the cloned tree or null if nothing was selected. |
586 | DIE *cloneDIE(const DWARFDie &InputDIE, const DWARFFile &File, |
587 | CompileUnit &U, int64_t PCOffset, uint32_t OutOffset, |
588 | unsigned Flags, bool IsLittleEndian, DIE *Die = nullptr); |
589 | |
590 | /// Construct the output DIE tree by cloning the DIEs we |
591 | /// chose to keep above. If there are no valid relocs, then there's |
592 | /// nothing to clone/emit. |
593 | uint64_t cloneAllCompileUnits(DWARFContext &DwarfContext, |
594 | const DWARFFile &File, bool IsLittleEndian); |
595 | |
596 | /// Emit the .debug_addr section for the \p Unit. |
597 | void emitDebugAddrSection(CompileUnit &Unit, |
598 | const uint16_t DwarfVersion) const; |
599 | |
600 | using ExpressionHandlerRef = function_ref<void( |
601 | SmallVectorImpl<uint8_t> &, SmallVectorImpl<uint8_t> &, |
602 | int64_t AddrRelocAdjustment)>; |
603 | |
604 | /// Compute and emit debug locations (.debug_loc, .debug_loclists) |
605 | /// for \p Unit, patch the attributes referencing it. |
606 | void generateUnitLocations(CompileUnit &Unit, const DWARFFile &File, |
607 | ExpressionHandlerRef ExprHandler); |
608 | |
609 | private: |
610 | using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec; |
611 | |
612 | /// Information gathered and exchanged between the various |
613 | /// clone*Attributes helpers about the attributes of a particular DIE. |
614 | struct AttributesInfo { |
615 | /// Names. |
616 | DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate; |
617 | |
618 | /// Offsets in the string pool. |
619 | uint32_t NameOffset = 0; |
620 | uint32_t MangledNameOffset = 0; |
621 | |
622 | /// Offset to apply to PC addresses inside a function. |
623 | int64_t PCOffset = 0; |
624 | |
625 | /// Does the DIE have a low_pc attribute? |
626 | bool HasLowPc = false; |
627 | |
628 | /// Does the DIE have a ranges attribute? |
629 | bool HasRanges = false; |
630 | |
631 | /// Is this DIE only a declaration? |
632 | bool IsDeclaration = false; |
633 | |
634 | /// Is there a DW_AT_str_offsets_base in the CU? |
635 | bool AttrStrOffsetBaseSeen = false; |
636 | |
637 | /// Is there a DW_AT_APPLE_origin in the CU? |
638 | bool HasAppleOrigin = false; |
639 | |
640 | AttributesInfo() = default; |
641 | }; |
642 | |
643 | /// Helper for cloneDIE. |
644 | unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE, |
645 | const DWARFFile &File, CompileUnit &U, |
646 | const DWARFFormValue &Val, |
647 | const AttributeSpec AttrSpec, unsigned AttrSize, |
648 | AttributesInfo &AttrInfo, bool IsLittleEndian); |
649 | |
650 | /// Clone a string attribute described by \p AttrSpec and add |
651 | /// it to \p Die. |
652 | /// \returns the size of the new attribute. |
653 | unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec, |
654 | const DWARFFormValue &Val, const DWARFUnit &U, |
655 | AttributesInfo &Info); |
656 | |
657 | /// Clone an attribute referencing another DIE and add |
658 | /// it to \p Die. |
659 | /// \returns the size of the new attribute. |
660 | unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE, |
661 | AttributeSpec AttrSpec, |
662 | unsigned AttrSize, |
663 | const DWARFFormValue &Val, |
664 | const DWARFFile &File, |
665 | CompileUnit &Unit); |
666 | |
667 | /// Clone a DWARF expression that may be referencing another DIE. |
668 | void (DataExtractor &Data, DWARFExpression Expression, |
669 | const DWARFFile &File, CompileUnit &Unit, |
670 | SmallVectorImpl<uint8_t> &OutputBuffer, |
671 | int64_t AddrRelocAdjustment, bool IsLittleEndian); |
672 | |
673 | /// Clone an attribute referencing another DIE and add |
674 | /// it to \p Die. |
675 | /// \returns the size of the new attribute. |
676 | unsigned cloneBlockAttribute(DIE &Die, const DWARFDie &InputDIE, |
677 | const DWARFFile &File, CompileUnit &Unit, |
678 | AttributeSpec AttrSpec, |
679 | const DWARFFormValue &Val, |
680 | bool IsLittleEndian); |
681 | |
682 | /// Clone an attribute referencing another DIE and add |
683 | /// it to \p Die. |
684 | /// \returns the size of the new attribute. |
685 | unsigned cloneAddressAttribute(DIE &Die, const DWARFDie &InputDIE, |
686 | AttributeSpec AttrSpec, unsigned AttrSize, |
687 | const DWARFFormValue &Val, |
688 | const CompileUnit &Unit, |
689 | AttributesInfo &Info); |
690 | |
691 | /// Clone a scalar attribute and add it to \p Die. |
692 | /// \returns the size of the new attribute. |
693 | unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE, |
694 | const DWARFFile &File, CompileUnit &U, |
695 | AttributeSpec AttrSpec, |
696 | const DWARFFormValue &Val, unsigned AttrSize, |
697 | AttributesInfo &Info); |
698 | |
699 | /// Get the potential name and mangled name for the entity |
700 | /// described by \p Die and store them in \Info if they are not |
701 | /// already there. |
702 | /// \returns is a name was found. |
703 | bool getDIENames(const DWARFDie &Die, AttributesInfo &Info, |
704 | OffsetsStringPool &StringPool, bool StripTemplate = false); |
705 | |
706 | uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U, |
707 | const DWARFFile &File, |
708 | int RecurseDepth = 0); |
709 | |
710 | /// Helper for cloneDIE. |
711 | void addObjCAccelerator(CompileUnit &Unit, const DIE *Die, |
712 | DwarfStringPoolEntryRef Name, |
713 | OffsetsStringPool &StringPool, bool SkipPubSection); |
714 | |
715 | void rememberUnitForMacroOffset(CompileUnit &Unit); |
716 | |
717 | /// Clone and emit the line table for the specified \p Unit. |
718 | /// Translate directories and file names if necessary. |
719 | /// Relocate address ranges. |
720 | void generateLineTableForUnit(CompileUnit &Unit); |
721 | }; |
722 | |
723 | /// Assign an abbreviation number to \p Abbrev |
724 | void assignAbbrev(DIEAbbrev &Abbrev); |
725 | |
726 | /// Compute and emit debug ranges(.debug_aranges, .debug_ranges, |
727 | /// .debug_rnglists) for \p Unit, patch the attributes referencing it. |
728 | void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File, |
729 | DebugDieValuePool &AddrPool) const; |
730 | |
731 | /// Emit the accelerator entries for \p Unit. |
732 | void emitAcceleratorEntriesForUnit(CompileUnit &Unit); |
733 | |
734 | /// Patch the frame info for an object file and emit it. |
735 | void patchFrameInfoForObject(LinkContext &Context); |
736 | |
737 | /// FoldingSet that uniques the abbreviations. |
738 | FoldingSet<DIEAbbrev> AbbreviationsSet; |
739 | |
740 | /// Storage for the unique Abbreviations. |
741 | /// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be |
742 | /// changed to a vector of unique_ptrs. |
743 | std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations; |
744 | |
745 | /// DIELoc objects that need to be destructed (but not freed!). |
746 | std::vector<DIELoc *> DIELocs; |
747 | |
748 | /// DIEBlock objects that need to be destructed (but not freed!). |
749 | std::vector<DIEBlock *> DIEBlocks; |
750 | |
751 | /// Allocator used for all the DIEValue objects. |
752 | BumpPtrAllocator DIEAlloc; |
753 | /// @} |
754 | |
755 | DwarfEmitter *TheDwarfEmitter = nullptr; |
756 | std::vector<LinkContext> ObjectContexts; |
757 | |
758 | /// The CIEs that have been emitted in the output section. The actual CIE |
759 | /// data serves a the key to this StringMap, this takes care of comparing the |
760 | /// semantics of CIEs defined in different object files. |
761 | StringMap<uint32_t> EmittedCIEs; |
762 | |
763 | /// Offset of the last CIE that has been emitted in the output |
764 | /// .debug_frame section. |
765 | uint32_t LastCIEOffset = 0; |
766 | |
767 | /// Apple accelerator tables. |
768 | DWARF5AccelTable DebugNames; |
769 | AccelTable<AppleAccelTableStaticOffsetData> AppleNames; |
770 | AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces; |
771 | AccelTable<AppleAccelTableStaticOffsetData> AppleObjc; |
772 | AccelTable<AppleAccelTableStaticTypeData> AppleTypes; |
773 | |
774 | /// Mapping the PCM filename to the DwoId. |
775 | StringMap<uint64_t> ClangModules; |
776 | |
777 | std::function<StringRef(StringRef)> StringsTranslator = nullptr; |
778 | |
779 | /// A unique ID that identifies each compile unit. |
780 | unsigned UniqueUnitID = 0; |
781 | |
782 | // error handler |
783 | MessageHandlerTy ErrorHandler = nullptr; |
784 | |
785 | // warning handler |
786 | MessageHandlerTy WarningHandler = nullptr; |
787 | |
788 | /// linking options |
789 | struct DWARFLinkerOptions { |
790 | /// DWARF version for the output. |
791 | uint16_t TargetDWARFVersion = 0; |
792 | |
793 | /// Generate processing log to the standard output. |
794 | bool Verbose = false; |
795 | |
796 | /// Print statistics. |
797 | bool Statistics = false; |
798 | |
799 | /// Verify the input DWARF. |
800 | bool VerifyInputDWARF = false; |
801 | |
802 | /// Do not unique types according to ODR |
803 | bool NoODR = false; |
804 | |
805 | /// Update |
806 | bool Update = false; |
807 | |
808 | /// Whether we want a static variable to force us to keep its enclosing |
809 | /// function. |
810 | bool KeepFunctionForStatic = false; |
811 | |
812 | /// Number of threads. |
813 | unsigned Threads = 1; |
814 | |
815 | /// The accelerator table kinds |
816 | SmallVector<AccelTableKind, 1> AccelTables; |
817 | |
818 | /// Prepend path for the clang modules. |
819 | std::string PrependPath; |
820 | |
821 | // input verification handler |
822 | InputVerificationHandlerTy InputVerificationHandler = nullptr; |
823 | |
824 | /// A list of all .swiftinterface files referenced by the debug |
825 | /// info, mapping Module name to path on disk. The entries need to |
826 | /// be uniqued and sorted and there are only few entries expected |
827 | /// per compile unit, which is why this is a std::map. |
828 | /// this is dsymutil specific fag. |
829 | SwiftInterfacesMapTy *ParseableSwiftInterfaces = nullptr; |
830 | |
831 | /// A list of remappings to apply to file paths. |
832 | ObjectPrefixMapTy *ObjectPrefixMap = nullptr; |
833 | } Options; |
834 | }; |
835 | |
836 | } // end of namespace classic |
837 | } // end of namespace dwarf_linker |
838 | } // end of namespace llvm |
839 | |
840 | #endif // LLVM_DWARFLINKER_CLASSIC_DWARFLINKER_H |
841 | |