xref: /openbsd/gnu/llvm/llvm/tools/dsymutil/DebugMap.h (revision d415bd75)
1 //=- tools/dsymutil/DebugMap.h - Generic debug map representation -*- 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 //
9 /// \file
10 ///
11 /// This file contains the class declaration of the DebugMap
12 /// entity. A DebugMap lists all the object files linked together to
13 /// produce an executable along with the linked address of all the
14 /// atoms used in these object files.
15 /// The DebugMap is an input to the DwarfLinker class that will
16 /// extract the Dwarf debug information from the referenced object
17 /// files and link their usefull debug info together.
18 //
19 //===----------------------------------------------------------------------===//
20 
21 #ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
22 #define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
23 
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/ADT/StringMap.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/ADT/Triple.h"
28 #include "llvm/ADT/iterator_range.h"
29 #include "llvm/Object/MachO.h"
30 #include "llvm/Support/Chrono.h"
31 #include "llvm/Support/ErrorOr.h"
32 #include "llvm/Support/YAMLTraits.h"
33 #include <chrono>
34 #include <cstddef>
35 #include <cstdint>
36 #include <memory>
37 #include <optional>
38 #include <string>
39 #include <utility>
40 #include <vector>
41 
42 namespace llvm {
43 
44 class raw_ostream;
45 
46 namespace dsymutil {
47 
48 class DebugMapObject;
49 
50 /// The DebugMap object stores the list of object files to query for debug
51 /// information along with the mapping between the symbols' addresses in the
52 /// object file to their linked address in the linked binary.
53 ///
54 /// A DebugMap producer could look like this:
55 /// DebugMap *DM = new DebugMap();
56 /// for (const auto &Obj: LinkedObjects) {
57 ///     DebugMapObject &DMO = DM->addDebugMapObject(Obj.getPath());
58 ///     for (const auto &Sym: Obj.getLinkedSymbols())
59 ///         DMO.addSymbol(Sym.getName(), Sym.getObjectFileAddress(),
60 ///                       Sym.getBinaryAddress());
61 /// }
62 ///
63 /// A DebugMap consumer can then use the map to link the debug
64 /// information. For example something along the lines of:
65 /// for (const auto &DMO: DM->objects()) {
66 ///     auto Obj = createBinary(DMO.getObjectFilename());
67 ///     for (auto &DIE: Obj.getDwarfDIEs()) {
68 ///         if (SymbolMapping *Sym = DMO.lookup(DIE.getName()))
69 ///             DIE.relocate(Sym->ObjectAddress, Sym->BinaryAddress);
70 ///         else
71 ///             DIE.discardSubtree();
72 ///     }
73 /// }
74 class DebugMap {
75   Triple BinaryTriple;
76   std::string BinaryPath;
77   std::vector<uint8_t> BinaryUUID;
78   using ObjectContainer = std::vector<std::unique_ptr<DebugMapObject>>;
79 
80   ObjectContainer Objects;
81 
82   /// For YAML IO support.
83   ///@{
84   friend yaml::MappingTraits<std::unique_ptr<DebugMap>>;
85   friend yaml::MappingTraits<DebugMap>;
86 
87   DebugMap() = default;
88   ///@}
89 
90 public:
91   DebugMap(const Triple &BinaryTriple, StringRef BinaryPath,
92            ArrayRef<uint8_t> BinaryUUID = ArrayRef<uint8_t>())
BinaryTriple(BinaryTriple)93       : BinaryTriple(BinaryTriple), BinaryPath(std::string(BinaryPath)),
94         BinaryUUID(BinaryUUID.begin(), BinaryUUID.end()) {}
95 
96   using const_iterator = ObjectContainer::const_iterator;
97 
objects()98   iterator_range<const_iterator> objects() const {
99     return make_range(begin(), end());
100   }
101 
begin()102   const_iterator begin() const { return Objects.begin(); }
103 
end()104   const_iterator end() const { return Objects.end(); }
105 
getNumberOfObjects()106   unsigned getNumberOfObjects() const { return Objects.size(); }
107 
108   /// This function adds an DebugMapObject to the list owned by this
109   /// debug map.
110   DebugMapObject &
111   addDebugMapObject(StringRef ObjectFilePath,
112                     sys::TimePoint<std::chrono::seconds> Timestamp,
113                     uint8_t Type = llvm::MachO::N_OSO);
114 
getTriple()115   const Triple &getTriple() const { return BinaryTriple; }
116 
getUUID()117   ArrayRef<uint8_t> getUUID() const { return ArrayRef<uint8_t>(BinaryUUID); }
118 
getBinaryPath()119   StringRef getBinaryPath() const { return BinaryPath; }
120 
121   void print(raw_ostream &OS) const;
122 
123 #ifndef NDEBUG
124   void dump() const;
125 #endif
126 
127   /// Read a debug map for \a InputFile.
128   static ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
129   parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose);
130 };
131 
132 /// The DebugMapObject represents one object file described by the DebugMap. It
133 /// contains a list of mappings between addresses in the object file and in the
134 /// linked binary for all the linked atoms in this object file.
135 class DebugMapObject {
136 public:
137   struct SymbolMapping {
138     std::optional<yaml::Hex64> ObjectAddress;
139     yaml::Hex64 BinaryAddress;
140     yaml::Hex32 Size;
141 
SymbolMappingSymbolMapping142     SymbolMapping(std::optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
143                   uint32_t Size)
144         : BinaryAddress(BinaryAddress), Size(Size) {
145       if (ObjectAddr)
146         ObjectAddress = *ObjectAddr;
147     }
148 
149     /// For YAML IO support
150     SymbolMapping() = default;
151   };
152 
153   using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
154   using DebugMapEntry = StringMapEntry<SymbolMapping>;
155 
156   /// Adds a symbol mapping to this DebugMapObject.
157   /// \returns false if the symbol was already registered. The request
158   /// is discarded in this case.
159   bool addSymbol(StringRef SymName, std::optional<uint64_t> ObjectAddress,
160                  uint64_t LinkedAddress, uint32_t Size);
161 
162   /// Lookup a symbol mapping.
163   /// \returns null if the symbol isn't found.
164   const DebugMapEntry *lookupSymbol(StringRef SymbolName) const;
165 
166   /// Lookup an object file address.
167   /// \returns null if the address isn't found.
168   const DebugMapEntry *lookupObjectAddress(uint64_t Address) const;
169 
getObjectFilename()170   StringRef getObjectFilename() const { return Filename; }
171 
getTimestamp()172   sys::TimePoint<std::chrono::seconds> getTimestamp() const {
173     return Timestamp;
174   }
175 
getType()176   uint8_t getType() const { return Type; }
177 
symbols()178   iterator_range<StringMap<SymbolMapping>::const_iterator> symbols() const {
179     return make_range(Symbols.begin(), Symbols.end());
180   }
181 
empty()182   bool empty() const { return Symbols.empty(); }
183 
addWarning(StringRef Warning)184   void addWarning(StringRef Warning) {
185     Warnings.push_back(std::string(Warning));
186   }
getWarnings()187   const std::vector<std::string> &getWarnings() const { return Warnings; }
188 
189   void print(raw_ostream &OS) const;
190 #ifndef NDEBUG
191   void dump() const;
192 #endif
193 
194 private:
195   friend class DebugMap;
196 
197   /// DebugMapObjects can only be constructed by the owning DebugMap.
198   DebugMapObject(StringRef ObjectFilename,
199                  sys::TimePoint<std::chrono::seconds> Timestamp, uint8_t Type);
200 
201   std::string Filename;
202   sys::TimePoint<std::chrono::seconds> Timestamp;
203   StringMap<SymbolMapping> Symbols;
204   DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
205   uint8_t Type;
206 
207   std::vector<std::string> Warnings;
208 
209   /// For YAMLIO support.
210   ///@{
211   friend yaml::MappingTraits<dsymutil::DebugMapObject>;
212   friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>;
213 
214   DebugMapObject() = default;
215 
216 public:
217   DebugMapObject(DebugMapObject &&) = default;
218   DebugMapObject &operator=(DebugMapObject &&) = default;
219   ///@}
220 };
221 
222 } // end namespace dsymutil
223 } // end namespace llvm
224 
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping)225 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping)
226 
227 namespace llvm {
228 namespace yaml {
229 
230 using namespace llvm::dsymutil;
231 
232 template <>
233 struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
234   static void mapping(IO &io,
235                       std::pair<std::string, DebugMapObject::SymbolMapping> &s);
236   static const bool flow = true;
237 };
238 
239 template <> struct MappingTraits<dsymutil::DebugMapObject> {
240   struct YamlDMO;
241   static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
242 };
243 
244 template <> struct ScalarTraits<Triple> {
245   static void output(const Triple &val, void *, raw_ostream &out);
246   static StringRef input(StringRef scalar, void *, Triple &value);
247   static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
248 };
249 
250 template <>
251 struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
252   static size_t
253   size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq);
254   static dsymutil::DebugMapObject &
255   element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
256           size_t index);
257 };
258 
259 template <> struct MappingTraits<dsymutil::DebugMap> {
260   static void mapping(IO &io, dsymutil::DebugMap &DM);
261 };
262 
263 template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> {
264   static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM);
265 };
266 
267 } // end namespace yaml
268 } // end namespace llvm
269 
270 #endif // LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
271