1 //===-- Opcode.cpp ----------------------------------------------*- C++ -*-===// 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-exception 6 // 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 <inttypes.h> 20 21 using namespace lldb; 22 using namespace lldb_private; 23 24 int Opcode::Dump(Stream *s, uint32_t min_byte_width) { 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::eType64: 42 s->Printf("0x%16.16" PRIx64, m_data.inst64); 43 break; 44 45 case Opcode::eTypeBytes: 46 for (uint32_t i = 0; i < m_data.inst.length; ++i) { 47 if (i > 0) 48 s->PutChar(' '); 49 s->Printf("%2.2x", m_data.inst.bytes[i]); 50 } 51 break; 52 } 53 54 uint32_t bytes_written_so_far = s->GetWrittenBytes() - previous_bytes; 55 // Add spaces to make sure bytes display comes out even in case opcodes aren't 56 // all the same size. 57 if (bytes_written_so_far < min_byte_width) 58 s->Printf("%*s", min_byte_width - bytes_written_so_far, ""); 59 return s->GetWrittenBytes() - previous_bytes; 60 } 61 62 lldb::ByteOrder Opcode::GetDataByteOrder() const { 63 if (m_byte_order != eByteOrderInvalid) { 64 return m_byte_order; 65 } 66 switch (m_type) { 67 case Opcode::eTypeInvalid: 68 break; 69 case Opcode::eType8: 70 case Opcode::eType16: 71 case Opcode::eType16_2: 72 case Opcode::eType32: 73 case Opcode::eType64: 74 return endian::InlHostByteOrder(); 75 case Opcode::eTypeBytes: 76 break; 77 } 78 return eByteOrderInvalid; 79 } 80 81 uint32_t Opcode::GetData(DataExtractor &data) const { 82 uint32_t byte_size = GetByteSize(); 83 uint8_t swap_buf[8]; 84 const void *buf = nullptr; 85 86 if (byte_size > 0) { 87 if (!GetEndianSwap()) { 88 if (m_type == Opcode::eType16_2) { 89 // 32 bit thumb instruction, we need to sizzle this a bit 90 swap_buf[0] = m_data.inst.bytes[2]; 91 swap_buf[1] = m_data.inst.bytes[3]; 92 swap_buf[2] = m_data.inst.bytes[0]; 93 swap_buf[3] = m_data.inst.bytes[1]; 94 buf = swap_buf; 95 } else { 96 buf = GetOpcodeDataBytes(); 97 } 98 } else { 99 switch (m_type) { 100 case Opcode::eTypeInvalid: 101 break; 102 case Opcode::eType8: 103 buf = GetOpcodeDataBytes(); 104 break; 105 case Opcode::eType16: 106 *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16); 107 buf = swap_buf; 108 break; 109 case Opcode::eType16_2: 110 swap_buf[0] = m_data.inst.bytes[1]; 111 swap_buf[1] = m_data.inst.bytes[0]; 112 swap_buf[2] = m_data.inst.bytes[3]; 113 swap_buf[3] = m_data.inst.bytes[2]; 114 buf = swap_buf; 115 break; 116 case Opcode::eType32: 117 *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32); 118 buf = swap_buf; 119 break; 120 case Opcode::eType64: 121 *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64); 122 buf = swap_buf; 123 break; 124 case Opcode::eTypeBytes: 125 buf = GetOpcodeDataBytes(); 126 break; 127 } 128 } 129 } 130 if (buf != nullptr) { 131 DataBufferSP buffer_sp; 132 133 buffer_sp = std::make_shared<DataBufferHeap>(buf, byte_size); 134 data.SetByteOrder(GetDataByteOrder()); 135 data.SetData(buffer_sp); 136 return byte_size; 137 } 138 data.Clear(); 139 return 0; 140 } 141