DwarfLinkerForBinary.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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 "llvm/DWARFLinker/DWARFLinker.h"
  14. #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
  15. #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
  16. #include "llvm/DWARFLinker/DWARFStreamer.h"
  17. #include "llvm/DebugInfo/DWARF/DWARFContext.h"
  18. #include "llvm/Remarks/RemarkFormat.h"
  19. #include "llvm/Remarks/RemarkLinker.h"
  20. namespace llvm {
  21. namespace dsymutil {
  22. /// The core of the Dsymutil Dwarf linking logic.
  23. ///
  24. /// The link of the dwarf information from the object files will be
  25. /// driven by DWARFLinker. DwarfLinkerForBinary reads DebugMap objects
  26. /// and pass information to the DWARFLinker. DWARFLinker
  27. /// optimizes DWARF taking into account valid relocations.
  28. /// Finally, optimized DWARF is passed to DwarfLinkerForBinary through
  29. /// DWARFEmitter interface.
  30. class DwarfLinkerForBinary {
  31. public:
  32. DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
  33. LinkOptions Options)
  34. : OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)) {}
  35. /// Link the contents of the DebugMap.
  36. bool link(const DebugMap &);
  37. void reportWarning(const Twine &Warning, StringRef Context,
  38. const DWARFDie *DIE = nullptr) const;
  39. /// Flags passed to DwarfLinker::lookForDIEsToKeep
  40. enum TraversalFlags {
  41. TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
  42. TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
  43. TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
  44. TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
  45. TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
  46. TF_SkipPC = 1 << 5, ///< Skip all location attributes.
  47. };
  48. private:
  49. /// Keeps track of relocations.
  50. class AddressManager : public AddressesMap {
  51. struct ValidReloc {
  52. uint64_t Offset;
  53. uint32_t Size;
  54. uint64_t Addend;
  55. const DebugMapObject::DebugMapEntry *Mapping;
  56. ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
  57. const DebugMapObject::DebugMapEntry *Mapping)
  58. : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
  59. bool operator<(const ValidReloc &RHS) const {
  60. return Offset < RHS.Offset;
  61. }
  62. bool operator<(uint64_t RHS) const { return Offset < RHS; }
  63. };
  64. const DwarfLinkerForBinary &Linker;
  65. /// The valid relocations for the current DebugMapObject.
  66. /// This vector is sorted by relocation offset.
  67. /// {
  68. std::vector<ValidReloc> ValidDebugInfoRelocs;
  69. std::vector<ValidReloc> ValidDebugAddrRelocs;
  70. /// }
  71. RangesTy AddressRanges;
  72. StringRef SrcFileName;
  73. /// Returns list of valid relocations from \p Relocs,
  74. /// between \p StartOffset and \p NextOffset.
  75. ///
  76. /// \returns true if any relocation is found.
  77. std::vector<ValidReloc>
  78. getRelocations(const std::vector<ValidReloc> &Relocs, uint64_t StartPos,
  79. uint64_t EndPos);
  80. /// Resolve specified relocation \p Reloc.
  81. ///
  82. /// \returns resolved value.
  83. uint64_t relocate(const ValidReloc &Reloc) const;
  84. /// Fill \p Info with address information for the specified \p Reloc.
  85. void fillDieInfo(const ValidReloc &Reloc, CompileUnit::DIEInfo &Info);
  86. /// Print contents of debug map entry for the specified \p Reloc.
  87. void printReloc(const ValidReloc &Reloc);
  88. public:
  89. AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
  90. const DebugMapObject &DMO)
  91. : Linker(Linker), SrcFileName(DMO.getObjectFilename()) {
  92. findValidRelocsInDebugSections(Obj, DMO);
  93. // Iterate over the debug map entries and put all the ones that are
  94. // functions (because they have a size) into the Ranges map. This map is
  95. // very similar to the FunctionRanges that are stored in each unit, with 2
  96. // notable differences:
  97. //
  98. // 1. Obviously this one is global, while the other ones are per-unit.
  99. //
  100. // 2. This one contains not only the functions described in the DIE
  101. // tree, but also the ones that are only in the debug map.
  102. //
  103. // The latter information is required to reproduce dsymutil's logic while
  104. // linking line tables. The cases where this information matters look like
  105. // bugs that need to be investigated, but for now we need to reproduce
  106. // dsymutil's behavior.
  107. // FIXME: Once we understood exactly if that information is needed,
  108. // maybe totally remove this (or try to use it to do a real
  109. // -gline-tables-only on Darwin.
  110. for (const auto &Entry : DMO.symbols()) {
  111. const auto &Mapping = Entry.getValue();
  112. if (Mapping.Size && Mapping.ObjectAddress)
  113. AddressRanges[*Mapping.ObjectAddress] = ObjFileAddressRange(
  114. *Mapping.ObjectAddress + Mapping.Size,
  115. int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
  116. }
  117. }
  118. virtual ~AddressManager() override { clear(); }
  119. virtual bool areRelocationsResolved() const override { return true; }
  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 hasLiveMemoryLocation(const DWARFDie &DIE,
  146. CompileUnit::DIEInfo &Info) override;
  147. bool hasLiveAddressRange(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. raw_fd_ostream &OutFile;
  172. BinaryHolder &BinHolder;
  173. LinkOptions Options;
  174. std::unique_ptr<DwarfStreamer> Streamer;
  175. std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking;
  176. std::vector<std::unique_ptr<DWARFContext>> ContextForLinking;
  177. std::vector<std::unique_ptr<AddressManager>> AddressMapForLinking;
  178. std::vector<std::string> EmptyWarnings;
  179. /// A list of all .swiftinterface files referenced by the debug
  180. /// info, mapping Module name to path on disk. The entries need to
  181. /// be uniqued and sorted and there are only few entries expected
  182. /// per compile unit, which is why this is a std::map.
  183. std::map<std::string, std::string> ParseableSwiftInterfaces;
  184. bool ModuleCacheHintDisplayed = false;
  185. bool ArchiveHintDisplayed = false;
  186. };
  187. } // end namespace dsymutil
  188. } // end namespace llvm
  189. #endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H