[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / tools / dsymutil / DwarfLinkerForBinary.h
blob623441c749a5d416db360556469dc6b00afbcd23
1 //===- tools/dsymutil/DwarfLinkerForBinary.h --------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
10 #define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
12 #include "BinaryHolder.h"
13 #include "DebugMap.h"
14 #include "LinkUtils.h"
15 #include "MachOUtils.h"
16 #include "llvm/DWARFLinker/DWARFLinker.h"
17 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
18 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
19 #include "llvm/DWARFLinker/DWARFStreamer.h"
20 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
21 #include "llvm/Remarks/RemarkFormat.h"
22 #include "llvm/Remarks/RemarkLinker.h"
24 namespace llvm {
25 namespace dsymutil {
27 /// The core of the Dsymutil Dwarf linking logic.
28 ///
29 /// The link of the dwarf information from the object files will be
30 /// driven by DWARFLinker. DwarfLinkerForBinary reads DebugMap objects
31 /// and pass information to the DWARFLinker. DWARFLinker
32 /// optimizes DWARF taking into account valid relocations.
33 /// Finally, optimized DWARF is passed to DwarfLinkerForBinary through
34 /// DWARFEmitter interface.
35 class DwarfLinkerForBinary {
36 public:
37 DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
38 LinkOptions Options)
39 : OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)) {}
41 /// Link the contents of the DebugMap.
42 bool link(const DebugMap &);
44 void reportWarning(const Twine &Warning, StringRef Context,
45 const DWARFDie *DIE = nullptr) const;
47 /// Flags passed to DwarfLinker::lookForDIEsToKeep
48 enum TraversalFlags {
49 TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
50 TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
51 TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
52 TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
53 TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
54 TF_SkipPC = 1 << 5, ///< Skip all location attributes.
57 private:
59 /// Keeps track of relocations.
60 class AddressManager : public AddressesMap {
61 struct ValidReloc {
62 uint64_t Offset;
63 uint32_t Size;
64 uint64_t Addend;
65 const DebugMapObject::DebugMapEntry *Mapping;
67 ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
68 const DebugMapObject::DebugMapEntry *Mapping)
69 : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
71 bool operator<(const ValidReloc &RHS) const {
72 return Offset < RHS.Offset;
74 bool operator<(uint64_t RHS) const { return Offset < RHS; }
77 const DwarfLinkerForBinary &Linker;
79 /// The valid relocations for the current DebugMapObject.
80 /// This vector is sorted by relocation offset.
81 /// {
82 std::vector<ValidReloc> ValidDebugInfoRelocs;
83 std::vector<ValidReloc> ValidDebugAddrRelocs;
84 /// }
86 RangesTy AddressRanges;
88 StringRef SrcFileName;
90 /// Returns list of valid relocations from \p Relocs,
91 /// between \p StartOffset and \p NextOffset.
92 ///
93 /// \returns true if any relocation is found.
94 std::vector<ValidReloc>
95 getRelocations(const std::vector<ValidReloc> &Relocs, uint64_t StartPos,
96 uint64_t EndPos);
98 /// Resolve specified relocation \p Reloc.
99 ///
100 /// \returns resolved value.
101 uint64_t relocate(const ValidReloc &Reloc) const;
103 /// Fill \p Info with address information for the specified \p Reloc.
104 void fillDieInfo(const ValidReloc &Reloc, CompileUnit::DIEInfo &Info);
106 /// Print contents of debug map entry for the specified \p Reloc.
107 void printReloc(const ValidReloc &Reloc);
109 public:
110 AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
111 const DebugMapObject &DMO)
112 : Linker(Linker), SrcFileName(DMO.getObjectFilename()) {
113 findValidRelocsInDebugSections(Obj, DMO);
115 // Iterate over the debug map entries and put all the ones that are
116 // functions (because they have a size) into the Ranges map. This map is
117 // very similar to the FunctionRanges that are stored in each unit, with 2
118 // notable differences:
120 // 1. Obviously this one is global, while the other ones are per-unit.
122 // 2. This one contains not only the functions described in the DIE
123 // tree, but also the ones that are only in the debug map.
125 // The latter information is required to reproduce dsymutil's logic while
126 // linking line tables. The cases where this information matters look like
127 // bugs that need to be investigated, but for now we need to reproduce
128 // dsymutil's behavior.
129 // FIXME: Once we understood exactly if that information is needed,
130 // maybe totally remove this (or try to use it to do a real
131 // -gline-tables-only on Darwin.
132 for (const auto &Entry : DMO.symbols()) {
133 const auto &Mapping = Entry.getValue();
134 if (Mapping.Size && Mapping.ObjectAddress)
135 AddressRanges.insert(
136 {*Mapping.ObjectAddress, *Mapping.ObjectAddress + Mapping.Size},
137 int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
140 ~AddressManager() override { clear(); }
142 bool hasValidRelocs() override {
143 return !ValidDebugInfoRelocs.empty() || !ValidDebugAddrRelocs.empty();
146 /// \defgroup FindValidRelocations Translate debug map into a list
147 /// of relevant relocations
149 /// @{
150 bool findValidRelocsInDebugSections(const object::ObjectFile &Obj,
151 const DebugMapObject &DMO);
153 bool findValidRelocs(const object::SectionRef &Section,
154 const object::ObjectFile &Obj,
155 const DebugMapObject &DMO,
156 std::vector<ValidReloc> &ValidRelocs);
158 void findValidRelocsMachO(const object::SectionRef &Section,
159 const object::MachOObjectFile &Obj,
160 const DebugMapObject &DMO,
161 std::vector<ValidReloc> &ValidRelocs);
162 /// @}
164 /// Checks that there is a relocation in the \p Relocs array against a
165 /// debug map entry between \p StartOffset and \p NextOffset.
167 /// \returns true and sets Info.InDebugMap if it is the case.
168 bool hasValidRelocationAt(const std::vector<ValidReloc> &Relocs,
169 uint64_t StartOffset, uint64_t EndOffset,
170 CompileUnit::DIEInfo &Info);
172 bool isLiveVariable(const DWARFDie &DIE,
173 CompileUnit::DIEInfo &Info) override;
174 bool isLiveSubprogram(const DWARFDie &DIE,
175 CompileUnit::DIEInfo &Info) override;
177 bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
178 bool IsLittleEndian) override;
180 llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t StartOffset,
181 uint64_t EndOffset) override;
183 RangesTy &getValidAddressRanges() override { return AddressRanges; }
185 void clear() override {
186 AddressRanges.clear();
187 ValidDebugInfoRelocs.clear();
188 ValidDebugAddrRelocs.clear();
192 private:
193 /// \defgroup Helpers Various helper methods.
195 /// @{
196 bool createStreamer(const Triple &TheTriple, raw_fd_ostream &OutFile);
198 /// Attempt to load a debug object from disk.
199 ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
200 const Triple &triple);
201 ErrorOr<DWARFFile &> loadObject(const DebugMapObject &Obj,
202 const DebugMap &DebugMap,
203 remarks::RemarkLinker &RL);
205 void collectRelocationsToApplyToSwiftReflectionSections(
206 const object::SectionRef &Section, StringRef &Contents,
207 const llvm::object::MachOObjectFile *MO,
208 const std::vector<uint64_t> &SectionToOffsetInDwarf,
209 const llvm::dsymutil::DebugMapObject *Obj,
210 std::vector<MachOUtils::DwarfRelocationApplicationInfo>
211 &RelocationsToApply) const;
213 void copySwiftReflectionMetadata(
214 const llvm::dsymutil::DebugMapObject *Obj, DwarfStreamer *Streamer,
215 std::vector<uint64_t> &SectionToOffsetInDwarf,
216 std::vector<MachOUtils::DwarfRelocationApplicationInfo>
217 &RelocationsToApply);
219 raw_fd_ostream &OutFile;
220 BinaryHolder &BinHolder;
221 LinkOptions Options;
222 std::unique_ptr<DwarfStreamer> Streamer;
223 std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking;
224 std::vector<std::unique_ptr<DWARFContext>> ContextForLinking;
225 std::vector<std::unique_ptr<AddressManager>> AddressMapForLinking;
226 std::vector<std::string> EmptyWarnings;
228 /// A list of all .swiftinterface files referenced by the debug
229 /// info, mapping Module name to path on disk. The entries need to
230 /// be uniqued and sorted and there are only few entries expected
231 /// per compile unit, which is why this is a std::map.
232 std::map<std::string, std::string> ParseableSwiftInterfaces;
234 bool ModuleCacheHintDisplayed = false;
235 bool ArchiveHintDisplayed = false;
238 } // end namespace dsymutil
239 } // end namespace llvm
241 #endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H