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) |
658 : name_(name), | |
659 code_(code), | |
Erik Corry
2011/02/02 13:10:25
Indentation
| |
660 script_(script), | |
661 lineinfo_(lineinfo), | |
662 tag_(tag) | |
647 { } | 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 { |
Erik Corry
2011/02/02 13:10:25
Why can't these return Address?
| |
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()); |
Erik Corry
2011/02/02 13:10:25
w->Write<Address>(...
| |
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, Writer::Slot<uint32_t> &, int); | |
963 | |
964 private: | |
965 CodeDescription *desc_; | |
966 | |
967 // DWARF3 Specification, Table 7.23 | |
968 enum CFIInstructions { | |
969 DW_CFA_ADVANCE_LOC = 0X40, | |
Erik Corry
2011/02/02 13:10:25
We use a small x everywhere in V8, so we should do
| |
970 DW_CFA_OFFSET = 0X80, | |
971 DW_CFA_RESTORE = 0XC0, | |
972 DW_CFA_NOP = 0X00, | |
973 DW_CFA_SET_LOC = 0X01, | |
974 DW_CFA_ADVANCE_LOC1 = 0X02, | |
975 DW_CFA_ADVANCE_LOC2 = 0X03, | |
976 DW_CFA_ADVANCE_LOC4 = 0X04, | |
977 DW_CFA_OFFSET_EXTENDED = 0X05, | |
978 DW_CFA_RESTORE_EXTENDED = 0X06, | |
979 DW_CFA_UNDEFINED = 0X07, | |
980 DW_CFA_SAME_VALUE = 0X08, | |
981 DW_CFA_REGISTER = 0X09, | |
982 DW_CFA_REMEMBER_STATE = 0X0A, | |
983 DW_CFA_RESTORE_STATE = 0X0B, | |
984 DW_CFA_DEF_CFA = 0X0C, | |
985 DW_CFA_DEF_CFA_REGISTER = 0X0D, | |
986 DW_CFA_DEF_CFA_OFFSET = 0X0E, | |
987 | |
988 DW_CFA_DEF_CFA_EXPRESSION = 0X0F, | |
989 DW_CFA_EXPRESSION = 0X10, | |
990 DW_CFA_OFFSET_EXTENDED_SF = 0X11, | |
991 DW_CFA_DEF_CFA_SF = 0X12, | |
992 DW_CFA_DEF_CFA_OFFSET_SF = 0X13, | |
993 DW_CFA_VAL_OFFSET = 0X14, | |
994 DW_CFA_VAL_OFFSET_SF = 0X15, | |
995 DW_CFA_VAL_EXPRESSION = 0X16 | |
996 }; | |
997 | |
998 // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36 | |
999 enum RegisterMapping { | |
1000 // Only the relevant ones have been added to reduce clutter. | |
1001 AMD64_RBP = 6, | |
1002 AMD64_RSP = 7, | |
1003 AMD64_RA = 16 | |
1004 }; | |
1005 | |
1006 enum CFIConstants { | |
1007 CIE_ID = 0, | |
1008 CIE_VERSION = 1, | |
1009 CODE_ALIGN_FACTOR = 1, | |
1010 DATA_ALIGN_FACTOR = 1, | |
1011 RETURN_ADDRESS_REGISTER = AMD64_RA | |
1012 }; | |
1013 }; | |
1014 | |
1015 | |
1016 void UnwindInfoSection::WriteLength(Writer *w, | |
1017 Writer::Slot<uint32_t> &length_slot, | |
1018 int initial_position) { | |
1019 uint32_t align = (w->position() - initial_position) % kPointerSize; | |
1020 | |
1021 if (align != 0) { | |
1022 for (uint32_t i = 0; i < (kPointerSize - align); i++) | |
Erik Corry
2011/02/02 13:10:25
Missing {} on multiline for statement.
| |
1023 w->Write<uint8_t>(DW_CFA_NOP); | |
1024 } | |
1025 | |
1026 ASSERT((w->position() - initial_position) % kPointerSize == 0); | |
1027 length_slot.set(w->position() - initial_position); | |
1028 } | |
1029 | |
1030 | |
1031 UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) | |
1032 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), desc_(desc) | |
1033 { } | |
1034 | |
1035 int UnwindInfoSection::WriteCIE(Writer *w) { | |
1036 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); | |
1037 uint32_t cie_position = w->position(); | |
1038 | |
1039 // Write out the CIE header. Currently no 'common instructions' are | |
1040 // emitted onto the CIE; every FDE has its own set of instructions. | |
1041 | |
1042 w->Write<uint32_t>(CIE_ID); | |
1043 w->Write<uint8_t>(CIE_VERSION); | |
1044 w->Write<uint8_t>(0); // Null augmentation string. | |
1045 w->WriteSLEB128(CODE_ALIGN_FACTOR); | |
1046 w->WriteSLEB128(DATA_ALIGN_FACTOR); | |
1047 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER); | |
1048 | |
1049 WriteLength(w, cie_length_slot, cie_position); | |
1050 | |
1051 return cie_position; | |
1052 } | |
1053 | |
1054 | |
1055 void UnwindInfoSection::WriteFDE(Writer *w, int cie_position) { | |
1056 // The only FDE for this function. The CFA is the current RBP. | |
1057 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>(); | |
1058 int fde_position = w->position(); | |
1059 w->Write<int32_t>(fde_position - cie_position + 4); | |
1060 | |
1061 w->Write<uintptr_t>(desc_->CodeStart()); | |
1062 w->Write<uintptr_t>(desc_->CodeSize()); | |
1063 | |
1064 WriteFDEStateOnEntry(w); | |
1065 WriteFDEStateAfterRBPPush(w); | |
1066 WriteFDEStateAfterRBPSet(w); | |
1067 WriteFDEStateAfterRBPPop(w); | |
1068 | |
1069 WriteLength(w, fde_length_slot, fde_position); | |
1070 } | |
1071 | |
1072 | |
1073 void UnwindInfoSection::WriteFDEStateOnEntry(Writer *w) { | |
1074 // The first state, just after the control has been transferred to the the | |
1075 // function. | |
1076 | |
1077 // RBP for this function will be the value of RSP after pushing the RBP | |
1078 // for the previous function. The previous RBP has not been pushed yet. | |
1079 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF); | |
1080 w->WriteULEB128(AMD64_RSP); | |
1081 w->WriteSLEB128(-kPointerSize); | |
1082 | |
1083 // The RA is stored at location CFA + kCallerPCOffset. This is an invariant, | |
1084 // and hence omitted from the next states. | |
1085 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); | |
1086 w->WriteULEB128(AMD64_RA); | |
1087 w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset); | |
1088 | |
1089 // The RBP of the previous function is still in RBP. | |
1090 w->Write<uint8_t>(DW_CFA_SAME_VALUE); | |
1091 w->WriteULEB128(AMD64_RBP); | |
1092 | |
1093 // Last location described by this entry. | |
1094 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1095 w->Write<uint64_t>( | |
1096 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH)); | |
1097 } | |
1098 | |
1099 | |
1100 void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer *w) { | |
1101 // The second state, just after RBP has been pushed. | |
1102 | |
1103 // RBP / CFA for this function is now the current RSP, so just set the | |
1104 // offset from the previous rule (from -8) to 0. | |
1105 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET); | |
1106 w->WriteULEB128(0); | |
1107 | |
1108 // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant | |
1109 // in this and the next state, and hence omitted in the next state. | |
1110 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); | |
1111 w->WriteULEB128(AMD64_RBP); | |
1112 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset); | |
1113 | |
1114 // Last location described by this entry. | |
1115 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1116 w->Write<uint64_t>( | |
1117 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET)); | |
1118 } | |
1119 | |
1120 | |
1121 void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer *w) { | |
1122 // The third state, after the RBP has been set. | |
1123 | |
1124 // The CFA can now directly be set to RBP. | |
1125 w->Write<uint8_t>(DW_CFA_DEF_CFA); | |
1126 w->WriteULEB128(AMD64_RBP); | |
1127 w->WriteULEB128(0); | |
1128 | |
1129 // Last location described by this entry. | |
1130 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1131 w->Write<uint64_t>( | |
1132 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP)); | |
1133 } | |
1134 | |
1135 | |
1136 void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer *w) { | |
1137 // The fourth (final) state. The RBP has been popped (just before issuing a | |
1138 // return). | |
1139 | |
1140 // The CFA can is now calculated in the same way as in the first state. | |
1141 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF); | |
1142 w->WriteULEB128(AMD64_RSP); | |
1143 w->WriteSLEB128(-kPointerSize); | |
1144 | |
1145 // The RBP | |
1146 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); | |
1147 w->WriteULEB128(AMD64_RBP); | |
1148 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset); | |
1149 | |
1150 // Last location described by this entry. | |
1151 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1152 w->Write<uint64_t>(desc_->CodeEnd()); | |
1153 } | |
1154 | |
1155 | |
1156 bool UnwindInfoSection::WriteBody(Writer *w) { | |
1157 uint32_t cie_position = WriteCIE(w); | |
1158 WriteFDE(w, cie_position); | |
1159 return true; | |
1160 } | |
1161 | |
1162 | |
1163 #endif // V8_TARGET_ARCH_X64 | |
1164 | |
1165 | |
903 static void CreateDWARFSections(CodeDescription* desc, ELF* elf) { | 1166 static void CreateDWARFSections(CodeDescription* desc, ELF* elf) { |
904 if (desc->is_line_info_available()) { | 1167 if (desc->IsLineInfoAvailable()) { |
905 elf->AddSection(new DebugInfoSection(desc)); | 1168 elf->AddSection(new DebugInfoSection(desc)); |
906 elf->AddSection(new DebugAbbrevSection); | 1169 elf->AddSection(new DebugAbbrevSection); |
907 elf->AddSection(new DebugLineSection(desc)); | 1170 elf->AddSection(new DebugLineSection(desc)); |
908 } | 1171 } |
909 } | 1172 #ifdef V8_TARGET_ARCH_X64 |
910 | 1173 elf->AddSection(new UnwindInfoSection(desc)); |
911 | 1174 #endif |
1175 } | |
1176 | |
1177 | |
912 // ------------------------------------------------------------------- | 1178 // ------------------------------------------------------------------- |
913 // Binary GDB JIT Interface as described in | 1179 // Binary GDB JIT Interface as described in |
914 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html | 1180 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html |
915 extern "C" { | 1181 extern "C" { |
916 typedef enum { | 1182 typedef enum { |
917 JIT_NOACTION = 0, | 1183 JIT_NOACTION = 0, |
918 JIT_REGISTER_FN, | 1184 JIT_REGISTER_FN, |
919 JIT_UNREGISTER_FN | 1185 JIT_UNREGISTER_FN |
920 } JITAction; | 1186 } JITAction; |
921 | 1187 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
998 static JITCodeEntry* CreateELFObject(CodeDescription* desc) { | 1264 static JITCodeEntry* CreateELFObject(CodeDescription* desc) { |
999 ZoneScope zone_scope(DELETE_ON_EXIT); | 1265 ZoneScope zone_scope(DELETE_ON_EXIT); |
1000 | 1266 |
1001 ELF elf; | 1267 ELF elf; |
1002 Writer w(&elf); | 1268 Writer w(&elf); |
1003 | 1269 |
1004 int text_section_index = elf.AddSection( | 1270 int text_section_index = elf.AddSection( |
1005 new FullHeaderELFSection(".text", | 1271 new FullHeaderELFSection(".text", |
1006 ELFSection::TYPE_NOBITS, | 1272 ELFSection::TYPE_NOBITS, |
1007 kCodeAlignment, | 1273 kCodeAlignment, |
1008 desc->code_start(), | 1274 desc->CodeStart(), |
1009 0, | 1275 0, |
1010 desc->code_size(), | 1276 desc->CodeSize(), |
1011 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); | 1277 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); |
1012 | 1278 |
1013 CreateSymbolsTable(desc, &elf, text_section_index); | 1279 CreateSymbolsTable(desc, &elf, text_section_index); |
1014 | 1280 |
1015 CreateDWARFSections(desc, &elf); | 1281 CreateDWARFSections(desc, &elf); |
1016 | 1282 |
1017 elf.Write(&w); | 1283 elf.Write(&w); |
1018 | 1284 |
1019 return CreateCodeEntry(w.buffer(), w.position()); | 1285 return CreateCodeEntry(w.buffer(), w.position()); |
1020 } | 1286 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1058 void GDBJITInterface::AddCode(Handle<String> name, | 1324 void GDBJITInterface::AddCode(Handle<String> name, |
1059 Handle<Script> script, | 1325 Handle<Script> script, |
1060 Handle<Code> code) { | 1326 Handle<Code> code) { |
1061 if (!FLAG_gdbjit) return; | 1327 if (!FLAG_gdbjit) return; |
1062 | 1328 |
1063 // Force initialization of line_ends array. | 1329 // Force initialization of line_ends array. |
1064 GetScriptLineNumber(script, 0); | 1330 GetScriptLineNumber(script, 0); |
1065 | 1331 |
1066 if (!name.is_null()) { | 1332 if (!name.is_null()) { |
1067 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); | 1333 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); |
1068 AddCode(*name_cstring, *code, *script); | 1334 AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script); |
1069 } else { | 1335 } else { |
1070 AddCode("", *code, *script); | 1336 AddCode("", *code, GDBJITInterface::FUNCTION, *script); |
1071 } | 1337 } |
1072 } | 1338 } |
1073 | 1339 |
1340 static void AddUnwindInfo(CodeDescription *desc) { | |
1341 #ifdef V8_TARGET_ARCH_X64 | |
1342 if (desc->tag() == GDBJITInterface::FUNCTION) { | |
1343 // To avoid propagating unwinding information through | |
1344 // compilation pipeline we rely on constant offsets as | |
1345 // function prologue and epilogue are the same for all | |
Erik Corry
2011/02/02 13:10:25
we rely on ... are the same -> we rely on ... bein
| |
1346 // code objects generated by the full code generator. | |
1347 static const int kFramePointerPushOffset = 1; | |
1348 static const int kFramePointerSetOffset = 4; | |
1349 static const int kFramePointerPopOffset = -3; | |
1350 | |
1351 uintptr_t frame_pointer_push_address = | |
1352 desc->CodeStart() + kFramePointerPushOffset; | |
1353 | |
1354 uintptr_t frame_pointer_set_address = | |
1355 desc->CodeStart() + kFramePointerSetOffset; | |
1356 | |
1357 uintptr_t frame_pointer_pop_address = | |
1358 desc->CodeEnd() + kFramePointerPopOffset; | |
1359 | |
1360 #ifdef DEBUG | |
1361 static const uint8_t kFramePointerPushInstruction = 0x48; // push ebp | |
1362 static const uint16_t kFramePointerSetInstruction = 0x5756; // mov ebp, esp | |
1363 static const uint8_t kFramePointerPopInstruction = 0xBE; // pop ebp | |
1364 | |
1365 ASSERT(*reinterpret_cast<uint8_t*>(frame_pointer_push_address) == | |
1366 kFramePointerPushInstruction); | |
1367 ASSERT(*reinterpret_cast<uint16_t*>(frame_pointer_set_address) == | |
1368 kFramePointerSetInstruction); | |
1369 ASSERT(*reinterpret_cast<uint8_t*>(frame_pointer_pop_address) == | |
1370 kFramePointerPopInstruction); | |
1371 #endif | |
1372 | |
1373 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH, | |
1374 frame_pointer_push_address); | |
1375 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET, | |
1376 frame_pointer_set_address); | |
1377 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP, | |
1378 frame_pointer_pop_address); | |
1379 } else { | |
1380 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH, | |
1381 desc->CodeStart()); | |
1382 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET, | |
1383 desc->CodeStart()); | |
1384 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP, | |
1385 desc->CodeEnd()); | |
1386 } | |
1387 #endif // V8_TARGET_ARCH_X64 | |
1388 } | |
1389 | |
1074 | 1390 |
1075 void GDBJITInterface::AddCode(const char* name, | 1391 void GDBJITInterface::AddCode(const char* name, |
1076 Code* code, | 1392 Code* code, |
1393 GDBJITInterface::CodeTag tag, | |
1077 Script* script) { | 1394 Script* script) { |
1078 if (!FLAG_gdbjit) return; | 1395 if (!FLAG_gdbjit) return; |
1079 AssertNoAllocation no_gc; | 1396 AssertNoAllocation no_gc; |
1080 | 1397 |
1081 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); | 1398 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); |
1082 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; | 1399 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; |
1083 | 1400 |
1084 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); | 1401 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); |
1085 CodeDescription code_desc(name, | 1402 CodeDescription code_desc(name, |
1086 code, | 1403 code, |
1087 script != NULL ? Handle<Script>(script) | 1404 script != NULL ? Handle<Script>(script) |
1088 : Handle<Script>(), | 1405 : Handle<Script>(), |
1089 lineinfo); | 1406 lineinfo, |
1407 tag); | |
1090 | 1408 |
1091 if (!FLAG_gdbjit_full && !code_desc.is_line_info_available()) { | 1409 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { |
1092 delete lineinfo; | 1410 delete lineinfo; |
1093 entries.Remove(code, HashForCodeObject(code)); | 1411 entries.Remove(code, HashForCodeObject(code)); |
1094 return; | 1412 return; |
1095 } | 1413 } |
1096 | 1414 |
1415 AddUnwindInfo(&code_desc); | |
1097 JITCodeEntry* entry = CreateELFObject(&code_desc); | 1416 JITCodeEntry* entry = CreateELFObject(&code_desc); |
1098 ASSERT(!IsLineInfoTagged(entry)); | 1417 ASSERT(!IsLineInfoTagged(entry)); |
1099 | 1418 |
1100 delete lineinfo; | 1419 delete lineinfo; |
1101 e->value = entry; | 1420 e->value = entry; |
1102 | 1421 |
1103 RegisterCodeEntry(entry); | 1422 RegisterCodeEntry(entry); |
1104 } | 1423 } |
1105 | 1424 |
1106 | 1425 |
1107 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | 1426 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, |
1108 const char* name, | 1427 const char* name, |
1109 Code* code) { | 1428 Code* code) { |
1110 if (!FLAG_gdbjit) return; | 1429 if (!FLAG_gdbjit) return; |
1111 | 1430 |
1112 EmbeddedVector<char, 256> buffer; | 1431 EmbeddedVector<char, 256> buffer; |
1113 StringBuilder builder(buffer.start(), buffer.length()); | 1432 StringBuilder builder(buffer.start(), buffer.length()); |
1114 | 1433 |
1115 builder.AddString(Tag2String(tag)); | 1434 builder.AddString(Tag2String(tag)); |
1116 if ((name != NULL) && (*name != '\0')) { | 1435 if ((name != NULL) && (*name != '\0')) { |
1117 builder.AddString(": "); | 1436 builder.AddString(": "); |
1118 builder.AddString(name); | 1437 builder.AddString(name); |
1119 } else { | 1438 } else { |
1120 builder.AddFormatted(": code object %p", static_cast<void*>(code)); | 1439 builder.AddFormatted(": code object %p", static_cast<void*>(code)); |
1121 } | 1440 } |
1122 | 1441 |
1123 AddCode(builder.Finalize(), code); | 1442 AddCode(builder.Finalize(), code, tag); |
1124 } | 1443 } |
1125 | 1444 |
1126 | 1445 |
1127 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | 1446 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, |
1128 String* name, | 1447 String* name, |
1129 Code* code) { | 1448 Code* code) { |
1130 if (!FLAG_gdbjit) return; | 1449 if (!FLAG_gdbjit) return; |
1131 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code); | 1450 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code); |
1132 } | 1451 } |
1133 | 1452 |
(...skipping 27 matching lines...) Expand all Loading... | |
1161 GDBJITLineInfo* line_info) { | 1480 GDBJITLineInfo* line_info) { |
1162 ASSERT(!IsLineInfoTagged(line_info)); | 1481 ASSERT(!IsLineInfoTagged(line_info)); |
1163 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); | 1482 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); |
1164 ASSERT(e->value == NULL); | 1483 ASSERT(e->value == NULL); |
1165 e->value = TagLineInfo(line_info); | 1484 e->value = TagLineInfo(line_info); |
1166 } | 1485 } |
1167 | 1486 |
1168 | 1487 |
1169 } } // namespace v8::internal | 1488 } } // namespace v8::internal |
1170 #endif | 1489 #endif |
OLD | NEW |