| OLD | NEW |
| 1 // Copyright 2007-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2007-2008 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 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 : converter_(converter), | 226 : converter_(converter), |
| 227 tmp_buffer_pos_(0), | 227 tmp_buffer_pos_(0), |
| 228 abort_on_unimplemented_(abort_on_unimplemented) { | 228 abort_on_unimplemented_(abort_on_unimplemented) { |
| 229 tmp_buffer_[0] = '\0'; | 229 tmp_buffer_[0] = '\0'; |
| 230 } | 230 } |
| 231 | 231 |
| 232 virtual ~DisassemblerIA32() {} | 232 virtual ~DisassemblerIA32() {} |
| 233 | 233 |
| 234 // Writes one disassembled instruction into 'buffer' (0-terminated). | 234 // Writes one disassembled instruction into 'buffer' (0-terminated). |
| 235 // Returns the length of the disassembled machine instruction in bytes. | 235 // Returns the length of the disassembled machine instruction in bytes. |
| 236 int InstructionDecode(char* buffer, const int buffer_size, byte* instruction); | 236 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); |
| 237 | 237 |
| 238 private: | 238 private: |
| 239 const NameConverter& converter_; | 239 const NameConverter& converter_; |
| 240 char tmp_buffer_[128]; | 240 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; |
| 241 unsigned int tmp_buffer_pos_; | 241 unsigned int tmp_buffer_pos_; |
| 242 bool abort_on_unimplemented_; | 242 bool abort_on_unimplemented_; |
| 243 | 243 |
| 244 | 244 |
| 245 enum { | 245 enum { |
| 246 eax = 0, | 246 eax = 0, |
| 247 ecx = 1, | 247 ecx = 1, |
| 248 edx = 2, | 248 edx = 2, |
| 249 ebx = 3, | 249 ebx = 3, |
| 250 esp = 4, | 250 esp = 4, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 if (abort_on_unimplemented_) { | 300 if (abort_on_unimplemented_) { |
| 301 UNIMPLEMENTED(); | 301 UNIMPLEMENTED(); |
| 302 } else { | 302 } else { |
| 303 AppendToBuffer("'Unimplemented Instruction'"); | 303 AppendToBuffer("'Unimplemented Instruction'"); |
| 304 } | 304 } |
| 305 } | 305 } |
| 306 }; | 306 }; |
| 307 | 307 |
| 308 | 308 |
| 309 void DisassemblerIA32::AppendToBuffer(const char* format, ...) { | 309 void DisassemblerIA32::AppendToBuffer(const char* format, ...) { |
| 310 char* str = tmp_buffer_ + tmp_buffer_pos_; | 310 v8::internal::Vector<char> buf = tmp_buffer_ + tmp_buffer_pos_; |
| 311 int size = (sizeof tmp_buffer_) - tmp_buffer_pos_; | |
| 312 va_list args; | 311 va_list args; |
| 313 va_start(args, format); | 312 va_start(args, format); |
| 314 #ifdef WIN32 | 313 int result = v8::internal::OS::VSNPrintF(buf, format, args); |
| 315 int result = _vsnprintf(str, size, format, args); | |
| 316 #else | |
| 317 int result = vsnprintf(str, size, format, args); | |
| 318 #endif | |
| 319 va_end(args); | 314 va_end(args); |
| 320 tmp_buffer_pos_ += result; | 315 tmp_buffer_pos_ += result; |
| 321 } | 316 } |
| 322 | 317 |
| 323 | 318 |
| 324 // Returns number of bytes used including the current *modrmp. | 319 // Returns number of bytes used including the current *modrmp. |
| 325 // Writes instruction's right operand to 'tmp_buffer_'. | 320 // Writes instruction's right operand to 'tmp_buffer_'. |
| 326 int DisassemblerIA32::PrintRightOperand(byte* modrmp) { | 321 int DisassemblerIA32::PrintRightOperand(byte* modrmp) { |
| 327 int mod, regop, rm; | 322 int mod, regop, rm; |
| 328 get_modrm(*modrmp, &mod, ®op, &rm); | 323 get_modrm(*modrmp, &mod, ®op, &rm); |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 case 0xAF: return "imul"; | 694 case 0xAF: return "imul"; |
| 700 case 0xA5: return "shld"; | 695 case 0xA5: return "shld"; |
| 701 case 0xAD: return "shrd"; | 696 case 0xAD: return "shrd"; |
| 702 case 0xAB: return "bts"; | 697 case 0xAB: return "bts"; |
| 703 default: return NULL; | 698 default: return NULL; |
| 704 } | 699 } |
| 705 } | 700 } |
| 706 | 701 |
| 707 | 702 |
| 708 // Disassembled instruction '*instr' and writes it intro 'out_buffer'. | 703 // Disassembled instruction '*instr' and writes it intro 'out_buffer'. |
| 709 int DisassemblerIA32::InstructionDecode(char* out_buffer, | 704 int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer, |
| 710 const int out_buffer_size, | |
| 711 byte* instr) { | 705 byte* instr) { |
| 712 tmp_buffer_pos_ = 0; // starting to write as position 0 | 706 tmp_buffer_pos_ = 0; // starting to write as position 0 |
| 713 byte* data = instr; | 707 byte* data = instr; |
| 714 // Check for hints. | 708 // Check for hints. |
| 715 const char* branch_hint = NULL; | 709 const char* branch_hint = NULL; |
| 716 // We use this two prefixes only with branch prediction | 710 // We use this two prefixes only with branch prediction |
| 717 if (*data == 0x3E /*ds*/) { | 711 if (*data == 0x3E /*ds*/) { |
| 718 branch_hint = "predicted taken"; | 712 branch_hint = "predicted taken"; |
| 719 data++; | 713 data++; |
| 720 } else if (*data == 0x2E /*cs*/) { | 714 } else if (*data == 0x2E /*cs*/) { |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 tmp_buffer_[tmp_buffer_pos_] = '\0'; | 1027 tmp_buffer_[tmp_buffer_pos_] = '\0'; |
| 1034 } | 1028 } |
| 1035 | 1029 |
| 1036 int instr_len = data - instr; | 1030 int instr_len = data - instr; |
| 1037 ASSERT(instr_len > 0); // Ensure progress. | 1031 ASSERT(instr_len > 0); // Ensure progress. |
| 1038 | 1032 |
| 1039 int outp = 0; | 1033 int outp = 0; |
| 1040 // Instruction bytes. | 1034 // Instruction bytes. |
| 1041 for (byte* bp = instr; bp < data; bp++) { | 1035 for (byte* bp = instr; bp < data; bp++) { |
| 1042 outp += v8::internal::OS::SNPrintF(out_buffer + outp, | 1036 outp += v8::internal::OS::SNPrintF(out_buffer + outp, |
| 1043 out_buffer_size - outp, | |
| 1044 "%02x", | 1037 "%02x", |
| 1045 *bp); | 1038 *bp); |
| 1046 } | 1039 } |
| 1047 for (int i = 6 - instr_len; i >= 0; i--) { | 1040 for (int i = 6 - instr_len; i >= 0; i--) { |
| 1048 outp += v8::internal::OS::SNPrintF(out_buffer + outp, | 1041 outp += v8::internal::OS::SNPrintF(out_buffer + outp, |
| 1049 out_buffer_size - outp, | |
| 1050 " "); | 1042 " "); |
| 1051 } | 1043 } |
| 1052 | 1044 |
| 1053 outp += v8::internal::OS::SNPrintF(out_buffer + outp, | 1045 outp += v8::internal::OS::SNPrintF(out_buffer + outp, |
| 1054 out_buffer_size - outp, | |
| 1055 " %s", | 1046 " %s", |
| 1056 tmp_buffer_); | 1047 tmp_buffer_.start()); |
| 1057 return instr_len; | 1048 return instr_len; |
| 1058 } | 1049 } |
| 1059 | 1050 |
| 1060 | 1051 |
| 1061 //------------------------------------------------------------------------------ | 1052 //------------------------------------------------------------------------------ |
| 1062 | 1053 |
| 1063 | 1054 |
| 1064 static const char* cpu_regs[8] = { | 1055 static const char* cpu_regs[8] = { |
| 1065 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", | 1056 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", |
| 1066 }; | 1057 }; |
| 1067 | 1058 |
| 1068 | 1059 |
| 1069 static const char* xmm_regs[8] = { | 1060 static const char* xmm_regs[8] = { |
| 1070 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", | 1061 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", |
| 1071 }; | 1062 }; |
| 1072 | 1063 |
| 1073 | 1064 |
| 1074 const char* NameConverter::NameOfAddress(byte* addr) const { | 1065 const char* NameConverter::NameOfAddress(byte* addr) const { |
| 1075 static char tmp_buffer[32]; | 1066 v8::internal::EmbeddedVector<char, 32> tmp_buffer; |
| 1076 #ifdef WIN32 | 1067 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr); |
| 1077 _snprintf(tmp_buffer, sizeof tmp_buffer, "%p", addr); | 1068 return tmp_buffer.start(); |
| 1078 #else | |
| 1079 snprintf(tmp_buffer, sizeof tmp_buffer, "%p", addr); | |
| 1080 #endif | |
| 1081 return tmp_buffer; | |
| 1082 } | 1069 } |
| 1083 | 1070 |
| 1084 | 1071 |
| 1085 const char* NameConverter::NameOfConstant(byte* addr) const { | 1072 const char* NameConverter::NameOfConstant(byte* addr) const { |
| 1086 return NameOfAddress(addr); | 1073 return NameOfAddress(addr); |
| 1087 } | 1074 } |
| 1088 | 1075 |
| 1089 | 1076 |
| 1090 const char* NameConverter::NameOfCPURegister(int reg) const { | 1077 const char* NameConverter::NameOfCPURegister(int reg) const { |
| 1091 if (0 <= reg && reg < 8) return cpu_regs[reg]; | 1078 if (0 <= reg && reg < 8) return cpu_regs[reg]; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1113 Disassembler::Disassembler() : converter_(defaultConverter) {} | 1100 Disassembler::Disassembler() : converter_(defaultConverter) {} |
| 1114 | 1101 |
| 1115 | 1102 |
| 1116 Disassembler::Disassembler(const NameConverter& converter) | 1103 Disassembler::Disassembler(const NameConverter& converter) |
| 1117 : converter_(converter) {} | 1104 : converter_(converter) {} |
| 1118 | 1105 |
| 1119 | 1106 |
| 1120 Disassembler::~Disassembler() {} | 1107 Disassembler::~Disassembler() {} |
| 1121 | 1108 |
| 1122 | 1109 |
| 1123 int Disassembler::InstructionDecode(char* buffer, | 1110 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, |
| 1124 const int buffer_size, | |
| 1125 byte* instruction) { | 1111 byte* instruction) { |
| 1126 DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/); | 1112 DisassemblerIA32 d(converter_, false /*do not crash if unimplemented*/); |
| 1127 return d.InstructionDecode(buffer, buffer_size, instruction); | 1113 return d.InstructionDecode(buffer, instruction); |
| 1128 } | 1114 } |
| 1129 | 1115 |
| 1130 | 1116 |
| 1131 // The IA-32 assembler does not currently use constant pools. | 1117 // The IA-32 assembler does not currently use constant pools. |
| 1132 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } | 1118 int Disassembler::ConstantPoolSizeAt(byte* instruction) { return -1; } |
| 1133 | 1119 |
| 1134 | 1120 |
| 1135 /*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { | 1121 /*static*/ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { |
| 1136 Disassembler d; | 1122 Disassembler d; |
| 1137 for (byte* pc = begin; pc < end;) { | 1123 for (byte* pc = begin; pc < end;) { |
| 1138 char buffer[128]; | 1124 v8::internal::EmbeddedVector<char, 128> buffer; |
| 1139 buffer[0] = '\0'; | 1125 buffer[0] = '\0'; |
| 1140 byte* prev_pc = pc; | 1126 byte* prev_pc = pc; |
| 1141 pc += d.InstructionDecode(buffer, sizeof buffer, pc); | 1127 pc += d.InstructionDecode(buffer, pc); |
| 1142 fprintf(f, "%p", prev_pc); | 1128 fprintf(f, "%p", prev_pc); |
| 1143 fprintf(f, " "); | 1129 fprintf(f, " "); |
| 1144 | 1130 |
| 1145 for (byte* bp = prev_pc; bp < pc; bp++) { | 1131 for (byte* bp = prev_pc; bp < pc; bp++) { |
| 1146 fprintf(f, "%02x", *bp); | 1132 fprintf(f, "%02x", *bp); |
| 1147 } | 1133 } |
| 1148 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { | 1134 for (int i = 6 - (pc - prev_pc); i >= 0; i--) { |
| 1149 fprintf(f, " "); | 1135 fprintf(f, " "); |
| 1150 } | 1136 } |
| 1151 fprintf(f, " %s\n", buffer); | 1137 fprintf(f, " %s\n", buffer.start()); |
| 1152 } | 1138 } |
| 1153 } | 1139 } |
| 1154 | 1140 |
| 1155 | 1141 |
| 1156 } // namespace disasm | 1142 } // namespace disasm |
| OLD | NEW |