/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Core/Opcode.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 6.04k | int Opcode::Dump(Stream *s, uint32_t min_byte_width) { |
25 | 6.04k | const uint32_t previous_bytes = s->GetWrittenBytes(); |
26 | 6.04k | switch (m_type) { |
27 | 0 | case Opcode::eTypeInvalid: |
28 | 0 | s->PutCString("<invalid>"); |
29 | 0 | break; |
30 | 0 | case Opcode::eType8: |
31 | 0 | s->Printf("0x%2.2x", m_data.inst8); |
32 | 0 | break; |
33 | 2 | case Opcode::eType16: |
34 | 2 | s->Printf("0x%4.4x", m_data.inst16); |
35 | 2 | break; |
36 | 0 | case Opcode::eType16_2: |
37 | 0 | case Opcode::eType32: |
38 | 0 | s->Printf("0x%8.8x", m_data.inst32); |
39 | 0 | break; |
40 | | |
41 | 0 | case Opcode::eType64: |
42 | 0 | s->Printf("0x%16.16" PRIx64, m_data.inst64); |
43 | 0 | break; |
44 | | |
45 | 6.04k | case Opcode::eTypeBytes: |
46 | 27.9k | for (uint32_t i = 0; i < m_data.inst.length; ++i21.8k ) { |
47 | 21.8k | if (i > 0) |
48 | 15.8k | s->PutChar(' '); |
49 | 21.8k | s->Printf("%2.2x", m_data.inst.bytes[i]); |
50 | 21.8k | } |
51 | 6.04k | break; |
52 | 6.04k | } |
53 | | |
54 | 6.04k | 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 | 6.04k | if (bytes_written_so_far < min_byte_width) |
58 | 6.04k | s->Printf("%*s", min_byte_width - bytes_written_so_far, ""); |
59 | 6.04k | return s->GetWrittenBytes() - previous_bytes; |
60 | 6.04k | } |
61 | | |
62 | 977k | lldb::ByteOrder Opcode::GetDataByteOrder() const { |
63 | 977k | if (m_byte_order != eByteOrderInvalid) { |
64 | 111 | return m_byte_order; |
65 | 111 | } |
66 | 977k | switch (m_type) { |
67 | 0 | case Opcode::eTypeInvalid: |
68 | 0 | break; |
69 | 0 | case Opcode::eType8: |
70 | 0 | case Opcode::eType16: |
71 | 0 | case Opcode::eType16_2: |
72 | 0 | case Opcode::eType32: |
73 | 0 | case Opcode::eType64: |
74 | 0 | return endian::InlHostByteOrder(); |
75 | 977k | case Opcode::eTypeBytes: |
76 | 977k | break; |
77 | 977k | } |
78 | 977k | return eByteOrderInvalid; |
79 | 977k | } |
80 | | |
81 | 977k | uint32_t Opcode::GetData(DataExtractor &data) const { |
82 | 977k | uint32_t byte_size = GetByteSize(); |
83 | 977k | uint8_t swap_buf[8]; |
84 | 977k | const void *buf = nullptr; |
85 | | |
86 | 977k | if (byte_size > 0) { |
87 | 977k | if (!GetEndianSwap()) { |
88 | 977k | if (m_type == Opcode::eType16_2) { |
89 | | // 32 bit thumb instruction, we need to sizzle this a bit |
90 | 7 | swap_buf[0] = m_data.inst.bytes[2]; |
91 | 7 | swap_buf[1] = m_data.inst.bytes[3]; |
92 | 7 | swap_buf[2] = m_data.inst.bytes[0]; |
93 | 7 | swap_buf[3] = m_data.inst.bytes[1]; |
94 | 7 | buf = swap_buf; |
95 | 977k | } else { |
96 | 977k | buf = GetOpcodeDataBytes(); |
97 | 977k | } |
98 | 977k | } else { |
99 | 0 | switch (m_type) { |
100 | 0 | case Opcode::eTypeInvalid: |
101 | 0 | break; |
102 | 0 | case Opcode::eType8: |
103 | 0 | buf = GetOpcodeDataBytes(); |
104 | 0 | break; |
105 | 0 | case Opcode::eType16: |
106 | 0 | *(uint16_t *)swap_buf = llvm::byteswap<uint16_t>(m_data.inst16); |
107 | 0 | buf = swap_buf; |
108 | 0 | break; |
109 | 0 | case Opcode::eType16_2: |
110 | 0 | swap_buf[0] = m_data.inst.bytes[1]; |
111 | 0 | swap_buf[1] = m_data.inst.bytes[0]; |
112 | 0 | swap_buf[2] = m_data.inst.bytes[3]; |
113 | 0 | swap_buf[3] = m_data.inst.bytes[2]; |
114 | 0 | buf = swap_buf; |
115 | 0 | break; |
116 | 0 | case Opcode::eType32: |
117 | 0 | *(uint32_t *)swap_buf = llvm::byteswap<uint32_t>(m_data.inst32); |
118 | 0 | buf = swap_buf; |
119 | 0 | break; |
120 | 0 | case Opcode::eType64: |
121 | 0 | *(uint32_t *)swap_buf = llvm::byteswap<uint64_t>(m_data.inst64); |
122 | 0 | buf = swap_buf; |
123 | 0 | break; |
124 | 0 | case Opcode::eTypeBytes: |
125 | 0 | buf = GetOpcodeDataBytes(); |
126 | 0 | break; |
127 | 0 | } |
128 | 0 | } |
129 | 977k | } |
130 | 977k | if (buf != nullptr) { |
131 | 977k | DataBufferSP buffer_sp; |
132 | | |
133 | 977k | buffer_sp = std::make_shared<DataBufferHeap>(buf, byte_size); |
134 | 977k | data.SetByteOrder(GetDataByteOrder()); |
135 | 977k | data.SetData(buffer_sp); |
136 | 977k | return byte_size; |
137 | 977k | } |
138 | 0 | data.Clear(); |
139 | 0 | return 0; |
140 | 977k | } |