LLDB mainline
Opcode.cpp
Go to the documentation of this file.
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
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) {
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;
37 case Opcode::eType32:
38 s->Printf("0x%8.8x", m_data.inst32);
39 break;
40
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
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't
77 // 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
85 return m_byte_order;
86 }
87 switch (m_type) {
89 break;
90 case Opcode::eType8:
91 case Opcode::eType16:
94 case Opcode::eType32:
95 case Opcode::eType64:
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 bit
112 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) {
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;
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;
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;
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);
160 data.SetData(buffer_sp);
161 return byte_size;
162 }
163 data.Clear();
164 return 0;
165}
An data extractor class.
void Clear()
Clears the object state.
void SetByteOrder(lldb::ByteOrder byte_order)
Set the byte_order value.
lldb::offset_t SetData(const void *bytes, lldb::offset_t length, lldb::ByteOrder byte_order)
Set data with a buffer that is caller owned.
uint32_t GetByteSize() const
Definition Opcode.h:229
bool GetEndianSwap() const
Definition Opcode.h:279
lldb::ByteOrder m_byte_order
Definition Opcode.h:286
Opcode::Type m_type
Definition Opcode.h:288
const void * GetOpcodeDataBytes() const
Definition Opcode.h:256
union lldb_private::Opcode::@156232132041300233024301123342201147024264135026 m_data
int Dump(Stream *s, uint32_t min_byte_width) const
Definition Opcode.cpp:24
lldb::ByteOrder GetDataByteOrder() const
Definition Opcode.cpp:83
uint32_t GetData(DataExtractor &data) const
Definition Opcode.cpp:103
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:65
size_t PutChar(char ch)
Definition Stream.cpp:131
size_t GetWrittenBytes() const
Definition Stream.h:118
lldb::ByteOrder InlHostByteOrder()
Definition Endian.h:25
A class that represents a running process on the host machine.
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP