Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
dwarf.h
Go to the documentation of this file.
1// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_DWARF_H_
6#define RUNTIME_VM_DWARF_H_
7
8#include "vm/allocation.h"
9#include "vm/hash.h"
10#include "vm/hash_map.h"
11#include "vm/image_snapshot.h"
12#include "vm/object.h"
13#include "vm/zone.h"
14
15namespace dart {
16
17#ifdef DART_PRECOMPILER
18
19class InliningNode;
20class LineNumberProgramWriter;
21
22struct ScriptIndexPair {
23 // Typedefs needed for the DirectChainedHashMap template.
24 typedef const Script* Key;
25 typedef intptr_t Value;
26 typedef ScriptIndexPair Pair;
27
28 static Key KeyOf(Pair kv) { return kv.script_; }
29
30 static Value ValueOf(Pair kv) { return kv.index_; }
31
32 static inline uword Hash(Key key) {
33 return String::Handle(key->url()).Hash();
34 }
35
36 static inline bool IsKeyEqual(Pair pair, Key key) {
37 return pair.script_->ptr() == key->ptr();
38 }
39
40 ScriptIndexPair(const Script* s, intptr_t index) : script_(s), index_(index) {
41 ASSERT(!s->IsNull());
42 DEBUG_ASSERT(s->IsNotTemporaryScopedHandle());
43 }
44
45 ScriptIndexPair() : script_(nullptr), index_(-1) {}
46
47 void Print() const;
48
49 const Script* script_;
50 intptr_t index_;
51};
52
53typedef DirectChainedHashMap<ScriptIndexPair> ScriptIndexMap;
54
55struct FunctionIndexPair {
56 // Typedefs needed for the DirectChainedHashMap template.
57 typedef const Function* Key;
58 typedef intptr_t Value;
59 typedef FunctionIndexPair Pair;
60
61 static Key KeyOf(Pair kv) { return kv.function_; }
62
63 static Value ValueOf(Pair kv) { return kv.index_; }
64
65 static inline uword Hash(Key key) { return key->token_pos().Hash(); }
66
67 static inline bool IsKeyEqual(Pair pair, Key key) {
68 return pair.function_->ptr() == key->ptr();
69 }
70
71 FunctionIndexPair(const Function* f, intptr_t index)
72 : function_(f), index_(index) {
73 ASSERT(!f->IsNull());
74 DEBUG_ASSERT(f->IsNotTemporaryScopedHandle());
75 }
76
77 FunctionIndexPair() : function_(nullptr), index_(-1) {}
78
79 void Print() const;
80
81 const Function* function_;
82 intptr_t index_;
83};
84
85typedef DirectChainedHashMap<FunctionIndexPair> FunctionIndexMap;
86
87// Assumes T has a copy constructor and is CopyAssignable.
88template <typename T>
89struct DwarfCodeKeyValueTrait {
90 // Typedefs needed for the DirectChainedHashMap template.
91 typedef const Code* Key;
92 typedef T Value;
93
94 struct Pair {
95 Pair(const Code* c, const T v) : code(c), value(v) {
96 ASSERT(c != nullptr);
97 ASSERT(!c->IsNull());
98 DEBUG_ASSERT(c->IsNotTemporaryScopedHandle());
99 }
100 Pair() : code(nullptr), value{} {}
101
102 // Don't implicitly delete copy and copy assignment constructors.
103 Pair(const Pair& other) = default;
104 Pair& operator=(const Pair& other) = default;
105
106 const Code* code;
107 T value;
108 };
109
110 static Key KeyOf(Pair kv) { return kv.code; }
111
112 static Value ValueOf(Pair kv) { return kv.value; }
113
114 static inline uword Hash(Key key) {
115 // Instructions are always allocated in old space, so they don't move.
116 return Utils::WordHash(key->PayloadStart());
117 }
118
119 static inline bool IsKeyEqual(Pair pair, Key key) {
120 // Code objects are always allocated in old space, so they don't move.
121 return pair.code->ptr() == key->ptr();
122 }
123};
124
125template <typename T>
126using DwarfCodeMap = DirectChainedHashMap<DwarfCodeKeyValueTrait<T>>;
127
128class DwarfWriteStream : public ValueObject {
129 public:
130 DwarfWriteStream() {}
131 virtual ~DwarfWriteStream() {}
132
133 virtual void sleb128(intptr_t value) = 0;
134 virtual void uleb128(uintptr_t value) = 0;
135 virtual void u1(uint8_t value) = 0;
136 virtual void u2(uint16_t value) = 0;
137 virtual void u4(uint32_t value) = 0;
138 virtual void u8(uint64_t value) = 0;
139 virtual void string(const char* cstr) = 0; // NOLINT
140
141 // Prefixes the content added by body with its length.
142 //
143 // symbol_prefix is used when a local symbol is created for the length.
144 virtual void WritePrefixedLength(const char* symbol_prefix,
145 std::function<void()> body) = 0;
146
147 virtual void OffsetFromSymbol(intptr_t label, intptr_t offset) = 0;
148
149 virtual void InitializeAbstractOrigins(intptr_t size) = 0;
150 virtual void RegisterAbstractOrigin(intptr_t index) = 0;
151 virtual void AbstractOrigin(intptr_t index) = 0;
152
153 DISALLOW_COPY_AND_ASSIGN(DwarfWriteStream);
154};
155
156class Dwarf : public ZoneAllocated {
157 public:
158 explicit Dwarf(Zone* zone, const Trie<const char>* deobfuscation_trie);
159
160 const ZoneGrowableArray<const Code*>& codes() const { return codes_; }
161
162 // Stores the code object for later creating the line number program.
163 void AddCode(const Code& code, intptr_t label);
164
165 intptr_t AddFunction(const Function& function);
166 intptr_t AddScript(const Script& script);
167 intptr_t LookupFunction(const Function& function);
168 intptr_t LookupScript(const Script& script);
169
170 void WriteAbbreviations(DwarfWriteStream* stream);
171 void WriteDebugInfo(DwarfWriteStream* stream);
172 void WriteLineNumberProgram(DwarfWriteStream* stream);
173
174 private:
175 friend class LineNumberProgramWriter;
176
177 static constexpr intptr_t DW_TAG_compile_unit = 0x11;
178 static constexpr intptr_t DW_TAG_inlined_subroutine = 0x1d;
179 static constexpr intptr_t DW_TAG_subprogram = 0x2e;
180
181 static constexpr intptr_t DW_CHILDREN_no = 0x0;
182 static constexpr intptr_t DW_CHILDREN_yes = 0x1;
183
184 static constexpr intptr_t DW_AT_sibling = 0x1;
185 static constexpr intptr_t DW_AT_name = 0x3;
186 static constexpr intptr_t DW_AT_stmt_list = 0x10;
187 static constexpr intptr_t DW_AT_low_pc = 0x11;
188 static constexpr intptr_t DW_AT_high_pc = 0x12;
189 static constexpr intptr_t DW_AT_comp_dir = 0x1b;
190 static constexpr intptr_t DW_AT_inline = 0x20;
191 static constexpr intptr_t DW_AT_producer = 0x25;
192 static constexpr intptr_t DW_AT_abstract_origin = 0x31;
193 static constexpr intptr_t DW_AT_artificial = 0x34;
194 static constexpr intptr_t DW_AT_decl_column = 0x39;
195 static constexpr intptr_t DW_AT_decl_file = 0x3a;
196 static constexpr intptr_t DW_AT_decl_line = 0x3b;
197 static constexpr intptr_t DW_AT_call_column = 0x57;
198 static constexpr intptr_t DW_AT_call_file = 0x58;
199 static constexpr intptr_t DW_AT_call_line = 0x59;
200
201 static constexpr intptr_t DW_FORM_addr = 0x01;
202 static constexpr intptr_t DW_FORM_string = 0x08;
203 static constexpr intptr_t DW_FORM_flag = 0x0c;
204 static constexpr intptr_t DW_FORM_udata = 0x0f;
205 static constexpr intptr_t DW_FORM_ref4 = 0x13;
206 static constexpr intptr_t DW_FORM_ref_udata = 0x15;
207 static constexpr intptr_t DW_FORM_sec_offset = 0x17;
208
209 static constexpr intptr_t DW_INL_not_inlined = 0x0;
210 static constexpr intptr_t DW_INL_inlined = 0x1;
211
212 static constexpr intptr_t DW_LNS_copy = 0x1;
213 static constexpr intptr_t DW_LNS_advance_pc = 0x2;
214 static constexpr intptr_t DW_LNS_advance_line = 0x3;
215 static constexpr intptr_t DW_LNS_set_file = 0x4;
216 static constexpr intptr_t DW_LNS_set_column = 0x5;
217
218 static constexpr intptr_t DW_LNE_end_sequence = 0x01;
219 static constexpr intptr_t DW_LNE_set_address = 0x02;
220
221 public:
222 // Public because they're also used in constructing .eh_frame ELF sections.
223 static constexpr intptr_t DW_CFA_offset = 0x80;
224 static constexpr intptr_t DW_CFA_val_offset = 0x14;
225 static constexpr intptr_t DW_CFA_def_cfa = 0x0c;
226
227 private:
228 enum {
229 kCompilationUnit = 1,
230 kAbstractFunction,
231 kConcreteFunction,
232 kInlinedFunction,
233 };
234
235 void WriteAbstractFunctions(DwarfWriteStream* stream);
236 void WriteConcreteFunctions(DwarfWriteStream* stream);
237 InliningNode* ExpandInliningTree(const Code& code);
238 void WriteInliningNode(DwarfWriteStream* stream,
239 InliningNode* node,
240 intptr_t root_label,
241 const Script& parent_script);
242
243 void WriteSyntheticLineNumberProgram(LineNumberProgramWriter* writer);
244 void WriteLineNumberProgramFromCodeSourceMaps(
245 LineNumberProgramWriter* writer);
246
247 Zone* const zone_;
248 const Trie<const char>* const deobfuscation_trie_;
249 ZoneGrowableArray<const Code*> codes_;
250 DwarfCodeMap<intptr_t> code_to_label_;
251 ZoneGrowableArray<const Function*> functions_;
252 FunctionIndexMap function_to_index_;
253 ZoneGrowableArray<const Script*> scripts_;
254 ScriptIndexMap script_to_index_;
255};
256
257#endif // DART_PRECOMPILER
258
259} // namespace dart
260
261#endif // RUNTIME_VM_DWARF_H_
TArray< uint32_t > Key
#define DEBUG_ASSERT(cond)
Definition assert.h:321
#define ASSERT(E)
struct MyStruct s
uint8_t value
Dart_NativeFunction function
Definition fuchsia.cc:51
uintptr_t uword
Definition globals.h:501
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
#define T
Point offset