1e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu/* 2e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * Copyright (C) 2014 The Android Open Source Project 3e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * 4e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * Licensed under the Apache License, Version 2.0 (the "License"); 5e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * you may not use this file except in compliance with the License. 6e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * You may obtain a copy of the License at 7e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * 8e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * http://www.apache.org/licenses/LICENSE-2.0 9e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * 10e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * Unless required by applicable law or agreed to in writing, software 11e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * distributed under the License is distributed on an "AS IS" BASIS, 12e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * See the License for the specific language governing permissions and 14e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu * limitations under the License. 15e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu */ 16e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu 17e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu#include "disassembler_arm64.h" 18e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu 19e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu#include <inttypes.h> 20e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu 21a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu#include <sstream> 22e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu 23e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu#include "base/logging.h" 24e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu#include "base/stringprintf.h" 25e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu#include "thread.h" 26e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu 27e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescunamespace art { 28e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescunamespace arm64 { 29e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu 30a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu// This enumeration should mirror the declarations in 31a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu// runtime/arch/arm64/registers_arm64.h. We do not include that file to 32a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu// avoid a dependency on libart. 33a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xuenum { 349bd88b0933a372e6a7b64b850868e6a7998567e2Serban Constantinescu TR = 19, 35a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu IP0 = 16, 36a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu IP1 = 17, 37a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu FP = 29, 38a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu LR = 30 39a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu}; 40a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu 41a37d925d405be9f589ac282869a997e73414d859Alexandre Ramesvoid CustomDisassembler::AppendRegisterNameToOutput( 42a37d925d405be9f589ac282869a997e73414d859Alexandre Rames const vixl::Instruction* instr, 43a37d925d405be9f589ac282869a997e73414d859Alexandre Rames const vixl::CPURegister& reg) { 44a37d925d405be9f589ac282869a997e73414d859Alexandre Rames USE(instr); 45d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames if (reg.IsRegister() && reg.Is64Bits()) { 46d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames if (reg.code() == TR) { 47d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames AppendToOutput("tr"); 48d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames return; 49d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames } else if (reg.code() == LR) { 50d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames AppendToOutput("lr"); 51d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames return; 52a37d925d405be9f589ac282869a997e73414d859Alexandre Rames } 53d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames // Fall through. 54a37d925d405be9f589ac282869a997e73414d859Alexandre Rames } 55a37d925d405be9f589ac282869a997e73414d859Alexandre Rames // Print other register names as usual. 56a37d925d405be9f589ac282869a997e73414d859Alexandre Rames Disassembler::AppendRegisterNameToOutput(instr, reg); 57a37d925d405be9f589ac282869a997e73414d859Alexandre Rames} 58a37d925d405be9f589ac282869a997e73414d859Alexandre Rames 59a37d925d405be9f589ac282869a997e73414d859Alexandre Ramesvoid CustomDisassembler::VisitLoadLiteral(const vixl::Instruction* instr) { 60a37d925d405be9f589ac282869a997e73414d859Alexandre Rames Disassembler::VisitLoadLiteral(instr); 61a37d925d405be9f589ac282869a997e73414d859Alexandre Rames 62a37d925d405be9f589ac282869a997e73414d859Alexandre Rames if (!read_literals_) { 63a37d925d405be9f589ac282869a997e73414d859Alexandre Rames return; 64a37d925d405be9f589ac282869a997e73414d859Alexandre Rames } 65a37d925d405be9f589ac282869a997e73414d859Alexandre Rames 66a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik // Get address of literal. Bail if not within expected buffer range to 67a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik // avoid trying to fetch invalid literals (we can encounter this when 68a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik // interpreting raw data as instructions). 6932f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu void* data_address = instr->LiteralAddress<void*>(); 70a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik if (data_address < base_address_ || data_address >= end_address_) { 71a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik AppendToOutput(" (?)"); 72a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik return; 73a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik } 74a37d925d405be9f589ac282869a997e73414d859Alexandre Rames 75a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik // Output information on literal. 76a6e95b32d499811bbb37602fc7446a5a0d05b9f8Aart Bik vixl::Instr op = instr->Mask(vixl::LoadLiteralMask); 77a37d925d405be9f589ac282869a997e73414d859Alexandre Rames switch (op) { 78a37d925d405be9f589ac282869a997e73414d859Alexandre Rames case vixl::LDR_w_lit: 79a37d925d405be9f589ac282869a997e73414d859Alexandre Rames case vixl::LDR_x_lit: 80a37d925d405be9f589ac282869a997e73414d859Alexandre Rames case vixl::LDRSW_x_lit: { 81a37d925d405be9f589ac282869a997e73414d859Alexandre Rames int64_t data = op == vixl::LDR_x_lit ? *reinterpret_cast<int64_t*>(data_address) 82a37d925d405be9f589ac282869a997e73414d859Alexandre Rames : *reinterpret_cast<int32_t*>(data_address); 83a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu AppendToOutput(" (0x%" PRIx64 " / %" PRId64 ")", data, data); 84a37d925d405be9f589ac282869a997e73414d859Alexandre Rames break; 85a37d925d405be9f589ac282869a997e73414d859Alexandre Rames } 86a37d925d405be9f589ac282869a997e73414d859Alexandre Rames case vixl::LDR_s_lit: 87a37d925d405be9f589ac282869a997e73414d859Alexandre Rames case vixl::LDR_d_lit: { 88a37d925d405be9f589ac282869a997e73414d859Alexandre Rames double data = (op == vixl::LDR_s_lit) ? *reinterpret_cast<float*>(data_address) 89a37d925d405be9f589ac282869a997e73414d859Alexandre Rames : *reinterpret_cast<double*>(data_address); 90a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu AppendToOutput(" (%g)", data); 91a37d925d405be9f589ac282869a997e73414d859Alexandre Rames break; 92a37d925d405be9f589ac282869a997e73414d859Alexandre Rames } 93a37d925d405be9f589ac282869a997e73414d859Alexandre Rames default: 94a37d925d405be9f589ac282869a997e73414d859Alexandre Rames break; 95a37d925d405be9f589ac282869a997e73414d859Alexandre Rames } 96a37d925d405be9f589ac282869a997e73414d859Alexandre Rames} 97a37d925d405be9f589ac282869a997e73414d859Alexandre Rames 98a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xuvoid CustomDisassembler::VisitLoadStoreUnsignedOffset(const vixl::Instruction* instr) { 99a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu Disassembler::VisitLoadStoreUnsignedOffset(instr); 100a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu 101a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu if (instr->Rn() == TR) { 102a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu int64_t offset = instr->ImmLSUnsigned() << instr->SizeLS(); 103a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu std::ostringstream tmp_stream; 104a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu Thread::DumpThreadOffset<8>(tmp_stream, static_cast<uint32_t>(offset)); 1055e2c8d323fbab4db8a71041ff94b6baf3953bca9Alexandre Rames AppendToOutput(" ; %s", tmp_stream.str().c_str()); 106a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu } 107a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu} 108a34e760fa5cc3102ce1998f10816d380c37f43aaZheng Xu 109e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescusize_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) { 110fef019c52ed7b131990d51a1e0d4444a3adf9b7bAlexandre Rames const vixl::Instruction* instr = reinterpret_cast<const vixl::Instruction*>(begin); 111fef019c52ed7b131990d51a1e0d4444a3adf9b7bAlexandre Rames decoder.Decode(instr); 112d737ab33a458537fca6207e9e4e25198a1511113Alexandre Rames os << FormatInstructionPointer(begin) 113fef019c52ed7b131990d51a1e0d4444a3adf9b7bAlexandre Rames << StringPrintf(": %08x\t%s\n", instr->InstructionBits(), disasm.GetOutput()); 114e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu return vixl::kInstructionSize; 115e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu} 116e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu 117e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescuvoid DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) { 118e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu for (const uint8_t* cur = begin; cur < end; cur += vixl::kInstructionSize) { 119e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu Dump(os, cur); 120e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu } 121e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu} 122e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu 123e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu} // namespace arm64 124e6622be6c353c7178f34adf814c58370a51c5ed7Serban Constantinescu} // namespace art 125