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-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 <cinttypes> |
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(cstr: "<invalid>" ); |
29 | break; |
30 | case Opcode::eType8: |
31 | s->Printf(format: "0x%2.2x" , m_data.inst8); |
32 | break; |
33 | case Opcode::eType16: |
34 | s->Printf(format: "0x%4.4x" , m_data.inst16); |
35 | break; |
36 | case Opcode::eType16_2: |
37 | case Opcode::eType32: |
38 | s->Printf(format: "0x%8.8x" , m_data.inst32); |
39 | break; |
40 | |
41 | case Opcode::eType64: |
42 | s->Printf(format: "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(ch: ' '); |
49 | s->Printf(format: "%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(format: "%*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::(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<uint16_t>(V: 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<uint32_t>(V: m_data.inst32); |
118 | buf = swap_buf; |
119 | break; |
120 | case Opcode::eType64: |
121 | *(uint32_t *)swap_buf = llvm::byteswap<uint64_t>(V: 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>(args&: buf, args&: byte_size); |
134 | data.SetByteOrder(GetDataByteOrder()); |
135 | data.SetData(data_sp: buffer_sp); |
136 | return byte_size; |
137 | } |
138 | data.Clear(); |
139 | return 0; |
140 | } |
141 | |