OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/dwarf.h" | 5 #include "vm/dwarf.h" |
6 | 6 |
7 #include "vm/code_descriptors.h" | 7 #include "vm/code_descriptors.h" |
8 #include "vm/object_store.h" | 8 #include "vm/object_store.h" |
9 | 9 |
10 namespace dart { | 10 namespace dart { |
(...skipping 30 matching lines...) Expand all Loading... |
41 | 41 |
42 const Function& function; | 42 const Function& function; |
43 TokenPosition call_pos; | 43 TokenPosition call_pos; |
44 int32_t start_pc_offset; | 44 int32_t start_pc_offset; |
45 int32_t end_pc_offset; | 45 int32_t end_pc_offset; |
46 InliningNode* children_head; | 46 InliningNode* children_head; |
47 InliningNode* children_tail; | 47 InliningNode* children_tail; |
48 InliningNode* children_next; | 48 InliningNode* children_next; |
49 }; | 49 }; |
50 | 50 |
51 | |
52 Dwarf::Dwarf(Zone* zone, WriteStream* stream) | 51 Dwarf::Dwarf(Zone* zone, WriteStream* stream) |
53 : zone_(zone), | 52 : zone_(zone), |
54 stream_(stream), | 53 stream_(stream), |
55 codes_(zone, 1024), | 54 codes_(zone, 1024), |
56 code_to_index_(zone), | 55 code_to_index_(zone), |
57 functions_(zone, 1024), | 56 functions_(zone, 1024), |
58 function_to_index_(zone), | 57 function_to_index_(zone), |
59 scripts_(zone, 1024), | 58 scripts_(zone, 1024), |
60 script_to_index_(zone), | 59 script_to_index_(zone), |
61 temp_(0) {} | 60 temp_(0) {} |
62 | 61 |
63 | |
64 intptr_t Dwarf::AddCode(const Code& code) { | 62 intptr_t Dwarf::AddCode(const Code& code) { |
65 ASSERT(!code.IsNull()); | 63 ASSERT(!code.IsNull()); |
66 CodeIndexPair* pair = code_to_index_.Lookup(&code); | 64 CodeIndexPair* pair = code_to_index_.Lookup(&code); |
67 if (pair != NULL) { | 65 if (pair != NULL) { |
68 return pair->index_; | 66 return pair->index_; |
69 } | 67 } |
70 intptr_t index = codes_.length(); | 68 intptr_t index = codes_.length(); |
71 const Code& zone_code = Code::ZoneHandle(zone_, code.raw()); | 69 const Code& zone_code = Code::ZoneHandle(zone_, code.raw()); |
72 code_to_index_.Insert(CodeIndexPair(&zone_code, index)); | 70 code_to_index_.Insert(CodeIndexPair(&zone_code, index)); |
73 codes_.Add(&zone_code); | 71 codes_.Add(&zone_code); |
74 if (code.IsFunctionCode()) { | 72 if (code.IsFunctionCode()) { |
75 const Function& function = Function::Handle(zone_, code.function()); | 73 const Function& function = Function::Handle(zone_, code.function()); |
76 AddFunction(function); | 74 AddFunction(function); |
77 } | 75 } |
78 const Array& inline_functions = | 76 const Array& inline_functions = |
79 Array::Handle(zone_, code.inlined_id_to_function()); | 77 Array::Handle(zone_, code.inlined_id_to_function()); |
80 if (!inline_functions.IsNull()) { | 78 if (!inline_functions.IsNull()) { |
81 Function& function = Function::Handle(zone_); | 79 Function& function = Function::Handle(zone_); |
82 for (intptr_t i = 0; i < inline_functions.Length(); i++) { | 80 for (intptr_t i = 0; i < inline_functions.Length(); i++) { |
83 function ^= inline_functions.At(i); | 81 function ^= inline_functions.At(i); |
84 AddFunction(function); | 82 AddFunction(function); |
85 } | 83 } |
86 } | 84 } |
87 return index; | 85 return index; |
88 } | 86 } |
89 | 87 |
90 | |
91 intptr_t Dwarf::AddFunction(const Function& function) { | 88 intptr_t Dwarf::AddFunction(const Function& function) { |
92 ASSERT(!function.IsNull()); | 89 ASSERT(!function.IsNull()); |
93 FunctionIndexPair* pair = function_to_index_.Lookup(&function); | 90 FunctionIndexPair* pair = function_to_index_.Lookup(&function); |
94 if (pair != NULL) { | 91 if (pair != NULL) { |
95 return pair->index_; | 92 return pair->index_; |
96 } | 93 } |
97 intptr_t index = functions_.length(); | 94 intptr_t index = functions_.length(); |
98 const Function& zone_func = Function::ZoneHandle(zone_, function.raw()); | 95 const Function& zone_func = Function::ZoneHandle(zone_, function.raw()); |
99 function_to_index_.Insert(FunctionIndexPair(&zone_func, index)); | 96 function_to_index_.Insert(FunctionIndexPair(&zone_func, index)); |
100 functions_.Add(&zone_func); | 97 functions_.Add(&zone_func); |
101 const Script& script = Script::Handle(zone_, function.script()); | 98 const Script& script = Script::Handle(zone_, function.script()); |
102 AddScript(script); | 99 AddScript(script); |
103 return index; | 100 return index; |
104 } | 101 } |
105 | 102 |
106 | |
107 intptr_t Dwarf::AddScript(const Script& script) { | 103 intptr_t Dwarf::AddScript(const Script& script) { |
108 ASSERT(!script.IsNull()); | 104 ASSERT(!script.IsNull()); |
109 ScriptIndexPair* pair = script_to_index_.Lookup(&script); | 105 ScriptIndexPair* pair = script_to_index_.Lookup(&script); |
110 if (pair != NULL) { | 106 if (pair != NULL) { |
111 return pair->index_; | 107 return pair->index_; |
112 } | 108 } |
113 // DWARF file numbers start from 1. | 109 // DWARF file numbers start from 1. |
114 intptr_t index = scripts_.length() + 1; | 110 intptr_t index = scripts_.length() + 1; |
115 const Script& zone_script = Script::ZoneHandle(zone_, script.raw()); | 111 const Script& zone_script = Script::ZoneHandle(zone_, script.raw()); |
116 script_to_index_.Insert(ScriptIndexPair(&zone_script, index)); | 112 script_to_index_.Insert(ScriptIndexPair(&zone_script, index)); |
117 scripts_.Add(&zone_script); | 113 scripts_.Add(&zone_script); |
118 return index; | 114 return index; |
119 } | 115 } |
120 | 116 |
121 | |
122 intptr_t Dwarf::LookupFunction(const Function& function) { | 117 intptr_t Dwarf::LookupFunction(const Function& function) { |
123 ASSERT(!function.IsNull()); | 118 ASSERT(!function.IsNull()); |
124 FunctionIndexPair* pair = function_to_index_.Lookup(&function); | 119 FunctionIndexPair* pair = function_to_index_.Lookup(&function); |
125 if (pair == NULL) { | 120 if (pair == NULL) { |
126 FATAL1("Function detected too late during DWARF generation: %s", | 121 FATAL1("Function detected too late during DWARF generation: %s", |
127 function.ToCString()); | 122 function.ToCString()); |
128 } | 123 } |
129 return pair->index_; | 124 return pair->index_; |
130 } | 125 } |
131 | 126 |
132 | |
133 intptr_t Dwarf::LookupScript(const Script& script) { | 127 intptr_t Dwarf::LookupScript(const Script& script) { |
134 ASSERT(!script.IsNull()); | 128 ASSERT(!script.IsNull()); |
135 ScriptIndexPair* pair = script_to_index_.Lookup(&script); | 129 ScriptIndexPair* pair = script_to_index_.Lookup(&script); |
136 if (pair == NULL) { | 130 if (pair == NULL) { |
137 FATAL1("Script detected too late during DWARF generation: %s", | 131 FATAL1("Script detected too late during DWARF generation: %s", |
138 script.ToCString()); | 132 script.ToCString()); |
139 } | 133 } |
140 return pair->index_; | 134 return pair->index_; |
141 } | 135 } |
142 | 136 |
143 | |
144 void Dwarf::Print(const char* format, ...) { | 137 void Dwarf::Print(const char* format, ...) { |
145 va_list args; | 138 va_list args; |
146 va_start(args, format); | 139 va_start(args, format); |
147 stream_->VPrint(format, args); | 140 stream_->VPrint(format, args); |
148 va_end(args); | 141 va_end(args); |
149 } | 142 } |
150 | 143 |
151 | |
152 void Dwarf::WriteAbbreviations() { | 144 void Dwarf::WriteAbbreviations() { |
153 // Dwarf data mostly takes the form of a tree, whose nodes are called | 145 // Dwarf data mostly takes the form of a tree, whose nodes are called |
154 // DIEs. Each DIE begins with an abbreviation code, and the abbreviation | 146 // DIEs. Each DIE begins with an abbreviation code, and the abbreviation |
155 // describes the attributes of that DIE and their representation. | 147 // describes the attributes of that DIE and their representation. |
156 | 148 |
157 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS) | 149 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS) |
158 Print(".section __DWARF,__debug_abbrev,regular,debug\n"); | 150 Print(".section __DWARF,__debug_abbrev,regular,debug\n"); |
159 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \ | 151 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \ |
160 defined(TARGET_OS_FUCHSIA) | 152 defined(TARGET_OS_FUCHSIA) |
161 Print(".section .debug_abbrev,\"\"\n"); | 153 Print(".section .debug_abbrev,\"\"\n"); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 uleb128(DW_AT_call_file); | 211 uleb128(DW_AT_call_file); |
220 uleb128(DW_FORM_udata); | 212 uleb128(DW_FORM_udata); |
221 uleb128(DW_AT_call_line); | 213 uleb128(DW_AT_call_line); |
222 uleb128(DW_FORM_udata); | 214 uleb128(DW_FORM_udata); |
223 uleb128(0); | 215 uleb128(0); |
224 uleb128(0); // End of attributes. | 216 uleb128(0); // End of attributes. |
225 | 217 |
226 uleb128(0); // End of abbreviations. | 218 uleb128(0); // End of abbreviations. |
227 } | 219 } |
228 | 220 |
229 | |
230 void Dwarf::WriteCompilationUnit() { | 221 void Dwarf::WriteCompilationUnit() { |
231 // 7.5.1.1 Compilation Unit Header | 222 // 7.5.1.1 Compilation Unit Header |
232 | 223 |
233 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS) | 224 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS) |
234 Print(".section __DWARF,__debug_info,regular,debug\n"); | 225 Print(".section __DWARF,__debug_info,regular,debug\n"); |
235 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \ | 226 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \ |
236 defined(TARGET_OS_FUCHSIA) | 227 defined(TARGET_OS_FUCHSIA) |
237 Print(".section .debug_info,\"\"\n"); | 228 Print(".section .debug_info,\"\"\n"); |
238 #else | 229 #else |
239 UNIMPLEMENTED(); | 230 UNIMPLEMENTED(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 | 273 |
283 WriteAbstractFunctions(); | 274 WriteAbstractFunctions(); |
284 WriteConcreteFunctions(); | 275 WriteConcreteFunctions(); |
285 | 276 |
286 uleb128(0); // End of children. | 277 uleb128(0); // End of children. |
287 | 278 |
288 uleb128(0); // End of entries. | 279 uleb128(0); // End of entries. |
289 Print(".Lcu_end:\n"); | 280 Print(".Lcu_end:\n"); |
290 } | 281 } |
291 | 282 |
292 | |
293 void Dwarf::WriteAbstractFunctions() { | 283 void Dwarf::WriteAbstractFunctions() { |
294 Script& script = Script::Handle(zone_); | 284 Script& script = Script::Handle(zone_); |
295 String& name = String::Handle(zone_); | 285 String& name = String::Handle(zone_); |
296 for (intptr_t i = 0; i < functions_.length(); i++) { | 286 for (intptr_t i = 0; i < functions_.length(); i++) { |
297 const Function& function = *(functions_[i]); | 287 const Function& function = *(functions_[i]); |
298 name = function.QualifiedUserVisibleName(); | 288 name = function.QualifiedUserVisibleName(); |
299 script = function.script(); | 289 script = function.script(); |
300 intptr_t file = LookupScript(script); | 290 intptr_t file = LookupScript(script); |
301 intptr_t line = 0; // Not known. Script has already lost its token stream. | 291 intptr_t line = 0; // Not known. Script has already lost its token stream. |
302 | 292 |
303 Print(".Lfunc%" Pd ":\n", i); // Label for DW_AT_abstract_origin references | 293 Print(".Lfunc%" Pd ":\n", i); // Label for DW_AT_abstract_origin references |
304 uleb128(kAbstractFunction); | 294 uleb128(kAbstractFunction); |
305 Print(".string \"%s\"\n", name.ToCString()); // DW_AT_name | 295 Print(".string \"%s\"\n", name.ToCString()); // DW_AT_name |
306 uleb128(file); // DW_AT_decl_file | 296 uleb128(file); // DW_AT_decl_file |
307 uleb128(line); // DW_AT_decl_line | 297 uleb128(line); // DW_AT_decl_line |
308 uleb128(DW_INL_inlined); // DW_AT_inline | 298 uleb128(DW_INL_inlined); // DW_AT_inline |
309 uleb128(0); // End of children. | 299 uleb128(0); // End of children. |
310 } | 300 } |
311 } | 301 } |
312 | 302 |
313 | |
314 void Dwarf::WriteConcreteFunctions() { | 303 void Dwarf::WriteConcreteFunctions() { |
315 Function& function = Function::Handle(zone_); | 304 Function& function = Function::Handle(zone_); |
316 Script& script = Script::Handle(zone_); | 305 Script& script = Script::Handle(zone_); |
317 for (intptr_t i = 0; i < codes_.length(); i++) { | 306 for (intptr_t i = 0; i < codes_.length(); i++) { |
318 const Code& code = *(codes_[i]); | 307 const Code& code = *(codes_[i]); |
319 if (!code.IsFunctionCode()) { | 308 if (!code.IsFunctionCode()) { |
320 continue; | 309 continue; |
321 } | 310 } |
322 function = code.function(); | 311 function = code.function(); |
323 intptr_t function_index = LookupFunction(function); | 312 intptr_t function_index = LookupFunction(function); |
(...skipping 18 matching lines...) Expand all Loading... |
342 for (InliningNode* child = node->children_head; child != NULL; | 331 for (InliningNode* child = node->children_head; child != NULL; |
343 child = child->children_next) { | 332 child = child->children_next) { |
344 WriteInliningNode(child, i, script); | 333 WriteInliningNode(child, i, script); |
345 } | 334 } |
346 } | 335 } |
347 | 336 |
348 uleb128(0); // End of children. | 337 uleb128(0); // End of children. |
349 } | 338 } |
350 } | 339 } |
351 | 340 |
352 | |
353 // Our state machine encodes position metadata such that we don't know the | 341 // Our state machine encodes position metadata such that we don't know the |
354 // end pc for an inlined function until it is popped, but DWARF DIEs encode | 342 // end pc for an inlined function until it is popped, but DWARF DIEs encode |
355 // it where the function is pushed. We expand the state transitions into | 343 // it where the function is pushed. We expand the state transitions into |
356 // an in-memory tree to do the conversion. | 344 // an in-memory tree to do the conversion. |
357 InliningNode* Dwarf::ExpandInliningTree(const Code& code) { | 345 InliningNode* Dwarf::ExpandInliningTree(const Code& code) { |
358 const CodeSourceMap& map = | 346 const CodeSourceMap& map = |
359 CodeSourceMap::Handle(zone_, code.code_source_map()); | 347 CodeSourceMap::Handle(zone_, code.code_source_map()); |
360 if (map.IsNull()) { | 348 if (map.IsNull()) { |
361 return NULL; | 349 return NULL; |
362 } | 350 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 | 405 |
418 while (node_stack.length() > 1) { | 406 while (node_stack.length() > 1) { |
419 node_stack.Last()->end_pc_offset = current_pc_offset; | 407 node_stack.Last()->end_pc_offset = current_pc_offset; |
420 node_stack.RemoveLast(); | 408 node_stack.RemoveLast(); |
421 token_positions.RemoveLast(); | 409 token_positions.RemoveLast(); |
422 } | 410 } |
423 ASSERT(node_stack[0] == root_node); | 411 ASSERT(node_stack[0] == root_node); |
424 return root_node; | 412 return root_node; |
425 } | 413 } |
426 | 414 |
427 | |
428 void Dwarf::WriteInliningNode(InliningNode* node, | 415 void Dwarf::WriteInliningNode(InliningNode* node, |
429 intptr_t root_code_index, | 416 intptr_t root_code_index, |
430 const Script& parent_script) { | 417 const Script& parent_script) { |
431 intptr_t file = LookupScript(parent_script); | 418 intptr_t file = LookupScript(parent_script); |
432 intptr_t line = node->call_pos.value(); | 419 intptr_t line = node->call_pos.value(); |
433 intptr_t function_index = LookupFunction(node->function); | 420 intptr_t function_index = LookupFunction(node->function); |
434 const Script& script = Script::Handle(zone_, node->function.script()); | 421 const Script& script = Script::Handle(zone_, node->function.script()); |
435 | 422 |
436 uleb128(kInlinedFunction); | 423 uleb128(kInlinedFunction); |
437 // DW_AT_abstract_origin | 424 // DW_AT_abstract_origin |
(...skipping 14 matching lines...) Expand all Loading... |
452 uleb128(line); | 439 uleb128(line); |
453 | 440 |
454 for (InliningNode* child = node->children_head; child != NULL; | 441 for (InliningNode* child = node->children_head; child != NULL; |
455 child = child->children_next) { | 442 child = child->children_next) { |
456 WriteInliningNode(child, root_code_index, script); | 443 WriteInliningNode(child, root_code_index, script); |
457 } | 444 } |
458 | 445 |
459 uleb128(0); // End of children. | 446 uleb128(0); // End of children. |
460 } | 447 } |
461 | 448 |
462 | |
463 void Dwarf::WriteLines() { | 449 void Dwarf::WriteLines() { |
464 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS) | 450 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS) |
465 Print(".section __DWARF,__debug_line,regular,debug\n"); | 451 Print(".section __DWARF,__debug_line,regular,debug\n"); |
466 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \ | 452 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \ |
467 defined(TARGET_OS_FUCHSIA) | 453 defined(TARGET_OS_FUCHSIA) |
468 Print(".section .debug_line,\"\"\n"); | 454 Print(".section .debug_line,\"\"\n"); |
469 #else | 455 #else |
470 UNIMPLEMENTED(); | 456 UNIMPLEMENTED(); |
471 #endif | 457 #endif |
472 | 458 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 u1(0); // This is an extended opcode | 628 u1(0); // This is an extended opcode |
643 u1(1); // that is 1 byte long | 629 u1(1); // that is 1 byte long |
644 u1(DW_LNE_end_sequence); | 630 u1(DW_LNE_end_sequence); |
645 | 631 |
646 Print(".Lline_end:\n"); | 632 Print(".Lline_end:\n"); |
647 } | 633 } |
648 | 634 |
649 #endif // DART_PRECOMPILER | 635 #endif // DART_PRECOMPILER |
650 | 636 |
651 } // namespace dart | 637 } // namespace dart |
OLD | NEW |