blob: 8d76f113e91e01bfd422c890b101fd3f5bf720e8 [file] [log] [blame]
Frederic Riss231f7142014-12-12 17:31:24 +00001//===- tools/dsymutil/DebugMap.h - Generic debug map representation -------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11///
12/// This file contains the class declaration of the DebugMap
13/// entity. A DebugMap lists all the object files linked together to
14/// produce an executable along with the linked address of all the
15/// atoms used in these object files.
16/// The DebugMap is an input to the DwarfLinker class that will
17/// extract the Dwarf debug information from the referenced object
18/// files and link their usefull debug info together.
19///
20//===----------------------------------------------------------------------===//
21#ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
22#define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
23
Frederic Riss1595c5d2015-02-13 23:18:16 +000024#include "llvm/ADT/DenseMap.h"
Frederic Riss231f7142014-12-12 17:31:24 +000025#include "llvm/ADT/StringMap.h"
Frederic Risse4a6fef2015-01-19 23:33:14 +000026#include "llvm/ADT/Triple.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000027#include "llvm/ADT/iterator_range.h"
Frederic Riss231f7142014-12-12 17:31:24 +000028#include "llvm/Object/ObjectFile.h"
29#include "llvm/Support/ErrorOr.h"
30#include "llvm/Support/Format.h"
Frederic Riss08462f72015-06-01 21:12:45 +000031#include "llvm/Support/YAMLTraits.h"
Frederic Riss231f7142014-12-12 17:31:24 +000032#include <vector>
33
34namespace llvm {
35class raw_ostream;
36
37namespace dsymutil {
38class DebugMapObject;
39
40/// \brief The DebugMap object stores the list of object files to
41/// query for debug information along with the mapping between the
42/// symbols' addresses in the object file to their linked address in
43/// the linked binary.
44///
45/// A DebugMap producer could look like this:
46/// DebugMap *DM = new DebugMap();
47/// for (const auto &Obj: LinkedObjects) {
48/// DebugMapObject &DMO = DM->addDebugMapObject(Obj.getPath());
49/// for (const auto &Sym: Obj.getLinkedSymbols())
50/// DMO.addSymbol(Sym.getName(), Sym.getObjectFileAddress(),
51/// Sym.getBinaryAddress());
52/// }
53///
54/// A DebugMap consumer can then use the map to link the debug
55/// information. For example something along the lines of:
56/// for (const auto &DMO: DM->objects()) {
57/// auto Obj = createBinary(DMO.getObjectFilename());
58/// for (auto &DIE: Obj.getDwarfDIEs()) {
59/// if (SymbolMapping *Sym = DMO.lookup(DIE.getName()))
60/// DIE.relocate(Sym->ObjectAddress, Sym->BinaryAddress);
61/// else
62/// DIE.discardSubtree();
63/// }
64/// }
65class DebugMap {
Frederic Risse4a6fef2015-01-19 23:33:14 +000066 Triple BinaryTriple;
Frederic Riss231f7142014-12-12 17:31:24 +000067 typedef std::vector<std::unique_ptr<DebugMapObject>> ObjectContainer;
68 ObjectContainer Objects;
69
Frederic Riss08462f72015-06-01 21:12:45 +000070 /// For YAML IO support.
71 ///@{
72 friend yaml::MappingTraits<DebugMap>;
73 DebugMap() = default;
74 ///@}
Frederic Riss231f7142014-12-12 17:31:24 +000075public:
Frederic Risse4a6fef2015-01-19 23:33:14 +000076 DebugMap(const Triple &BinaryTriple) : BinaryTriple(BinaryTriple) {}
77
Frederic Riss231f7142014-12-12 17:31:24 +000078 typedef ObjectContainer::const_iterator const_iterator;
79
80 iterator_range<const_iterator> objects() const {
81 return make_range(begin(), end());
82 }
83
84 const_iterator begin() const { return Objects.begin(); }
85
86 const_iterator end() const { return Objects.end(); }
87
88 /// This function adds an DebugMapObject to the list owned by this
89 /// debug map.
90 DebugMapObject &addDebugMapObject(StringRef ObjectFilePath);
91
Frederic Riss717354f2015-02-28 00:28:56 +000092 const Triple &getTriple() const { return BinaryTriple; }
Frederic Risse4a6fef2015-01-19 23:33:14 +000093
Frederic Riss231f7142014-12-12 17:31:24 +000094 void print(raw_ostream &OS) const;
95
96#ifndef NDEBUG
97 void dump() const;
98#endif
99};
100
101/// \brief The DebugMapObject represents one object file described by
102/// the DebugMap. It contains a list of mappings between addresses in
103/// the object file and in the linked binary for all the linked atoms
104/// in this object file.
105class DebugMapObject {
106public:
107 struct SymbolMapping {
Frederic Riss08462f72015-06-01 21:12:45 +0000108 yaml::Hex64 ObjectAddress;
109 yaml::Hex64 BinaryAddress;
110 yaml::Hex32 Size;
Frederic Riss912d0f12015-03-15 01:29:30 +0000111 SymbolMapping(uint64_t ObjectAddress, uint64_t BinaryAddress, uint32_t Size)
112 : ObjectAddress(ObjectAddress), BinaryAddress(BinaryAddress),
113 Size(Size) {}
Frederic Riss08462f72015-06-01 21:12:45 +0000114 /// For YAML IO support
115 SymbolMapping() = default;
Frederic Riss231f7142014-12-12 17:31:24 +0000116 };
117
Frederic Riss1595c5d2015-02-13 23:18:16 +0000118 typedef StringMapEntry<SymbolMapping> DebugMapEntry;
119
Frederic Riss231f7142014-12-12 17:31:24 +0000120 /// \brief Adds a symbol mapping to this DebugMapObject.
121 /// \returns false if the symbol was already registered. The request
122 /// is discarded in this case.
123 bool addSymbol(llvm::StringRef SymName, uint64_t ObjectAddress,
Frederic Riss912d0f12015-03-15 01:29:30 +0000124 uint64_t LinkedAddress, uint32_t Size);
Frederic Riss231f7142014-12-12 17:31:24 +0000125
Benjamin Kramer342554f2014-12-13 19:19:07 +0000126 /// \brief Lookup a symbol mapping.
Frederic Riss231f7142014-12-12 17:31:24 +0000127 /// \returns null if the symbol isn't found.
Frederic Riss1595c5d2015-02-13 23:18:16 +0000128 const DebugMapEntry *lookupSymbol(StringRef SymbolName) const;
129
130 /// \brief Lookup an objectfile address.
131 /// \returns null if the address isn't found.
132 const DebugMapEntry *lookupObjectAddress(uint64_t Address) const;
Frederic Riss231f7142014-12-12 17:31:24 +0000133
134 llvm::StringRef getObjectFilename() const { return Filename; }
135
Frederic Rissb0464082015-03-15 02:02:53 +0000136 iterator_range<StringMap<SymbolMapping>::const_iterator> symbols() const {
137 return make_range(Symbols.begin(), Symbols.end());
138 }
139
Frederic Riss231f7142014-12-12 17:31:24 +0000140 void print(raw_ostream &OS) const;
141#ifndef NDEBUG
142 void dump() const;
143#endif
144private:
145 friend class DebugMap;
146 /// DebugMapObjects can only be constructed by the owning DebugMap.
147 DebugMapObject(StringRef ObjectFilename);
148
149 std::string Filename;
150 StringMap<SymbolMapping> Symbols;
Frederic Riss1595c5d2015-02-13 23:18:16 +0000151 DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
Frederic Riss08462f72015-06-01 21:12:45 +0000152
153 /// For YAMLIO support.
154 ///@{
155 typedef std::pair<std::string, SymbolMapping> YAMLSymbolMapping;
156 friend yaml::MappingTraits<dsymutil::DebugMapObject>;
157 friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>;
158 friend yaml::SequenceTraits<std::vector<YAMLSymbolMapping>>;
159 DebugMapObject() = default;
160 ///@}
161};
162}
163}
164
Frederic Riss88ad8d22015-06-01 21:25:53 +0000165LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping)
Frederic Riss08462f72015-06-01 21:12:45 +0000166
167namespace llvm {
168namespace yaml {
169
170using namespace llvm::dsymutil;
171
172template <>
173struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
174
175 static void
176 mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
177 io.mapRequired("sym", s.first);
178 io.mapRequired("objAddr", s.second.ObjectAddress);
179 io.mapRequired("binAddr", s.second.BinaryAddress);
180 io.mapOptional("size", s.second.Size);
181 }
182
183 static const bool flow = true;
184};
185
186template <> struct MappingTraits<dsymutil::DebugMapObject> {
187 typedef StringMap<dsymutil::DebugMapObject::SymbolMapping> SymbolMap;
188
189 struct SequencedStringMap {
190 SequencedStringMap(IO &io) {}
191
192 SequencedStringMap(IO &io, SymbolMap &Map) {
193 Entries.reserve(Map.size());
194 for (auto &Entry : Map)
195 Entries.push_back(std::make_pair(Entry.getKey(), Entry.getValue()));
196 }
197
198 SymbolMap denormalize(IO &) {
199 SymbolMap Res;
200
201 for (auto &Entry : Entries)
202 Res[Entry.first] = Entry.second;
203
Frederic Rissf30ad9bb2015-06-01 22:03:05 +0000204 return Res;
Frederic Riss08462f72015-06-01 21:12:45 +0000205 }
206
207 std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
208 };
209
210 static void mapping(IO &io, dsymutil::DebugMapObject &s) {
211 MappingNormalization<SequencedStringMap, SymbolMap> seq(io, s.Symbols);
212 io.mapRequired("filename", s.Filename);
213 io.mapRequired("symbols", seq->Entries);
214 }
215};
216
217template <> struct ScalarTraits<Triple> {
218
219 static void output(const Triple &val, void *, llvm::raw_ostream &out) {
220 out << val.str();
221 }
222
223 static StringRef input(StringRef scalar, void *, Triple &value) {
224 value = Triple(scalar);
225 return value.str();
226 }
227
228 static bool mustQuote(StringRef) { return true; }
229};
230
231template <>
232struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
233
234 static size_t
235 size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq) {
236 return seq.size();
237 }
238
239 static dsymutil::DebugMapObject &
240 element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
241 size_t index) {
242 if (index >= seq.size()) {
243 seq.resize(index + 1);
244 seq[index].reset(new dsymutil::DebugMapObject);
245 }
246 return *seq[index];
247 }
248};
249
250template <> struct MappingTraits<dsymutil::DebugMap> {
251 static void mapping(IO &io, dsymutil::DebugMap &DM) {
252 io.mapRequired("triple", DM.BinaryTriple);
253 io.mapOptional("objects", DM.Objects);
254 }
Frederic Riss231f7142014-12-12 17:31:24 +0000255};
256}
257}
258
259#endif // LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H