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