166 lines · cpp
1//===-- Opcode.cpp --------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/Opcode.h"10 11#include "lldb/Utility/DataBufferHeap.h"12#include "lldb/Utility/DataExtractor.h"13#include "lldb/Utility/Endian.h"14#include "lldb/Utility/Stream.h"15#include "lldb/lldb-forward.h"16 17#include <memory>18 19#include <cinttypes>20 21using namespace lldb;22using namespace lldb_private;23 24int Opcode::Dump(Stream *s, uint32_t min_byte_width) const {25 const uint32_t previous_bytes = s->GetWrittenBytes();26 switch (m_type) {27 case Opcode::eTypeInvalid:28 s->PutCString("<invalid>");29 break;30 case Opcode::eType8:31 s->Printf("0x%2.2x", m_data.inst8);32 break;33 case Opcode::eType16:34 s->Printf("0x%4.4x", m_data.inst16);35 break;36 case Opcode::eType16_2:37 case Opcode::eType32:38 s->Printf("0x%8.8x", m_data.inst32);39 break;40 41 case Opcode::eType16_32Tuples: {42 const bool format_as_words = (m_data.inst.length % 4) == 0;43 uint32_t i = 0;44 while (i < m_data.inst.length) {45 if (i > 0)46 s->PutChar(' ');47 if (format_as_words) {48 // Format as words; print 1 or more UInt32 values.49 s->Printf("%2.2x%2.2x%2.2x%2.2x", m_data.inst.bytes[i + 3],50 m_data.inst.bytes[i + 2], m_data.inst.bytes[i + 1],51 m_data.inst.bytes[i + 0]);52 i += 4;53 } else {54 // Format as halfwords; print 1 or more UInt16 values.55 s->Printf("%2.2x%2.2x", m_data.inst.bytes[i + 1],56 m_data.inst.bytes[i + 0]);57 i += 2;58 }59 }60 } break;61 62 case Opcode::eType64:63 s->Printf("0x%16.16" PRIx64, m_data.inst64);64 break;65 66 case Opcode::eTypeBytes:67 for (uint32_t i = 0; i < m_data.inst.length; ++i) {68 if (i > 0)69 s->PutChar(' ');70 s->Printf("%2.2x", m_data.inst.bytes[i]);71 }72 break;73 }74 75 uint32_t bytes_written_so_far = s->GetWrittenBytes() - previous_bytes;76 // Add spaces to make sure bytes display comes out even in case opcodes aren't77 // all the same size.78 if (bytes_written_so_far < min_byte_width)79 s->Printf("%*s", min_byte_width - bytes_written_so_far, "");80 return s->GetWrittenBytes() - previous_bytes;81}82 83lldb::ByteOrder Opcode::GetDataByteOrder() const {84 if (m_byte_order != eByteOrderInvalid) {85 return m_byte_order;86 }87 switch (m_type) {88 case Opcode::eTypeInvalid:89 break;90 case Opcode::eType8:91 case Opcode::eType16:92 case Opcode::eType16_2:93 case Opcode::eType16_32Tuples:94 case Opcode::eType32:95 case Opcode::eType64:96 return endian::InlHostByteOrder();97 case Opcode::eTypeBytes:98 break;99 }100 return eByteOrderInvalid;101}102 103uint32_t Opcode::GetData(DataExtractor &data) const {104 uint32_t byte_size = GetByteSize();105 uint8_t swap_buf[8];106 const void *buf = nullptr;107 108 if (byte_size > 0) {109 if (!GetEndianSwap()) {110 if (m_type == Opcode::eType16_2) {111 // 32 bit thumb instruction, we need to sizzle this a bit112 swap_buf[0] = m_data.inst.bytes[2];113 swap_buf[1] = m_data.inst.bytes[3];114 swap_buf[2] = m_data.inst.bytes[0];115 swap_buf[3] = m_data.inst.bytes[1];116 buf = swap_buf;117 } else {118 buf = GetOpcodeDataBytes();119 }120 } else {121 switch (m_type) {122 case Opcode::eTypeInvalid:123 break;124 case Opcode::eType8:125 buf = GetOpcodeDataBytes();126 break;127 case Opcode::eType16:128 *(uint16_t *)swap_buf = llvm::byteswap<uint16_t>(m_data.inst16);129 buf = swap_buf;130 break;131 case Opcode::eType16_2:132 swap_buf[0] = m_data.inst.bytes[1];133 swap_buf[1] = m_data.inst.bytes[0];134 swap_buf[2] = m_data.inst.bytes[3];135 swap_buf[3] = m_data.inst.bytes[2];136 buf = swap_buf;137 break;138 case Opcode::eType16_32Tuples:139 buf = GetOpcodeDataBytes();140 break;141 case Opcode::eType32:142 *(uint32_t *)swap_buf = llvm::byteswap<uint32_t>(m_data.inst32);143 buf = swap_buf;144 break;145 case Opcode::eType64:146 *(uint32_t *)swap_buf = llvm::byteswap<uint64_t>(m_data.inst64);147 buf = swap_buf;148 break;149 case Opcode::eTypeBytes:150 buf = GetOpcodeDataBytes();151 break;152 }153 }154 }155 if (buf != nullptr) {156 DataBufferSP buffer_sp;157 158 buffer_sp = std::make_shared<DataBufferHeap>(buf, byte_size);159 data.SetByteOrder(GetDataByteOrder());160 data.SetData(buffer_sp);161 return byte_size;162 }163 data.Clear();164 return 0;165}166