DwarfLinkerForBinary.h 9.3 KB

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