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 |