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