1 //===-- Opcode.cpp ----------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Core/Opcode.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 #include "llvm/ADT/Triple.h" 16 17 // Project includes 18 #include "lldb/Core/ArchSpec.h" 19 #include "lldb/Core/DataBufferHeap.h" 20 #include "lldb/Core/DataExtractor.h" 21 #include "lldb/Core/Stream.h" 22 #include "lldb/Host/Endian.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 int Opcode::Dump(Stream *s, uint32_t min_byte_width) { 28 int bytes_written = 0; 29 switch (m_type) { 30 case Opcode::eTypeInvalid: 31 bytes_written = s->PutCString("<invalid>"); 32 break; 33 case Opcode::eType8: 34 bytes_written = s->Printf("0x%2.2x", m_data.inst8); 35 break; 36 case Opcode::eType16: 37 bytes_written = s->Printf("0x%4.4x", m_data.inst16); 38 break; 39 case Opcode::eType16_2: 40 case Opcode::eType32: 41 bytes_written = s->Printf("0x%8.8x", m_data.inst32); 42 break; 43 44 case Opcode::eType64: 45 bytes_written = s->Printf("0x%16.16" PRIx64, m_data.inst64); 46 break; 47 48 case Opcode::eTypeBytes: 49 for (uint32_t i = 0; i < m_data.inst.length; ++i) { 50 if (i > 0) 51 bytes_written += s->PutChar(' '); 52 bytes_written += s->Printf("%2.2x", m_data.inst.bytes[i]); 53 } 54 break; 55 } 56 57 // Add spaces to make sure bytes dispay comes out even in case opcodes 58 // aren't all the same size 59 if (static_cast<uint32_t>(bytes_written) < min_byte_width) 60 bytes_written = s->Printf("%*s", min_byte_width - bytes_written, ""); 61 return bytes_written; 62 } 63 64 lldb::ByteOrder Opcode::GetDataByteOrder() const { 65 if (m_byte_order != eByteOrderInvalid) { 66 return m_byte_order; 67 } 68 switch (m_type) { 69 case Opcode::eTypeInvalid: 70 break; 71 case Opcode::eType8: 72 case Opcode::eType16: 73 case Opcode::eType16_2: 74 case Opcode::eType32: 75 case Opcode::eType64: 76 return endian::InlHostByteOrder(); 77 case Opcode::eTypeBytes: 78 break; 79 } 80 return eByteOrderInvalid; 81 } 82 83 uint32_t Opcode::GetData(DataExtractor &data) const { 84 uint32_t byte_size = GetByteSize(); 85 uint8_t swap_buf[8]; 86 const void *buf = nullptr; 87 88 if (byte_size > 0) { 89 if (!GetEndianSwap()) { 90 if (m_type == Opcode::eType16_2) { 91 // 32 bit thumb instruction, we need to sizzle this a bit 92 swap_buf[0] = m_data.inst.bytes[2]; 93 swap_buf[1] = m_data.inst.bytes[3]; 94 swap_buf[2] = m_data.inst.bytes[0]; 95 swap_buf[3] = m_data.inst.bytes[1]; 96 buf = swap_buf; 97 } else { 98 buf = GetOpcodeDataBytes(); 99 } 100 } else { 101 switch (m_type) { 102 case Opcode::eTypeInvalid: 103 break; 104 case Opcode::eType8: 105 buf = GetOpcodeDataBytes(); 106 break; 107 case Opcode::eType16: 108 *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16); 109 buf = swap_buf; 110 break; 111 case Opcode::eType16_2: 112 swap_buf[0] = m_data.inst.bytes[1]; 113 swap_buf[1] = m_data.inst.bytes[0]; 114 swap_buf[2] = m_data.inst.bytes[3]; 115 swap_buf[3] = m_data.inst.bytes[2]; 116 buf = swap_buf; 117 break; 118 case Opcode::eType32: 119 *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32); 120 buf = swap_buf; 121 break; 122 case Opcode::eType64: 123 *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64); 124 buf = swap_buf; 125 break; 126 case Opcode::eTypeBytes: 127 buf = GetOpcodeDataBytes(); 128 break; 129 } 130 } 131 } 132 if (buf != nullptr) { 133 DataBufferSP buffer_sp; 134 135 buffer_sp.reset(new DataBufferHeap(buf, byte_size)); 136 data.SetByteOrder(GetDataByteOrder()); 137 data.SetData(buffer_sp); 138 return byte_size; 139 } 140 data.Clear(); 141 return 0; 142 } 143