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