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