xref: /src/contrib/llvm-project/lldb/source/Core/EmulateInstruction.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1cfca06d7SDimitry Andric //===-- EmulateInstruction.cpp --------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Core/EmulateInstruction.h"
10f034231aSEd Maste 
11f034231aSEd Maste #include "lldb/Core/Address.h"
12f73363f1SDimitry Andric #include "lldb/Core/DumpRegisterValue.h"
13f034231aSEd Maste #include "lldb/Core/PluginManager.h"
14b1c73532SDimitry Andric #include "lldb/Host/StreamFile.h"
15f034231aSEd Maste #include "lldb/Symbol/UnwindPlan.h"
16f034231aSEd Maste #include "lldb/Target/Process.h"
17f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
1894994d37SDimitry Andric #include "lldb/Target/StackFrame.h"
1994994d37SDimitry Andric #include "lldb/Utility/ConstString.h"
2074a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
2194994d37SDimitry Andric #include "lldb/Utility/RegisterValue.h"
22b76161e4SDimitry Andric #include "lldb/Utility/Status.h"
2394994d37SDimitry Andric #include "lldb/Utility/Stream.h"
2474a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
2594994d37SDimitry Andric #include "lldb/lldb-forward.h"
2694994d37SDimitry Andric #include "lldb/lldb-private-interfaces.h"
2774a628f7SDimitry Andric 
2894994d37SDimitry Andric #include "llvm/ADT/StringRef.h"
2974a628f7SDimitry Andric 
3074a628f7SDimitry Andric #include <cstring>
3194994d37SDimitry Andric #include <memory>
32e3b55780SDimitry Andric #include <optional>
3374a628f7SDimitry Andric 
34344a3780SDimitry Andric #include <cinttypes>
35344a3780SDimitry Andric #include <cstdio>
3674a628f7SDimitry Andric 
3774a628f7SDimitry Andric namespace lldb_private {
3874a628f7SDimitry Andric class Target;
3974a628f7SDimitry Andric }
40f034231aSEd Maste 
41f034231aSEd Maste using namespace lldb;
42f034231aSEd Maste using namespace lldb_private;
43f034231aSEd Maste 
44f034231aSEd Maste EmulateInstruction *
FindPlugin(const ArchSpec & arch,InstructionType supported_inst_type,const char * plugin_name)4514f1b3e8SDimitry Andric EmulateInstruction::FindPlugin(const ArchSpec &arch,
4614f1b3e8SDimitry Andric                                InstructionType supported_inst_type,
4714f1b3e8SDimitry Andric                                const char *plugin_name) {
48f3fbd1c0SDimitry Andric   EmulateInstructionCreateInstance create_callback = nullptr;
4914f1b3e8SDimitry Andric   if (plugin_name) {
5014f1b3e8SDimitry Andric     create_callback =
5114f1b3e8SDimitry Andric         PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
52c0981da4SDimitry Andric             plugin_name);
5314f1b3e8SDimitry Andric     if (create_callback) {
5414f1b3e8SDimitry Andric       EmulateInstruction *emulate_insn_ptr =
5514f1b3e8SDimitry Andric           create_callback(arch, supported_inst_type);
56f034231aSEd Maste       if (emulate_insn_ptr)
57f034231aSEd Maste         return emulate_insn_ptr;
58f034231aSEd Maste     }
5914f1b3e8SDimitry Andric   } else {
6014f1b3e8SDimitry Andric     for (uint32_t idx = 0;
6114f1b3e8SDimitry Andric          (create_callback =
6214f1b3e8SDimitry Andric               PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) !=
6314f1b3e8SDimitry Andric          nullptr;
6414f1b3e8SDimitry Andric          ++idx) {
6514f1b3e8SDimitry Andric       EmulateInstruction *emulate_insn_ptr =
6614f1b3e8SDimitry Andric           create_callback(arch, supported_inst_type);
67f034231aSEd Maste       if (emulate_insn_ptr)
68f034231aSEd Maste         return emulate_insn_ptr;
69f034231aSEd Maste     }
70f034231aSEd Maste   }
71f3fbd1c0SDimitry Andric   return nullptr;
72f034231aSEd Maste }
73f034231aSEd Maste 
EmulateInstruction(const ArchSpec & arch)745f29bb8aSDimitry Andric EmulateInstruction::EmulateInstruction(const ArchSpec &arch) : m_arch(arch) {}
75f034231aSEd Maste 
76e3b55780SDimitry Andric std::optional<RegisterValue>
ReadRegister(const RegisterInfo & reg_info)77e3b55780SDimitry Andric EmulateInstruction::ReadRegister(const RegisterInfo &reg_info) {
78e3b55780SDimitry Andric   if (m_read_reg_callback == nullptr)
79e3b55780SDimitry Andric     return {};
80e3b55780SDimitry Andric 
81e3b55780SDimitry Andric   RegisterValue reg_value;
82e3b55780SDimitry Andric   bool success = m_read_reg_callback(this, m_baton, &reg_info, reg_value);
83e3b55780SDimitry Andric   if (success)
84e3b55780SDimitry Andric     return reg_value;
85e3b55780SDimitry Andric   return {};
86f034231aSEd Maste }
87f034231aSEd Maste 
ReadRegister(lldb::RegisterKind reg_kind,uint32_t reg_num,RegisterValue & reg_value)8814f1b3e8SDimitry Andric bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind,
8914f1b3e8SDimitry Andric                                       uint32_t reg_num,
9014f1b3e8SDimitry Andric                                       RegisterValue &reg_value) {
91e3b55780SDimitry Andric   std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num);
92e3b55780SDimitry Andric   if (!reg_info)
93f034231aSEd Maste     return false;
94e3b55780SDimitry Andric 
95e3b55780SDimitry Andric   std::optional<RegisterValue> value = ReadRegister(*reg_info);
96e3b55780SDimitry Andric   if (value)
97e3b55780SDimitry Andric     reg_value = *value;
98e3b55780SDimitry Andric   return value.has_value();
99f034231aSEd Maste }
100f034231aSEd Maste 
ReadRegisterUnsigned(lldb::RegisterKind reg_kind,uint32_t reg_num,uint64_t fail_value,bool * success_ptr)10114f1b3e8SDimitry Andric uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind,
102f034231aSEd Maste                                                   uint32_t reg_num,
103f034231aSEd Maste                                                   uint64_t fail_value,
10414f1b3e8SDimitry Andric                                                   bool *success_ptr) {
105f034231aSEd Maste   RegisterValue reg_value;
106f034231aSEd Maste   if (ReadRegister(reg_kind, reg_num, reg_value))
107f034231aSEd Maste     return reg_value.GetAsUInt64(fail_value, success_ptr);
108f034231aSEd Maste   if (success_ptr)
109f034231aSEd Maste     *success_ptr = false;
110f034231aSEd Maste   return fail_value;
111f034231aSEd Maste }
112f034231aSEd Maste 
ReadRegisterUnsigned(const RegisterInfo & reg_info,uint64_t fail_value,bool * success_ptr)113e3b55780SDimitry Andric uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo &reg_info,
114f034231aSEd Maste                                                   uint64_t fail_value,
11514f1b3e8SDimitry Andric                                                   bool *success_ptr) {
116e3b55780SDimitry Andric   std::optional<RegisterValue> reg_value = ReadRegister(reg_info);
117e3b55780SDimitry Andric   if (!reg_value) {
118f034231aSEd Maste     if (success_ptr)
119f034231aSEd Maste       *success_ptr = false;
120f034231aSEd Maste     return fail_value;
121f034231aSEd Maste   }
122f034231aSEd Maste 
123e3b55780SDimitry Andric   return reg_value->GetAsUInt64(fail_value, success_ptr);
124e3b55780SDimitry Andric }
125e3b55780SDimitry Andric 
WriteRegister(const Context & context,const RegisterInfo & reg_info,const RegisterValue & reg_value)12614f1b3e8SDimitry Andric bool EmulateInstruction::WriteRegister(const Context &context,
127e3b55780SDimitry Andric                                        const RegisterInfo &reg_info,
12814f1b3e8SDimitry Andric                                        const RegisterValue &reg_value) {
129f3fbd1c0SDimitry Andric   if (m_write_reg_callback != nullptr)
130e3b55780SDimitry Andric     return m_write_reg_callback(this, m_baton, context, &reg_info, reg_value);
131f034231aSEd Maste   return false;
132f034231aSEd Maste }
133f034231aSEd Maste 
WriteRegister(const Context & context,lldb::RegisterKind reg_kind,uint32_t reg_num,const RegisterValue & reg_value)13414f1b3e8SDimitry Andric bool EmulateInstruction::WriteRegister(const Context &context,
1350cac4ca3SEd Maste                                        lldb::RegisterKind reg_kind,
136f034231aSEd Maste                                        uint32_t reg_num,
13714f1b3e8SDimitry Andric                                        const RegisterValue &reg_value) {
138e3b55780SDimitry Andric   std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num);
139e3b55780SDimitry Andric   if (reg_info)
140e3b55780SDimitry Andric     return WriteRegister(context, *reg_info, reg_value);
141f034231aSEd Maste   return false;
142f034231aSEd Maste }
143f034231aSEd Maste 
WriteRegisterUnsigned(const Context & context,lldb::RegisterKind reg_kind,uint32_t reg_num,uint64_t uint_value)14414f1b3e8SDimitry Andric bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
1450cac4ca3SEd Maste                                                lldb::RegisterKind reg_kind,
146f034231aSEd Maste                                                uint32_t reg_num,
14714f1b3e8SDimitry Andric                                                uint64_t uint_value) {
148e3b55780SDimitry Andric   std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num);
149e3b55780SDimitry Andric   if (reg_info) {
150f034231aSEd Maste     RegisterValue reg_value;
151e3b55780SDimitry Andric     if (reg_value.SetUInt(uint_value, reg_info->byte_size))
152e3b55780SDimitry Andric       return WriteRegister(context, *reg_info, reg_value);
153f034231aSEd Maste   }
154f034231aSEd Maste   return false;
155f034231aSEd Maste }
156f034231aSEd Maste 
WriteRegisterUnsigned(const Context & context,const RegisterInfo & reg_info,uint64_t uint_value)15714f1b3e8SDimitry Andric bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
158e3b55780SDimitry Andric                                                const RegisterInfo &reg_info,
15914f1b3e8SDimitry Andric                                                uint64_t uint_value) {
160f034231aSEd Maste   RegisterValue reg_value;
161e3b55780SDimitry Andric   if (reg_value.SetUInt(uint_value, reg_info.byte_size))
162f034231aSEd Maste     return WriteRegister(context, reg_info, reg_value);
163f034231aSEd Maste   return false;
164f034231aSEd Maste }
165f034231aSEd Maste 
ReadMemory(const Context & context,lldb::addr_t addr,void * dst,size_t dst_len)16614f1b3e8SDimitry Andric size_t EmulateInstruction::ReadMemory(const Context &context, lldb::addr_t addr,
16714f1b3e8SDimitry Andric                                       void *dst, size_t dst_len) {
168f3fbd1c0SDimitry Andric   if (m_read_mem_callback != nullptr)
16914f1b3e8SDimitry Andric     return m_read_mem_callback(this, m_baton, context, addr, dst, dst_len) ==
17014f1b3e8SDimitry Andric            dst_len;
171f034231aSEd Maste   return false;
172f034231aSEd Maste }
173f034231aSEd Maste 
ReadMemoryUnsigned(const Context & context,lldb::addr_t addr,size_t byte_size,uint64_t fail_value,bool * success_ptr)17414f1b3e8SDimitry Andric uint64_t EmulateInstruction::ReadMemoryUnsigned(const Context &context,
17514f1b3e8SDimitry Andric                                                 lldb::addr_t addr,
17614f1b3e8SDimitry Andric                                                 size_t byte_size,
17714f1b3e8SDimitry Andric                                                 uint64_t fail_value,
17814f1b3e8SDimitry Andric                                                 bool *success_ptr) {
179f034231aSEd Maste   uint64_t uval64 = 0;
180f034231aSEd Maste   bool success = false;
18114f1b3e8SDimitry Andric   if (byte_size <= 8) {
182f034231aSEd Maste     uint8_t buf[sizeof(uint64_t)];
18314f1b3e8SDimitry Andric     size_t bytes_read =
18414f1b3e8SDimitry Andric         m_read_mem_callback(this, m_baton, context, addr, buf, byte_size);
18514f1b3e8SDimitry Andric     if (bytes_read == byte_size) {
186f034231aSEd Maste       lldb::offset_t offset = 0;
187f034231aSEd Maste       DataExtractor data(buf, byte_size, GetByteOrder(), GetAddressByteSize());
188f034231aSEd Maste       uval64 = data.GetMaxU64(&offset, byte_size);
189f034231aSEd Maste       success = true;
190f034231aSEd Maste     }
191f034231aSEd Maste   }
192f034231aSEd Maste 
193f034231aSEd Maste   if (success_ptr)
194f034231aSEd Maste     *success_ptr = success;
195f034231aSEd Maste 
196f034231aSEd Maste   if (!success)
197f034231aSEd Maste     uval64 = fail_value;
198f034231aSEd Maste   return uval64;
199f034231aSEd Maste }
200f034231aSEd Maste 
WriteMemoryUnsigned(const Context & context,lldb::addr_t addr,uint64_t uval,size_t uval_byte_size)20114f1b3e8SDimitry Andric bool EmulateInstruction::WriteMemoryUnsigned(const Context &context,
20214f1b3e8SDimitry Andric                                              lldb::addr_t addr, uint64_t uval,
20314f1b3e8SDimitry Andric                                              size_t uval_byte_size) {
204f034231aSEd Maste   StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
205f034231aSEd Maste   strm.PutMaxHex64(uval, uval_byte_size);
206f034231aSEd Maste 
20714f1b3e8SDimitry Andric   size_t bytes_written = m_write_mem_callback(
20814f1b3e8SDimitry Andric       this, m_baton, context, addr, strm.GetString().data(), uval_byte_size);
209f3fbd1c0SDimitry Andric   return (bytes_written == uval_byte_size);
210f034231aSEd Maste }
211f034231aSEd Maste 
WriteMemory(const Context & context,lldb::addr_t addr,const void * src,size_t src_len)21214f1b3e8SDimitry Andric bool EmulateInstruction::WriteMemory(const Context &context, lldb::addr_t addr,
21314f1b3e8SDimitry Andric                                      const void *src, size_t src_len) {
214f3fbd1c0SDimitry Andric   if (m_write_mem_callback != nullptr)
21514f1b3e8SDimitry Andric     return m_write_mem_callback(this, m_baton, context, addr, src, src_len) ==
21614f1b3e8SDimitry Andric            src_len;
217f034231aSEd Maste   return false;
218f034231aSEd Maste }
219f034231aSEd Maste 
SetBaton(void * baton)22014f1b3e8SDimitry Andric void EmulateInstruction::SetBaton(void *baton) { m_baton = baton; }
221f034231aSEd Maste 
SetCallbacks(ReadMemoryCallback read_mem_callback,WriteMemoryCallback write_mem_callback,ReadRegisterCallback read_reg_callback,WriteRegisterCallback write_reg_callback)22214f1b3e8SDimitry Andric void EmulateInstruction::SetCallbacks(
22314f1b3e8SDimitry Andric     ReadMemoryCallback read_mem_callback,
224f034231aSEd Maste     WriteMemoryCallback write_mem_callback,
225f034231aSEd Maste     ReadRegisterCallback read_reg_callback,
22614f1b3e8SDimitry Andric     WriteRegisterCallback write_reg_callback) {
227f034231aSEd Maste   m_read_mem_callback = read_mem_callback;
228f034231aSEd Maste   m_write_mem_callback = write_mem_callback;
229f034231aSEd Maste   m_read_reg_callback = read_reg_callback;
230f034231aSEd Maste   m_write_reg_callback = write_reg_callback;
231f034231aSEd Maste }
232f034231aSEd Maste 
SetReadMemCallback(ReadMemoryCallback read_mem_callback)23314f1b3e8SDimitry Andric void EmulateInstruction::SetReadMemCallback(
23414f1b3e8SDimitry Andric     ReadMemoryCallback read_mem_callback) {
235f034231aSEd Maste   m_read_mem_callback = read_mem_callback;
236f034231aSEd Maste }
237f034231aSEd Maste 
SetWriteMemCallback(WriteMemoryCallback write_mem_callback)23814f1b3e8SDimitry Andric void EmulateInstruction::SetWriteMemCallback(
23914f1b3e8SDimitry Andric     WriteMemoryCallback write_mem_callback) {
240f034231aSEd Maste   m_write_mem_callback = write_mem_callback;
241f034231aSEd Maste }
242f034231aSEd Maste 
SetReadRegCallback(ReadRegisterCallback read_reg_callback)24314f1b3e8SDimitry Andric void EmulateInstruction::SetReadRegCallback(
24414f1b3e8SDimitry Andric     ReadRegisterCallback read_reg_callback) {
245f034231aSEd Maste   m_read_reg_callback = read_reg_callback;
246f034231aSEd Maste }
247f034231aSEd Maste 
SetWriteRegCallback(WriteRegisterCallback write_reg_callback)24814f1b3e8SDimitry Andric void EmulateInstruction::SetWriteRegCallback(
24914f1b3e8SDimitry Andric     WriteRegisterCallback write_reg_callback) {
250f034231aSEd Maste   m_write_reg_callback = write_reg_callback;
251f034231aSEd Maste }
252f034231aSEd Maste 
253f034231aSEd Maste //
254f034231aSEd Maste //  Read & Write Memory and Registers callback functions.
255f034231aSEd Maste //
256f034231aSEd Maste 
ReadMemoryFrame(EmulateInstruction * instruction,void * baton,const Context & context,lldb::addr_t addr,void * dst,size_t dst_len)25714f1b3e8SDimitry Andric size_t EmulateInstruction::ReadMemoryFrame(EmulateInstruction *instruction,
25814f1b3e8SDimitry Andric                                            void *baton, const Context &context,
25914f1b3e8SDimitry Andric                                            lldb::addr_t addr, void *dst,
26014f1b3e8SDimitry Andric                                            size_t dst_len) {
261f3fbd1c0SDimitry Andric   if (baton == nullptr || dst == nullptr || dst_len == 0)
262f034231aSEd Maste     return 0;
263f034231aSEd Maste 
264f034231aSEd Maste   StackFrame *frame = (StackFrame *)baton;
265f034231aSEd Maste 
266f034231aSEd Maste   ProcessSP process_sp(frame->CalculateProcess());
26714f1b3e8SDimitry Andric   if (process_sp) {
268b76161e4SDimitry Andric     Status error;
269f034231aSEd Maste     return process_sp->ReadMemory(addr, dst, dst_len, error);
270f034231aSEd Maste   }
271f034231aSEd Maste   return 0;
272f034231aSEd Maste }
273f034231aSEd Maste 
WriteMemoryFrame(EmulateInstruction * instruction,void * baton,const Context & context,lldb::addr_t addr,const void * src,size_t src_len)27414f1b3e8SDimitry Andric size_t EmulateInstruction::WriteMemoryFrame(EmulateInstruction *instruction,
27514f1b3e8SDimitry Andric                                             void *baton, const Context &context,
27614f1b3e8SDimitry Andric                                             lldb::addr_t addr, const void *src,
27714f1b3e8SDimitry Andric                                             size_t src_len) {
278f3fbd1c0SDimitry Andric   if (baton == nullptr || src == nullptr || src_len == 0)
279f034231aSEd Maste     return 0;
280f034231aSEd Maste 
281f034231aSEd Maste   StackFrame *frame = (StackFrame *)baton;
282f034231aSEd Maste 
283f034231aSEd Maste   ProcessSP process_sp(frame->CalculateProcess());
28414f1b3e8SDimitry Andric   if (process_sp) {
285b76161e4SDimitry Andric     Status error;
286f034231aSEd Maste     return process_sp->WriteMemory(addr, src, src_len, error);
287f034231aSEd Maste   }
288f034231aSEd Maste 
289f034231aSEd Maste   return 0;
290f034231aSEd Maste }
291f034231aSEd Maste 
ReadRegisterFrame(EmulateInstruction * instruction,void * baton,const RegisterInfo * reg_info,RegisterValue & reg_value)29214f1b3e8SDimitry Andric bool EmulateInstruction::ReadRegisterFrame(EmulateInstruction *instruction,
293f034231aSEd Maste                                            void *baton,
294f034231aSEd Maste                                            const RegisterInfo *reg_info,
29514f1b3e8SDimitry Andric                                            RegisterValue &reg_value) {
296f3fbd1c0SDimitry Andric   if (baton == nullptr)
297f034231aSEd Maste     return false;
298f034231aSEd Maste 
299f034231aSEd Maste   StackFrame *frame = (StackFrame *)baton;
300f034231aSEd Maste   return frame->GetRegisterContext()->ReadRegister(reg_info, reg_value);
301f034231aSEd Maste }
302f034231aSEd Maste 
WriteRegisterFrame(EmulateInstruction * instruction,void * baton,const Context & context,const RegisterInfo * reg_info,const RegisterValue & reg_value)30314f1b3e8SDimitry Andric bool EmulateInstruction::WriteRegisterFrame(EmulateInstruction *instruction,
30414f1b3e8SDimitry Andric                                             void *baton, const Context &context,
305f034231aSEd Maste                                             const RegisterInfo *reg_info,
30614f1b3e8SDimitry Andric                                             const RegisterValue &reg_value) {
307f3fbd1c0SDimitry Andric   if (baton == nullptr)
308f034231aSEd Maste     return false;
309f034231aSEd Maste 
310f034231aSEd Maste   StackFrame *frame = (StackFrame *)baton;
311f034231aSEd Maste   return frame->GetRegisterContext()->WriteRegister(reg_info, reg_value);
312f034231aSEd Maste }
313f034231aSEd Maste 
ReadMemoryDefault(EmulateInstruction * instruction,void * baton,const Context & context,lldb::addr_t addr,void * dst,size_t length)31414f1b3e8SDimitry Andric size_t EmulateInstruction::ReadMemoryDefault(EmulateInstruction *instruction,
315f034231aSEd Maste                                              void *baton,
316f034231aSEd Maste                                              const Context &context,
31714f1b3e8SDimitry Andric                                              lldb::addr_t addr, void *dst,
31814f1b3e8SDimitry Andric                                              size_t length) {
319f034231aSEd Maste   StreamFile strm(stdout, false);
32014f1b3e8SDimitry Andric   strm.Printf("    Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64
32114f1b3e8SDimitry Andric               ", context = ",
32214f1b3e8SDimitry Andric               addr, (uint64_t)length);
323f034231aSEd Maste   context.Dump(strm, instruction);
324f034231aSEd Maste   strm.EOL();
325f034231aSEd Maste   *((uint64_t *)dst) = 0xdeadbeef;
326f034231aSEd Maste   return length;
327f034231aSEd Maste }
328f034231aSEd Maste 
WriteMemoryDefault(EmulateInstruction * instruction,void * baton,const Context & context,lldb::addr_t addr,const void * dst,size_t length)32914f1b3e8SDimitry Andric size_t EmulateInstruction::WriteMemoryDefault(EmulateInstruction *instruction,
330f034231aSEd Maste                                               void *baton,
331f034231aSEd Maste                                               const Context &context,
332f034231aSEd Maste                                               lldb::addr_t addr,
33314f1b3e8SDimitry Andric                                               const void *dst, size_t length) {
334f034231aSEd Maste   StreamFile strm(stdout, false);
33514f1b3e8SDimitry Andric   strm.Printf("    Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64
33614f1b3e8SDimitry Andric               ", context = ",
33714f1b3e8SDimitry Andric               addr, (uint64_t)length);
338f034231aSEd Maste   context.Dump(strm, instruction);
339f034231aSEd Maste   strm.EOL();
340f034231aSEd Maste   return length;
341f034231aSEd Maste }
342f034231aSEd Maste 
ReadRegisterDefault(EmulateInstruction * instruction,void * baton,const RegisterInfo * reg_info,RegisterValue & reg_value)34314f1b3e8SDimitry Andric bool EmulateInstruction::ReadRegisterDefault(EmulateInstruction *instruction,
344f034231aSEd Maste                                              void *baton,
345f034231aSEd Maste                                              const RegisterInfo *reg_info,
34614f1b3e8SDimitry Andric                                              RegisterValue &reg_value) {
347f034231aSEd Maste   StreamFile strm(stdout, false);
348f034231aSEd Maste   strm.Printf("  Read Register (%s)\n", reg_info->name);
3490cac4ca3SEd Maste   lldb::RegisterKind reg_kind;
3500cac4ca3SEd Maste   uint32_t reg_num;
351f034231aSEd Maste   if (GetBestRegisterKindAndNumber(reg_info, reg_kind, reg_num))
352f034231aSEd Maste     reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num);
353f034231aSEd Maste   else
354f034231aSEd Maste     reg_value.SetUInt64(0);
355f034231aSEd Maste 
356f034231aSEd Maste   return true;
357f034231aSEd Maste }
358f034231aSEd Maste 
WriteRegisterDefault(EmulateInstruction * instruction,void * baton,const Context & context,const RegisterInfo * reg_info,const RegisterValue & reg_value)35914f1b3e8SDimitry Andric bool EmulateInstruction::WriteRegisterDefault(EmulateInstruction *instruction,
360f034231aSEd Maste                                               void *baton,
361f034231aSEd Maste                                               const Context &context,
362f034231aSEd Maste                                               const RegisterInfo *reg_info,
36314f1b3e8SDimitry Andric                                               const RegisterValue &reg_value) {
364f034231aSEd Maste   StreamFile strm(stdout, false);
365f034231aSEd Maste   strm.Printf("    Write to Register (name = %s, value = ", reg_info->name);
3667fa27ce4SDimitry Andric   DumpRegisterValue(reg_value, strm, *reg_info, false, false, eFormatDefault);
367f034231aSEd Maste   strm.PutCString(", context = ");
368f034231aSEd Maste   context.Dump(strm, instruction);
369f034231aSEd Maste   strm.EOL();
370f034231aSEd Maste   return true;
371f034231aSEd Maste }
372f034231aSEd Maste 
Dump(Stream & strm,EmulateInstruction * instruction) const37314f1b3e8SDimitry Andric void EmulateInstruction::Context::Dump(Stream &strm,
37414f1b3e8SDimitry Andric                                        EmulateInstruction *instruction) const {
37514f1b3e8SDimitry Andric   switch (type) {
376f034231aSEd Maste   case eContextReadOpcode:
377f034231aSEd Maste     strm.PutCString("reading opcode");
378f034231aSEd Maste     break;
379f034231aSEd Maste 
380f034231aSEd Maste   case eContextImmediate:
381f034231aSEd Maste     strm.PutCString("immediate");
382f034231aSEd Maste     break;
383f034231aSEd Maste 
384f034231aSEd Maste   case eContextPushRegisterOnStack:
385f034231aSEd Maste     strm.PutCString("push register");
386f034231aSEd Maste     break;
387f034231aSEd Maste 
388f034231aSEd Maste   case eContextPopRegisterOffStack:
389f034231aSEd Maste     strm.PutCString("pop register");
390f034231aSEd Maste     break;
391f034231aSEd Maste 
392f034231aSEd Maste   case eContextAdjustStackPointer:
393f034231aSEd Maste     strm.PutCString("adjust sp");
394f034231aSEd Maste     break;
395f034231aSEd Maste 
396f034231aSEd Maste   case eContextSetFramePointer:
397f034231aSEd Maste     strm.PutCString("set frame pointer");
398f034231aSEd Maste     break;
399f034231aSEd Maste 
400f034231aSEd Maste   case eContextAdjustBaseRegister:
401f034231aSEd Maste     strm.PutCString("adjusting (writing value back to) a base register");
402f034231aSEd Maste     break;
403f034231aSEd Maste 
404f034231aSEd Maste   case eContextRegisterPlusOffset:
405f034231aSEd Maste     strm.PutCString("register + offset");
406f034231aSEd Maste     break;
407f034231aSEd Maste 
408f034231aSEd Maste   case eContextRegisterStore:
409f034231aSEd Maste     strm.PutCString("store register");
410f034231aSEd Maste     break;
411f034231aSEd Maste 
412f034231aSEd Maste   case eContextRegisterLoad:
413f034231aSEd Maste     strm.PutCString("load register");
414f034231aSEd Maste     break;
415f034231aSEd Maste 
416f034231aSEd Maste   case eContextRelativeBranchImmediate:
417f034231aSEd Maste     strm.PutCString("relative branch immediate");
418f034231aSEd Maste     break;
419f034231aSEd Maste 
420f034231aSEd Maste   case eContextAbsoluteBranchRegister:
421f034231aSEd Maste     strm.PutCString("absolute branch register");
422f034231aSEd Maste     break;
423f034231aSEd Maste 
424f034231aSEd Maste   case eContextSupervisorCall:
425f034231aSEd Maste     strm.PutCString("supervisor call");
426f034231aSEd Maste     break;
427f034231aSEd Maste 
428f034231aSEd Maste   case eContextTableBranchReadMemory:
429f034231aSEd Maste     strm.PutCString("table branch read memory");
430f034231aSEd Maste     break;
431f034231aSEd Maste 
432f034231aSEd Maste   case eContextWriteRegisterRandomBits:
433f034231aSEd Maste     strm.PutCString("write random bits to a register");
434f034231aSEd Maste     break;
435f034231aSEd Maste 
436f034231aSEd Maste   case eContextWriteMemoryRandomBits:
437f034231aSEd Maste     strm.PutCString("write random bits to a memory address");
438f034231aSEd Maste     break;
439f034231aSEd Maste 
440f034231aSEd Maste   case eContextArithmetic:
441f034231aSEd Maste     strm.PutCString("arithmetic");
442f034231aSEd Maste     break;
443f034231aSEd Maste 
444f034231aSEd Maste   case eContextReturnFromException:
445f034231aSEd Maste     strm.PutCString("return from exception");
446f034231aSEd Maste     break;
447f034231aSEd Maste 
448f034231aSEd Maste   default:
449f034231aSEd Maste     strm.PutCString("unrecognized context.");
450f034231aSEd Maste     break;
451f034231aSEd Maste   }
452f034231aSEd Maste 
453e3b55780SDimitry Andric   switch (GetInfoType()) {
454f034231aSEd Maste   case eInfoTypeRegisterPlusOffset:
455f034231aSEd Maste     strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")",
456f034231aSEd Maste                 info.RegisterPlusOffset.reg.name,
457f034231aSEd Maste                 info.RegisterPlusOffset.signed_offset);
458f034231aSEd Maste     break;
459f034231aSEd Maste 
460f034231aSEd Maste   case eInfoTypeRegisterPlusIndirectOffset:
461f034231aSEd Maste     strm.Printf(" (reg_plus_reg = %s + %s)",
462f034231aSEd Maste                 info.RegisterPlusIndirectOffset.base_reg.name,
463f034231aSEd Maste                 info.RegisterPlusIndirectOffset.offset_reg.name);
464f034231aSEd Maste     break;
465f034231aSEd Maste 
466f034231aSEd Maste   case eInfoTypeRegisterToRegisterPlusOffset:
467f034231aSEd Maste     strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)",
468f034231aSEd Maste                 info.RegisterToRegisterPlusOffset.base_reg.name,
469f034231aSEd Maste                 info.RegisterToRegisterPlusOffset.offset,
470f034231aSEd Maste                 info.RegisterToRegisterPlusOffset.data_reg.name);
471f034231aSEd Maste     break;
472f034231aSEd Maste 
473f034231aSEd Maste   case eInfoTypeRegisterToRegisterPlusIndirectOffset:
474f034231aSEd Maste     strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)",
475f034231aSEd Maste                 info.RegisterToRegisterPlusIndirectOffset.base_reg.name,
476f034231aSEd Maste                 info.RegisterToRegisterPlusIndirectOffset.offset_reg.name,
477f034231aSEd Maste                 info.RegisterToRegisterPlusIndirectOffset.data_reg.name);
478f034231aSEd Maste     break;
479f034231aSEd Maste 
480f034231aSEd Maste   case eInfoTypeRegisterRegisterOperands:
481f034231aSEd Maste     strm.Printf(" (register to register binary op: %s and %s)",
482f034231aSEd Maste                 info.RegisterRegisterOperands.operand1.name,
483f034231aSEd Maste                 info.RegisterRegisterOperands.operand2.name);
484f034231aSEd Maste     break;
485f034231aSEd Maste 
486f034231aSEd Maste   case eInfoTypeOffset:
487f034231aSEd Maste     strm.Printf(" (signed_offset = %+" PRId64 ")", info.signed_offset);
488f034231aSEd Maste     break;
489f034231aSEd Maste 
490f034231aSEd Maste   case eInfoTypeRegister:
491f034231aSEd Maste     strm.Printf(" (reg = %s)", info.reg.name);
492f034231aSEd Maste     break;
493f034231aSEd Maste 
494f034231aSEd Maste   case eInfoTypeImmediate:
495f034231aSEd Maste     strm.Printf(" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))",
49614f1b3e8SDimitry Andric                 info.unsigned_immediate, info.unsigned_immediate);
497f034231aSEd Maste     break;
498f034231aSEd Maste 
499f034231aSEd Maste   case eInfoTypeImmediateSigned:
500f034231aSEd Maste     strm.Printf(" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))",
50114f1b3e8SDimitry Andric                 info.signed_immediate, info.signed_immediate);
502f034231aSEd Maste     break;
503f034231aSEd Maste 
504f034231aSEd Maste   case eInfoTypeAddress:
505f034231aSEd Maste     strm.Printf(" (address = 0x%" PRIx64 ")", info.address);
506f034231aSEd Maste     break;
507f034231aSEd Maste 
508f034231aSEd Maste   case eInfoTypeISAAndImmediate:
509f034231aSEd Maste     strm.Printf(" (isa = %u, unsigned_immediate = %u (0x%8.8x))",
51014f1b3e8SDimitry Andric                 info.ISAAndImmediate.isa, info.ISAAndImmediate.unsigned_data32,
511f034231aSEd Maste                 info.ISAAndImmediate.unsigned_data32);
512f034231aSEd Maste     break;
513f034231aSEd Maste 
514f034231aSEd Maste   case eInfoTypeISAAndImmediateSigned:
515f034231aSEd Maste     strm.Printf(" (isa = %u, signed_immediate = %i (0x%8.8x))",
516f034231aSEd Maste                 info.ISAAndImmediateSigned.isa,
517f034231aSEd Maste                 info.ISAAndImmediateSigned.signed_data32,
518f034231aSEd Maste                 info.ISAAndImmediateSigned.signed_data32);
519f034231aSEd Maste     break;
520f034231aSEd Maste 
521f034231aSEd Maste   case eInfoTypeISA:
522f034231aSEd Maste     strm.Printf(" (isa = %u)", info.isa);
523f034231aSEd Maste     break;
524f034231aSEd Maste 
525f034231aSEd Maste   case eInfoTypeNoArgs:
526f034231aSEd Maste     break;
527f034231aSEd Maste   }
528f034231aSEd Maste }
529f034231aSEd Maste 
SetInstruction(const Opcode & opcode,const Address & inst_addr,Target * target)53014f1b3e8SDimitry Andric bool EmulateInstruction::SetInstruction(const Opcode &opcode,
53114f1b3e8SDimitry Andric                                         const Address &inst_addr,
53214f1b3e8SDimitry Andric                                         Target *target) {
533f034231aSEd Maste   m_opcode = opcode;
534f034231aSEd Maste   m_addr = LLDB_INVALID_ADDRESS;
53514f1b3e8SDimitry Andric   if (inst_addr.IsValid()) {
536f3fbd1c0SDimitry Andric     if (target != nullptr)
537f034231aSEd Maste       m_addr = inst_addr.GetLoadAddress(target);
538f034231aSEd Maste     if (m_addr == LLDB_INVALID_ADDRESS)
539f034231aSEd Maste       m_addr = inst_addr.GetFileAddress();
540f034231aSEd Maste   }
541f034231aSEd Maste   return true;
542f034231aSEd Maste }
543f034231aSEd Maste 
GetBestRegisterKindAndNumber(const RegisterInfo * reg_info,lldb::RegisterKind & reg_kind,uint32_t & reg_num)54414f1b3e8SDimitry Andric bool EmulateInstruction::GetBestRegisterKindAndNumber(
54514f1b3e8SDimitry Andric     const RegisterInfo *reg_info, lldb::RegisterKind &reg_kind,
54614f1b3e8SDimitry Andric     uint32_t &reg_num) {
547f034231aSEd Maste   // Generic and DWARF should be the two most popular register kinds when
548f034231aSEd Maste   // emulating instructions since they are the most platform agnostic...
549f034231aSEd Maste   reg_num = reg_info->kinds[eRegisterKindGeneric];
55014f1b3e8SDimitry Andric   if (reg_num != LLDB_INVALID_REGNUM) {
551f034231aSEd Maste     reg_kind = eRegisterKindGeneric;
552f034231aSEd Maste     return true;
553f034231aSEd Maste   }
554f034231aSEd Maste 
555f034231aSEd Maste   reg_num = reg_info->kinds[eRegisterKindDWARF];
55614f1b3e8SDimitry Andric   if (reg_num != LLDB_INVALID_REGNUM) {
557f034231aSEd Maste     reg_kind = eRegisterKindDWARF;
558f034231aSEd Maste     return true;
559f034231aSEd Maste   }
560f034231aSEd Maste 
561f034231aSEd Maste   reg_num = reg_info->kinds[eRegisterKindLLDB];
56214f1b3e8SDimitry Andric   if (reg_num != LLDB_INVALID_REGNUM) {
563f034231aSEd Maste     reg_kind = eRegisterKindLLDB;
564f034231aSEd Maste     return true;
565f034231aSEd Maste   }
566f034231aSEd Maste 
567e81d9d49SDimitry Andric   reg_num = reg_info->kinds[eRegisterKindEHFrame];
56814f1b3e8SDimitry Andric   if (reg_num != LLDB_INVALID_REGNUM) {
569e81d9d49SDimitry Andric     reg_kind = eRegisterKindEHFrame;
570f034231aSEd Maste     return true;
571f034231aSEd Maste   }
572f034231aSEd Maste 
573e81d9d49SDimitry Andric   reg_num = reg_info->kinds[eRegisterKindProcessPlugin];
57414f1b3e8SDimitry Andric   if (reg_num != LLDB_INVALID_REGNUM) {
575e81d9d49SDimitry Andric     reg_kind = eRegisterKindProcessPlugin;
576f034231aSEd Maste     return true;
577f034231aSEd Maste   }
578f034231aSEd Maste   return false;
579f034231aSEd Maste }
580f034231aSEd Maste 
581f034231aSEd Maste uint32_t
GetInternalRegisterNumber(RegisterContext * reg_ctx,const RegisterInfo & reg_info)58214f1b3e8SDimitry Andric EmulateInstruction::GetInternalRegisterNumber(RegisterContext *reg_ctx,
58314f1b3e8SDimitry Andric                                               const RegisterInfo &reg_info) {
5840cac4ca3SEd Maste   lldb::RegisterKind reg_kind;
5850cac4ca3SEd Maste   uint32_t reg_num;
586f034231aSEd Maste   if (reg_ctx && GetBestRegisterKindAndNumber(&reg_info, reg_kind, reg_num))
587f034231aSEd Maste     return reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
588f034231aSEd Maste   return LLDB_INVALID_REGNUM;
589f034231aSEd Maste }
590f034231aSEd Maste 
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)59114f1b3e8SDimitry Andric bool EmulateInstruction::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
592f034231aSEd Maste   unwind_plan.Clear();
593f034231aSEd Maste   return false;
594f034231aSEd Maste }
595