Fix test failures introduced by PR #113697 (#116941)
[llvm-project.git] / llvm / tools / dsymutil / DwarfLinkerForBinary.h
blob53f9e183ebe88d2b787565de2ea1a7e8e511fcb3
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 "RelocationMap.h"
17 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
18 #include "llvm/Remarks/RemarkFormat.h"
19 #include "llvm/Remarks/RemarkLinker.h"
20 #include <mutex>
21 #include <optional>
23 namespace llvm {
24 using namespace dwarf_linker;
26 namespace dsymutil {
28 /// DwarfLinkerForBinaryRelocationMap contains the logic to handle the
29 /// relocations and to store them inside an associated RelocationMap.
30 class DwarfLinkerForBinaryRelocationMap {
31 public:
32 void init(DWARFContext &Context);
34 bool isInitialized() {
35 return StoredValidDebugInfoRelocsMap.getMemorySize() != 0;
38 void addValidRelocs(RelocationMap &RM);
40 void updateAndSaveValidRelocs(bool IsDWARF5,
41 std::vector<ValidReloc> &InRelocs,
42 uint64_t UnitOffset, int64_t LinkedOffset);
44 void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
45 uint64_t OutputUnitOffset);
47 /// Map compilation unit offset to the valid relocations to store
48 /// @{
49 DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugInfoRelocsMap;
50 DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugAddrRelocsMap;
51 /// @}
53 DwarfLinkerForBinaryRelocationMap() = default;
56 struct ObjectWithRelocMap {
57 ObjectWithRelocMap(
58 std::unique_ptr<DWARFFile> Object,
59 std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs)
60 : Object(std::move(Object)), OutRelocs(OutRelocs) {}
61 std::unique_ptr<DWARFFile> Object;
62 std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs;
65 /// The core of the Dsymutil Dwarf linking logic.
66 ///
67 /// The link of the dwarf information from the object files will be
68 /// driven by DWARFLinker. DwarfLinkerForBinary reads DebugMap objects
69 /// and pass information to the DWARFLinker. DWARFLinker
70 /// optimizes DWARF taking into account valid relocations.
71 /// Finally, optimized DWARF is passed to DwarfLinkerForBinary through
72 /// DWARFEmitter interface.
73 class DwarfLinkerForBinary {
74 public:
75 DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
76 LinkOptions Options, std::mutex &ErrorHandlerMutex)
77 : OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)),
78 ErrorHandlerMutex(ErrorHandlerMutex) {}
80 /// Link the contents of the DebugMap.
81 bool link(const DebugMap &);
83 void reportWarning(Twine Warning, Twine Context = {},
84 const DWARFDie *DIE = nullptr) const;
85 void reportError(Twine Error, Twine Context = {},
86 const DWARFDie *DIE = nullptr) const;
88 /// Returns true if input verification is enabled and verification errors were
89 /// found.
90 bool InputVerificationFailed() const { return HasVerificationErrors; }
92 /// Flags passed to DwarfLinker::lookForDIEsToKeep
93 enum TraversalFlags {
94 TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
95 TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
96 TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
97 TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
98 TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
99 TF_SkipPC = 1 << 5, ///< Skip all location attributes.
102 private:
104 /// Keeps track of relocations.
105 class AddressManager : public dwarf_linker::AddressesMap {
107 const DwarfLinkerForBinary &Linker;
109 /// The valid relocations for the current DebugMapObject.
110 /// These vectors are sorted by relocation offset.
111 /// {
112 std::vector<ValidReloc> ValidDebugInfoRelocs;
113 std::vector<ValidReloc> ValidDebugAddrRelocs;
114 /// }
116 StringRef SrcFileName;
118 uint8_t DebugMapObjectType;
120 std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DwarfLinkerRelocMap;
122 std::optional<std::string> LibInstallName;
124 /// Returns list of valid relocations from \p Relocs,
125 /// between \p StartOffset and \p NextOffset.
127 /// \returns true if any relocation is found.
128 std::vector<ValidReloc>
129 getRelocations(const std::vector<ValidReloc> &Relocs, uint64_t StartPos,
130 uint64_t EndPos);
132 /// Resolve specified relocation \p Reloc.
134 /// \returns resolved value.
135 uint64_t relocate(const ValidReloc &Reloc) const;
137 /// \returns value for the specified \p Reloc.
138 int64_t getRelocValue(const ValidReloc &Reloc);
140 /// Print contents of debug map entry for the specified \p Reloc.
141 void printReloc(const ValidReloc &Reloc);
143 public:
144 AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
145 const DebugMapObject &DMO,
146 std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM)
147 : Linker(Linker), SrcFileName(DMO.getObjectFilename()),
148 DebugMapObjectType(MachO::N_OSO), DwarfLinkerRelocMap(DLBRM) {
149 if (DMO.getRelocationMap().has_value()) {
150 DebugMapObjectType = MachO::N_LIB;
151 LibInstallName.emplace(DMO.getInstallName().value());
152 const RelocationMap &RM = DMO.getRelocationMap().value();
153 for (const auto &Reloc : RM.relocations()) {
154 const auto *DebugMapEntry = DMO.lookupSymbol(Reloc.SymbolName);
155 if (!DebugMapEntry)
156 continue;
157 std::optional<uint64_t> ObjAddress;
158 ObjAddress.emplace(DebugMapEntry->getValue().ObjectAddress.value());
159 ValidDebugInfoRelocs.emplace_back(
160 Reloc.Offset, Reloc.Size, Reloc.Addend, Reloc.SymbolName,
161 SymbolMapping(ObjAddress, DebugMapEntry->getValue().BinaryAddress,
162 DebugMapEntry->getValue().Size));
163 // FIXME: Support relocations debug_addr.
165 } else {
166 findValidRelocsInDebugSections(Obj, DMO);
169 ~AddressManager() override { clear(); }
171 bool hasValidRelocs() override {
172 return !ValidDebugInfoRelocs.empty() || !ValidDebugAddrRelocs.empty();
175 /// \defgroup FindValidRelocations Translate debug map into a list
176 /// of relevant relocations
178 /// @{
179 bool findValidRelocsInDebugSections(const object::ObjectFile &Obj,
180 const DebugMapObject &DMO);
182 bool findValidRelocs(const object::SectionRef &Section,
183 const object::ObjectFile &Obj,
184 const DebugMapObject &DMO,
185 std::vector<ValidReloc> &ValidRelocs);
187 void findValidRelocsMachO(const object::SectionRef &Section,
188 const object::MachOObjectFile &Obj,
189 const DebugMapObject &DMO,
190 std::vector<ValidReloc> &ValidRelocs);
191 /// @}
193 /// Checks that there is a relocation in the \p Relocs array against a
194 /// debug map entry between \p StartOffset and \p NextOffset.
195 /// Print debug output if \p Verbose is set.
197 /// \returns relocation value if relocation exist, otherwise std::nullopt.
198 std::optional<int64_t>
199 hasValidRelocationAt(const std::vector<ValidReloc> &Relocs,
200 uint64_t StartOffset, uint64_t EndOffset,
201 bool Verbose);
203 std::optional<int64_t> getExprOpAddressRelocAdjustment(
204 DWARFUnit &U, const DWARFExpression::Operation &Op,
205 uint64_t StartOffset, uint64_t EndOffset, bool Verbose) override;
207 std::optional<int64_t> getSubprogramRelocAdjustment(const DWARFDie &DIE,
208 bool Verbose) override;
210 std::optional<StringRef> getLibraryInstallName() override;
212 bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
213 bool IsLittleEndian) override;
215 bool needToSaveValidRelocs() override { return true; }
217 void updateAndSaveValidRelocs(bool IsDWARF5, uint64_t OriginalUnitOffset,
218 int64_t LinkedOffset, uint64_t StartOffset,
219 uint64_t EndOffset) override;
221 void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
222 uint64_t OutputUnitOffset) override;
224 void clear() override {
225 ValidDebugInfoRelocs.clear();
226 ValidDebugAddrRelocs.clear();
230 private:
231 /// \defgroup Helpers Various helper methods.
233 /// @{
234 template <typename OutStreamer>
235 bool createStreamer(const Triple &TheTriple,
236 typename OutStreamer::OutputFileType FileType,
237 std::unique_ptr<OutStreamer> &Streamer,
238 raw_fd_ostream &OutFile);
240 /// Attempt to load a debug object from disk.
241 ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
242 const Triple &triple);
243 ErrorOr<std::unique_ptr<dwarf_linker::DWARFFile>>
244 loadObject(const DebugMapObject &Obj, const DebugMap &DebugMap,
245 remarks::RemarkLinker &RL,
246 std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM);
248 void collectRelocationsToApplyToSwiftReflectionSections(
249 const object::SectionRef &Section, StringRef &Contents,
250 const llvm::object::MachOObjectFile *MO,
251 const std::vector<uint64_t> &SectionToOffsetInDwarf,
252 const llvm::dsymutil::DebugMapObject *Obj,
253 std::vector<MachOUtils::DwarfRelocationApplicationInfo>
254 &RelocationsToApply) const;
256 Error copySwiftInterfaces(StringRef Architecture) const;
258 void copySwiftReflectionMetadata(
259 const llvm::dsymutil::DebugMapObject *Obj,
260 classic::DwarfStreamer *Streamer,
261 std::vector<uint64_t> &SectionToOffsetInDwarf,
262 std::vector<MachOUtils::DwarfRelocationApplicationInfo>
263 &RelocationsToApply);
265 template <typename Linker>
266 bool linkImpl(const DebugMap &Map,
267 typename Linker::OutputFileType ObjectType);
269 Error emitRelocations(const DebugMap &DM,
270 std::vector<ObjectWithRelocMap> &ObjectsForLinking);
272 raw_fd_ostream &OutFile;
273 BinaryHolder &BinHolder;
274 LinkOptions Options;
275 std::mutex &ErrorHandlerMutex;
277 std::vector<std::string> EmptyWarnings;
279 /// A list of all .swiftinterface files referenced by the debug
280 /// info, mapping Module name to path on disk. The entries need to
281 /// be uniqued and sorted and there are only few entries expected
282 /// per compile unit, which is why this is a std::map.
283 std::map<std::string, std::string> ParseableSwiftInterfaces;
285 bool ModuleCacheHintDisplayed = false;
286 bool ArchiveHintDisplayed = false;
287 bool HasVerificationErrors = false;
290 } // end namespace dsymutil
291 } // end namespace llvm
293 #endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H