| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/disassembler.h" | 5 #include "vm/disassembler.h" |
| 6 | 6 |
| 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 8 #if defined(TARGET_ARCH_ARM) | 8 #if defined(TARGET_ARCH_ARM) |
| 9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
| 10 | 10 |
| 11 namespace dart { | 11 namespace dart { |
| 12 | 12 |
| 13 class ARMDecoder : public ValueObject { | 13 class ARMDecoder : public ValueObject { |
| 14 public: | 14 public: |
| 15 ARMDecoder(char* buffer, size_t buffer_size) | 15 ARMDecoder(char* buffer, size_t buffer_size) |
| 16 : buffer_(buffer), | 16 : buffer_(buffer), |
| 17 buffer_size_(buffer_size), | 17 buffer_size_(buffer_size), |
| 18 buffer_pos_(0) { | 18 buffer_pos_(0), |
| 19 decode_failure_(false) { |
| 19 buffer_[buffer_pos_] = '\0'; | 20 buffer_[buffer_pos_] = '\0'; |
| 20 } | 21 } |
| 21 | 22 |
| 22 ~ARMDecoder() {} | 23 ~ARMDecoder() {} |
| 23 | 24 |
| 24 // Writes one disassembled instruction into 'buffer' (0-terminated). | 25 // Writes one disassembled instruction into 'buffer' (0-terminated). |
| 26 // Returns true if the instruction was successfully decoded, false otherwise. |
| 25 void InstructionDecode(uword pc); | 27 void InstructionDecode(uword pc); |
| 26 | 28 |
| 29 void DetectedDecodeFailure() { decode_failure_ = true; } |
| 30 bool GetDecodeFailure() const { return decode_failure_; } |
| 31 |
| 27 private: | 32 private: |
| 28 // Bottleneck functions to print into the out_buffer. | 33 // Bottleneck functions to print into the out_buffer. |
| 29 void Print(const char* str); | 34 void Print(const char* str); |
| 30 | 35 |
| 31 // Printing of common values. | 36 // Printing of common values. |
| 32 void PrintRegister(int reg); | 37 void PrintRegister(int reg); |
| 33 void PrintSRegister(int reg); | 38 void PrintSRegister(int reg); |
| 34 void PrintDRegister(int reg); | 39 void PrintDRegister(int reg); |
| 35 void PrintCondition(Instr* instr); | 40 void PrintCondition(Instr* instr); |
| 36 void PrintShiftRm(Instr* instr); | 41 void PrintShiftRm(Instr* instr); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 59 | 64 |
| 60 // Convenience functions. | 65 // Convenience functions. |
| 61 char* get_buffer() const { return buffer_; } | 66 char* get_buffer() const { return buffer_; } |
| 62 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } | 67 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } |
| 63 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } | 68 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } |
| 64 | 69 |
| 65 char* buffer_; // Decode instructions into this buffer. | 70 char* buffer_; // Decode instructions into this buffer. |
| 66 size_t buffer_size_; // The size of the character buffer. | 71 size_t buffer_size_; // The size of the character buffer. |
| 67 size_t buffer_pos_; // Current character position in buffer. | 72 size_t buffer_pos_; // Current character position in buffer. |
| 68 | 73 |
| 74 bool decode_failure_; // Set to true when a failure to decode is detected. |
| 75 |
| 69 DISALLOW_ALLOCATION(); | 76 DISALLOW_ALLOCATION(); |
| 70 DISALLOW_COPY_AND_ASSIGN(ARMDecoder); | 77 DISALLOW_COPY_AND_ASSIGN(ARMDecoder); |
| 71 }; | 78 }; |
| 72 | 79 |
| 73 | 80 |
| 74 // Support for assertions in the ARMDecoder formatting functions. | 81 // Support for assertions in the ARMDecoder formatting functions. |
| 75 #define STRING_STARTS_WITH(string, compare_string) \ | 82 #define STRING_STARTS_WITH(string, compare_string) \ |
| 76 (strncmp(string, compare_string, strlen(compare_string)) == 0) | 83 (strncmp(string, compare_string, strlen(compare_string)) == 0) |
| 77 | 84 |
| 78 | 85 |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 cur = *format++; | 572 cur = *format++; |
| 566 } | 573 } |
| 567 buffer_[buffer_pos_] = '\0'; | 574 buffer_[buffer_pos_] = '\0'; |
| 568 } | 575 } |
| 569 | 576 |
| 570 | 577 |
| 571 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 578 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 572 // which will just print "unknown" of the instruction bits. | 579 // which will just print "unknown" of the instruction bits. |
| 573 void ARMDecoder::Unknown(Instr* instr) { | 580 void ARMDecoder::Unknown(Instr* instr) { |
| 574 Format(instr, "unknown"); | 581 Format(instr, "unknown"); |
| 582 DetectedDecodeFailure(); |
| 575 } | 583 } |
| 576 | 584 |
| 577 | 585 |
| 578 void ARMDecoder::DecodeType01(Instr* instr) { | 586 void ARMDecoder::DecodeType01(Instr* instr) { |
| 579 if (!instr->IsDataProcessing()) { | 587 if (!instr->IsDataProcessing()) { |
| 580 // miscellaneous, multiply, sync primitives, extra loads and stores. | 588 // miscellaneous, multiply, sync primitives, extra loads and stores. |
| 581 if (instr->IsMiscellaneous()) { | 589 if (instr->IsMiscellaneous()) { |
| 582 switch (instr->Bits(4, 3)) { | 590 switch (instr->Bits(4, 3)) { |
| 583 case 1: { | 591 case 1: { |
| 584 if (instr->Bits(21, 2) == 0x3) { | 592 if (instr->Bits(21, 2) == 0x3) { |
| (...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 } | 1211 } |
| 1204 } else if (instr->IsMrcIdIsar0()) { | 1212 } else if (instr->IsMrcIdIsar0()) { |
| 1205 Format(instr, "mrc'cond p15, 0, 'rd, c0, c2, 0"); | 1213 Format(instr, "mrc'cond p15, 0, 'rd, c0, c2, 0"); |
| 1206 } else { | 1214 } else { |
| 1207 Unknown(instr); | 1215 Unknown(instr); |
| 1208 } | 1216 } |
| 1209 } | 1217 } |
| 1210 | 1218 |
| 1211 | 1219 |
| 1212 void ARMDecoder::InstructionDecode(uword pc) { | 1220 void ARMDecoder::InstructionDecode(uword pc) { |
| 1213 Instr* instr = Instr::At(pc); | 1221 Instr* instr = Instr::At(pc); |
| 1222 |
| 1214 if (instr->ConditionField() == kSpecialCondition) { | 1223 if (instr->ConditionField() == kSpecialCondition) { |
| 1215 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { | 1224 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { |
| 1216 Format(instr, "clrex"); | 1225 Format(instr, "clrex"); |
| 1217 } else { | 1226 } else { |
| 1218 Unknown(instr); | 1227 Unknown(instr); |
| 1219 } | 1228 } |
| 1220 } else { | 1229 } else { |
| 1221 switch (instr->TypeField()) { | 1230 switch (instr->TypeField()) { |
| 1222 case 0: | 1231 case 0: |
| 1223 case 1: { | 1232 case 1: { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1251 default: { | 1260 default: { |
| 1252 // The type field is 3-bits in the ARM encoding. | 1261 // The type field is 3-bits in the ARM encoding. |
| 1253 UNREACHABLE(); | 1262 UNREACHABLE(); |
| 1254 break; | 1263 break; |
| 1255 } | 1264 } |
| 1256 } | 1265 } |
| 1257 } | 1266 } |
| 1258 } | 1267 } |
| 1259 | 1268 |
| 1260 | 1269 |
| 1261 int Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, | 1270 bool Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, |
| 1262 char* human_buffer, intptr_t human_size, | 1271 char* human_buffer, intptr_t human_size, |
| 1263 uword pc) { | 1272 int* out_instr_size, uword pc) { |
| 1264 ARMDecoder decoder(human_buffer, human_size); | 1273 ARMDecoder decoder(human_buffer, human_size); |
| 1265 decoder.InstructionDecode(pc); | 1274 decoder.InstructionDecode(pc); |
| 1266 int32_t instruction_bits = Instr::At(pc)->InstructionBits(); | 1275 int32_t instruction_bits = Instr::At(pc)->InstructionBits(); |
| 1267 OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits); | 1276 OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits); |
| 1268 return Instr::kInstrSize; | 1277 if (out_instr_size) { |
| 1278 *out_instr_size = Instr::kInstrSize; |
| 1279 } |
| 1280 return !decoder.GetDecodeFailure(); |
| 1269 } | 1281 } |
| 1270 | 1282 |
| 1271 | 1283 |
| 1272 void Disassembler::Disassemble(uword start, | 1284 bool Disassembler::Disassemble(uword start, |
| 1273 uword end, | 1285 uword end, |
| 1274 DisassemblyFormatter* formatter, | 1286 DisassemblyFormatter* formatter, |
| 1275 const Code::Comments& comments) { | 1287 const Code::Comments& comments) { |
| 1276 ASSERT(formatter != NULL); | 1288 ASSERT(formatter != NULL); |
| 1289 bool success = true; |
| 1277 char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form. | 1290 char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form. |
| 1278 char human_buffer[kUserReadableBufferSize]; // Human-readable instruction. | 1291 char human_buffer[kUserReadableBufferSize]; // Human-readable instruction. |
| 1279 uword pc = start; | 1292 uword pc = start; |
| 1280 intptr_t comment_finger = 0; | 1293 intptr_t comment_finger = 0; |
| 1281 while (pc < end) { | 1294 while (pc < end) { |
| 1282 const intptr_t offset = pc - start; | 1295 const intptr_t offset = pc - start; |
| 1283 while (comment_finger < comments.Length() && | 1296 while (comment_finger < comments.Length() && |
| 1284 comments.PCOffsetAt(comment_finger) <= offset) { | 1297 comments.PCOffsetAt(comment_finger) <= offset) { |
| 1285 formatter->Print( | 1298 formatter->Print( |
| 1286 " ;; %s\n", | 1299 " ;; %s\n", |
| 1287 String::Handle(comments.CommentAt(comment_finger)).ToCString()); | 1300 String::Handle(comments.CommentAt(comment_finger)).ToCString()); |
| 1288 comment_finger++; | 1301 comment_finger++; |
| 1289 } | 1302 } |
| 1290 int instruction_length = DecodeInstruction(hex_buffer, | 1303 int instruction_length; |
| 1291 sizeof(hex_buffer), | 1304 bool res = DecodeInstruction(hex_buffer, sizeof(hex_buffer), |
| 1292 human_buffer, | 1305 human_buffer, sizeof(human_buffer), |
| 1293 sizeof(human_buffer), | 1306 &instruction_length, pc); |
| 1294 pc); | 1307 if (!res) { |
| 1308 success = false; |
| 1309 } |
| 1295 formatter->ConsumeInstruction(hex_buffer, | 1310 formatter->ConsumeInstruction(hex_buffer, |
| 1296 sizeof(hex_buffer), | 1311 sizeof(hex_buffer), |
| 1297 human_buffer, | 1312 human_buffer, |
| 1298 sizeof(human_buffer), | 1313 sizeof(human_buffer), |
| 1299 pc); | 1314 pc); |
| 1300 pc += instruction_length; | 1315 pc += instruction_length; |
| 1301 } | 1316 } |
| 1317 |
| 1318 return success; |
| 1302 } | 1319 } |
| 1303 | 1320 |
| 1304 } // namespace dart | 1321 } // namespace dart |
| 1305 | 1322 |
| 1306 #endif // defined TARGET_ARCH_ARM | 1323 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |