| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 TYPE_STRTAB = 3, | 194 TYPE_STRTAB = 3, |
| 195 TYPE_RELA = 4, | 195 TYPE_RELA = 4, |
| 196 TYPE_HASH = 5, | 196 TYPE_HASH = 5, |
| 197 TYPE_DYNAMIC = 6, | 197 TYPE_DYNAMIC = 6, |
| 198 TYPE_NOTE = 7, | 198 TYPE_NOTE = 7, |
| 199 TYPE_NOBITS = 8, | 199 TYPE_NOBITS = 8, |
| 200 TYPE_REL = 9, | 200 TYPE_REL = 9, |
| 201 TYPE_SHLIB = 10, | 201 TYPE_SHLIB = 10, |
| 202 TYPE_DYNSYM = 11, | 202 TYPE_DYNSYM = 11, |
| 203 TYPE_LOPROC = 0x70000000, | 203 TYPE_LOPROC = 0x70000000, |
| 204 TYPE_X86_64_UNWIND = 0x70000001, |
| 204 TYPE_HIPROC = 0x7fffffff, | 205 TYPE_HIPROC = 0x7fffffff, |
| 205 TYPE_LOUSER = 0x80000000, | 206 TYPE_LOUSER = 0x80000000, |
| 206 TYPE_HIUSER = 0xffffffff | 207 TYPE_HIUSER = 0xffffffff |
| 207 }; | 208 }; |
| 208 | 209 |
| 209 enum Flags { | 210 enum Flags { |
| 210 FLAG_WRITE = 1, | 211 FLAG_WRITE = 1, |
| 211 FLAG_ALLOC = 2, | 212 FLAG_ALLOC = 2, |
| 212 FLAG_EXEC = 4 | 213 FLAG_EXEC = 4 |
| 213 }; | 214 }; |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 } | 633 } |
| 633 } | 634 } |
| 634 | 635 |
| 635 ZoneList<ELFSymbol> locals_; | 636 ZoneList<ELFSymbol> locals_; |
| 636 ZoneList<ELFSymbol> globals_; | 637 ZoneList<ELFSymbol> globals_; |
| 637 }; | 638 }; |
| 638 | 639 |
| 639 | 640 |
| 640 class CodeDescription BASE_EMBEDDED { | 641 class CodeDescription BASE_EMBEDDED { |
| 641 public: | 642 public: |
| 643 |
| 644 #ifdef V8_TARGET_ARCH_X64 |
| 645 enum StackState { |
| 646 POST_RBP_PUSH, |
| 647 POST_RBP_SET, |
| 648 POST_RBP_POP, |
| 649 STACK_STATE_MAX |
| 650 }; |
| 651 #endif |
| 652 |
| 642 CodeDescription(const char* name, | 653 CodeDescription(const char* name, |
| 643 Code* code, | 654 Code* code, |
| 644 Handle<Script> script, | 655 Handle<Script> script, |
| 645 GDBJITLineInfo* lineinfo) | 656 GDBJITLineInfo* lineinfo, |
| 646 : name_(name), code_(code), script_(script), lineinfo_(lineinfo) | 657 GDBJITInterface::CodeTag tag) |
| 647 { } | 658 : name_(name), |
| 659 code_(code), |
| 660 script_(script), |
| 661 lineinfo_(lineinfo), |
| 662 tag_(tag) { |
| 663 } |
| 648 | 664 |
| 649 const char* code_name() const { | 665 const char* name() const { |
| 650 return name_; | 666 return name_; |
| 651 } | 667 } |
| 652 | 668 |
| 653 uintptr_t code_size() const { | 669 GDBJITLineInfo* lineinfo() const { |
| 654 return code_->instruction_end() - code_->instruction_start(); | 670 return lineinfo_; |
| 655 } | 671 } |
| 656 | 672 |
| 657 uintptr_t code_start() const { | 673 GDBJITInterface::CodeTag tag() const { |
| 658 return (uintptr_t)code_->instruction_start(); | 674 return tag_; |
| 659 } | 675 } |
| 660 | 676 |
| 661 bool is_line_info_available() { | 677 uintptr_t CodeStart() const { |
| 678 return reinterpret_cast<uintptr_t>(code_->instruction_start()); |
| 679 } |
| 680 |
| 681 uintptr_t CodeEnd() const { |
| 682 return reinterpret_cast<uintptr_t>(code_->instruction_end()); |
| 683 } |
| 684 |
| 685 uintptr_t CodeSize() const { |
| 686 return CodeEnd() - CodeStart(); |
| 687 } |
| 688 |
| 689 bool IsLineInfoAvailable() { |
| 662 return !script_.is_null() && | 690 return !script_.is_null() && |
| 663 script_->source()->IsString() && | 691 script_->source()->IsString() && |
| 664 script_->HasValidSource() && | 692 script_->HasValidSource() && |
| 665 script_->name()->IsString() && | 693 script_->name()->IsString() && |
| 666 lineinfo_ != NULL; | 694 lineinfo_ != NULL; |
| 667 } | 695 } |
| 668 | 696 |
| 669 GDBJITLineInfo* lineinfo() const { return lineinfo_; } | 697 #ifdef V8_TARGET_ARCH_X64 |
| 698 uintptr_t GetStackStateStartAddress(StackState state) const { |
| 699 ASSERT(state < STACK_STATE_MAX); |
| 700 return stack_state_start_addresses_[state]; |
| 701 } |
| 670 | 702 |
| 671 SmartPointer<char> filename() { | 703 void SetStackStateStartAddress(StackState state, uintptr_t addr) { |
| 704 ASSERT(state < STACK_STATE_MAX); |
| 705 stack_state_start_addresses_[state] = addr; |
| 706 } |
| 707 #endif |
| 708 |
| 709 SmartPointer<char> GetFilename() { |
| 672 return String::cast(script_->name())->ToCString(); | 710 return String::cast(script_->name())->ToCString(); |
| 673 } | 711 } |
| 674 | 712 |
| 675 int GetScriptLineNumber(int pos) { | 713 int GetScriptLineNumber(int pos) { |
| 676 return GetScriptLineNumberSafe(script_, pos) + 1; | 714 return GetScriptLineNumberSafe(script_, pos) + 1; |
| 677 } | 715 } |
| 678 | 716 |
| 717 |
| 679 private: | 718 private: |
| 680 const char* name_; | 719 const char* name_; |
| 681 Code* code_; | 720 Code* code_; |
| 682 Handle<Script> script_; | 721 Handle<Script> script_; |
| 683 GDBJITLineInfo* lineinfo_; | 722 GDBJITLineInfo* lineinfo_; |
| 723 GDBJITInterface::CodeTag tag_; |
| 724 #ifdef V8_TARGET_ARCH_X64 |
| 725 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; |
| 726 #endif |
| 684 }; | 727 }; |
| 685 | 728 |
| 686 | 729 |
| 687 static void CreateSymbolsTable(CodeDescription* desc, | 730 static void CreateSymbolsTable(CodeDescription* desc, |
| 688 ELF* elf, | 731 ELF* elf, |
| 689 int text_section_index) { | 732 int text_section_index) { |
| 690 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab"); | 733 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab"); |
| 691 StringTable* strtab = new StringTable(".strtab"); | 734 StringTable* strtab = new StringTable(".strtab"); |
| 692 | 735 |
| 693 // Symbol table should be followed by the linked string table. | 736 // Symbol table should be followed by the linked string table. |
| 694 elf->AddSection(symtab); | 737 elf->AddSection(symtab); |
| 695 elf->AddSection(strtab); | 738 elf->AddSection(strtab); |
| 696 | 739 |
| 697 symtab->Add(ELFSymbol("V8 Code", | 740 symtab->Add(ELFSymbol("V8 Code", |
| 698 0, | 741 0, |
| 699 0, | 742 0, |
| 700 ELFSymbol::BIND_LOCAL, | 743 ELFSymbol::BIND_LOCAL, |
| 701 ELFSymbol::TYPE_FILE, | 744 ELFSymbol::TYPE_FILE, |
| 702 ELFSection::INDEX_ABSOLUTE)); | 745 ELFSection::INDEX_ABSOLUTE)); |
| 703 | 746 |
| 704 symtab->Add(ELFSymbol(desc->code_name(), | 747 symtab->Add(ELFSymbol(desc->name(), |
| 705 0, | 748 0, |
| 706 desc->code_size(), | 749 desc->CodeSize(), |
| 707 ELFSymbol::BIND_GLOBAL, | 750 ELFSymbol::BIND_GLOBAL, |
| 708 ELFSymbol::TYPE_FUNC, | 751 ELFSymbol::TYPE_FUNC, |
| 709 text_section_index)); | 752 text_section_index)); |
| 710 } | 753 } |
| 711 | 754 |
| 712 | 755 |
| 713 class DebugInfoSection : public ELFSection { | 756 class DebugInfoSection : public ELFSection { |
| 714 public: | 757 public: |
| 715 explicit DebugInfoSection(CodeDescription* desc) | 758 explicit DebugInfoSection(CodeDescription* desc) |
| 716 : ELFSection(".debug_info", TYPE_PROGBITS, 1), desc_(desc) { } | 759 : ELFSection(".debug_info", TYPE_PROGBITS, 1), desc_(desc) { } |
| 717 | 760 |
| 718 bool WriteBody(Writer* w) { | 761 bool WriteBody(Writer* w) { |
| 719 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>(); | 762 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>(); |
| 720 uintptr_t start = w->position(); | 763 uintptr_t start = w->position(); |
| 721 w->Write<uint16_t>(2); // DWARF version. | 764 w->Write<uint16_t>(2); // DWARF version. |
| 722 w->Write<uint32_t>(0); // Abbreviation table offset. | 765 w->Write<uint32_t>(0); // Abbreviation table offset. |
| 723 w->Write<uint8_t>(sizeof(intptr_t)); | 766 w->Write<uint8_t>(sizeof(intptr_t)); |
| 724 | 767 |
| 725 w->WriteULEB128(1); // Abbreviation code. | 768 w->WriteULEB128(1); // Abbreviation code. |
| 726 w->WriteString(*desc_->filename()); | 769 w->WriteString(*desc_->GetFilename()); |
| 727 w->Write<intptr_t>(desc_->code_start()); | 770 w->Write<intptr_t>(desc_->CodeStart()); |
| 728 w->Write<intptr_t>(desc_->code_start() + desc_->code_size()); | 771 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); |
| 729 w->Write<uint32_t>(0); | 772 w->Write<uint32_t>(0); |
| 730 size.set(static_cast<uint32_t>(w->position() - start)); | 773 size.set(static_cast<uint32_t>(w->position() - start)); |
| 731 return true; | 774 return true; |
| 732 } | 775 } |
| 733 | 776 |
| 734 private: | 777 private: |
| 735 CodeDescription* desc_; | 778 CodeDescription* desc_; |
| 736 }; | 779 }; |
| 737 | 780 |
| 738 | 781 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 w->Write<int8_t>(0); // Field line_base. | 865 w->Write<int8_t>(0); // Field line_base. |
| 823 w->Write<uint8_t>(2); // Field line_range. | 866 w->Write<uint8_t>(2); // Field line_range. |
| 824 w->Write<uint8_t>(DW_LNS_NEGATE_STMT + 1); // Field opcode_base. | 867 w->Write<uint8_t>(DW_LNS_NEGATE_STMT + 1); // Field opcode_base. |
| 825 w->Write<uint8_t>(0); // DW_LNS_COPY operands count. | 868 w->Write<uint8_t>(0); // DW_LNS_COPY operands count. |
| 826 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_PC operands count. | 869 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_PC operands count. |
| 827 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_LINE operands count. | 870 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_LINE operands count. |
| 828 w->Write<uint8_t>(1); // DW_LNS_SET_FILE operands count. | 871 w->Write<uint8_t>(1); // DW_LNS_SET_FILE operands count. |
| 829 w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count. | 872 w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count. |
| 830 w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count. | 873 w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count. |
| 831 w->Write<uint8_t>(0); // Empty include_directories sequence. | 874 w->Write<uint8_t>(0); // Empty include_directories sequence. |
| 832 w->WriteString(*desc_->filename()); // File name. | 875 w->WriteString(*desc_->GetFilename()); // File name. |
| 833 w->WriteULEB128(0); // Current directory. | 876 w->WriteULEB128(0); // Current directory. |
| 834 w->WriteULEB128(0); // Unknown modification time. | 877 w->WriteULEB128(0); // Unknown modification time. |
| 835 w->WriteULEB128(0); // Unknown file size. | 878 w->WriteULEB128(0); // Unknown file size. |
| 836 w->Write<uint8_t>(0); | 879 w->Write<uint8_t>(0); |
| 837 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start)); | 880 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start)); |
| 838 | 881 |
| 839 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t)); | 882 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t)); |
| 840 w->Write<intptr_t>(desc_->code_start()); | 883 w->Write<intptr_t>(desc_->CodeStart()); |
| 841 | 884 |
| 842 intptr_t pc = 0; | 885 intptr_t pc = 0; |
| 843 intptr_t line = 1; | 886 intptr_t line = 1; |
| 844 bool is_statement = true; | 887 bool is_statement = true; |
| 845 | 888 |
| 846 List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info(); | 889 List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info(); |
| 847 pc_info->Sort(&ComparePCInfo); | 890 pc_info->Sort(&ComparePCInfo); |
| 848 for (int i = 0; i < pc_info->length(); i++) { | 891 for (int i = 0; i < pc_info->length(); i++) { |
| 849 GDBJITLineInfo::PCInfo* info = &pc_info->at(i); | 892 GDBJITLineInfo::PCInfo* info = &pc_info->at(i); |
| 850 uintptr_t pc_diff = info->pc_ - pc; | 893 uintptr_t pc_diff = info->pc_ - pc; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 return +1; | 936 return +1; |
| 894 } else { | 937 } else { |
| 895 return -1; | 938 return -1; |
| 896 } | 939 } |
| 897 } | 940 } |
| 898 | 941 |
| 899 CodeDescription* desc_; | 942 CodeDescription* desc_; |
| 900 }; | 943 }; |
| 901 | 944 |
| 902 | 945 |
| 946 #ifdef V8_TARGET_ARCH_X64 |
| 947 |
| 948 |
| 949 class UnwindInfoSection : public ELFSection { |
| 950 public: |
| 951 explicit UnwindInfoSection(CodeDescription *desc); |
| 952 virtual bool WriteBody(Writer *w); |
| 953 |
| 954 int WriteCIE(Writer *w); |
| 955 void WriteFDE(Writer *w, int); |
| 956 |
| 957 void WriteFDEStateOnEntry(Writer *w); |
| 958 void WriteFDEStateAfterRBPPush(Writer *w); |
| 959 void WriteFDEStateAfterRBPSet(Writer *w); |
| 960 void WriteFDEStateAfterRBPPop(Writer *w); |
| 961 |
| 962 void WriteLength(Writer *w, |
| 963 Writer::Slot<uint32_t>* length_slot, |
| 964 int initial_position); |
| 965 |
| 966 private: |
| 967 CodeDescription *desc_; |
| 968 |
| 969 // DWARF3 Specification, Table 7.23 |
| 970 enum CFIInstructions { |
| 971 DW_CFA_ADVANCE_LOC = 0x40, |
| 972 DW_CFA_OFFSET = 0x80, |
| 973 DW_CFA_RESTORE = 0xC0, |
| 974 DW_CFA_NOP = 0x00, |
| 975 DW_CFA_SET_LOC = 0x01, |
| 976 DW_CFA_ADVANCE_LOC1 = 0x02, |
| 977 DW_CFA_ADVANCE_LOC2 = 0x03, |
| 978 DW_CFA_ADVANCE_LOC4 = 0x04, |
| 979 DW_CFA_OFFSET_EXTENDED = 0x05, |
| 980 DW_CFA_RESTORE_EXTENDED = 0x06, |
| 981 DW_CFA_UNDEFINED = 0x07, |
| 982 DW_CFA_SAME_VALUE = 0x08, |
| 983 DW_CFA_REGISTER = 0x09, |
| 984 DW_CFA_REMEMBER_STATE = 0x0A, |
| 985 DW_CFA_RESTORE_STATE = 0x0B, |
| 986 DW_CFA_DEF_CFA = 0x0C, |
| 987 DW_CFA_DEF_CFA_REGISTER = 0x0D, |
| 988 DW_CFA_DEF_CFA_OFFSET = 0x0E, |
| 989 |
| 990 DW_CFA_DEF_CFA_EXPRESSION = 0x0F, |
| 991 DW_CFA_EXPRESSION = 0x10, |
| 992 DW_CFA_OFFSET_EXTENDED_SF = 0x11, |
| 993 DW_CFA_DEF_CFA_SF = 0x12, |
| 994 DW_CFA_DEF_CFA_OFFSET_SF = 0x13, |
| 995 DW_CFA_VAL_OFFSET = 0x14, |
| 996 DW_CFA_VAL_OFFSET_SF = 0x15, |
| 997 DW_CFA_VAL_EXPRESSION = 0x16 |
| 998 }; |
| 999 |
| 1000 // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36 |
| 1001 enum RegisterMapping { |
| 1002 // Only the relevant ones have been added to reduce clutter. |
| 1003 AMD64_RBP = 6, |
| 1004 AMD64_RSP = 7, |
| 1005 AMD64_RA = 16 |
| 1006 }; |
| 1007 |
| 1008 enum CFIConstants { |
| 1009 CIE_ID = 0, |
| 1010 CIE_VERSION = 1, |
| 1011 CODE_ALIGN_FACTOR = 1, |
| 1012 DATA_ALIGN_FACTOR = 1, |
| 1013 RETURN_ADDRESS_REGISTER = AMD64_RA |
| 1014 }; |
| 1015 }; |
| 1016 |
| 1017 |
| 1018 void UnwindInfoSection::WriteLength(Writer *w, |
| 1019 Writer::Slot<uint32_t>* length_slot, |
| 1020 int initial_position) { |
| 1021 uint32_t align = (w->position() - initial_position) % kPointerSize; |
| 1022 |
| 1023 if (align != 0) { |
| 1024 for (uint32_t i = 0; i < (kPointerSize - align); i++) { |
| 1025 w->Write<uint8_t>(DW_CFA_NOP); |
| 1026 } |
| 1027 } |
| 1028 |
| 1029 ASSERT((w->position() - initial_position) % kPointerSize == 0); |
| 1030 length_slot->set(w->position() - initial_position); |
| 1031 } |
| 1032 |
| 1033 |
| 1034 UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) |
| 1035 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), desc_(desc) |
| 1036 { } |
| 1037 |
| 1038 int UnwindInfoSection::WriteCIE(Writer *w) { |
| 1039 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); |
| 1040 uint32_t cie_position = w->position(); |
| 1041 |
| 1042 // Write out the CIE header. Currently no 'common instructions' are |
| 1043 // emitted onto the CIE; every FDE has its own set of instructions. |
| 1044 |
| 1045 w->Write<uint32_t>(CIE_ID); |
| 1046 w->Write<uint8_t>(CIE_VERSION); |
| 1047 w->Write<uint8_t>(0); // Null augmentation string. |
| 1048 w->WriteSLEB128(CODE_ALIGN_FACTOR); |
| 1049 w->WriteSLEB128(DATA_ALIGN_FACTOR); |
| 1050 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER); |
| 1051 |
| 1052 WriteLength(w, &cie_length_slot, cie_position); |
| 1053 |
| 1054 return cie_position; |
| 1055 } |
| 1056 |
| 1057 |
| 1058 void UnwindInfoSection::WriteFDE(Writer *w, int cie_position) { |
| 1059 // The only FDE for this function. The CFA is the current RBP. |
| 1060 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>(); |
| 1061 int fde_position = w->position(); |
| 1062 w->Write<int32_t>(fde_position - cie_position + 4); |
| 1063 |
| 1064 w->Write<uintptr_t>(desc_->CodeStart()); |
| 1065 w->Write<uintptr_t>(desc_->CodeSize()); |
| 1066 |
| 1067 WriteFDEStateOnEntry(w); |
| 1068 WriteFDEStateAfterRBPPush(w); |
| 1069 WriteFDEStateAfterRBPSet(w); |
| 1070 WriteFDEStateAfterRBPPop(w); |
| 1071 |
| 1072 WriteLength(w, &fde_length_slot, fde_position); |
| 1073 } |
| 1074 |
| 1075 |
| 1076 void UnwindInfoSection::WriteFDEStateOnEntry(Writer *w) { |
| 1077 // The first state, just after the control has been transferred to the the |
| 1078 // function. |
| 1079 |
| 1080 // RBP for this function will be the value of RSP after pushing the RBP |
| 1081 // for the previous function. The previous RBP has not been pushed yet. |
| 1082 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF); |
| 1083 w->WriteULEB128(AMD64_RSP); |
| 1084 w->WriteSLEB128(-kPointerSize); |
| 1085 |
| 1086 // The RA is stored at location CFA + kCallerPCOffset. This is an invariant, |
| 1087 // and hence omitted from the next states. |
| 1088 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); |
| 1089 w->WriteULEB128(AMD64_RA); |
| 1090 w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset); |
| 1091 |
| 1092 // The RBP of the previous function is still in RBP. |
| 1093 w->Write<uint8_t>(DW_CFA_SAME_VALUE); |
| 1094 w->WriteULEB128(AMD64_RBP); |
| 1095 |
| 1096 // Last location described by this entry. |
| 1097 w->Write<uint8_t>(DW_CFA_SET_LOC); |
| 1098 w->Write<uint64_t>( |
| 1099 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH)); |
| 1100 } |
| 1101 |
| 1102 |
| 1103 void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer *w) { |
| 1104 // The second state, just after RBP has been pushed. |
| 1105 |
| 1106 // RBP / CFA for this function is now the current RSP, so just set the |
| 1107 // offset from the previous rule (from -8) to 0. |
| 1108 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET); |
| 1109 w->WriteULEB128(0); |
| 1110 |
| 1111 // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant |
| 1112 // in this and the next state, and hence omitted in the next state. |
| 1113 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); |
| 1114 w->WriteULEB128(AMD64_RBP); |
| 1115 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset); |
| 1116 |
| 1117 // Last location described by this entry. |
| 1118 w->Write<uint8_t>(DW_CFA_SET_LOC); |
| 1119 w->Write<uint64_t>( |
| 1120 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET)); |
| 1121 } |
| 1122 |
| 1123 |
| 1124 void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer *w) { |
| 1125 // The third state, after the RBP has been set. |
| 1126 |
| 1127 // The CFA can now directly be set to RBP. |
| 1128 w->Write<uint8_t>(DW_CFA_DEF_CFA); |
| 1129 w->WriteULEB128(AMD64_RBP); |
| 1130 w->WriteULEB128(0); |
| 1131 |
| 1132 // Last location described by this entry. |
| 1133 w->Write<uint8_t>(DW_CFA_SET_LOC); |
| 1134 w->Write<uint64_t>( |
| 1135 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP)); |
| 1136 } |
| 1137 |
| 1138 |
| 1139 void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer *w) { |
| 1140 // The fourth (final) state. The RBP has been popped (just before issuing a |
| 1141 // return). |
| 1142 |
| 1143 // The CFA can is now calculated in the same way as in the first state. |
| 1144 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF); |
| 1145 w->WriteULEB128(AMD64_RSP); |
| 1146 w->WriteSLEB128(-kPointerSize); |
| 1147 |
| 1148 // The RBP |
| 1149 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); |
| 1150 w->WriteULEB128(AMD64_RBP); |
| 1151 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset); |
| 1152 |
| 1153 // Last location described by this entry. |
| 1154 w->Write<uint8_t>(DW_CFA_SET_LOC); |
| 1155 w->Write<uint64_t>(desc_->CodeEnd()); |
| 1156 } |
| 1157 |
| 1158 |
| 1159 bool UnwindInfoSection::WriteBody(Writer *w) { |
| 1160 uint32_t cie_position = WriteCIE(w); |
| 1161 WriteFDE(w, cie_position); |
| 1162 return true; |
| 1163 } |
| 1164 |
| 1165 |
| 1166 #endif // V8_TARGET_ARCH_X64 |
| 1167 |
| 1168 |
| 903 static void CreateDWARFSections(CodeDescription* desc, ELF* elf) { | 1169 static void CreateDWARFSections(CodeDescription* desc, ELF* elf) { |
| 904 if (desc->is_line_info_available()) { | 1170 if (desc->IsLineInfoAvailable()) { |
| 905 elf->AddSection(new DebugInfoSection(desc)); | 1171 elf->AddSection(new DebugInfoSection(desc)); |
| 906 elf->AddSection(new DebugAbbrevSection); | 1172 elf->AddSection(new DebugAbbrevSection); |
| 907 elf->AddSection(new DebugLineSection(desc)); | 1173 elf->AddSection(new DebugLineSection(desc)); |
| 908 } | 1174 } |
| 909 } | 1175 #ifdef V8_TARGET_ARCH_X64 |
| 910 | 1176 elf->AddSection(new UnwindInfoSection(desc)); |
| 911 | 1177 #endif |
| 1178 } |
| 1179 |
| 1180 |
| 912 // ------------------------------------------------------------------- | 1181 // ------------------------------------------------------------------- |
| 913 // Binary GDB JIT Interface as described in | 1182 // Binary GDB JIT Interface as described in |
| 914 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html | 1183 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html |
| 915 extern "C" { | 1184 extern "C" { |
| 916 typedef enum { | 1185 typedef enum { |
| 917 JIT_NOACTION = 0, | 1186 JIT_NOACTION = 0, |
| 918 JIT_REGISTER_FN, | 1187 JIT_REGISTER_FN, |
| 919 JIT_UNREGISTER_FN | 1188 JIT_UNREGISTER_FN |
| 920 } JITAction; | 1189 } JITAction; |
| 921 | 1190 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 static JITCodeEntry* CreateELFObject(CodeDescription* desc) { | 1267 static JITCodeEntry* CreateELFObject(CodeDescription* desc) { |
| 999 ZoneScope zone_scope(DELETE_ON_EXIT); | 1268 ZoneScope zone_scope(DELETE_ON_EXIT); |
| 1000 | 1269 |
| 1001 ELF elf; | 1270 ELF elf; |
| 1002 Writer w(&elf); | 1271 Writer w(&elf); |
| 1003 | 1272 |
| 1004 int text_section_index = elf.AddSection( | 1273 int text_section_index = elf.AddSection( |
| 1005 new FullHeaderELFSection(".text", | 1274 new FullHeaderELFSection(".text", |
| 1006 ELFSection::TYPE_NOBITS, | 1275 ELFSection::TYPE_NOBITS, |
| 1007 kCodeAlignment, | 1276 kCodeAlignment, |
| 1008 desc->code_start(), | 1277 desc->CodeStart(), |
| 1009 0, | 1278 0, |
| 1010 desc->code_size(), | 1279 desc->CodeSize(), |
| 1011 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); | 1280 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); |
| 1012 | 1281 |
| 1013 CreateSymbolsTable(desc, &elf, text_section_index); | 1282 CreateSymbolsTable(desc, &elf, text_section_index); |
| 1014 | 1283 |
| 1015 CreateDWARFSections(desc, &elf); | 1284 CreateDWARFSections(desc, &elf); |
| 1016 | 1285 |
| 1017 elf.Write(&w); | 1286 elf.Write(&w); |
| 1018 | 1287 |
| 1019 return CreateCodeEntry(w.buffer(), w.position()); | 1288 return CreateCodeEntry(w.buffer(), w.position()); |
| 1020 } | 1289 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 void GDBJITInterface::AddCode(Handle<String> name, | 1327 void GDBJITInterface::AddCode(Handle<String> name, |
| 1059 Handle<Script> script, | 1328 Handle<Script> script, |
| 1060 Handle<Code> code) { | 1329 Handle<Code> code) { |
| 1061 if (!FLAG_gdbjit) return; | 1330 if (!FLAG_gdbjit) return; |
| 1062 | 1331 |
| 1063 // Force initialization of line_ends array. | 1332 // Force initialization of line_ends array. |
| 1064 GetScriptLineNumber(script, 0); | 1333 GetScriptLineNumber(script, 0); |
| 1065 | 1334 |
| 1066 if (!name.is_null()) { | 1335 if (!name.is_null()) { |
| 1067 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); | 1336 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); |
| 1068 AddCode(*name_cstring, *code, *script); | 1337 AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script); |
| 1069 } else { | 1338 } else { |
| 1070 AddCode("", *code, *script); | 1339 AddCode("", *code, GDBJITInterface::FUNCTION, *script); |
| 1071 } | 1340 } |
| 1072 } | 1341 } |
| 1073 | 1342 |
| 1343 static void AddUnwindInfo(CodeDescription *desc) { |
| 1344 #ifdef V8_TARGET_ARCH_X64 |
| 1345 if (desc->tag() == GDBJITInterface::FUNCTION) { |
| 1346 // To avoid propagating unwinding information through |
| 1347 // compilation pipeline we rely on function prologue |
| 1348 // and epilogue being the same for all code objects generated |
| 1349 // by the full code generator. |
| 1350 static const int kFramePointerPushOffset = 1; |
| 1351 static const int kFramePointerSetOffset = 4; |
| 1352 static const int kFramePointerPopOffset = -3; |
| 1353 |
| 1354 uintptr_t frame_pointer_push_address = |
| 1355 desc->CodeStart() + kFramePointerPushOffset; |
| 1356 |
| 1357 uintptr_t frame_pointer_set_address = |
| 1358 desc->CodeStart() + kFramePointerSetOffset; |
| 1359 |
| 1360 uintptr_t frame_pointer_pop_address = |
| 1361 desc->CodeEnd() + kFramePointerPopOffset; |
| 1362 |
| 1363 #ifdef DEBUG |
| 1364 static const uint8_t kFramePointerPushInstruction = 0x48; // push ebp |
| 1365 static const uint16_t kFramePointerSetInstruction = 0x5756; // mov ebp, esp |
| 1366 static const uint8_t kFramePointerPopInstruction = 0xBE; // pop ebp |
| 1367 |
| 1368 ASSERT(*reinterpret_cast<uint8_t*>(frame_pointer_push_address) == |
| 1369 kFramePointerPushInstruction); |
| 1370 ASSERT(*reinterpret_cast<uint16_t*>(frame_pointer_set_address) == |
| 1371 kFramePointerSetInstruction); |
| 1372 ASSERT(*reinterpret_cast<uint8_t*>(frame_pointer_pop_address) == |
| 1373 kFramePointerPopInstruction); |
| 1374 #endif |
| 1375 |
| 1376 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH, |
| 1377 frame_pointer_push_address); |
| 1378 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET, |
| 1379 frame_pointer_set_address); |
| 1380 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP, |
| 1381 frame_pointer_pop_address); |
| 1382 } else { |
| 1383 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH, |
| 1384 desc->CodeStart()); |
| 1385 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET, |
| 1386 desc->CodeStart()); |
| 1387 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP, |
| 1388 desc->CodeEnd()); |
| 1389 } |
| 1390 #endif // V8_TARGET_ARCH_X64 |
| 1391 } |
| 1392 |
| 1074 | 1393 |
| 1075 void GDBJITInterface::AddCode(const char* name, | 1394 void GDBJITInterface::AddCode(const char* name, |
| 1076 Code* code, | 1395 Code* code, |
| 1396 GDBJITInterface::CodeTag tag, |
| 1077 Script* script) { | 1397 Script* script) { |
| 1078 if (!FLAG_gdbjit) return; | 1398 if (!FLAG_gdbjit) return; |
| 1079 AssertNoAllocation no_gc; | 1399 AssertNoAllocation no_gc; |
| 1080 | 1400 |
| 1081 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); | 1401 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); |
| 1082 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; | 1402 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; |
| 1083 | 1403 |
| 1084 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); | 1404 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); |
| 1085 CodeDescription code_desc(name, | 1405 CodeDescription code_desc(name, |
| 1086 code, | 1406 code, |
| 1087 script != NULL ? Handle<Script>(script) | 1407 script != NULL ? Handle<Script>(script) |
| 1088 : Handle<Script>(), | 1408 : Handle<Script>(), |
| 1089 lineinfo); | 1409 lineinfo, |
| 1410 tag); |
| 1090 | 1411 |
| 1091 if (!FLAG_gdbjit_full && !code_desc.is_line_info_available()) { | 1412 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { |
| 1092 delete lineinfo; | 1413 delete lineinfo; |
| 1093 entries.Remove(code, HashForCodeObject(code)); | 1414 entries.Remove(code, HashForCodeObject(code)); |
| 1094 return; | 1415 return; |
| 1095 } | 1416 } |
| 1096 | 1417 |
| 1418 AddUnwindInfo(&code_desc); |
| 1097 JITCodeEntry* entry = CreateELFObject(&code_desc); | 1419 JITCodeEntry* entry = CreateELFObject(&code_desc); |
| 1098 ASSERT(!IsLineInfoTagged(entry)); | 1420 ASSERT(!IsLineInfoTagged(entry)); |
| 1099 | 1421 |
| 1100 delete lineinfo; | 1422 delete lineinfo; |
| 1101 e->value = entry; | 1423 e->value = entry; |
| 1102 | 1424 |
| 1103 RegisterCodeEntry(entry); | 1425 RegisterCodeEntry(entry); |
| 1104 } | 1426 } |
| 1105 | 1427 |
| 1106 | 1428 |
| 1107 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | 1429 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, |
| 1108 const char* name, | 1430 const char* name, |
| 1109 Code* code) { | 1431 Code* code) { |
| 1110 if (!FLAG_gdbjit) return; | 1432 if (!FLAG_gdbjit) return; |
| 1111 | 1433 |
| 1112 EmbeddedVector<char, 256> buffer; | 1434 EmbeddedVector<char, 256> buffer; |
| 1113 StringBuilder builder(buffer.start(), buffer.length()); | 1435 StringBuilder builder(buffer.start(), buffer.length()); |
| 1114 | 1436 |
| 1115 builder.AddString(Tag2String(tag)); | 1437 builder.AddString(Tag2String(tag)); |
| 1116 if ((name != NULL) && (*name != '\0')) { | 1438 if ((name != NULL) && (*name != '\0')) { |
| 1117 builder.AddString(": "); | 1439 builder.AddString(": "); |
| 1118 builder.AddString(name); | 1440 builder.AddString(name); |
| 1119 } else { | 1441 } else { |
| 1120 builder.AddFormatted(": code object %p", static_cast<void*>(code)); | 1442 builder.AddFormatted(": code object %p", static_cast<void*>(code)); |
| 1121 } | 1443 } |
| 1122 | 1444 |
| 1123 AddCode(builder.Finalize(), code); | 1445 AddCode(builder.Finalize(), code, tag); |
| 1124 } | 1446 } |
| 1125 | 1447 |
| 1126 | 1448 |
| 1127 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | 1449 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, |
| 1128 String* name, | 1450 String* name, |
| 1129 Code* code) { | 1451 Code* code) { |
| 1130 if (!FLAG_gdbjit) return; | 1452 if (!FLAG_gdbjit) return; |
| 1131 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code); | 1453 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code); |
| 1132 } | 1454 } |
| 1133 | 1455 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1161 GDBJITLineInfo* line_info) { | 1483 GDBJITLineInfo* line_info) { |
| 1162 ASSERT(!IsLineInfoTagged(line_info)); | 1484 ASSERT(!IsLineInfoTagged(line_info)); |
| 1163 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); | 1485 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); |
| 1164 ASSERT(e->value == NULL); | 1486 ASSERT(e->value == NULL); |
| 1165 e->value = TagLineInfo(line_info); | 1487 e->value = TagLineInfo(line_info); |
| 1166 } | 1488 } |
| 1167 | 1489 |
| 1168 | 1490 |
| 1169 } } // namespace v8::internal | 1491 } } // namespace v8::internal |
| 1170 #endif | 1492 #endif |
| OLD | NEW |