| 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 |