File: | llvm/lib/DWARFLinker/DWARFLinker.cpp |
Warning: | line 989, column 9 Value stored to 'RealSize' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //=== DWARFLinker.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 "llvm/DWARFLinker/DWARFLinker.h" |
10 | #include "llvm/ADT/ArrayRef.h" |
11 | #include "llvm/ADT/BitVector.h" |
12 | #include "llvm/ADT/STLExtras.h" |
13 | #include "llvm/ADT/Triple.h" |
14 | #include "llvm/CodeGen/NonRelocatableStringpool.h" |
15 | #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h" |
16 | #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" |
17 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
18 | #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" |
19 | #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" |
20 | #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" |
21 | #include "llvm/DebugInfo/DWARF/DWARFDie.h" |
22 | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" |
23 | #include "llvm/DebugInfo/DWARF/DWARFSection.h" |
24 | #include "llvm/DebugInfo/DWARF/DWARFUnit.h" |
25 | #include "llvm/Support/DataExtractor.h" |
26 | #include "llvm/Support/Error.h" |
27 | #include "llvm/Support/ErrorHandling.h" |
28 | #include "llvm/Support/ErrorOr.h" |
29 | #include "llvm/Support/FormatVariadic.h" |
30 | #include "llvm/Support/LEB128.h" |
31 | #include "llvm/Support/Path.h" |
32 | #include "llvm/Support/ThreadPool.h" |
33 | #include <vector> |
34 | |
35 | namespace llvm { |
36 | |
37 | /// Hold the input and output of the debug info size in bytes. |
38 | struct DebugInfoSize { |
39 | uint64_t Input; |
40 | uint64_t Output; |
41 | }; |
42 | |
43 | /// Compute the total size of the debug info. |
44 | static uint64_t getDebugInfoSize(DWARFContext &Dwarf) { |
45 | uint64_t Size = 0; |
46 | for (auto &Unit : Dwarf.compile_units()) { |
47 | Size += Unit->getLength(); |
48 | } |
49 | return Size; |
50 | } |
51 | |
52 | /// Similar to DWARFUnitSection::getUnitForOffset(), but returning our |
53 | /// CompileUnit object instead. |
54 | static CompileUnit *getUnitForOffset(const UnitListTy &Units, uint64_t Offset) { |
55 | auto CU = llvm::upper_bound( |
56 | Units, Offset, [](uint64_t LHS, const std::unique_ptr<CompileUnit> &RHS) { |
57 | return LHS < RHS->getOrigUnit().getNextUnitOffset(); |
58 | }); |
59 | return CU != Units.end() ? CU->get() : nullptr; |
60 | } |
61 | |
62 | /// Resolve the DIE attribute reference that has been extracted in \p RefValue. |
63 | /// The resulting DIE might be in another CompileUnit which is stored into \p |
64 | /// ReferencedCU. \returns null if resolving fails for any reason. |
65 | DWARFDie DWARFLinker::resolveDIEReference(const DWARFFile &File, |
66 | const UnitListTy &Units, |
67 | const DWARFFormValue &RefValue, |
68 | const DWARFDie &DIE, |
69 | CompileUnit *&RefCU) { |
70 | assert(RefValue.isFormClass(DWARFFormValue::FC_Reference))(static_cast<void> (0)); |
71 | uint64_t RefOffset = *RefValue.getAsReference(); |
72 | if ((RefCU = getUnitForOffset(Units, RefOffset))) |
73 | if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) { |
74 | // In a file with broken references, an attribute might point to a NULL |
75 | // DIE. |
76 | if (!RefDie.isNULL()) |
77 | return RefDie; |
78 | } |
79 | |
80 | reportWarning("could not find referenced DIE", File, &DIE); |
81 | return DWARFDie(); |
82 | } |
83 | |
84 | /// \returns whether the passed \a Attr type might contain a DIE reference |
85 | /// suitable for ODR uniquing. |
86 | static bool isODRAttribute(uint16_t Attr) { |
87 | switch (Attr) { |
88 | default: |
89 | return false; |
90 | case dwarf::DW_AT_type: |
91 | case dwarf::DW_AT_containing_type: |
92 | case dwarf::DW_AT_specification: |
93 | case dwarf::DW_AT_abstract_origin: |
94 | case dwarf::DW_AT_import: |
95 | return true; |
96 | } |
97 | llvm_unreachable("Improper attribute.")__builtin_unreachable(); |
98 | } |
99 | |
100 | static bool isTypeTag(uint16_t Tag) { |
101 | switch (Tag) { |
102 | case dwarf::DW_TAG_array_type: |
103 | case dwarf::DW_TAG_class_type: |
104 | case dwarf::DW_TAG_enumeration_type: |
105 | case dwarf::DW_TAG_pointer_type: |
106 | case dwarf::DW_TAG_reference_type: |
107 | case dwarf::DW_TAG_string_type: |
108 | case dwarf::DW_TAG_structure_type: |
109 | case dwarf::DW_TAG_subroutine_type: |
110 | case dwarf::DW_TAG_typedef: |
111 | case dwarf::DW_TAG_union_type: |
112 | case dwarf::DW_TAG_ptr_to_member_type: |
113 | case dwarf::DW_TAG_set_type: |
114 | case dwarf::DW_TAG_subrange_type: |
115 | case dwarf::DW_TAG_base_type: |
116 | case dwarf::DW_TAG_const_type: |
117 | case dwarf::DW_TAG_constant: |
118 | case dwarf::DW_TAG_file_type: |
119 | case dwarf::DW_TAG_namelist: |
120 | case dwarf::DW_TAG_packed_type: |
121 | case dwarf::DW_TAG_volatile_type: |
122 | case dwarf::DW_TAG_restrict_type: |
123 | case dwarf::DW_TAG_atomic_type: |
124 | case dwarf::DW_TAG_interface_type: |
125 | case dwarf::DW_TAG_unspecified_type: |
126 | case dwarf::DW_TAG_shared_type: |
127 | return true; |
128 | default: |
129 | break; |
130 | } |
131 | return false; |
132 | } |
133 | |
134 | AddressesMap::~AddressesMap() {} |
135 | |
136 | DwarfEmitter::~DwarfEmitter() {} |
137 | |
138 | static Optional<StringRef> StripTemplateParameters(StringRef Name) { |
139 | // We are looking for template parameters to strip from Name. e.g. |
140 | // |
141 | // operator<<B> |
142 | // |
143 | // We look for > at the end but if it does not contain any < then we |
144 | // have something like operator>>. We check for the operator<=> case. |
145 | if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>")) |
146 | return {}; |
147 | |
148 | // How many < until we have the start of the template parameters. |
149 | size_t NumLeftAnglesToSkip = 1; |
150 | |
151 | // If we have operator<=> then we need to skip its < as well. |
152 | NumLeftAnglesToSkip += Name.count("<=>"); |
153 | |
154 | size_t RightAngleCount = Name.count('>'); |
155 | size_t LeftAngleCount = Name.count('<'); |
156 | |
157 | // If we have more < than > we have operator< or operator<< |
158 | // we to account for their < as well. |
159 | if (LeftAngleCount > RightAngleCount) |
160 | NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount; |
161 | |
162 | size_t StartOfTemplate = 0; |
163 | while (NumLeftAnglesToSkip--) |
164 | StartOfTemplate = Name.find('<', StartOfTemplate) + 1; |
165 | |
166 | return Name.substr(0, StartOfTemplate - 1); |
167 | } |
168 | |
169 | bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die, |
170 | AttributesInfo &Info, |
171 | OffsetsStringPool &StringPool, |
172 | bool StripTemplate) { |
173 | // This function will be called on DIEs having low_pcs and |
174 | // ranges. As getting the name might be more expansive, filter out |
175 | // blocks directly. |
176 | if (Die.getTag() == dwarf::DW_TAG_lexical_block) |
177 | return false; |
178 | |
179 | if (!Info.MangledName) |
180 | if (const char *MangledName = Die.getLinkageName()) |
181 | Info.MangledName = StringPool.getEntry(MangledName); |
182 | |
183 | if (!Info.Name) |
184 | if (const char *Name = Die.getShortName()) |
185 | Info.Name = StringPool.getEntry(Name); |
186 | |
187 | if (!Info.MangledName) |
188 | Info.MangledName = Info.Name; |
189 | |
190 | if (StripTemplate && Info.Name && Info.MangledName != Info.Name) { |
191 | StringRef Name = Info.Name.getString(); |
192 | if (Optional<StringRef> StrippedName = StripTemplateParameters(Name)) |
193 | Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName); |
194 | } |
195 | |
196 | return Info.Name || Info.MangledName; |
197 | } |
198 | |
199 | /// Resolve the relative path to a build artifact referenced by DWARF by |
200 | /// applying DW_AT_comp_dir. |
201 | static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) { |
202 | sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), "")); |
203 | } |
204 | |
205 | /// Collect references to parseable Swift interfaces in imported |
206 | /// DW_TAG_module blocks. |
207 | static void analyzeImportedModule( |
208 | const DWARFDie &DIE, CompileUnit &CU, |
209 | swiftInterfacesMap *ParseableSwiftInterfaces, |
210 | std::function<void(const Twine &, const DWARFDie &)> ReportWarning) { |
211 | if (CU.getLanguage() != dwarf::DW_LANG_Swift) |
212 | return; |
213 | |
214 | if (!ParseableSwiftInterfaces) |
215 | return; |
216 | |
217 | StringRef Path = dwarf::toStringRef(DIE.find(dwarf::DW_AT_LLVM_include_path)); |
218 | if (!Path.endswith(".swiftinterface")) |
219 | return; |
220 | // Don't track interfaces that are part of the SDK. |
221 | StringRef SysRoot = dwarf::toStringRef(DIE.find(dwarf::DW_AT_LLVM_sysroot)); |
222 | if (SysRoot.empty()) |
223 | SysRoot = CU.getSysRoot(); |
224 | if (!SysRoot.empty() && Path.startswith(SysRoot)) |
225 | return; |
226 | if (Optional<DWARFFormValue> Val = DIE.find(dwarf::DW_AT_name)) |
227 | if (Optional<const char *> Name = Val->getAsCString()) { |
228 | auto &Entry = (*ParseableSwiftInterfaces)[*Name]; |
229 | // The prepend path is applied later when copying. |
230 | DWARFDie CUDie = CU.getOrigUnit().getUnitDIE(); |
231 | SmallString<128> ResolvedPath; |
232 | if (sys::path::is_relative(Path)) |
233 | resolveRelativeObjectPath(ResolvedPath, CUDie); |
234 | sys::path::append(ResolvedPath, Path); |
235 | if (!Entry.empty() && Entry != ResolvedPath) |
236 | ReportWarning( |
237 | Twine("Conflicting parseable interfaces for Swift Module ") + |
238 | *Name + ": " + Entry + " and " + Path, |
239 | DIE); |
240 | Entry = std::string(ResolvedPath.str()); |
241 | } |
242 | } |
243 | |
244 | /// The distinct types of work performed by the work loop in |
245 | /// analyzeContextInfo. |
246 | enum class ContextWorklistItemType : uint8_t { |
247 | AnalyzeContextInfo, |
248 | UpdateChildPruning, |
249 | UpdatePruning, |
250 | }; |
251 | |
252 | /// This class represents an item in the work list. The type defines what kind |
253 | /// of work needs to be performed when processing the current item. Everything |
254 | /// but the Type and Die fields are optional based on the type. |
255 | struct ContextWorklistItem { |
256 | DWARFDie Die; |
257 | unsigned ParentIdx; |
258 | union { |
259 | CompileUnit::DIEInfo *OtherInfo; |
260 | DeclContext *Context; |
261 | }; |
262 | ContextWorklistItemType Type; |
263 | bool InImportedModule; |
264 | |
265 | ContextWorklistItem(DWARFDie Die, ContextWorklistItemType T, |
266 | CompileUnit::DIEInfo *OtherInfo = nullptr) |
267 | : Die(Die), ParentIdx(0), OtherInfo(OtherInfo), Type(T), |
268 | InImportedModule(false) {} |
269 | |
270 | ContextWorklistItem(DWARFDie Die, DeclContext *Context, unsigned ParentIdx, |
271 | bool InImportedModule) |
272 | : Die(Die), ParentIdx(ParentIdx), Context(Context), |
273 | Type(ContextWorklistItemType::AnalyzeContextInfo), |
274 | InImportedModule(InImportedModule) {} |
275 | }; |
276 | |
277 | static bool updatePruning(const DWARFDie &Die, CompileUnit &CU, |
278 | uint64_t ModulesEndOffset) { |
279 | CompileUnit::DIEInfo &Info = CU.getInfo(Die); |
280 | |
281 | // Prune this DIE if it is either a forward declaration inside a |
282 | // DW_TAG_module or a DW_TAG_module that contains nothing but |
283 | // forward declarations. |
284 | Info.Prune &= (Die.getTag() == dwarf::DW_TAG_module) || |
285 | (isTypeTag(Die.getTag()) && |
286 | dwarf::toUnsigned(Die.find(dwarf::DW_AT_declaration), 0)); |
287 | |
288 | // Only prune forward declarations inside a DW_TAG_module for which a |
289 | // definition exists elsewhere. |
290 | if (ModulesEndOffset == 0) |
291 | Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset(); |
292 | else |
293 | Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() > 0 && |
294 | Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset; |
295 | |
296 | return Info.Prune; |
297 | } |
298 | |
299 | static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU, |
300 | CompileUnit::DIEInfo &ChildInfo) { |
301 | CompileUnit::DIEInfo &Info = CU.getInfo(Die); |
302 | Info.Prune &= ChildInfo.Prune; |
303 | } |
304 | |
305 | /// Recursive helper to build the global DeclContext information and |
306 | /// gather the child->parent relationships in the original compile unit. |
307 | /// |
308 | /// This function uses the same work list approach as lookForDIEsToKeep. |
309 | /// |
310 | /// \return true when this DIE and all of its children are only |
311 | /// forward declarations to types defined in external clang modules |
312 | /// (i.e., forward declarations that are children of a DW_TAG_module). |
313 | static bool analyzeContextInfo( |
314 | const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, |
315 | DeclContext *CurrentDeclContext, DeclContextTree &Contexts, |
316 | uint64_t ModulesEndOffset, swiftInterfacesMap *ParseableSwiftInterfaces, |
317 | std::function<void(const Twine &, const DWARFDie &)> ReportWarning, |
318 | bool InImportedModule = false) { |
319 | // LIFO work list. |
320 | std::vector<ContextWorklistItem> Worklist; |
321 | Worklist.emplace_back(DIE, CurrentDeclContext, ParentIdx, InImportedModule); |
322 | |
323 | while (!Worklist.empty()) { |
324 | ContextWorklistItem Current = Worklist.back(); |
325 | Worklist.pop_back(); |
326 | |
327 | switch (Current.Type) { |
328 | case ContextWorklistItemType::UpdatePruning: |
329 | updatePruning(Current.Die, CU, ModulesEndOffset); |
330 | continue; |
331 | case ContextWorklistItemType::UpdateChildPruning: |
332 | updateChildPruning(Current.Die, CU, *Current.OtherInfo); |
333 | continue; |
334 | case ContextWorklistItemType::AnalyzeContextInfo: |
335 | break; |
336 | } |
337 | |
338 | unsigned Idx = CU.getOrigUnit().getDIEIndex(Current.Die); |
339 | CompileUnit::DIEInfo &Info = CU.getInfo(Idx); |
340 | |
341 | // Clang imposes an ODR on modules(!) regardless of the language: |
342 | // "The module-id should consist of only a single identifier, |
343 | // which provides the name of the module being defined. Each |
344 | // module shall have a single definition." |
345 | // |
346 | // This does not extend to the types inside the modules: |
347 | // "[I]n C, this implies that if two structs are defined in |
348 | // different submodules with the same name, those two types are |
349 | // distinct types (but may be compatible types if their |
350 | // definitions match)." |
351 | // |
352 | // We treat non-C++ modules like namespaces for this reason. |
353 | if (Current.Die.getTag() == dwarf::DW_TAG_module && |
354 | Current.ParentIdx == 0 && |
355 | dwarf::toString(Current.Die.find(dwarf::DW_AT_name), "") != |
356 | CU.getClangModuleName()) { |
357 | Current.InImportedModule = true; |
358 | analyzeImportedModule(Current.Die, CU, ParseableSwiftInterfaces, |
359 | ReportWarning); |
360 | } |
361 | |
362 | Info.ParentIdx = Current.ParentIdx; |
363 | bool InClangModule = CU.isClangModule() || Current.InImportedModule; |
364 | if (CU.hasODR() || InClangModule) { |
365 | if (Current.Context) { |
366 | auto PtrInvalidPair = Contexts.getChildDeclContext( |
367 | *Current.Context, Current.Die, CU, InClangModule); |
368 | Current.Context = PtrInvalidPair.getPointer(); |
369 | Info.Ctxt = |
370 | PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer(); |
371 | if (Info.Ctxt) |
372 | Info.Ctxt->setDefinedInClangModule(InClangModule); |
373 | } else |
374 | Info.Ctxt = Current.Context = nullptr; |
375 | } |
376 | |
377 | Info.Prune = Current.InImportedModule; |
378 | // Add children in reverse order to the worklist to effectively process |
379 | // them in order. |
380 | Worklist.emplace_back(Current.Die, ContextWorklistItemType::UpdatePruning); |
381 | for (auto Child : reverse(Current.Die.children())) { |
382 | CompileUnit::DIEInfo &ChildInfo = CU.getInfo(Child); |
383 | Worklist.emplace_back( |
384 | Current.Die, ContextWorklistItemType::UpdateChildPruning, &ChildInfo); |
385 | Worklist.emplace_back(Child, Current.Context, Idx, |
386 | Current.InImportedModule); |
387 | } |
388 | } |
389 | |
390 | return CU.getInfo(DIE).Prune; |
391 | } |
392 | |
393 | static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) { |
394 | switch (Tag) { |
395 | default: |
396 | return false; |
397 | case dwarf::DW_TAG_class_type: |
398 | case dwarf::DW_TAG_common_block: |
399 | case dwarf::DW_TAG_lexical_block: |
400 | case dwarf::DW_TAG_structure_type: |
401 | case dwarf::DW_TAG_subprogram: |
402 | case dwarf::DW_TAG_subroutine_type: |
403 | case dwarf::DW_TAG_union_type: |
404 | return true; |
405 | } |
406 | llvm_unreachable("Invalid Tag")__builtin_unreachable(); |
407 | } |
408 | |
409 | void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) { |
410 | Context.clear(); |
411 | |
412 | for (auto I = DIEBlocks.begin(), E = DIEBlocks.end(); I != E; ++I) |
413 | (*I)->~DIEBlock(); |
414 | for (auto I = DIELocs.begin(), E = DIELocs.end(); I != E; ++I) |
415 | (*I)->~DIELoc(); |
416 | |
417 | DIEBlocks.clear(); |
418 | DIELocs.clear(); |
419 | DIEAlloc.Reset(); |
420 | } |
421 | |
422 | /// Check if a variable describing DIE should be kept. |
423 | /// \returns updated TraversalFlags. |
424 | unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr, |
425 | const DWARFDie &DIE, |
426 | CompileUnit::DIEInfo &MyInfo, |
427 | unsigned Flags) { |
428 | const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); |
429 | |
430 | // Global variables with constant value can always be kept. |
431 | if (!(Flags & TF_InFunctionScope) && |
432 | Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) { |
433 | MyInfo.InDebugMap = true; |
434 | return Flags | TF_Keep; |
435 | } |
436 | |
437 | // See if there is a relocation to a valid debug map entry inside this |
438 | // variable's location. The order is important here. We want to always check |
439 | // if the variable has a valid relocation, so that the DIEInfo is filled. |
440 | // However, we don't want a static variable in a function to force us to keep |
441 | // the enclosing function, unless requested explicitly. |
442 | const bool HasLiveMemoryLocation = |
443 | RelocMgr.hasLiveMemoryLocation(DIE, MyInfo); |
444 | if (!HasLiveMemoryLocation || ((Flags & TF_InFunctionScope) && |
445 | !LLVM_UNLIKELY(Options.KeepFunctionForStatic)__builtin_expect((bool)(Options.KeepFunctionForStatic), false ))) |
446 | return Flags; |
447 | |
448 | if (Options.Verbose) { |
449 | outs() << "Keeping variable DIE:"; |
450 | DIDumpOptions DumpOpts; |
451 | DumpOpts.ChildRecurseDepth = 0; |
452 | DumpOpts.Verbose = Options.Verbose; |
453 | DIE.dump(outs(), 8 /* Indent */, DumpOpts); |
454 | } |
455 | |
456 | return Flags | TF_Keep; |
457 | } |
458 | |
459 | /// Check if a function describing DIE should be kept. |
460 | /// \returns updated TraversalFlags. |
461 | unsigned DWARFLinker::shouldKeepSubprogramDIE( |
462 | AddressesMap &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE, |
463 | const DWARFFile &File, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, |
464 | unsigned Flags) { |
465 | Flags |= TF_InFunctionScope; |
466 | |
467 | auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc)); |
468 | if (!LowPc) |
469 | return Flags; |
470 | |
471 | assert(LowPc.hasValue() && "low_pc attribute is not an address.")(static_cast<void> (0)); |
472 | if (!RelocMgr.hasLiveAddressRange(DIE, MyInfo)) |
473 | return Flags; |
474 | |
475 | if (Options.Verbose) { |
476 | outs() << "Keeping subprogram DIE:"; |
477 | DIDumpOptions DumpOpts; |
478 | DumpOpts.ChildRecurseDepth = 0; |
479 | DumpOpts.Verbose = Options.Verbose; |
480 | DIE.dump(outs(), 8 /* Indent */, DumpOpts); |
481 | } |
482 | |
483 | if (DIE.getTag() == dwarf::DW_TAG_label) { |
484 | if (Unit.hasLabelAt(*LowPc)) |
485 | return Flags; |
486 | |
487 | DWARFUnit &OrigUnit = Unit.getOrigUnit(); |
488 | // FIXME: dsymutil-classic compat. dsymutil-classic doesn't consider labels |
489 | // that don't fall into the CU's aranges. This is wrong IMO. Debug info |
490 | // generation bugs aside, this is really wrong in the case of labels, where |
491 | // a label marking the end of a function will have a PC == CU's high_pc. |
492 | if (dwarf::toAddress(OrigUnit.getUnitDIE().find(dwarf::DW_AT_high_pc)) |
493 | .getValueOr(UINT64_MAX(18446744073709551615UL)) <= LowPc) |
494 | return Flags; |
495 | Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust); |
496 | return Flags | TF_Keep; |
497 | } |
498 | |
499 | Flags |= TF_Keep; |
500 | |
501 | Optional<uint64_t> HighPc = DIE.getHighPC(*LowPc); |
502 | if (!HighPc) { |
503 | reportWarning("Function without high_pc. Range will be discarded.\n", File, |
504 | &DIE); |
505 | return Flags; |
506 | } |
507 | |
508 | // Replace the debug map range with a more accurate one. |
509 | Ranges[*LowPc] = ObjFileAddressRange(*HighPc, MyInfo.AddrAdjust); |
510 | Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust); |
511 | return Flags; |
512 | } |
513 | |
514 | /// Check if a DIE should be kept. |
515 | /// \returns updated TraversalFlags. |
516 | unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr, RangesTy &Ranges, |
517 | const DWARFDie &DIE, const DWARFFile &File, |
518 | CompileUnit &Unit, |
519 | CompileUnit::DIEInfo &MyInfo, |
520 | unsigned Flags) { |
521 | switch (DIE.getTag()) { |
522 | case dwarf::DW_TAG_constant: |
523 | case dwarf::DW_TAG_variable: |
524 | return shouldKeepVariableDIE(RelocMgr, DIE, MyInfo, Flags); |
525 | case dwarf::DW_TAG_subprogram: |
526 | case dwarf::DW_TAG_label: |
527 | return shouldKeepSubprogramDIE(RelocMgr, Ranges, DIE, File, Unit, MyInfo, |
528 | Flags); |
529 | case dwarf::DW_TAG_base_type: |
530 | // DWARF Expressions may reference basic types, but scanning them |
531 | // is expensive. Basic types are tiny, so just keep all of them. |
532 | case dwarf::DW_TAG_imported_module: |
533 | case dwarf::DW_TAG_imported_declaration: |
534 | case dwarf::DW_TAG_imported_unit: |
535 | // We always want to keep these. |
536 | return Flags | TF_Keep; |
537 | default: |
538 | break; |
539 | } |
540 | |
541 | return Flags; |
542 | } |
543 | |
544 | /// Helper that updates the completeness of the current DIE based on the |
545 | /// completeness of one of its children. It depends on the incompleteness of |
546 | /// the children already being computed. |
547 | static void updateChildIncompleteness(const DWARFDie &Die, CompileUnit &CU, |
548 | CompileUnit::DIEInfo &ChildInfo) { |
549 | switch (Die.getTag()) { |
550 | case dwarf::DW_TAG_structure_type: |
551 | case dwarf::DW_TAG_class_type: |
552 | break; |
553 | default: |
554 | return; |
555 | } |
556 | |
557 | CompileUnit::DIEInfo &MyInfo = CU.getInfo(Die); |
558 | |
559 | if (ChildInfo.Incomplete || ChildInfo.Prune) |
560 | MyInfo.Incomplete = true; |
561 | } |
562 | |
563 | /// Helper that updates the completeness of the current DIE based on the |
564 | /// completeness of the DIEs it references. It depends on the incompleteness of |
565 | /// the referenced DIE already being computed. |
566 | static void updateRefIncompleteness(const DWARFDie &Die, CompileUnit &CU, |
567 | CompileUnit::DIEInfo &RefInfo) { |
568 | switch (Die.getTag()) { |
569 | case dwarf::DW_TAG_typedef: |
570 | case dwarf::DW_TAG_member: |
571 | case dwarf::DW_TAG_reference_type: |
572 | case dwarf::DW_TAG_ptr_to_member_type: |
573 | case dwarf::DW_TAG_pointer_type: |
574 | break; |
575 | default: |
576 | return; |
577 | } |
578 | |
579 | CompileUnit::DIEInfo &MyInfo = CU.getInfo(Die); |
580 | |
581 | if (MyInfo.Incomplete) |
582 | return; |
583 | |
584 | if (RefInfo.Incomplete) |
585 | MyInfo.Incomplete = true; |
586 | } |
587 | |
588 | /// Look at the children of the given DIE and decide whether they should be |
589 | /// kept. |
590 | void DWARFLinker::lookForChildDIEsToKeep( |
591 | const DWARFDie &Die, CompileUnit &CU, unsigned Flags, |
592 | SmallVectorImpl<WorklistItem> &Worklist) { |
593 | // The TF_ParentWalk flag tells us that we are currently walking up the |
594 | // parent chain of a required DIE, and we don't want to mark all the children |
595 | // of the parents as kept (consider for example a DW_TAG_namespace node in |
596 | // the parent chain). There are however a set of DIE types for which we want |
597 | // to ignore that directive and still walk their children. |
598 | if (dieNeedsChildrenToBeMeaningful(Die.getTag())) |
599 | Flags &= ~DWARFLinker::TF_ParentWalk; |
600 | |
601 | // We're finished if this DIE has no children or we're walking the parent |
602 | // chain. |
603 | if (!Die.hasChildren() || (Flags & DWARFLinker::TF_ParentWalk)) |
604 | return; |
605 | |
606 | // Add children in reverse order to the worklist to effectively process them |
607 | // in order. |
608 | for (auto Child : reverse(Die.children())) { |
609 | // Add a worklist item before every child to calculate incompleteness right |
610 | // after the current child is processed. |
611 | CompileUnit::DIEInfo &ChildInfo = CU.getInfo(Child); |
612 | Worklist.emplace_back(Die, CU, WorklistItemType::UpdateChildIncompleteness, |
613 | &ChildInfo); |
614 | Worklist.emplace_back(Child, CU, Flags); |
615 | } |
616 | } |
617 | |
618 | /// Look at DIEs referenced by the given DIE and decide whether they should be |
619 | /// kept. All DIEs referenced though attributes should be kept. |
620 | void DWARFLinker::lookForRefDIEsToKeep( |
621 | const DWARFDie &Die, CompileUnit &CU, unsigned Flags, |
622 | const UnitListTy &Units, const DWARFFile &File, |
623 | SmallVectorImpl<WorklistItem> &Worklist) { |
624 | bool UseOdr = (Flags & DWARFLinker::TF_DependencyWalk) |
625 | ? (Flags & DWARFLinker::TF_ODR) |
626 | : CU.hasODR(); |
627 | DWARFUnit &Unit = CU.getOrigUnit(); |
628 | DWARFDataExtractor Data = Unit.getDebugInfoExtractor(); |
629 | const auto *Abbrev = Die.getAbbreviationDeclarationPtr(); |
630 | uint64_t Offset = Die.getOffset() + getULEB128Size(Abbrev->getCode()); |
631 | |
632 | SmallVector<std::pair<DWARFDie, CompileUnit &>, 4> ReferencedDIEs; |
633 | for (const auto &AttrSpec : Abbrev->attributes()) { |
634 | DWARFFormValue Val(AttrSpec.Form); |
635 | if (!Val.isFormClass(DWARFFormValue::FC_Reference) || |
636 | AttrSpec.Attr == dwarf::DW_AT_sibling) { |
637 | DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, |
638 | Unit.getFormParams()); |
639 | continue; |
640 | } |
641 | |
642 | Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit); |
643 | CompileUnit *ReferencedCU; |
644 | if (auto RefDie = |
645 | resolveDIEReference(File, Units, Val, Die, ReferencedCU)) { |
646 | CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefDie); |
647 | bool IsModuleRef = Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() && |
648 | Info.Ctxt->isDefinedInClangModule(); |
649 | // If the referenced DIE has a DeclContext that has already been |
650 | // emitted, then do not keep the one in this CU. We'll link to |
651 | // the canonical DIE in cloneDieReferenceAttribute. |
652 | // |
653 | // FIXME: compatibility with dsymutil-classic. UseODR shouldn't |
654 | // be necessary and could be advantageously replaced by |
655 | // ReferencedCU->hasODR() && CU.hasODR(). |
656 | // |
657 | // FIXME: compatibility with dsymutil-classic. There is no |
658 | // reason not to unique ref_addr references. |
659 | if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && (UseOdr || IsModuleRef) && |
660 | Info.Ctxt && |
661 | Info.Ctxt != ReferencedCU->getInfo(Info.ParentIdx).Ctxt && |
662 | Info.Ctxt->getCanonicalDIEOffset() && isODRAttribute(AttrSpec.Attr)) |
663 | continue; |
664 | |
665 | // Keep a module forward declaration if there is no definition. |
666 | if (!(isODRAttribute(AttrSpec.Attr) && Info.Ctxt && |
667 | Info.Ctxt->getCanonicalDIEOffset())) |
668 | Info.Prune = false; |
669 | ReferencedDIEs.emplace_back(RefDie, *ReferencedCU); |
670 | } |
671 | } |
672 | |
673 | unsigned ODRFlag = UseOdr ? DWARFLinker::TF_ODR : 0; |
674 | |
675 | // Add referenced DIEs in reverse order to the worklist to effectively |
676 | // process them in order. |
677 | for (auto &P : reverse(ReferencedDIEs)) { |
678 | // Add a worklist item before every child to calculate incompleteness right |
679 | // after the current child is processed. |
680 | CompileUnit::DIEInfo &Info = P.second.getInfo(P.first); |
681 | Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness, |
682 | &Info); |
683 | Worklist.emplace_back(P.first, P.second, |
684 | DWARFLinker::TF_Keep | |
685 | DWARFLinker::TF_DependencyWalk | ODRFlag); |
686 | } |
687 | } |
688 | |
689 | /// Look at the parent of the given DIE and decide whether they should be kept. |
690 | void DWARFLinker::lookForParentDIEsToKeep( |
691 | unsigned AncestorIdx, CompileUnit &CU, unsigned Flags, |
692 | SmallVectorImpl<WorklistItem> &Worklist) { |
693 | // Stop if we encounter an ancestor that's already marked as kept. |
694 | if (CU.getInfo(AncestorIdx).Keep) |
695 | return; |
696 | |
697 | DWARFUnit &Unit = CU.getOrigUnit(); |
698 | DWARFDie ParentDIE = Unit.getDIEAtIndex(AncestorIdx); |
699 | Worklist.emplace_back(CU.getInfo(AncestorIdx).ParentIdx, CU, Flags); |
700 | Worklist.emplace_back(ParentDIE, CU, Flags); |
701 | } |
702 | |
703 | /// Recursively walk the \p DIE tree and look for DIEs to keep. Store that |
704 | /// information in \p CU's DIEInfo. |
705 | /// |
706 | /// This function is the entry point of the DIE selection algorithm. It is |
707 | /// expected to walk the DIE tree in file order and (though the mediation of |
708 | /// its helper) call hasValidRelocation() on each DIE that might be a 'root |
709 | /// DIE' (See DwarfLinker class comment). |
710 | /// |
711 | /// While walking the dependencies of root DIEs, this function is also called, |
712 | /// but during these dependency walks the file order is not respected. The |
713 | /// TF_DependencyWalk flag tells us which kind of traversal we are currently |
714 | /// doing. |
715 | /// |
716 | /// The recursive algorithm is implemented iteratively as a work list because |
717 | /// very deep recursion could exhaust the stack for large projects. The work |
718 | /// list acts as a scheduler for different types of work that need to be |
719 | /// performed. |
720 | /// |
721 | /// The recursive nature of the algorithm is simulated by running the "main" |
722 | /// algorithm (LookForDIEsToKeep) followed by either looking at more DIEs |
723 | /// (LookForChildDIEsToKeep, LookForRefDIEsToKeep, LookForParentDIEsToKeep) or |
724 | /// fixing up a computed property (UpdateChildIncompleteness, |
725 | /// UpdateRefIncompleteness). |
726 | /// |
727 | /// The return value indicates whether the DIE is incomplete. |
728 | void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap, |
729 | RangesTy &Ranges, const UnitListTy &Units, |
730 | const DWARFDie &Die, const DWARFFile &File, |
731 | CompileUnit &Cu, unsigned Flags) { |
732 | // LIFO work list. |
733 | SmallVector<WorklistItem, 4> Worklist; |
734 | Worklist.emplace_back(Die, Cu, Flags); |
735 | |
736 | while (!Worklist.empty()) { |
737 | WorklistItem Current = Worklist.pop_back_val(); |
738 | |
739 | // Look at the worklist type to decide what kind of work to perform. |
740 | switch (Current.Type) { |
741 | case WorklistItemType::UpdateChildIncompleteness: |
742 | updateChildIncompleteness(Current.Die, Current.CU, *Current.OtherInfo); |
743 | continue; |
744 | case WorklistItemType::UpdateRefIncompleteness: |
745 | updateRefIncompleteness(Current.Die, Current.CU, *Current.OtherInfo); |
746 | continue; |
747 | case WorklistItemType::LookForChildDIEsToKeep: |
748 | lookForChildDIEsToKeep(Current.Die, Current.CU, Current.Flags, Worklist); |
749 | continue; |
750 | case WorklistItemType::LookForRefDIEsToKeep: |
751 | lookForRefDIEsToKeep(Current.Die, Current.CU, Current.Flags, Units, File, |
752 | Worklist); |
753 | continue; |
754 | case WorklistItemType::LookForParentDIEsToKeep: |
755 | lookForParentDIEsToKeep(Current.AncestorIdx, Current.CU, Current.Flags, |
756 | Worklist); |
757 | continue; |
758 | case WorklistItemType::LookForDIEsToKeep: |
759 | break; |
760 | } |
761 | |
762 | unsigned Idx = Current.CU.getOrigUnit().getDIEIndex(Current.Die); |
763 | CompileUnit::DIEInfo &MyInfo = Current.CU.getInfo(Idx); |
764 | |
765 | if (MyInfo.Prune) |
766 | continue; |
767 | |
768 | // If the Keep flag is set, we are marking a required DIE's dependencies. |
769 | // If our target is already marked as kept, we're all set. |
770 | bool AlreadyKept = MyInfo.Keep; |
771 | if ((Current.Flags & TF_DependencyWalk) && AlreadyKept) |
772 | continue; |
773 | |
774 | // We must not call shouldKeepDIE while called from keepDIEAndDependencies, |
775 | // because it would screw up the relocation finding logic. |
776 | if (!(Current.Flags & TF_DependencyWalk)) |
777 | Current.Flags = shouldKeepDIE(AddressesMap, Ranges, Current.Die, File, |
778 | Current.CU, MyInfo, Current.Flags); |
779 | |
780 | // Finish by looking for child DIEs. Because of the LIFO worklist we need |
781 | // to schedule that work before any subsequent items are added to the |
782 | // worklist. |
783 | Worklist.emplace_back(Current.Die, Current.CU, Current.Flags, |
784 | WorklistItemType::LookForChildDIEsToKeep); |
785 | |
786 | if (AlreadyKept || !(Current.Flags & TF_Keep)) |
787 | continue; |
788 | |
789 | // If it is a newly kept DIE mark it as well as all its dependencies as |
790 | // kept. |
791 | MyInfo.Keep = true; |
792 | |
793 | // We're looking for incomplete types. |
794 | MyInfo.Incomplete = |
795 | Current.Die.getTag() != dwarf::DW_TAG_subprogram && |
796 | Current.Die.getTag() != dwarf::DW_TAG_member && |
797 | dwarf::toUnsigned(Current.Die.find(dwarf::DW_AT_declaration), 0); |
798 | |
799 | // After looking at the parent chain, look for referenced DIEs. Because of |
800 | // the LIFO worklist we need to schedule that work before any subsequent |
801 | // items are added to the worklist. |
802 | Worklist.emplace_back(Current.Die, Current.CU, Current.Flags, |
803 | WorklistItemType::LookForRefDIEsToKeep); |
804 | |
805 | bool UseOdr = (Current.Flags & TF_DependencyWalk) ? (Current.Flags & TF_ODR) |
806 | : Current.CU.hasODR(); |
807 | unsigned ODRFlag = UseOdr ? TF_ODR : 0; |
808 | unsigned ParFlags = TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag; |
809 | |
810 | // Now schedule the parent walk. |
811 | Worklist.emplace_back(MyInfo.ParentIdx, Current.CU, ParFlags); |
812 | } |
813 | } |
814 | |
815 | /// Assign an abbreviation number to \p Abbrev. |
816 | /// |
817 | /// Our DIEs get freed after every DebugMapObject has been processed, |
818 | /// thus the FoldingSet we use to unique DIEAbbrevs cannot refer to |
819 | /// the instances hold by the DIEs. When we encounter an abbreviation |
820 | /// that we don't know, we create a permanent copy of it. |
821 | void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) { |
822 | // Check the set for priors. |
823 | FoldingSetNodeID ID; |
824 | Abbrev.Profile(ID); |
825 | void *InsertToken; |
826 | DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken); |
827 | |
828 | // If it's newly added. |
829 | if (InSet) { |
830 | // Assign existing abbreviation number. |
831 | Abbrev.setNumber(InSet->getNumber()); |
832 | } else { |
833 | // Add to abbreviation list. |
834 | Abbreviations.push_back( |
835 | std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren())); |
836 | for (const auto &Attr : Abbrev.getData()) |
837 | Abbreviations.back()->AddAttribute(Attr.getAttribute(), Attr.getForm()); |
838 | AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken); |
839 | // Assign the unique abbreviation number. |
840 | Abbrev.setNumber(Abbreviations.size()); |
841 | Abbreviations.back()->setNumber(Abbreviations.size()); |
842 | } |
843 | } |
844 | |
845 | unsigned DWARFLinker::DIECloner::cloneStringAttribute( |
846 | DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val, |
847 | const DWARFUnit &U, OffsetsStringPool &StringPool, AttributesInfo &Info) { |
848 | Optional<const char *> String = Val.getAsCString(); |
849 | if (!String) |
850 | return 0; |
851 | |
852 | // Switch everything to out of line strings. |
853 | auto StringEntry = StringPool.getEntry(*String); |
854 | |
855 | // Update attributes info. |
856 | if (AttrSpec.Attr == dwarf::DW_AT_name) |
857 | Info.Name = StringEntry; |
858 | else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name || |
859 | AttrSpec.Attr == dwarf::DW_AT_linkage_name) |
860 | Info.MangledName = StringEntry; |
861 | |
862 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_strp, |
863 | DIEInteger(StringEntry.getOffset())); |
864 | |
865 | return 4; |
866 | } |
867 | |
868 | unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute( |
869 | DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec, |
870 | unsigned AttrSize, const DWARFFormValue &Val, const DWARFFile &File, |
871 | CompileUnit &Unit) { |
872 | const DWARFUnit &U = Unit.getOrigUnit(); |
873 | uint64_t Ref = *Val.getAsReference(); |
874 | |
875 | DIE *NewRefDie = nullptr; |
876 | CompileUnit *RefUnit = nullptr; |
877 | DeclContext *Ctxt = nullptr; |
878 | |
879 | DWARFDie RefDie = |
880 | Linker.resolveDIEReference(File, CompileUnits, Val, InputDIE, RefUnit); |
881 | |
882 | // If the referenced DIE is not found, drop the attribute. |
883 | if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling) |
884 | return 0; |
885 | |
886 | CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(RefDie); |
887 | |
888 | // If we already have emitted an equivalent DeclContext, just point |
889 | // at it. |
890 | if (isODRAttribute(AttrSpec.Attr)) { |
891 | Ctxt = RefInfo.Ctxt; |
892 | if (Ctxt && Ctxt->getCanonicalDIEOffset()) { |
893 | DIEInteger Attr(Ctxt->getCanonicalDIEOffset()); |
894 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
895 | dwarf::DW_FORM_ref_addr, Attr); |
896 | return U.getRefAddrByteSize(); |
897 | } |
898 | } |
899 | |
900 | if (!RefInfo.Clone) { |
901 | assert(Ref > InputDIE.getOffset())(static_cast<void> (0)); |
902 | // We haven't cloned this DIE yet. Just create an empty one and |
903 | // store it. It'll get really cloned when we process it. |
904 | RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag())); |
905 | } |
906 | NewRefDie = RefInfo.Clone; |
907 | |
908 | if (AttrSpec.Form == dwarf::DW_FORM_ref_addr || |
909 | (Unit.hasODR() && isODRAttribute(AttrSpec.Attr))) { |
910 | // We cannot currently rely on a DIEEntry to emit ref_addr |
911 | // references, because the implementation calls back to DwarfDebug |
912 | // to find the unit offset. (We don't have a DwarfDebug) |
913 | // FIXME: we should be able to design DIEEntry reliance on |
914 | // DwarfDebug away. |
915 | uint64_t Attr; |
916 | if (Ref < InputDIE.getOffset()) { |
917 | // We must have already cloned that DIE. |
918 | uint32_t NewRefOffset = |
919 | RefUnit->getStartOffset() + NewRefDie->getOffset(); |
920 | Attr = NewRefOffset; |
921 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
922 | dwarf::DW_FORM_ref_addr, DIEInteger(Attr)); |
923 | } else { |
924 | // A forward reference. Note and fixup later. |
925 | Attr = 0xBADDEF; |
926 | Unit.noteForwardReference( |
927 | NewRefDie, RefUnit, Ctxt, |
928 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
929 | dwarf::DW_FORM_ref_addr, DIEInteger(Attr))); |
930 | } |
931 | return U.getRefAddrByteSize(); |
932 | } |
933 | |
934 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
935 | dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie)); |
936 | |
937 | return AttrSize; |
938 | } |
939 | |
940 | void DWARFLinker::DIECloner::cloneExpression( |
941 | DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File, |
942 | CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer) { |
943 | using Encoding = DWARFExpression::Operation::Encoding; |
944 | |
945 | uint64_t OpOffset = 0; |
946 | for (auto &Op : Expression) { |
947 | auto Description = Op.getDescription(); |
948 | // DW_OP_const_type is variable-length and has 3 |
949 | // operands. DWARFExpression thus far only supports 2. |
950 | auto Op0 = Description.Op[0]; |
951 | auto Op1 = Description.Op[1]; |
952 | if ((Op0 == Encoding::BaseTypeRef && Op1 != Encoding::SizeNA) || |
953 | (Op1 == Encoding::BaseTypeRef && Op0 != Encoding::Size1)) |
954 | Linker.reportWarning("Unsupported DW_OP encoding.", File); |
955 | |
956 | if ((Op0 == Encoding::BaseTypeRef && Op1 == Encoding::SizeNA) || |
957 | (Op1 == Encoding::BaseTypeRef && Op0 == Encoding::Size1)) { |
958 | // This code assumes that the other non-typeref operand fits into 1 byte. |
959 | assert(OpOffset < Op.getEndOffset())(static_cast<void> (0)); |
960 | uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1; |
961 | assert(ULEBsize <= 16)(static_cast<void> (0)); |
962 | |
963 | // Copy over the operation. |
964 | OutputBuffer.push_back(Op.getCode()); |
965 | uint64_t RefOffset; |
966 | if (Op1 == Encoding::SizeNA) { |
967 | RefOffset = Op.getRawOperand(0); |
968 | } else { |
969 | OutputBuffer.push_back(Op.getRawOperand(0)); |
970 | RefOffset = Op.getRawOperand(1); |
971 | } |
972 | uint32_t Offset = 0; |
973 | // Look up the base type. For DW_OP_convert, the operand may be 0 to |
974 | // instead indicate the generic type. The same holds for |
975 | // DW_OP_reinterpret, which is currently not supported. |
976 | if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) { |
977 | auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset); |
978 | CompileUnit::DIEInfo &Info = Unit.getInfo(RefDie); |
979 | if (DIE *Clone = Info.Clone) |
980 | Offset = Clone->getOffset(); |
981 | else |
982 | Linker.reportWarning( |
983 | "base type ref doesn't point to DW_TAG_base_type.", File); |
984 | } |
985 | uint8_t ULEB[16]; |
986 | unsigned RealSize = encodeULEB128(Offset, ULEB, ULEBsize); |
987 | if (RealSize > ULEBsize) { |
988 | // Emit the generic type as a fallback. |
989 | RealSize = encodeULEB128(0, ULEB, ULEBsize); |
Value stored to 'RealSize' is never read | |
990 | Linker.reportWarning("base type ref doesn't fit.", File); |
991 | } |
992 | assert(RealSize == ULEBsize && "padding failed")(static_cast<void> (0)); |
993 | ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize); |
994 | OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end()); |
995 | } else { |
996 | // Copy over everything else unmodified. |
997 | StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset()); |
998 | OutputBuffer.append(Bytes.begin(), Bytes.end()); |
999 | } |
1000 | OpOffset = Op.getEndOffset(); |
1001 | } |
1002 | } |
1003 | |
1004 | unsigned DWARFLinker::DIECloner::cloneBlockAttribute( |
1005 | DIE &Die, const DWARFFile &File, CompileUnit &Unit, AttributeSpec AttrSpec, |
1006 | const DWARFFormValue &Val, unsigned AttrSize, bool IsLittleEndian) { |
1007 | DIEValueList *Attr; |
1008 | DIEValue Value; |
1009 | DIELoc *Loc = nullptr; |
1010 | DIEBlock *Block = nullptr; |
1011 | if (AttrSpec.Form == dwarf::DW_FORM_exprloc) { |
1012 | Loc = new (DIEAlloc) DIELoc; |
1013 | Linker.DIELocs.push_back(Loc); |
1014 | } else { |
1015 | Block = new (DIEAlloc) DIEBlock; |
1016 | Linker.DIEBlocks.push_back(Block); |
1017 | } |
1018 | Attr = Loc ? static_cast<DIEValueList *>(Loc) |
1019 | : static_cast<DIEValueList *>(Block); |
1020 | |
1021 | if (Loc) |
1022 | Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), |
1023 | dwarf::Form(AttrSpec.Form), Loc); |
1024 | else |
1025 | Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), |
1026 | dwarf::Form(AttrSpec.Form), Block); |
1027 | |
1028 | // If the block is a DWARF Expression, clone it into the temporary |
1029 | // buffer using cloneExpression(), otherwise copy the data directly. |
1030 | SmallVector<uint8_t, 32> Buffer; |
1031 | ArrayRef<uint8_t> Bytes = *Val.getAsBlock(); |
1032 | if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) && |
1033 | (Val.isFormClass(DWARFFormValue::FC_Block) || |
1034 | Val.isFormClass(DWARFFormValue::FC_Exprloc))) { |
1035 | DWARFUnit &OrigUnit = Unit.getOrigUnit(); |
1036 | DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()), |
1037 | IsLittleEndian, OrigUnit.getAddressByteSize()); |
1038 | DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(), |
1039 | OrigUnit.getFormParams().Format); |
1040 | cloneExpression(Data, Expr, File, Unit, Buffer); |
1041 | Bytes = Buffer; |
1042 | } |
1043 | for (auto Byte : Bytes) |
1044 | Attr->addValue(DIEAlloc, static_cast<dwarf::Attribute>(0), |
1045 | dwarf::DW_FORM_data1, DIEInteger(Byte)); |
1046 | |
1047 | // FIXME: If DIEBlock and DIELoc just reuses the Size field of |
1048 | // the DIE class, this "if" could be replaced by |
1049 | // Attr->setSize(Bytes.size()). |
1050 | if (Loc) |
1051 | Loc->setSize(Bytes.size()); |
1052 | else |
1053 | Block->setSize(Bytes.size()); |
1054 | |
1055 | Die.addValue(DIEAlloc, Value); |
1056 | return AttrSize; |
1057 | } |
1058 | |
1059 | unsigned DWARFLinker::DIECloner::cloneAddressAttribute( |
1060 | DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val, |
1061 | const CompileUnit &Unit, AttributesInfo &Info) { |
1062 | if (LLVM_UNLIKELY(Linker.Options.Update)__builtin_expect((bool)(Linker.Options.Update), false)) { |
1063 | if (AttrSpec.Attr == dwarf::DW_AT_low_pc) |
1064 | Info.HasLowPc = true; |
1065 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
1066 | dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue())); |
1067 | return Unit.getOrigUnit().getAddressByteSize(); |
1068 | } |
1069 | |
1070 | dwarf::Form Form = AttrSpec.Form; |
1071 | uint64_t Addr = 0; |
1072 | if (Form == dwarf::DW_FORM_addrx) { |
1073 | if (Optional<uint64_t> AddrOffsetSectionBase = |
1074 | Unit.getOrigUnit().getAddrOffsetSectionBase()) { |
1075 | uint64_t StartOffset = *AddrOffsetSectionBase + Val.getRawUValue(); |
1076 | uint64_t EndOffset = |
1077 | StartOffset + Unit.getOrigUnit().getAddressByteSize(); |
1078 | if (llvm::Expected<uint64_t> RelocAddr = |
1079 | ObjFile.Addresses->relocateIndexedAddr(StartOffset, EndOffset)) |
1080 | Addr = *RelocAddr; |
1081 | else |
1082 | Linker.reportWarning(toString(RelocAddr.takeError()), ObjFile); |
1083 | } else |
1084 | Linker.reportWarning("no base offset for address table", ObjFile); |
1085 | |
1086 | // If this is an indexed address emit the debug_info address. |
1087 | Form = dwarf::DW_FORM_addr; |
1088 | } else |
1089 | Addr = *Val.getAsAddress(); |
1090 | |
1091 | if (AttrSpec.Attr == dwarf::DW_AT_low_pc) { |
1092 | if (Die.getTag() == dwarf::DW_TAG_inlined_subroutine || |
1093 | Die.getTag() == dwarf::DW_TAG_lexical_block || |
1094 | Die.getTag() == dwarf::DW_TAG_label) { |
1095 | // The low_pc of a block or inline subroutine might get |
1096 | // relocated because it happens to match the low_pc of the |
1097 | // enclosing subprogram. To prevent issues with that, always use |
1098 | // the low_pc from the input DIE if relocations have been applied. |
1099 | Addr = (Info.OrigLowPc != std::numeric_limits<uint64_t>::max() |
1100 | ? Info.OrigLowPc |
1101 | : Addr) + |
1102 | Info.PCOffset; |
1103 | } else if (Die.getTag() == dwarf::DW_TAG_compile_unit) { |
1104 | Addr = Unit.getLowPc(); |
1105 | if (Addr == std::numeric_limits<uint64_t>::max()) |
1106 | return 0; |
1107 | } |
1108 | Info.HasLowPc = true; |
1109 | } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc) { |
1110 | if (Die.getTag() == dwarf::DW_TAG_compile_unit) { |
1111 | if (uint64_t HighPc = Unit.getHighPc()) |
1112 | Addr = HighPc; |
1113 | else |
1114 | return 0; |
1115 | } else |
1116 | // If we have a high_pc recorded for the input DIE, use |
1117 | // it. Otherwise (when no relocations where applied) just use the |
1118 | // one we just decoded. |
1119 | Addr = (Info.OrigHighPc ? Info.OrigHighPc : Addr) + Info.PCOffset; |
1120 | } else if (AttrSpec.Attr == dwarf::DW_AT_call_return_pc) { |
1121 | // Relocate a return PC address within a call site entry. |
1122 | if (Die.getTag() == dwarf::DW_TAG_call_site) |
1123 | Addr = (Info.OrigCallReturnPc ? Info.OrigCallReturnPc : Addr) + |
1124 | Info.PCOffset; |
1125 | } else if (AttrSpec.Attr == dwarf::DW_AT_call_pc) { |
1126 | // Relocate the address of a branch instruction within a call site entry. |
1127 | if (Die.getTag() == dwarf::DW_TAG_call_site) |
1128 | Addr = (Info.OrigCallPc ? Info.OrigCallPc : Addr) + Info.PCOffset; |
1129 | } |
1130 | |
1131 | Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr), |
1132 | static_cast<dwarf::Form>(Form), DIEInteger(Addr)); |
1133 | return Unit.getOrigUnit().getAddressByteSize(); |
1134 | } |
1135 | |
1136 | unsigned DWARFLinker::DIECloner::cloneScalarAttribute( |
1137 | DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File, |
1138 | CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, |
1139 | unsigned AttrSize, AttributesInfo &Info) { |
1140 | uint64_t Value; |
1141 | |
1142 | if (LLVM_UNLIKELY(Linker.Options.Update)__builtin_expect((bool)(Linker.Options.Update), false)) { |
1143 | if (auto OptionalValue = Val.getAsUnsignedConstant()) |
1144 | Value = *OptionalValue; |
1145 | else if (auto OptionalValue = Val.getAsSignedConstant()) |
1146 | Value = *OptionalValue; |
1147 | else if (auto OptionalValue = Val.getAsSectionOffset()) |
1148 | Value = *OptionalValue; |
1149 | else { |
1150 | Linker.reportWarning( |
1151 | "Unsupported scalar attribute form. Dropping attribute.", File, |
1152 | &InputDIE); |
1153 | return 0; |
1154 | } |
1155 | if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) |
1156 | Info.IsDeclaration = true; |
1157 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
1158 | dwarf::Form(AttrSpec.Form), DIEInteger(Value)); |
1159 | return AttrSize; |
1160 | } |
1161 | |
1162 | if (AttrSpec.Attr == dwarf::DW_AT_high_pc && |
1163 | Die.getTag() == dwarf::DW_TAG_compile_unit) { |
1164 | if (Unit.getLowPc() == -1ULL) |
1165 | return 0; |
1166 | // Dwarf >= 4 high_pc is an size, not an address. |
1167 | Value = Unit.getHighPc() - Unit.getLowPc(); |
1168 | } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset) |
1169 | Value = *Val.getAsSectionOffset(); |
1170 | else if (AttrSpec.Form == dwarf::DW_FORM_sdata) |
1171 | Value = *Val.getAsSignedConstant(); |
1172 | else if (auto OptionalValue = Val.getAsUnsignedConstant()) |
1173 | Value = *OptionalValue; |
1174 | else { |
1175 | Linker.reportWarning( |
1176 | "Unsupported scalar attribute form. Dropping attribute.", File, |
1177 | &InputDIE); |
1178 | return 0; |
1179 | } |
1180 | PatchLocation Patch = |
1181 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
1182 | dwarf::Form(AttrSpec.Form), DIEInteger(Value)); |
1183 | if (AttrSpec.Attr == dwarf::DW_AT_ranges) { |
1184 | Unit.noteRangeAttribute(Die, Patch); |
1185 | Info.HasRanges = true; |
1186 | } |
1187 | |
1188 | // A more generic way to check for location attributes would be |
1189 | // nice, but it's very unlikely that any other attribute needs a |
1190 | // location list. |
1191 | // FIXME: use DWARFAttribute::mayHaveLocationDescription(). |
1192 | else if (AttrSpec.Attr == dwarf::DW_AT_location || |
1193 | AttrSpec.Attr == dwarf::DW_AT_frame_base) { |
1194 | Unit.noteLocationAttribute(Patch, Info.PCOffset); |
1195 | } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) |
1196 | Info.IsDeclaration = true; |
1197 | |
1198 | return AttrSize; |
1199 | } |
1200 | |
1201 | /// Clone \p InputDIE's attribute described by \p AttrSpec with |
1202 | /// value \p Val, and add it to \p Die. |
1203 | /// \returns the size of the cloned attribute. |
1204 | unsigned DWARFLinker::DIECloner::cloneAttribute( |
1205 | DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File, |
1206 | CompileUnit &Unit, OffsetsStringPool &StringPool, const DWARFFormValue &Val, |
1207 | const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info, |
1208 | bool IsLittleEndian) { |
1209 | const DWARFUnit &U = Unit.getOrigUnit(); |
1210 | |
1211 | switch (AttrSpec.Form) { |
1212 | case dwarf::DW_FORM_strp: |
1213 | case dwarf::DW_FORM_string: |
1214 | case dwarf::DW_FORM_strx: |
1215 | case dwarf::DW_FORM_strx1: |
1216 | case dwarf::DW_FORM_strx2: |
1217 | case dwarf::DW_FORM_strx3: |
1218 | case dwarf::DW_FORM_strx4: |
1219 | return cloneStringAttribute(Die, AttrSpec, Val, U, StringPool, Info); |
1220 | case dwarf::DW_FORM_ref_addr: |
1221 | case dwarf::DW_FORM_ref1: |
1222 | case dwarf::DW_FORM_ref2: |
1223 | case dwarf::DW_FORM_ref4: |
1224 | case dwarf::DW_FORM_ref8: |
1225 | return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, |
1226 | File, Unit); |
1227 | case dwarf::DW_FORM_block: |
1228 | case dwarf::DW_FORM_block1: |
1229 | case dwarf::DW_FORM_block2: |
1230 | case dwarf::DW_FORM_block4: |
1231 | case dwarf::DW_FORM_exprloc: |
1232 | return cloneBlockAttribute(Die, File, Unit, AttrSpec, Val, AttrSize, |
1233 | IsLittleEndian); |
1234 | case dwarf::DW_FORM_addr: |
1235 | case dwarf::DW_FORM_addrx: |
1236 | return cloneAddressAttribute(Die, AttrSpec, Val, Unit, Info); |
1237 | case dwarf::DW_FORM_data1: |
1238 | case dwarf::DW_FORM_data2: |
1239 | case dwarf::DW_FORM_data4: |
1240 | case dwarf::DW_FORM_data8: |
1241 | case dwarf::DW_FORM_udata: |
1242 | case dwarf::DW_FORM_sdata: |
1243 | case dwarf::DW_FORM_sec_offset: |
1244 | case dwarf::DW_FORM_flag: |
1245 | case dwarf::DW_FORM_flag_present: |
1246 | return cloneScalarAttribute(Die, InputDIE, File, Unit, AttrSpec, Val, |
1247 | AttrSize, Info); |
1248 | default: |
1249 | Linker.reportWarning("Unsupported attribute form " + |
1250 | dwarf::FormEncodingString(AttrSpec.Form) + |
1251 | " in cloneAttribute. Dropping.", |
1252 | File, &InputDIE); |
1253 | } |
1254 | |
1255 | return 0; |
1256 | } |
1257 | |
1258 | static bool isObjCSelector(StringRef Name) { |
1259 | return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') && |
1260 | (Name[1] == '['); |
1261 | } |
1262 | |
1263 | void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit, |
1264 | const DIE *Die, |
1265 | DwarfStringPoolEntryRef Name, |
1266 | OffsetsStringPool &StringPool, |
1267 | bool SkipPubSection) { |
1268 | assert(isObjCSelector(Name.getString()) && "not an objc selector")(static_cast<void> (0)); |
1269 | // Objective C method or class function. |
1270 | // "- [Class(Category) selector :withArg ...]" |
1271 | StringRef ClassNameStart(Name.getString().drop_front(2)); |
1272 | size_t FirstSpace = ClassNameStart.find(' '); |
1273 | if (FirstSpace == StringRef::npos) |
1274 | return; |
1275 | |
1276 | StringRef SelectorStart(ClassNameStart.data() + FirstSpace + 1); |
1277 | if (!SelectorStart.size()) |
1278 | return; |
1279 | |
1280 | StringRef Selector(SelectorStart.data(), SelectorStart.size() - 1); |
1281 | Unit.addNameAccelerator(Die, StringPool.getEntry(Selector), SkipPubSection); |
1282 | |
1283 | // Add an entry for the class name that points to this |
1284 | // method/class function. |
1285 | StringRef ClassName(ClassNameStart.data(), FirstSpace); |
1286 | Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassName), SkipPubSection); |
1287 | |
1288 | if (ClassName[ClassName.size() - 1] == ')') { |
1289 | size_t OpenParens = ClassName.find('('); |
1290 | if (OpenParens != StringRef::npos) { |
1291 | StringRef ClassNameNoCategory(ClassName.data(), OpenParens); |
1292 | Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassNameNoCategory), |
1293 | SkipPubSection); |
1294 | |
1295 | std::string MethodNameNoCategory(Name.getString().data(), OpenParens + 2); |
1296 | // FIXME: The missing space here may be a bug, but |
1297 | // dsymutil-classic also does it this way. |
1298 | MethodNameNoCategory.append(std::string(SelectorStart)); |
1299 | Unit.addNameAccelerator(Die, StringPool.getEntry(MethodNameNoCategory), |
1300 | SkipPubSection); |
1301 | } |
1302 | } |
1303 | } |
1304 | |
1305 | static bool |
1306 | shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, |
1307 | uint16_t Tag, bool InDebugMap, bool SkipPC, |
1308 | bool InFunctionScope) { |
1309 | switch (AttrSpec.Attr) { |
1310 | default: |
1311 | return false; |
1312 | case dwarf::DW_AT_low_pc: |
1313 | case dwarf::DW_AT_high_pc: |
1314 | case dwarf::DW_AT_ranges: |
1315 | return SkipPC; |
1316 | case dwarf::DW_AT_str_offsets_base: |
1317 | // FIXME: Use the string offset table with Dwarf 5. |
1318 | return true; |
1319 | case dwarf::DW_AT_location: |
1320 | case dwarf::DW_AT_frame_base: |
1321 | // FIXME: for some reason dsymutil-classic keeps the location attributes |
1322 | // when they are of block type (i.e. not location lists). This is totally |
1323 | // wrong for globals where we will keep a wrong address. It is mostly |
1324 | // harmless for locals, but there is no point in keeping these anyway when |
1325 | // the function wasn't linked. |
1326 | return (SkipPC || (!InFunctionScope && Tag == dwarf::DW_TAG_variable && |
1327 | !InDebugMap)) && |
1328 | !DWARFFormValue(AttrSpec.Form).isFormClass(DWARFFormValue::FC_Block); |
1329 | } |
1330 | } |
1331 | |
1332 | DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, |
1333 | const DWARFFile &File, CompileUnit &Unit, |
1334 | OffsetsStringPool &StringPool, |
1335 | int64_t PCOffset, uint32_t OutOffset, |
1336 | unsigned Flags, bool IsLittleEndian, |
1337 | DIE *Die) { |
1338 | DWARFUnit &U = Unit.getOrigUnit(); |
1339 | unsigned Idx = U.getDIEIndex(InputDIE); |
1340 | CompileUnit::DIEInfo &Info = Unit.getInfo(Idx); |
1341 | |
1342 | // Should the DIE appear in the output? |
1343 | if (!Unit.getInfo(Idx).Keep) |
1344 | return nullptr; |
1345 | |
1346 | uint64_t Offset = InputDIE.getOffset(); |
1347 | assert(!(Die && Info.Clone) && "Can't supply a DIE and a cloned DIE")(static_cast<void> (0)); |
1348 | if (!Die) { |
1349 | // The DIE might have been already created by a forward reference |
1350 | // (see cloneDieReferenceAttribute()). |
1351 | if (!Info.Clone) |
1352 | Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag())); |
1353 | Die = Info.Clone; |
1354 | } |
1355 | |
1356 | assert(Die->getTag() == InputDIE.getTag())(static_cast<void> (0)); |
1357 | Die->setOffset(OutOffset); |
1358 | if ((Unit.hasODR() || Unit.isClangModule()) && !Info.Incomplete && |
1359 | Die->getTag() != dwarf::DW_TAG_namespace && Info.Ctxt && |
1360 | Info.Ctxt != Unit.getInfo(Info.ParentIdx).Ctxt && |
1361 | !Info.Ctxt->getCanonicalDIEOffset()) { |
1362 | // We are about to emit a DIE that is the root of its own valid |
1363 | // DeclContext tree. Make the current offset the canonical offset |
1364 | // for this context. |
1365 | Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset()); |
1366 | } |
1367 | |
1368 | // Extract and clone every attribute. |
1369 | DWARFDataExtractor Data = U.getDebugInfoExtractor(); |
1370 | // Point to the next DIE (generally there is always at least a NULL |
1371 | // entry after the current one). If this is a lone |
1372 | // DW_TAG_compile_unit without any children, point to the next unit. |
1373 | uint64_t NextOffset = (Idx + 1 < U.getNumDIEs()) |
1374 | ? U.getDIEAtIndex(Idx + 1).getOffset() |
1375 | : U.getNextUnitOffset(); |
1376 | AttributesInfo AttrInfo; |
1377 | |
1378 | // We could copy the data only if we need to apply a relocation to it. After |
1379 | // testing, it seems there is no performance downside to doing the copy |
1380 | // unconditionally, and it makes the code simpler. |
1381 | SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset)); |
1382 | Data = |
1383 | DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize()); |
1384 | |
1385 | // Modify the copy with relocated addresses. |
1386 | if (ObjFile.Addresses->areRelocationsResolved() && |
1387 | ObjFile.Addresses->applyValidRelocs(DIECopy, Offset, |
1388 | Data.isLittleEndian())) { |
1389 | // If we applied relocations, we store the value of high_pc that was |
1390 | // potentially stored in the input DIE. If high_pc is an address |
1391 | // (Dwarf version == 2), then it might have been relocated to a |
1392 | // totally unrelated value (because the end address in the object |
1393 | // file might be start address of another function which got moved |
1394 | // independently by the linker). The computation of the actual |
1395 | // high_pc value is done in cloneAddressAttribute(). |
1396 | AttrInfo.OrigHighPc = |
1397 | dwarf::toAddress(InputDIE.find(dwarf::DW_AT_high_pc), 0); |
1398 | // Also store the low_pc. It might get relocated in an |
1399 | // inline_subprogram that happens at the beginning of its |
1400 | // inlining function. |
1401 | AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc), |
1402 | std::numeric_limits<uint64_t>::max()); |
1403 | AttrInfo.OrigCallReturnPc = |
1404 | dwarf::toAddress(InputDIE.find(dwarf::DW_AT_call_return_pc), 0); |
1405 | AttrInfo.OrigCallPc = |
1406 | dwarf::toAddress(InputDIE.find(dwarf::DW_AT_call_pc), 0); |
1407 | } |
1408 | |
1409 | // Reset the Offset to 0 as we will be working on the local copy of |
1410 | // the data. |
1411 | Offset = 0; |
1412 | |
1413 | const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr(); |
1414 | Offset += getULEB128Size(Abbrev->getCode()); |
1415 | |
1416 | // We are entering a subprogram. Get and propagate the PCOffset. |
1417 | if (Die->getTag() == dwarf::DW_TAG_subprogram) |
1418 | PCOffset = Info.AddrAdjust; |
1419 | AttrInfo.PCOffset = PCOffset; |
1420 | |
1421 | if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) { |
1422 | Flags |= TF_InFunctionScope; |
1423 | if (!Info.InDebugMap && LLVM_LIKELY(!Update)__builtin_expect((bool)(!Update), true)) |
1424 | Flags |= TF_SkipPC; |
1425 | } |
1426 | |
1427 | for (const auto &AttrSpec : Abbrev->attributes()) { |
1428 | if (LLVM_LIKELY(!Update)__builtin_expect((bool)(!Update), true) && |
1429 | shouldSkipAttribute(AttrSpec, Die->getTag(), Info.InDebugMap, |
1430 | Flags & TF_SkipPC, Flags & TF_InFunctionScope)) { |
1431 | DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, |
1432 | U.getFormParams()); |
1433 | continue; |
1434 | } |
1435 | |
1436 | DWARFFormValue Val(AttrSpec.Form); |
1437 | uint64_t AttrSize = Offset; |
1438 | Val.extractValue(Data, &Offset, U.getFormParams(), &U); |
1439 | AttrSize = Offset - AttrSize; |
1440 | |
1441 | OutOffset += cloneAttribute(*Die, InputDIE, File, Unit, StringPool, Val, |
1442 | AttrSpec, AttrSize, AttrInfo, IsLittleEndian); |
1443 | } |
1444 | |
1445 | // Look for accelerator entries. |
1446 | uint16_t Tag = InputDIE.getTag(); |
1447 | // FIXME: This is slightly wrong. An inline_subroutine without a |
1448 | // low_pc, but with AT_ranges might be interesting to get into the |
1449 | // accelerator tables too. For now stick with dsymutil's behavior. |
1450 | if ((Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) && |
1451 | Tag != dwarf::DW_TAG_compile_unit && |
1452 | getDIENames(InputDIE, AttrInfo, StringPool, |
1453 | Tag != dwarf::DW_TAG_inlined_subroutine)) { |
1454 | if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name) |
1455 | Unit.addNameAccelerator(Die, AttrInfo.MangledName, |
1456 | Tag == dwarf::DW_TAG_inlined_subroutine); |
1457 | if (AttrInfo.Name) { |
1458 | if (AttrInfo.NameWithoutTemplate) |
1459 | Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate, |
1460 | /* SkipPubSection */ true); |
1461 | Unit.addNameAccelerator(Die, AttrInfo.Name, |
1462 | Tag == dwarf::DW_TAG_inlined_subroutine); |
1463 | } |
1464 | if (AttrInfo.Name && isObjCSelector(AttrInfo.Name.getString())) |
1465 | addObjCAccelerator(Unit, Die, AttrInfo.Name, StringPool, |
1466 | /* SkipPubSection =*/true); |
1467 | |
1468 | } else if (Tag == dwarf::DW_TAG_namespace) { |
1469 | if (!AttrInfo.Name) |
1470 | AttrInfo.Name = StringPool.getEntry("(anonymous namespace)"); |
1471 | Unit.addNamespaceAccelerator(Die, AttrInfo.Name); |
1472 | } else if (isTypeTag(Tag) && !AttrInfo.IsDeclaration && |
1473 | getDIENames(InputDIE, AttrInfo, StringPool) && AttrInfo.Name && |
1474 | AttrInfo.Name.getString()[0]) { |
1475 | uint32_t Hash = hashFullyQualifiedName(InputDIE, Unit, File); |
1476 | uint64_t RuntimeLang = |
1477 | dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class)) |
1478 | .getValueOr(0); |
1479 | bool ObjCClassIsImplementation = |
1480 | (RuntimeLang == dwarf::DW_LANG_ObjC || |
1481 | RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) && |
1482 | dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type)) |
1483 | .getValueOr(0); |
1484 | Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation, |
1485 | Hash); |
1486 | } |
1487 | |
1488 | // Determine whether there are any children that we want to keep. |
1489 | bool HasChildren = false; |
1490 | for (auto Child : InputDIE.children()) { |
1491 | unsigned Idx = U.getDIEIndex(Child); |
1492 | if (Unit.getInfo(Idx).Keep) { |
1493 | HasChildren = true; |
1494 | break; |
1495 | } |
1496 | } |
1497 | |
1498 | DIEAbbrev NewAbbrev = Die->generateAbbrev(); |
1499 | if (HasChildren) |
1500 | NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); |
1501 | // Assign a permanent abbrev number |
1502 | Linker.assignAbbrev(NewAbbrev); |
1503 | Die->setAbbrevNumber(NewAbbrev.getNumber()); |
1504 | |
1505 | // Add the size of the abbreviation number to the output offset. |
1506 | OutOffset += getULEB128Size(Die->getAbbrevNumber()); |
1507 | |
1508 | if (!HasChildren) { |
1509 | // Update our size. |
1510 | Die->setSize(OutOffset - Die->getOffset()); |
1511 | return Die; |
1512 | } |
1513 | |
1514 | // Recursively clone children. |
1515 | for (auto Child : InputDIE.children()) { |
1516 | if (DIE *Clone = cloneDIE(Child, File, Unit, StringPool, PCOffset, |
1517 | OutOffset, Flags, IsLittleEndian)) { |
1518 | Die->addChild(Clone); |
1519 | OutOffset = Clone->getOffset() + Clone->getSize(); |
1520 | } |
1521 | } |
1522 | |
1523 | // Account for the end of children marker. |
1524 | OutOffset += sizeof(int8_t); |
1525 | // Update our size. |
1526 | Die->setSize(OutOffset - Die->getOffset()); |
1527 | return Die; |
1528 | } |
1529 | |
1530 | /// Patch the input object file relevant debug_ranges entries |
1531 | /// and emit them in the output file. Update the relevant attributes |
1532 | /// to point at the new entries. |
1533 | void DWARFLinker::patchRangesForUnit(const CompileUnit &Unit, |
1534 | DWARFContext &OrigDwarf, |
1535 | const DWARFFile &File) const { |
1536 | DWARFDebugRangeList RangeList; |
1537 | const auto &FunctionRanges = Unit.getFunctionRanges(); |
1538 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
1539 | DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(), |
1540 | OrigDwarf.getDWARFObj().getRangesSection(), |
1541 | OrigDwarf.isLittleEndian(), AddressSize); |
1542 | auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; |
1543 | DWARFUnit &OrigUnit = Unit.getOrigUnit(); |
1544 | auto OrigUnitDie = OrigUnit.getUnitDIE(false); |
1545 | uint64_t OrigLowPc = |
1546 | dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), -1ULL); |
1547 | // Ranges addresses are based on the unit's low_pc. Compute the |
1548 | // offset we need to apply to adapt to the new unit's low_pc. |
1549 | int64_t UnitPcOffset = 0; |
1550 | if (OrigLowPc != -1ULL) |
1551 | UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc(); |
1552 | |
1553 | for (const auto &RangeAttribute : Unit.getRangesAttributes()) { |
1554 | uint64_t Offset = RangeAttribute.get(); |
1555 | RangeAttribute.set(TheDwarfEmitter->getRangesSectionSize()); |
1556 | if (Error E = RangeList.extract(RangeExtractor, &Offset)) { |
1557 | llvm::consumeError(std::move(E)); |
1558 | reportWarning("invalid range list ignored.", File); |
1559 | RangeList.clear(); |
1560 | } |
1561 | const auto &Entries = RangeList.getEntries(); |
1562 | if (!Entries.empty()) { |
1563 | const DWARFDebugRangeList::RangeListEntry &First = Entries.front(); |
1564 | |
1565 | if (CurrRange == InvalidRange || |
1566 | First.StartAddress + OrigLowPc < CurrRange.start() || |
1567 | First.StartAddress + OrigLowPc >= CurrRange.stop()) { |
1568 | CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc); |
1569 | if (CurrRange == InvalidRange || |
1570 | CurrRange.start() > First.StartAddress + OrigLowPc) { |
1571 | reportWarning("no mapping for range.", File); |
1572 | continue; |
1573 | } |
1574 | } |
1575 | } |
1576 | |
1577 | TheDwarfEmitter->emitRangesEntries(UnitPcOffset, OrigLowPc, CurrRange, |
1578 | Entries, AddressSize); |
1579 | } |
1580 | } |
1581 | |
1582 | /// Generate the debug_aranges entries for \p Unit and if the |
1583 | /// unit has a DW_AT_ranges attribute, also emit the debug_ranges |
1584 | /// contribution for this attribute. |
1585 | /// FIXME: this could actually be done right in patchRangesForUnit, |
1586 | /// but for the sake of initial bit-for-bit compatibility with legacy |
1587 | /// dsymutil, we have to do it in a delayed pass. |
1588 | void DWARFLinker::generateUnitRanges(CompileUnit &Unit) const { |
1589 | auto Attr = Unit.getUnitRangesAttribute(); |
1590 | if (Attr) |
1591 | Attr->set(TheDwarfEmitter->getRangesSectionSize()); |
1592 | TheDwarfEmitter->emitUnitRangesEntries(Unit, static_cast<bool>(Attr)); |
1593 | } |
1594 | |
1595 | /// Insert the new line info sequence \p Seq into the current |
1596 | /// set of already linked line info \p Rows. |
1597 | static void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq, |
1598 | std::vector<DWARFDebugLine::Row> &Rows) { |
1599 | if (Seq.empty()) |
1600 | return; |
1601 | |
1602 | if (!Rows.empty() && Rows.back().Address < Seq.front().Address) { |
1603 | llvm::append_range(Rows, Seq); |
1604 | Seq.clear(); |
1605 | return; |
1606 | } |
1607 | |
1608 | object::SectionedAddress Front = Seq.front().Address; |
1609 | auto InsertPoint = partition_point( |
1610 | Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; }); |
1611 | |
1612 | // FIXME: this only removes the unneeded end_sequence if the |
1613 | // sequences have been inserted in order. Using a global sort like |
1614 | // described in patchLineTableForUnit() and delaying the end_sequene |
1615 | // elimination to emitLineTableForUnit() we can get rid of all of them. |
1616 | if (InsertPoint != Rows.end() && InsertPoint->Address == Front && |
1617 | InsertPoint->EndSequence) { |
1618 | *InsertPoint = Seq.front(); |
1619 | Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end()); |
1620 | } else { |
1621 | Rows.insert(InsertPoint, Seq.begin(), Seq.end()); |
1622 | } |
1623 | |
1624 | Seq.clear(); |
1625 | } |
1626 | |
1627 | static void patchStmtList(DIE &Die, DIEInteger Offset) { |
1628 | for (auto &V : Die.values()) |
1629 | if (V.getAttribute() == dwarf::DW_AT_stmt_list) { |
1630 | V = DIEValue(V.getAttribute(), V.getForm(), Offset); |
1631 | return; |
1632 | } |
1633 | |
1634 | llvm_unreachable("Didn't find DW_AT_stmt_list in cloned DIE!")__builtin_unreachable(); |
1635 | } |
1636 | |
1637 | /// Extract the line table for \p Unit from \p OrigDwarf, and |
1638 | /// recreate a relocated version of these for the address ranges that |
1639 | /// are present in the binary. |
1640 | void DWARFLinker::patchLineTableForUnit(CompileUnit &Unit, |
1641 | DWARFContext &OrigDwarf, |
1642 | const DWARFFile &File) { |
1643 | DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE(); |
1644 | auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list)); |
1645 | if (!StmtList) |
1646 | return; |
1647 | |
1648 | // Update the cloned DW_AT_stmt_list with the correct debug_line offset. |
1649 | if (auto *OutputDIE = Unit.getOutputUnitDIE()) |
1650 | patchStmtList(*OutputDIE, |
1651 | DIEInteger(TheDwarfEmitter->getLineSectionSize())); |
1652 | |
1653 | RangesTy &Ranges = File.Addresses->getValidAddressRanges(); |
1654 | |
1655 | // Parse the original line info for the unit. |
1656 | DWARFDebugLine::LineTable LineTable; |
1657 | uint64_t StmtOffset = *StmtList; |
1658 | DWARFDataExtractor LineExtractor( |
1659 | OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(), |
1660 | OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize()); |
1661 | if (needToTranslateStrings()) |
1662 | return TheDwarfEmitter->translateLineTable(LineExtractor, StmtOffset); |
1663 | |
1664 | if (Error Err = |
1665 | LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf, |
1666 | &Unit.getOrigUnit(), OrigDwarf.getWarningHandler())) |
1667 | OrigDwarf.getWarningHandler()(std::move(Err)); |
1668 | |
1669 | // This vector is the output line table. |
1670 | std::vector<DWARFDebugLine::Row> NewRows; |
1671 | NewRows.reserve(LineTable.Rows.size()); |
1672 | |
1673 | // Current sequence of rows being extracted, before being inserted |
1674 | // in NewRows. |
1675 | std::vector<DWARFDebugLine::Row> Seq; |
1676 | const auto &FunctionRanges = Unit.getFunctionRanges(); |
1677 | auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; |
1678 | |
1679 | // FIXME: This logic is meant to generate exactly the same output as |
1680 | // Darwin's classic dsymutil. There is a nicer way to implement this |
1681 | // by simply putting all the relocated line info in NewRows and simply |
1682 | // sorting NewRows before passing it to emitLineTableForUnit. This |
1683 | // should be correct as sequences for a function should stay |
1684 | // together in the sorted output. There are a few corner cases that |
1685 | // look suspicious though, and that required to implement the logic |
1686 | // this way. Revisit that once initial validation is finished. |
1687 | |
1688 | // Iterate over the object file line info and extract the sequences |
1689 | // that correspond to linked functions. |
1690 | for (auto &Row : LineTable.Rows) { |
1691 | // Check whether we stepped out of the range. The range is |
1692 | // half-open, but consider accept the end address of the range if |
1693 | // it is marked as end_sequence in the input (because in that |
1694 | // case, the relocation offset is accurate and that entry won't |
1695 | // serve as the start of another function). |
1696 | if (CurrRange == InvalidRange || Row.Address.Address < CurrRange.start() || |
1697 | Row.Address.Address > CurrRange.stop() || |
1698 | (Row.Address.Address == CurrRange.stop() && !Row.EndSequence)) { |
1699 | // We just stepped out of a known range. Insert a end_sequence |
1700 | // corresponding to the end of the range. |
1701 | uint64_t StopAddress = CurrRange != InvalidRange |
1702 | ? CurrRange.stop() + CurrRange.value() |
1703 | : -1ULL; |
1704 | CurrRange = FunctionRanges.find(Row.Address.Address); |
1705 | bool CurrRangeValid = |
1706 | CurrRange != InvalidRange && CurrRange.start() <= Row.Address.Address; |
1707 | if (!CurrRangeValid) { |
1708 | CurrRange = InvalidRange; |
1709 | if (StopAddress != -1ULL) { |
1710 | // Try harder by looking in the Address ranges map. |
1711 | // There are corner cases where this finds a |
1712 | // valid entry. It's unclear if this is right or wrong, but |
1713 | // for now do as dsymutil. |
1714 | // FIXME: Understand exactly what cases this addresses and |
1715 | // potentially remove it along with the Ranges map. |
1716 | auto Range = Ranges.lower_bound(Row.Address.Address); |
1717 | if (Range != Ranges.begin() && Range != Ranges.end()) |
1718 | --Range; |
1719 | |
1720 | if (Range != Ranges.end() && Range->first <= Row.Address.Address && |
1721 | Range->second.HighPC >= Row.Address.Address) { |
1722 | StopAddress = Row.Address.Address + Range->second.Offset; |
1723 | } |
1724 | } |
1725 | } |
1726 | if (StopAddress != -1ULL && !Seq.empty()) { |
1727 | // Insert end sequence row with the computed end address, but |
1728 | // the same line as the previous one. |
1729 | auto NextLine = Seq.back(); |
1730 | NextLine.Address.Address = StopAddress; |
1731 | NextLine.EndSequence = 1; |
1732 | NextLine.PrologueEnd = 0; |
1733 | NextLine.BasicBlock = 0; |
1734 | NextLine.EpilogueBegin = 0; |
1735 | Seq.push_back(NextLine); |
1736 | insertLineSequence(Seq, NewRows); |
1737 | } |
1738 | |
1739 | if (!CurrRangeValid) |
1740 | continue; |
1741 | } |
1742 | |
1743 | // Ignore empty sequences. |
1744 | if (Row.EndSequence && Seq.empty()) |
1745 | continue; |
1746 | |
1747 | // Relocate row address and add it to the current sequence. |
1748 | Row.Address.Address += CurrRange.value(); |
1749 | Seq.emplace_back(Row); |
1750 | |
1751 | if (Row.EndSequence) |
1752 | insertLineSequence(Seq, NewRows); |
1753 | } |
1754 | |
1755 | // Finished extracting, now emit the line tables. |
1756 | // FIXME: LLVM hard-codes its prologue values. We just copy the |
1757 | // prologue over and that works because we act as both producer and |
1758 | // consumer. It would be nicer to have a real configurable line |
1759 | // table emitter. |
1760 | if (LineTable.Prologue.getVersion() < 2 || |
1761 | LineTable.Prologue.getVersion() > 5 || |
1762 | LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT1 || |
1763 | LineTable.Prologue.OpcodeBase > 13) |
1764 | reportWarning("line table parameters mismatch. Cannot emit.", File); |
1765 | else { |
1766 | uint32_t PrologueEnd = *StmtList + 10 + LineTable.Prologue.PrologueLength; |
1767 | // DWARF v5 has an extra 2 bytes of information before the header_length |
1768 | // field. |
1769 | if (LineTable.Prologue.getVersion() == 5) |
1770 | PrologueEnd += 2; |
1771 | StringRef LineData = OrigDwarf.getDWARFObj().getLineSection().Data; |
1772 | MCDwarfLineTableParams Params; |
1773 | Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; |
1774 | Params.DWARF2LineBase = LineTable.Prologue.LineBase; |
1775 | Params.DWARF2LineRange = LineTable.Prologue.LineRange; |
1776 | TheDwarfEmitter->emitLineTableForUnit( |
1777 | Params, LineData.slice(*StmtList + 4, PrologueEnd), |
1778 | LineTable.Prologue.MinInstLength, NewRows, |
1779 | Unit.getOrigUnit().getAddressByteSize()); |
1780 | } |
1781 | } |
1782 | |
1783 | void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) { |
1784 | switch (Options.TheAccelTableKind) { |
1785 | case AccelTableKind::Apple: |
1786 | emitAppleAcceleratorEntriesForUnit(Unit); |
1787 | break; |
1788 | case AccelTableKind::Dwarf: |
1789 | emitDwarfAcceleratorEntriesForUnit(Unit); |
1790 | break; |
1791 | case AccelTableKind::Pub: |
1792 | emitPubAcceleratorEntriesForUnit(Unit); |
1793 | break; |
1794 | case AccelTableKind::Default: |
1795 | llvm_unreachable("The default must be updated to a concrete value.")__builtin_unreachable(); |
1796 | break; |
1797 | } |
1798 | } |
1799 | |
1800 | void DWARFLinker::emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit) { |
1801 | // Add namespaces. |
1802 | for (const auto &Namespace : Unit.getNamespaces()) |
1803 | AppleNamespaces.addName(Namespace.Name, |
1804 | Namespace.Die->getOffset() + Unit.getStartOffset()); |
1805 | |
1806 | /// Add names. |
1807 | for (const auto &Pubname : Unit.getPubnames()) |
1808 | AppleNames.addName(Pubname.Name, |
1809 | Pubname.Die->getOffset() + Unit.getStartOffset()); |
1810 | |
1811 | /// Add types. |
1812 | for (const auto &Pubtype : Unit.getPubtypes()) |
1813 | AppleTypes.addName( |
1814 | Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(), |
1815 | Pubtype.Die->getTag(), |
1816 | Pubtype.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation |
1817 | : 0, |
1818 | Pubtype.QualifiedNameHash); |
1819 | |
1820 | /// Add ObjC names. |
1821 | for (const auto &ObjC : Unit.getObjC()) |
1822 | AppleObjc.addName(ObjC.Name, ObjC.Die->getOffset() + Unit.getStartOffset()); |
1823 | } |
1824 | |
1825 | void DWARFLinker::emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit) { |
1826 | for (const auto &Namespace : Unit.getNamespaces()) |
1827 | DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(), |
1828 | Namespace.Die->getTag(), Unit.getUniqueID()); |
1829 | for (const auto &Pubname : Unit.getPubnames()) |
1830 | DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(), |
1831 | Pubname.Die->getTag(), Unit.getUniqueID()); |
1832 | for (const auto &Pubtype : Unit.getPubtypes()) |
1833 | DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(), |
1834 | Pubtype.Die->getTag(), Unit.getUniqueID()); |
1835 | } |
1836 | |
1837 | void DWARFLinker::emitPubAcceleratorEntriesForUnit(CompileUnit &Unit) { |
1838 | TheDwarfEmitter->emitPubNamesForUnit(Unit); |
1839 | TheDwarfEmitter->emitPubTypesForUnit(Unit); |
1840 | } |
1841 | |
1842 | /// Read the frame info stored in the object, and emit the |
1843 | /// patched frame descriptions for the resulting file. |
1844 | /// |
1845 | /// This is actually pretty easy as the data of the CIEs and FDEs can |
1846 | /// be considered as black boxes and moved as is. The only thing to do |
1847 | /// is to patch the addresses in the headers. |
1848 | void DWARFLinker::patchFrameInfoForObject(const DWARFFile &File, |
1849 | RangesTy &Ranges, |
1850 | DWARFContext &OrigDwarf, |
1851 | unsigned AddrSize) { |
1852 | StringRef FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data; |
1853 | if (FrameData.empty()) |
1854 | return; |
1855 | |
1856 | DataExtractor Data(FrameData, OrigDwarf.isLittleEndian(), 0); |
1857 | uint64_t InputOffset = 0; |
1858 | |
1859 | // Store the data of the CIEs defined in this object, keyed by their |
1860 | // offsets. |
1861 | DenseMap<uint64_t, StringRef> LocalCIES; |
1862 | |
1863 | while (Data.isValidOffset(InputOffset)) { |
1864 | uint64_t EntryOffset = InputOffset; |
1865 | uint32_t InitialLength = Data.getU32(&InputOffset); |
1866 | if (InitialLength == 0xFFFFFFFF) |
1867 | return reportWarning("Dwarf64 bits no supported", File); |
1868 | |
1869 | uint32_t CIEId = Data.getU32(&InputOffset); |
1870 | if (CIEId == 0xFFFFFFFF) { |
1871 | // This is a CIE, store it. |
1872 | StringRef CIEData = FrameData.substr(EntryOffset, InitialLength + 4); |
1873 | LocalCIES[EntryOffset] = CIEData; |
1874 | // The -4 is to account for the CIEId we just read. |
1875 | InputOffset += InitialLength - 4; |
1876 | continue; |
1877 | } |
1878 | |
1879 | uint32_t Loc = Data.getUnsigned(&InputOffset, AddrSize); |
1880 | |
1881 | // Some compilers seem to emit frame info that doesn't start at |
1882 | // the function entry point, thus we can't just lookup the address |
1883 | // in the debug map. Use the AddressInfo's range map to see if the FDE |
1884 | // describes something that we can relocate. |
1885 | auto Range = Ranges.upper_bound(Loc); |
1886 | if (Range != Ranges.begin()) |
1887 | --Range; |
1888 | if (Range == Ranges.end() || Range->first > Loc || |
1889 | Range->second.HighPC <= Loc) { |
1890 | // The +4 is to account for the size of the InitialLength field itself. |
1891 | InputOffset = EntryOffset + InitialLength + 4; |
1892 | continue; |
1893 | } |
1894 | |
1895 | // This is an FDE, and we have a mapping. |
1896 | // Have we already emitted a corresponding CIE? |
1897 | StringRef CIEData = LocalCIES[CIEId]; |
1898 | if (CIEData.empty()) |
1899 | return reportWarning("Inconsistent debug_frame content. Dropping.", File); |
1900 | |
1901 | // Look if we already emitted a CIE that corresponds to the |
1902 | // referenced one (the CIE data is the key of that lookup). |
1903 | auto IteratorInserted = EmittedCIEs.insert( |
1904 | std::make_pair(CIEData, TheDwarfEmitter->getFrameSectionSize())); |
1905 | // If there is no CIE yet for this ID, emit it. |
1906 | if (IteratorInserted.second) { |
1907 | LastCIEOffset = TheDwarfEmitter->getFrameSectionSize(); |
1908 | IteratorInserted.first->getValue() = LastCIEOffset; |
1909 | TheDwarfEmitter->emitCIE(CIEData); |
1910 | } |
1911 | |
1912 | // Emit the FDE with updated address and CIE pointer. |
1913 | // (4 + AddrSize) is the size of the CIEId + initial_location |
1914 | // fields that will get reconstructed by emitFDE(). |
1915 | unsigned FDERemainingBytes = InitialLength - (4 + AddrSize); |
1916 | TheDwarfEmitter->emitFDE(IteratorInserted.first->getValue(), AddrSize, |
1917 | Loc + Range->second.Offset, |
1918 | FrameData.substr(InputOffset, FDERemainingBytes)); |
1919 | InputOffset += FDERemainingBytes; |
1920 | } |
1921 | } |
1922 | |
1923 | uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE, |
1924 | CompileUnit &U, |
1925 | const DWARFFile &File, |
1926 | int ChildRecurseDepth) { |
1927 | const char *Name = nullptr; |
1928 | DWARFUnit *OrigUnit = &U.getOrigUnit(); |
1929 | CompileUnit *CU = &U; |
1930 | Optional<DWARFFormValue> Ref; |
1931 | |
1932 | while (1) { |
1933 | if (const char *CurrentName = DIE.getName(DINameKind::ShortName)) |
1934 | Name = CurrentName; |
1935 | |
1936 | if (!(Ref = DIE.find(dwarf::DW_AT_specification)) && |
1937 | !(Ref = DIE.find(dwarf::DW_AT_abstract_origin))) |
1938 | break; |
1939 | |
1940 | if (!Ref->isFormClass(DWARFFormValue::FC_Reference)) |
1941 | break; |
1942 | |
1943 | CompileUnit *RefCU; |
1944 | if (auto RefDIE = |
1945 | Linker.resolveDIEReference(File, CompileUnits, *Ref, DIE, RefCU)) { |
1946 | CU = RefCU; |
1947 | OrigUnit = &RefCU->getOrigUnit(); |
1948 | DIE = RefDIE; |
1949 | } |
1950 | } |
1951 | |
1952 | unsigned Idx = OrigUnit->getDIEIndex(DIE); |
1953 | if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace) |
1954 | Name = "(anonymous namespace)"; |
1955 | |
1956 | if (CU->getInfo(Idx).ParentIdx == 0 || |
1957 | // FIXME: dsymutil-classic compatibility. Ignore modules. |
1958 | CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() == |
1959 | dwarf::DW_TAG_module) |
1960 | return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::")); |
1961 | |
1962 | DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx); |
1963 | return djbHash( |
1964 | (Name ? Name : ""), |
1965 | djbHash((Name ? "::" : ""), |
1966 | hashFullyQualifiedName(Die, *CU, File, ++ChildRecurseDepth))); |
1967 | } |
1968 | |
1969 | static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) { |
1970 | auto DwoId = dwarf::toUnsigned( |
1971 | CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id})); |
1972 | if (DwoId) |
1973 | return *DwoId; |
1974 | return 0; |
1975 | } |
1976 | |
1977 | static std::string remapPath(StringRef Path, |
1978 | const objectPrefixMap &ObjectPrefixMap) { |
1979 | if (ObjectPrefixMap.empty()) |
1980 | return Path.str(); |
1981 | |
1982 | SmallString<256> p = Path; |
1983 | for (const auto &Entry : ObjectPrefixMap) |
1984 | if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second)) |
1985 | break; |
1986 | return p.str().str(); |
1987 | } |
1988 | |
1989 | bool DWARFLinker::registerModuleReference(DWARFDie CUDie, const DWARFUnit &Unit, |
1990 | const DWARFFile &File, |
1991 | OffsetsStringPool &StringPool, |
1992 | DeclContextTree &ODRContexts, |
1993 | uint64_t ModulesEndOffset, |
1994 | unsigned &UnitID, bool IsLittleEndian, |
1995 | unsigned Indent, bool Quiet) { |
1996 | std::string PCMfile = dwarf::toString( |
1997 | CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); |
1998 | if (PCMfile.empty()) |
1999 | return false; |
2000 | if (Options.ObjectPrefixMap) |
2001 | PCMfile = remapPath(PCMfile, *Options.ObjectPrefixMap); |
2002 | |
2003 | // Clang module DWARF skeleton CUs abuse this for the path to the module. |
2004 | uint64_t DwoId = getDwoId(CUDie, Unit); |
2005 | |
2006 | std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); |
2007 | if (Name.empty()) { |
2008 | if (!Quiet) |
2009 | reportWarning("Anonymous module skeleton CU for " + PCMfile, File); |
2010 | return true; |
2011 | } |
2012 | |
2013 | if (!Quiet && Options.Verbose) { |
2014 | outs().indent(Indent); |
2015 | outs() << "Found clang module reference " << PCMfile; |
2016 | } |
2017 | |
2018 | auto Cached = ClangModules.find(PCMfile); |
2019 | if (Cached != ClangModules.end()) { |
2020 | // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is |
2021 | // fixed in clang, only warn about DWO_id mismatches in verbose mode. |
2022 | // ASTFileSignatures will change randomly when a module is rebuilt. |
2023 | if (!Quiet && Options.Verbose && (Cached->second != DwoId)) |
2024 | reportWarning(Twine("hash mismatch: this object file was built against a " |
2025 | "different version of the module ") + |
2026 | PCMfile, |
2027 | File); |
2028 | if (!Quiet && Options.Verbose) |
2029 | outs() << " [cached].\n"; |
2030 | return true; |
2031 | } |
2032 | if (!Quiet && Options.Verbose) |
2033 | outs() << " ...\n"; |
2034 | |
2035 | // Cyclic dependencies are disallowed by Clang, but we still |
2036 | // shouldn't run into an infinite loop, so mark it as processed now. |
2037 | ClangModules.insert({PCMfile, DwoId}); |
2038 | |
2039 | if (Error E = loadClangModule(CUDie, PCMfile, Name, DwoId, File, StringPool, |
2040 | ODRContexts, ModulesEndOffset, UnitID, |
2041 | IsLittleEndian, Indent + 2, Quiet)) { |
2042 | consumeError(std::move(E)); |
2043 | return false; |
2044 | } |
2045 | return true; |
2046 | } |
2047 | |
2048 | Error DWARFLinker::loadClangModule( |
2049 | DWARFDie CUDie, StringRef Filename, StringRef ModuleName, uint64_t DwoId, |
2050 | const DWARFFile &File, OffsetsStringPool &StringPool, |
2051 | DeclContextTree &ODRContexts, uint64_t ModulesEndOffset, unsigned &UnitID, |
2052 | bool IsLittleEndian, unsigned Indent, bool Quiet) { |
2053 | /// Using a SmallString<0> because loadClangModule() is recursive. |
2054 | SmallString<0> Path(Options.PrependPath); |
2055 | if (sys::path::is_relative(Filename)) |
2056 | resolveRelativeObjectPath(Path, CUDie); |
2057 | sys::path::append(Path, Filename); |
2058 | // Don't use the cached binary holder because we have no thread-safety |
2059 | // guarantee and the lifetime is limited. |
2060 | |
2061 | if (Options.ObjFileLoader == nullptr) |
2062 | return Error::success(); |
2063 | |
2064 | auto ErrOrObj = Options.ObjFileLoader(File.FileName, Path); |
2065 | if (!ErrOrObj) |
2066 | return Error::success(); |
2067 | |
2068 | std::unique_ptr<CompileUnit> Unit; |
2069 | |
2070 | for (const auto &CU : ErrOrObj->Dwarf->compile_units()) { |
2071 | updateDwarfVersion(CU->getVersion()); |
2072 | // Recursively get all modules imported by this one. |
2073 | auto CUDie = CU->getUnitDIE(false); |
2074 | if (!CUDie) |
2075 | continue; |
2076 | if (!registerModuleReference(CUDie, *CU, File, StringPool, ODRContexts, |
2077 | ModulesEndOffset, UnitID, IsLittleEndian, |
2078 | Indent, Quiet)) { |
2079 | if (Unit) { |
2080 | std::string Err = |
2081 | (Filename + |
2082 | ": Clang modules are expected to have exactly 1 compile unit.\n") |
2083 | .str(); |
2084 | reportError(Err, File); |
2085 | return make_error<StringError>(Err, inconvertibleErrorCode()); |
2086 | } |
2087 | // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is |
2088 | // fixed in clang, only warn about DWO_id mismatches in verbose mode. |
2089 | // ASTFileSignatures will change randomly when a module is rebuilt. |
2090 | uint64_t PCMDwoId = getDwoId(CUDie, *CU); |
2091 | if (PCMDwoId != DwoId) { |
2092 | if (!Quiet && Options.Verbose) |
2093 | reportWarning( |
2094 | Twine("hash mismatch: this object file was built against a " |
2095 | "different version of the module ") + |
2096 | Filename, |
2097 | File); |
2098 | // Update the cache entry with the DwoId of the module loaded from disk. |
2099 | ClangModules[Filename] = PCMDwoId; |
2100 | } |
2101 | |
2102 | // Add this module. |
2103 | Unit = std::make_unique<CompileUnit>(*CU, UnitID++, !Options.NoODR, |
2104 | ModuleName); |
2105 | Unit->setHasInterestingContent(); |
2106 | analyzeContextInfo(CUDie, 0, *Unit, &ODRContexts.getRoot(), ODRContexts, |
2107 | ModulesEndOffset, Options.ParseableSwiftInterfaces, |
2108 | [&](const Twine &Warning, const DWARFDie &DIE) { |
2109 | reportWarning(Warning, File, &DIE); |
2110 | }); |
2111 | // Keep everything. |
2112 | Unit->markEverythingAsKept(); |
2113 | } |
2114 | } |
2115 | assert(Unit && "CompileUnit is not set!")(static_cast<void> (0)); |
2116 | if (!Unit->getOrigUnit().getUnitDIE().hasChildren()) |
2117 | return Error::success(); |
2118 | if (!Quiet && Options.Verbose) { |
2119 | outs().indent(Indent); |
2120 | outs() << "cloning .debug_info from " << Filename << "\n"; |
2121 | } |
2122 | |
2123 | UnitListTy CompileUnits; |
2124 | CompileUnits.push_back(std::move(Unit)); |
2125 | assert(TheDwarfEmitter)(static_cast<void> (0)); |
2126 | DIECloner(*this, TheDwarfEmitter, *ErrOrObj, DIEAlloc, CompileUnits, |
2127 | Options.Update) |
2128 | .cloneAllCompileUnits(*(ErrOrObj->Dwarf), File, StringPool, |
2129 | IsLittleEndian); |
2130 | return Error::success(); |
2131 | } |
2132 | |
2133 | uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits( |
2134 | DWARFContext &DwarfContext, const DWARFFile &File, |
2135 | OffsetsStringPool &StringPool, bool IsLittleEndian) { |
2136 | uint64_t OutputDebugInfoSize = |
2137 | Linker.Options.NoOutput ? 0 : Emitter->getDebugInfoSectionSize(); |
2138 | const uint64_t StartOutputDebugInfoSize = OutputDebugInfoSize; |
2139 | |
2140 | for (auto &CurrentUnit : CompileUnits) { |
2141 | const uint16_t DwarfVersion = CurrentUnit->getOrigUnit().getVersion(); |
2142 | const uint32_t UnitHeaderSize = DwarfVersion >= 5 ? 12 : 11; |
2143 | auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); |
2144 | CurrentUnit->setStartOffset(OutputDebugInfoSize); |
2145 | if (!InputDIE) { |
2146 | OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion); |
2147 | continue; |
2148 | } |
2149 | if (CurrentUnit->getInfo(0).Keep) { |
2150 | // Clone the InputDIE into your Unit DIE in our compile unit since it |
2151 | // already has a DIE inside of it. |
2152 | CurrentUnit->createOutputDIE(); |
2153 | cloneDIE(InputDIE, File, *CurrentUnit, StringPool, 0 /* PC offset */, |
2154 | UnitHeaderSize, 0, IsLittleEndian, |
2155 | CurrentUnit->getOutputUnitDIE()); |
2156 | } |
2157 | |
2158 | OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(DwarfVersion); |
2159 | |
2160 | if (!Linker.Options.NoOutput) { |
2161 | assert(Emitter)(static_cast<void> (0)); |
2162 | |
2163 | if (LLVM_LIKELY(!Linker.Options.Update)__builtin_expect((bool)(!Linker.Options.Update), true) || |
2164 | Linker.needToTranslateStrings()) |
2165 | Linker.patchLineTableForUnit(*CurrentUnit, DwarfContext, File); |
2166 | |
2167 | Linker.emitAcceleratorEntriesForUnit(*CurrentUnit); |
2168 | |
2169 | if (LLVM_UNLIKELY(Linker.Options.Update)__builtin_expect((bool)(Linker.Options.Update), false)) |
2170 | continue; |
2171 | |
2172 | Linker.patchRangesForUnit(*CurrentUnit, DwarfContext, File); |
2173 | auto ProcessExpr = [&](StringRef Bytes, |
2174 | SmallVectorImpl<uint8_t> &Buffer) { |
2175 | DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit(); |
2176 | DataExtractor Data(Bytes, IsLittleEndian, |
2177 | OrigUnit.getAddressByteSize()); |
2178 | cloneExpression(Data, |
2179 | DWARFExpression(Data, OrigUnit.getAddressByteSize(), |
2180 | OrigUnit.getFormParams().Format), |
2181 | File, *CurrentUnit, Buffer); |
2182 | }; |
2183 | Emitter->emitLocationsForUnit(*CurrentUnit, DwarfContext, ProcessExpr); |
2184 | } |
2185 | } |
2186 | |
2187 | if (!Linker.Options.NoOutput) { |
2188 | assert(Emitter)(static_cast<void> (0)); |
2189 | // Emit all the compile unit's debug information. |
2190 | for (auto &CurrentUnit : CompileUnits) { |
2191 | if (LLVM_LIKELY(!Linker.Options.Update)__builtin_expect((bool)(!Linker.Options.Update), true)) |
2192 | Linker.generateUnitRanges(*CurrentUnit); |
2193 | |
2194 | CurrentUnit->fixupForwardReferences(); |
2195 | |
2196 | if (!CurrentUnit->getOutputUnitDIE()) |
2197 | continue; |
2198 | |
2199 | unsigned DwarfVersion = CurrentUnit->getOrigUnit().getVersion(); |
2200 | |
2201 | assert(Emitter->getDebugInfoSectionSize() ==(static_cast<void> (0)) |
2202 | CurrentUnit->getStartOffset())(static_cast<void> (0)); |
2203 | Emitter->emitCompileUnitHeader(*CurrentUnit, DwarfVersion); |
2204 | Emitter->emitDIE(*CurrentUnit->getOutputUnitDIE()); |
2205 | assert(Emitter->getDebugInfoSectionSize() ==(static_cast<void> (0)) |
2206 | CurrentUnit->computeNextUnitOffset(DwarfVersion))(static_cast<void> (0)); |
2207 | } |
2208 | } |
2209 | |
2210 | return OutputDebugInfoSize - StartOutputDebugInfoSize; |
2211 | } |
2212 | |
2213 | void DWARFLinker::updateAccelKind(DWARFContext &Dwarf) { |
2214 | if (Options.TheAccelTableKind != AccelTableKind::Default) |
2215 | return; |
2216 | |
2217 | auto &DwarfObj = Dwarf.getDWARFObj(); |
2218 | |
2219 | if (!AtLeastOneDwarfAccelTable && |
2220 | (!DwarfObj.getAppleNamesSection().Data.empty() || |
2221 | !DwarfObj.getAppleTypesSection().Data.empty() || |
2222 | !DwarfObj.getAppleNamespacesSection().Data.empty() || |
2223 | !DwarfObj.getAppleObjCSection().Data.empty())) { |
2224 | AtLeastOneAppleAccelTable = true; |
2225 | } |
2226 | |
2227 | if (!AtLeastOneDwarfAccelTable && !DwarfObj.getNamesSection().Data.empty()) { |
2228 | AtLeastOneDwarfAccelTable = true; |
2229 | } |
2230 | } |
2231 | |
2232 | bool DWARFLinker::emitPaperTrailWarnings(const DWARFFile &File, |
2233 | OffsetsStringPool &StringPool) { |
2234 | |
2235 | if (File.Warnings.empty()) |
2236 | return false; |
2237 | |
2238 | DIE *CUDie = DIE::get(DIEAlloc, dwarf::DW_TAG_compile_unit); |
2239 | CUDie->setOffset(11); |
2240 | StringRef Producer; |
2241 | StringRef WarningHeader; |
2242 | |
2243 | switch (DwarfLinkerClientID) { |
2244 | case DwarfLinkerClient::Dsymutil: |
2245 | Producer = StringPool.internString("dsymutil"); |
2246 | WarningHeader = "dsymutil_warning"; |
2247 | break; |
2248 | |
2249 | default: |
2250 | Producer = StringPool.internString("dwarfopt"); |
2251 | WarningHeader = "dwarfopt_warning"; |
2252 | break; |
2253 | } |
2254 | |
2255 | StringRef FileName = StringPool.internString(File.FileName); |
2256 | CUDie->addValue(DIEAlloc, dwarf::DW_AT_producer, dwarf::DW_FORM_strp, |
2257 | DIEInteger(StringPool.getStringOffset(Producer))); |
2258 | DIEBlock *String = new (DIEAlloc) DIEBlock(); |
2259 | DIEBlocks.push_back(String); |
2260 | for (auto &C : FileName) |
2261 | String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1, |
2262 | DIEInteger(C)); |
2263 | String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1, |
2264 | DIEInteger(0)); |
2265 | |
2266 | CUDie->addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_string, String); |
2267 | for (const auto &Warning : File.Warnings) { |
2268 | DIE &ConstDie = CUDie->addChild(DIE::get(DIEAlloc, dwarf::DW_TAG_constant)); |
2269 | ConstDie.addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, |
2270 | DIEInteger(StringPool.getStringOffset(WarningHeader))); |
2271 | ConstDie.addValue(DIEAlloc, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, |
2272 | DIEInteger(1)); |
2273 | ConstDie.addValue(DIEAlloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_strp, |
2274 | DIEInteger(StringPool.getStringOffset(Warning))); |
2275 | } |
2276 | unsigned Size = 4 /* FORM_strp */ + FileName.size() + 1 + |
2277 | File.Warnings.size() * (4 + 1 + 4) + 1 /* End of children */; |
2278 | DIEAbbrev Abbrev = CUDie->generateAbbrev(); |
2279 | assignAbbrev(Abbrev); |
2280 | CUDie->setAbbrevNumber(Abbrev.getNumber()); |
2281 | Size += getULEB128Size(Abbrev.getNumber()); |
2282 | // Abbreviation ordering needed for classic compatibility. |
2283 | for (auto &Child : CUDie->children()) { |
2284 | Abbrev = Child.generateAbbrev(); |
2285 | assignAbbrev(Abbrev); |
2286 | Child.setAbbrevNumber(Abbrev.getNumber()); |
2287 | Size += getULEB128Size(Abbrev.getNumber()); |
2288 | } |
2289 | CUDie->setSize(Size); |
2290 | TheDwarfEmitter->emitPaperTrailWarningsDie(*CUDie); |
2291 | |
2292 | return true; |
2293 | } |
2294 | |
2295 | void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) { |
2296 | if (!needToTranslateStrings()) |
2297 | TheDwarfEmitter->emitSectionContents( |
2298 | Dwarf.getDWARFObj().getLineSection().Data, "debug_line"); |
2299 | TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getLocSection().Data, |
2300 | "debug_loc"); |
2301 | TheDwarfEmitter->emitSectionContents( |
2302 | Dwarf.getDWARFObj().getRangesSection().Data, "debug_ranges"); |
2303 | TheDwarfEmitter->emitSectionContents( |
2304 | Dwarf.getDWARFObj().getFrameSection().Data, "debug_frame"); |
2305 | TheDwarfEmitter->emitSectionContents(Dwarf.getDWARFObj().getArangesSection(), |
2306 | "debug_aranges"); |
2307 | } |
2308 | |
2309 | void DWARFLinker::addObjectFile(DWARFFile &File) { |
2310 | ObjectContexts.emplace_back(LinkContext(File)); |
2311 | |
2312 | if (ObjectContexts.back().File.Dwarf) |
2313 | updateAccelKind(*ObjectContexts.back().File.Dwarf); |
2314 | } |
2315 | |
2316 | bool DWARFLinker::link() { |
2317 | assert(Options.NoOutput || TheDwarfEmitter)(static_cast<void> (0)); |
2318 | |
2319 | // A unique ID that identifies each compile unit. |
2320 | unsigned UnitID = 0; |
2321 | |
2322 | // First populate the data structure we need for each iteration of the |
2323 | // parallel loop. |
2324 | unsigned NumObjects = ObjectContexts.size(); |
2325 | |
2326 | // This Dwarf string pool which is used for emission. It must be used |
2327 | // serially as the order of calling getStringOffset matters for |
2328 | // reproducibility. |
2329 | OffsetsStringPool OffsetsStringPool(StringsTranslator, true); |
2330 | |
2331 | // ODR Contexts for the optimize. |
2332 | DeclContextTree ODRContexts; |
2333 | |
2334 | // If we haven't decided on an accelerator table kind yet, we base ourselves |
2335 | // on the DWARF we have seen so far. At this point we haven't pulled in debug |
2336 | // information from modules yet, so it is technically possible that they |
2337 | // would affect the decision. However, as they're built with the same |
2338 | // compiler and flags, it is safe to assume that they will follow the |
2339 | // decision made here. |
2340 | if (Options.TheAccelTableKind == AccelTableKind::Default) { |
2341 | if (AtLeastOneDwarfAccelTable && !AtLeastOneAppleAccelTable) |
2342 | Options.TheAccelTableKind = AccelTableKind::Dwarf; |
2343 | else |
2344 | Options.TheAccelTableKind = AccelTableKind::Apple; |
2345 | } |
2346 | |
2347 | for (LinkContext &OptContext : ObjectContexts) { |
2348 | if (Options.Verbose) { |
2349 | if (DwarfLinkerClientID == DwarfLinkerClient::Dsymutil) |
2350 | outs() << "DEBUG MAP OBJECT: " << OptContext.File.FileName << "\n"; |
2351 | else |
2352 | outs() << "OBJECT FILE: " << OptContext.File.FileName << "\n"; |
2353 | } |
2354 | |
2355 | if (emitPaperTrailWarnings(OptContext.File, OffsetsStringPool)) |
2356 | continue; |
2357 | |
2358 | if (!OptContext.File.Dwarf) |
2359 | continue; |
2360 | // Look for relocations that correspond to address map entries. |
2361 | |
2362 | // there was findvalidrelocations previously ... probably we need to gather |
2363 | // info here |
2364 | if (LLVM_LIKELY(!Options.Update)__builtin_expect((bool)(!Options.Update), true) && |
2365 | !OptContext.File.Addresses->hasValidRelocs()) { |
2366 | if (Options.Verbose) |
2367 | outs() << "No valid relocations found. Skipping.\n"; |
2368 | |
2369 | // Set "Skip" flag as a signal to other loops that we should not |
2370 | // process this iteration. |
2371 | OptContext.Skip = true; |
2372 | continue; |
2373 | } |
2374 | |
2375 | // Setup access to the debug info. |
2376 | if (!OptContext.File.Dwarf) |
2377 | continue; |
2378 | |
2379 | // In a first phase, just read in the debug info and load all clang modules. |
2380 | OptContext.CompileUnits.reserve( |
2381 | OptContext.File.Dwarf->getNumCompileUnits()); |
2382 | |
2383 | for (const auto &CU : OptContext.File.Dwarf->compile_units()) { |
2384 | updateDwarfVersion(CU->getVersion()); |
2385 | auto CUDie = CU->getUnitDIE(false); |
2386 | if (Options.Verbose) { |
2387 | outs() << "Input compilation unit:"; |
2388 | DIDumpOptions DumpOpts; |
2389 | DumpOpts.ChildRecurseDepth = 0; |
2390 | DumpOpts.Verbose = Options.Verbose; |
2391 | CUDie.dump(outs(), 0, DumpOpts); |
2392 | } |
2393 | if (CUDie && !LLVM_UNLIKELY(Options.Update)__builtin_expect((bool)(Options.Update), false)) |
2394 | registerModuleReference(CUDie, *CU, OptContext.File, OffsetsStringPool, |
2395 | ODRContexts, 0, UnitID, |
2396 | OptContext.File.Dwarf->isLittleEndian()); |
2397 | } |
2398 | } |
2399 | |
2400 | // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. |
2401 | if (MaxDwarfVersion == 0) |
2402 | MaxDwarfVersion = 3; |
2403 | |
2404 | // At this point we know how much data we have emitted. We use this value to |
2405 | // compare canonical DIE offsets in analyzeContextInfo to see if a definition |
2406 | // is already emitted, without being affected by canonical die offsets set |
2407 | // later. This prevents undeterminism when analyze and clone execute |
2408 | // concurrently, as clone set the canonical DIE offset and analyze reads it. |
2409 | const uint64_t ModulesEndOffset = |
2410 | Options.NoOutput ? 0 : TheDwarfEmitter->getDebugInfoSectionSize(); |
2411 | |
2412 | // These variables manage the list of processed object files. |
2413 | // The mutex and condition variable are to ensure that this is thread safe. |
2414 | std::mutex ProcessedFilesMutex; |
2415 | std::condition_variable ProcessedFilesConditionVariable; |
2416 | BitVector ProcessedFiles(NumObjects, false); |
2417 | |
2418 | // Analyzing the context info is particularly expensive so it is executed in |
2419 | // parallel with emitting the previous compile unit. |
2420 | auto AnalyzeLambda = [&](size_t I) { |
2421 | auto &Context = ObjectContexts[I]; |
2422 | |
2423 | if (Context.Skip || !Context.File.Dwarf) |
2424 | return; |
2425 | |
2426 | for (const auto &CU : Context.File.Dwarf->compile_units()) { |
2427 | updateDwarfVersion(CU->getVersion()); |
2428 | // The !registerModuleReference() condition effectively skips |
2429 | // over fully resolved skeleton units. This second pass of |
2430 | // registerModuleReferences doesn't do any new work, but it |
2431 | // will collect top-level errors, which are suppressed. Module |
2432 | // warnings were already displayed in the first iteration. |
2433 | bool Quiet = true; |
2434 | auto CUDie = CU->getUnitDIE(false); |
2435 | if (!CUDie || LLVM_UNLIKELY(Options.Update)__builtin_expect((bool)(Options.Update), false) || |
2436 | !registerModuleReference(CUDie, *CU, Context.File, OffsetsStringPool, |
2437 | ODRContexts, ModulesEndOffset, UnitID, |
2438 | Quiet)) { |
2439 | Context.CompileUnits.push_back(std::make_unique<CompileUnit>( |
2440 | *CU, UnitID++, !Options.NoODR && !Options.Update, "")); |
2441 | } |
2442 | } |
2443 | |
2444 | // Now build the DIE parent links that we will use during the next phase. |
2445 | for (auto &CurrentUnit : Context.CompileUnits) { |
2446 | auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE(); |
2447 | if (!CUDie) |
2448 | continue; |
2449 | analyzeContextInfo(CurrentUnit->getOrigUnit().getUnitDIE(), 0, |
2450 | *CurrentUnit, &ODRContexts.getRoot(), ODRContexts, |
2451 | ModulesEndOffset, Options.ParseableSwiftInterfaces, |
2452 | [&](const Twine &Warning, const DWARFDie &DIE) { |
2453 | reportWarning(Warning, Context.File, &DIE); |
2454 | }); |
2455 | } |
2456 | }; |
2457 | |
2458 | // For each object file map how many bytes were emitted. |
2459 | StringMap<DebugInfoSize> SizeByObject; |
2460 | |
2461 | // And then the remaining work in serial again. |
2462 | // Note, although this loop runs in serial, it can run in parallel with |
2463 | // the analyzeContextInfo loop so long as we process files with indices >= |
2464 | // than those processed by analyzeContextInfo. |
2465 | auto CloneLambda = [&](size_t I) { |
2466 | auto &OptContext = ObjectContexts[I]; |
2467 | if (OptContext.Skip || !OptContext.File.Dwarf) |
2468 | return; |
2469 | |
2470 | // Then mark all the DIEs that need to be present in the generated output |
2471 | // and collect some information about them. |
2472 | // Note that this loop can not be merged with the previous one because |
2473 | // cross-cu references require the ParentIdx to be setup for every CU in |
2474 | // the object file before calling this. |
2475 | if (LLVM_UNLIKELY(Options.Update)__builtin_expect((bool)(Options.Update), false)) { |
2476 | for (auto &CurrentUnit : OptContext.CompileUnits) |
2477 | CurrentUnit->markEverythingAsKept(); |
2478 | copyInvariantDebugSection(*OptContext.File.Dwarf); |
2479 | } else { |
2480 | for (auto &CurrentUnit : OptContext.CompileUnits) |
2481 | lookForDIEsToKeep(*OptContext.File.Addresses, |
2482 | OptContext.File.Addresses->getValidAddressRanges(), |
2483 | OptContext.CompileUnits, |
2484 | CurrentUnit->getOrigUnit().getUnitDIE(), |
2485 | OptContext.File, *CurrentUnit, 0); |
2486 | } |
2487 | |
2488 | // The calls to applyValidRelocs inside cloneDIE will walk the reloc |
2489 | // array again (in the same way findValidRelocsInDebugInfo() did). We |
2490 | // need to reset the NextValidReloc index to the beginning. |
2491 | if (OptContext.File.Addresses->hasValidRelocs() || |
2492 | LLVM_UNLIKELY(Options.Update)__builtin_expect((bool)(Options.Update), false)) { |
2493 | SizeByObject[OptContext.File.FileName].Input = |
2494 | getDebugInfoSize(*OptContext.File.Dwarf); |
2495 | SizeByObject[OptContext.File.FileName].Output = |
2496 | DIECloner(*this, TheDwarfEmitter, OptContext.File, DIEAlloc, |
2497 | OptContext.CompileUnits, Options.Update) |
2498 | .cloneAllCompileUnits(*OptContext.File.Dwarf, OptContext.File, |
2499 | OffsetsStringPool, |
2500 | OptContext.File.Dwarf->isLittleEndian()); |
2501 | } |
2502 | if (!Options.NoOutput && !OptContext.CompileUnits.empty() && |
2503 | LLVM_LIKELY(!Options.Update)__builtin_expect((bool)(!Options.Update), true)) |
2504 | patchFrameInfoForObject( |
2505 | OptContext.File, OptContext.File.Addresses->getValidAddressRanges(), |
2506 | *OptContext.File.Dwarf, |
2507 | OptContext.CompileUnits[0]->getOrigUnit().getAddressByteSize()); |
2508 | |
2509 | // Clean-up before starting working on the next object. |
2510 | cleanupAuxiliarryData(OptContext); |
2511 | }; |
2512 | |
2513 | auto EmitLambda = [&]() { |
2514 | // Emit everything that's global. |
2515 | if (!Options.NoOutput) { |
2516 | TheDwarfEmitter->emitAbbrevs(Abbreviations, MaxDwarfVersion); |
2517 | TheDwarfEmitter->emitStrings(OffsetsStringPool); |
2518 | switch (Options.TheAccelTableKind) { |
2519 | case AccelTableKind::Apple: |
2520 | TheDwarfEmitter->emitAppleNames(AppleNames); |
2521 | TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces); |
2522 | TheDwarfEmitter->emitAppleTypes(AppleTypes); |
2523 | TheDwarfEmitter->emitAppleObjc(AppleObjc); |
2524 | break; |
2525 | case AccelTableKind::Dwarf: |
2526 | TheDwarfEmitter->emitDebugNames(DebugNames); |
2527 | break; |
2528 | case AccelTableKind::Pub: |
2529 | // Already emitted by emitPubAcceleratorEntriesForUnit. |
2530 | break; |
2531 | case AccelTableKind::Default: |
2532 | llvm_unreachable("Default should have already been resolved.")__builtin_unreachable(); |
2533 | break; |
2534 | } |
2535 | } |
2536 | }; |
2537 | |
2538 | auto AnalyzeAll = [&]() { |
2539 | for (unsigned I = 0, E = NumObjects; I != E; ++I) { |
2540 | AnalyzeLambda(I); |
2541 | |
2542 | std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex); |
2543 | ProcessedFiles.set(I); |
2544 | ProcessedFilesConditionVariable.notify_one(); |
2545 | } |
2546 | }; |
2547 | |
2548 | auto CloneAll = [&]() { |
2549 | for (unsigned I = 0, E = NumObjects; I != E; ++I) { |
2550 | { |
2551 | std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex); |
2552 | if (!ProcessedFiles[I]) { |
2553 | ProcessedFilesConditionVariable.wait( |
2554 | LockGuard, [&]() { return ProcessedFiles[I]; }); |
2555 | } |
2556 | } |
2557 | |
2558 | CloneLambda(I); |
2559 | } |
2560 | EmitLambda(); |
2561 | }; |
2562 | |
2563 | // To limit memory usage in the single threaded case, analyze and clone are |
2564 | // run sequentially so the OptContext is freed after processing each object |
2565 | // in endDebugObject. |
2566 | if (Options.Threads == 1) { |
2567 | for (unsigned I = 0, E = NumObjects; I != E; ++I) { |
2568 | AnalyzeLambda(I); |
2569 | CloneLambda(I); |
2570 | } |
2571 | EmitLambda(); |
2572 | } else { |
2573 | ThreadPool Pool(hardware_concurrency(2)); |
2574 | Pool.async(AnalyzeAll); |
2575 | Pool.async(CloneAll); |
2576 | Pool.wait(); |
2577 | } |
2578 | |
2579 | if (Options.Statistics) { |
2580 | // Create a vector sorted in descending order by output size. |
2581 | std::vector<std::pair<StringRef, DebugInfoSize>> Sorted; |
2582 | for (auto &E : SizeByObject) |
2583 | Sorted.emplace_back(E.first(), E.second); |
2584 | llvm::sort(Sorted, [](auto &LHS, auto &RHS) { |
2585 | return LHS.second.Output > RHS.second.Output; |
2586 | }); |
2587 | |
2588 | auto ComputePercentange = [](int64_t Input, int64_t Output) -> float { |
2589 | const float Difference = Output - Input; |
2590 | const float Sum = Input + Output; |
2591 | if (Sum == 0) |
2592 | return 0; |
2593 | return (Difference / (Sum / 2)); |
2594 | }; |
2595 | |
2596 | int64_t InputTotal = 0; |
2597 | int64_t OutputTotal = 0; |
2598 | const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n"; |
2599 | |
2600 | // Print header. |
2601 | outs() << ".debug_info section size (in bytes)\n"; |
2602 | outs() << "----------------------------------------------------------------" |
2603 | "---------------\n"; |
2604 | outs() << "Filename Object " |
2605 | " dSYM Change\n"; |
2606 | outs() << "----------------------------------------------------------------" |
2607 | "---------------\n"; |
2608 | |
2609 | // Print body. |
2610 | for (auto &E : Sorted) { |
2611 | InputTotal += E.second.Input; |
2612 | OutputTotal += E.second.Output; |
2613 | llvm::outs() << formatv( |
2614 | FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input, |
2615 | E.second.Output, ComputePercentange(E.second.Input, E.second.Output)); |
2616 | } |
2617 | // Print total and footer. |
2618 | outs() << "----------------------------------------------------------------" |
2619 | "---------------\n"; |
2620 | llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal, |
2621 | ComputePercentange(InputTotal, OutputTotal)); |
2622 | outs() << "----------------------------------------------------------------" |
2623 | "---------------\n\n"; |
2624 | } |
2625 | |
2626 | return true; |
2627 | } |
2628 | |
2629 | } // namespace llvm |