xref: /openbsd-src/gnu/llvm/lldb/source/Core/EmulateInstruction.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- EmulateInstruction.cpp --------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Core/EmulateInstruction.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Core/Address.h"
12061da546Spatrick #include "lldb/Core/DumpRegisterValue.h"
13061da546Spatrick #include "lldb/Core/PluginManager.h"
14061da546Spatrick #include "lldb/Core/StreamFile.h"
15061da546Spatrick #include "lldb/Symbol/UnwindPlan.h"
16061da546Spatrick #include "lldb/Target/Process.h"
17061da546Spatrick #include "lldb/Target/RegisterContext.h"
18061da546Spatrick #include "lldb/Target/StackFrame.h"
19061da546Spatrick #include "lldb/Utility/ConstString.h"
20061da546Spatrick #include "lldb/Utility/DataExtractor.h"
21061da546Spatrick #include "lldb/Utility/RegisterValue.h"
22061da546Spatrick #include "lldb/Utility/Status.h"
23061da546Spatrick #include "lldb/Utility/Stream.h"
24061da546Spatrick #include "lldb/Utility/StreamString.h"
25061da546Spatrick #include "lldb/lldb-forward.h"
26061da546Spatrick #include "lldb/lldb-private-interfaces.h"
27061da546Spatrick 
28061da546Spatrick #include "llvm/ADT/StringRef.h"
29061da546Spatrick 
30061da546Spatrick #include <cstring>
31061da546Spatrick #include <memory>
32*f6aab3d8Srobert #include <optional>
33061da546Spatrick 
34be691f3bSpatrick #include <cinttypes>
35be691f3bSpatrick #include <cstdio>
36061da546Spatrick 
37061da546Spatrick namespace lldb_private {
38061da546Spatrick class Target;
39061da546Spatrick }
40061da546Spatrick 
41061da546Spatrick using namespace lldb;
42061da546Spatrick using namespace lldb_private;
43061da546Spatrick 
44061da546Spatrick EmulateInstruction *
FindPlugin(const ArchSpec & arch,InstructionType supported_inst_type,const char * plugin_name)45061da546Spatrick EmulateInstruction::FindPlugin(const ArchSpec &arch,
46061da546Spatrick                                InstructionType supported_inst_type,
47061da546Spatrick                                const char *plugin_name) {
48061da546Spatrick   EmulateInstructionCreateInstance create_callback = nullptr;
49061da546Spatrick   if (plugin_name) {
50061da546Spatrick     create_callback =
51061da546Spatrick         PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
52*f6aab3d8Srobert             plugin_name);
53061da546Spatrick     if (create_callback) {
54061da546Spatrick       EmulateInstruction *emulate_insn_ptr =
55061da546Spatrick           create_callback(arch, supported_inst_type);
56061da546Spatrick       if (emulate_insn_ptr)
57061da546Spatrick         return emulate_insn_ptr;
58061da546Spatrick     }
59061da546Spatrick   } else {
60061da546Spatrick     for (uint32_t idx = 0;
61061da546Spatrick          (create_callback =
62061da546Spatrick               PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) !=
63061da546Spatrick          nullptr;
64061da546Spatrick          ++idx) {
65061da546Spatrick       EmulateInstruction *emulate_insn_ptr =
66061da546Spatrick           create_callback(arch, supported_inst_type);
67061da546Spatrick       if (emulate_insn_ptr)
68061da546Spatrick         return emulate_insn_ptr;
69061da546Spatrick     }
70061da546Spatrick   }
71061da546Spatrick   return nullptr;
72061da546Spatrick }
73061da546Spatrick 
EmulateInstruction(const ArchSpec & arch)74061da546Spatrick EmulateInstruction::EmulateInstruction(const ArchSpec &arch) : m_arch(arch) {}
75061da546Spatrick 
76*f6aab3d8Srobert std::optional<RegisterValue>
ReadRegister(const RegisterInfo & reg_info)77*f6aab3d8Srobert EmulateInstruction::ReadRegister(const RegisterInfo &reg_info) {
78*f6aab3d8Srobert   if (m_read_reg_callback == nullptr)
79*f6aab3d8Srobert     return {};
80*f6aab3d8Srobert 
81*f6aab3d8Srobert   RegisterValue reg_value;
82*f6aab3d8Srobert   bool success = m_read_reg_callback(this, m_baton, &reg_info, reg_value);
83*f6aab3d8Srobert   if (success)
84*f6aab3d8Srobert     return reg_value;
85*f6aab3d8Srobert   return {};
86061da546Spatrick }
87061da546Spatrick 
ReadRegister(lldb::RegisterKind reg_kind,uint32_t reg_num,RegisterValue & reg_value)88061da546Spatrick bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind,
89061da546Spatrick                                       uint32_t reg_num,
90061da546Spatrick                                       RegisterValue &reg_value) {
91*f6aab3d8Srobert   std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num);
92*f6aab3d8Srobert   if (!reg_info)
93061da546Spatrick     return false;
94*f6aab3d8Srobert 
95*f6aab3d8Srobert   std::optional<RegisterValue> value = ReadRegister(*reg_info);
96*f6aab3d8Srobert   if (value)
97*f6aab3d8Srobert     reg_value = *value;
98*f6aab3d8Srobert   return value.has_value();
99061da546Spatrick }
100061da546Spatrick 
ReadRegisterUnsigned(lldb::RegisterKind reg_kind,uint32_t reg_num,uint64_t fail_value,bool * success_ptr)101061da546Spatrick uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind,
102061da546Spatrick                                                   uint32_t reg_num,
103061da546Spatrick                                                   uint64_t fail_value,
104061da546Spatrick                                                   bool *success_ptr) {
105061da546Spatrick   RegisterValue reg_value;
106061da546Spatrick   if (ReadRegister(reg_kind, reg_num, reg_value))
107061da546Spatrick     return reg_value.GetAsUInt64(fail_value, success_ptr);
108061da546Spatrick   if (success_ptr)
109061da546Spatrick     *success_ptr = false;
110061da546Spatrick   return fail_value;
111061da546Spatrick }
112061da546Spatrick 
ReadRegisterUnsigned(const RegisterInfo & reg_info,uint64_t fail_value,bool * success_ptr)113*f6aab3d8Srobert uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo &reg_info,
114061da546Spatrick                                                   uint64_t fail_value,
115061da546Spatrick                                                   bool *success_ptr) {
116*f6aab3d8Srobert   std::optional<RegisterValue> reg_value = ReadRegister(reg_info);
117*f6aab3d8Srobert   if (!reg_value) {
118061da546Spatrick     if (success_ptr)
119061da546Spatrick       *success_ptr = false;
120061da546Spatrick     return fail_value;
121061da546Spatrick   }
122061da546Spatrick 
123*f6aab3d8Srobert   return reg_value->GetAsUInt64(fail_value, success_ptr);
124*f6aab3d8Srobert }
125*f6aab3d8Srobert 
WriteRegister(const Context & context,const RegisterInfo & reg_info,const RegisterValue & reg_value)126061da546Spatrick bool EmulateInstruction::WriteRegister(const Context &context,
127*f6aab3d8Srobert                                        const RegisterInfo &reg_info,
128061da546Spatrick                                        const RegisterValue &reg_value) {
129061da546Spatrick   if (m_write_reg_callback != nullptr)
130*f6aab3d8Srobert     return m_write_reg_callback(this, m_baton, context, &reg_info, reg_value);
131061da546Spatrick   return false;
132061da546Spatrick }
133061da546Spatrick 
WriteRegister(const Context & context,lldb::RegisterKind reg_kind,uint32_t reg_num,const RegisterValue & reg_value)134061da546Spatrick bool EmulateInstruction::WriteRegister(const Context &context,
135061da546Spatrick                                        lldb::RegisterKind reg_kind,
136061da546Spatrick                                        uint32_t reg_num,
137061da546Spatrick                                        const RegisterValue &reg_value) {
138*f6aab3d8Srobert   std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num);
139*f6aab3d8Srobert   if (reg_info)
140*f6aab3d8Srobert     return WriteRegister(context, *reg_info, reg_value);
141061da546Spatrick   return false;
142061da546Spatrick }
143061da546Spatrick 
WriteRegisterUnsigned(const Context & context,lldb::RegisterKind reg_kind,uint32_t reg_num,uint64_t uint_value)144061da546Spatrick bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
145061da546Spatrick                                                lldb::RegisterKind reg_kind,
146061da546Spatrick                                                uint32_t reg_num,
147061da546Spatrick                                                uint64_t uint_value) {
148*f6aab3d8Srobert   std::optional<RegisterInfo> reg_info = GetRegisterInfo(reg_kind, reg_num);
149*f6aab3d8Srobert   if (reg_info) {
150061da546Spatrick     RegisterValue reg_value;
151*f6aab3d8Srobert     if (reg_value.SetUInt(uint_value, reg_info->byte_size))
152*f6aab3d8Srobert       return WriteRegister(context, *reg_info, reg_value);
153061da546Spatrick   }
154061da546Spatrick   return false;
155061da546Spatrick }
156061da546Spatrick 
WriteRegisterUnsigned(const Context & context,const RegisterInfo & reg_info,uint64_t uint_value)157061da546Spatrick bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
158*f6aab3d8Srobert                                                const RegisterInfo &reg_info,
159061da546Spatrick                                                uint64_t uint_value) {
160061da546Spatrick   RegisterValue reg_value;
161*f6aab3d8Srobert   if (reg_value.SetUInt(uint_value, reg_info.byte_size))
162061da546Spatrick     return WriteRegister(context, reg_info, reg_value);
163061da546Spatrick   return false;
164061da546Spatrick }
165061da546Spatrick 
ReadMemory(const Context & context,lldb::addr_t addr,void * dst,size_t dst_len)166061da546Spatrick size_t EmulateInstruction::ReadMemory(const Context &context, lldb::addr_t addr,
167061da546Spatrick                                       void *dst, size_t dst_len) {
168061da546Spatrick   if (m_read_mem_callback != nullptr)
169061da546Spatrick     return m_read_mem_callback(this, m_baton, context, addr, dst, dst_len) ==
170061da546Spatrick            dst_len;
171061da546Spatrick   return false;
172061da546Spatrick }
173061da546Spatrick 
ReadMemoryUnsigned(const Context & context,lldb::addr_t addr,size_t byte_size,uint64_t fail_value,bool * success_ptr)174061da546Spatrick uint64_t EmulateInstruction::ReadMemoryUnsigned(const Context &context,
175061da546Spatrick                                                 lldb::addr_t addr,
176061da546Spatrick                                                 size_t byte_size,
177061da546Spatrick                                                 uint64_t fail_value,
178061da546Spatrick                                                 bool *success_ptr) {
179061da546Spatrick   uint64_t uval64 = 0;
180061da546Spatrick   bool success = false;
181061da546Spatrick   if (byte_size <= 8) {
182061da546Spatrick     uint8_t buf[sizeof(uint64_t)];
183061da546Spatrick     size_t bytes_read =
184061da546Spatrick         m_read_mem_callback(this, m_baton, context, addr, buf, byte_size);
185061da546Spatrick     if (bytes_read == byte_size) {
186061da546Spatrick       lldb::offset_t offset = 0;
187061da546Spatrick       DataExtractor data(buf, byte_size, GetByteOrder(), GetAddressByteSize());
188061da546Spatrick       uval64 = data.GetMaxU64(&offset, byte_size);
189061da546Spatrick       success = true;
190061da546Spatrick     }
191061da546Spatrick   }
192061da546Spatrick 
193061da546Spatrick   if (success_ptr)
194061da546Spatrick     *success_ptr = success;
195061da546Spatrick 
196061da546Spatrick   if (!success)
197061da546Spatrick     uval64 = fail_value;
198061da546Spatrick   return uval64;
199061da546Spatrick }
200061da546Spatrick 
WriteMemoryUnsigned(const Context & context,lldb::addr_t addr,uint64_t uval,size_t uval_byte_size)201061da546Spatrick bool EmulateInstruction::WriteMemoryUnsigned(const Context &context,
202061da546Spatrick                                              lldb::addr_t addr, uint64_t uval,
203061da546Spatrick                                              size_t uval_byte_size) {
204061da546Spatrick   StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
205061da546Spatrick   strm.PutMaxHex64(uval, uval_byte_size);
206061da546Spatrick 
207061da546Spatrick   size_t bytes_written = m_write_mem_callback(
208061da546Spatrick       this, m_baton, context, addr, strm.GetString().data(), uval_byte_size);
209061da546Spatrick   return (bytes_written == uval_byte_size);
210061da546Spatrick }
211061da546Spatrick 
WriteMemory(const Context & context,lldb::addr_t addr,const void * src,size_t src_len)212061da546Spatrick bool EmulateInstruction::WriteMemory(const Context &context, lldb::addr_t addr,
213061da546Spatrick                                      const void *src, size_t src_len) {
214061da546Spatrick   if (m_write_mem_callback != nullptr)
215061da546Spatrick     return m_write_mem_callback(this, m_baton, context, addr, src, src_len) ==
216061da546Spatrick            src_len;
217061da546Spatrick   return false;
218061da546Spatrick }
219061da546Spatrick 
SetBaton(void * baton)220061da546Spatrick void EmulateInstruction::SetBaton(void *baton) { m_baton = baton; }
221061da546Spatrick 
SetCallbacks(ReadMemoryCallback read_mem_callback,WriteMemoryCallback write_mem_callback,ReadRegisterCallback read_reg_callback,WriteRegisterCallback write_reg_callback)222061da546Spatrick void EmulateInstruction::SetCallbacks(
223061da546Spatrick     ReadMemoryCallback read_mem_callback,
224061da546Spatrick     WriteMemoryCallback write_mem_callback,
225061da546Spatrick     ReadRegisterCallback read_reg_callback,
226061da546Spatrick     WriteRegisterCallback write_reg_callback) {
227061da546Spatrick   m_read_mem_callback = read_mem_callback;
228061da546Spatrick   m_write_mem_callback = write_mem_callback;
229061da546Spatrick   m_read_reg_callback = read_reg_callback;
230061da546Spatrick   m_write_reg_callback = write_reg_callback;
231061da546Spatrick }
232061da546Spatrick 
SetReadMemCallback(ReadMemoryCallback read_mem_callback)233061da546Spatrick void EmulateInstruction::SetReadMemCallback(
234061da546Spatrick     ReadMemoryCallback read_mem_callback) {
235061da546Spatrick   m_read_mem_callback = read_mem_callback;
236061da546Spatrick }
237061da546Spatrick 
SetWriteMemCallback(WriteMemoryCallback write_mem_callback)238061da546Spatrick void EmulateInstruction::SetWriteMemCallback(
239061da546Spatrick     WriteMemoryCallback write_mem_callback) {
240061da546Spatrick   m_write_mem_callback = write_mem_callback;
241061da546Spatrick }
242061da546Spatrick 
SetReadRegCallback(ReadRegisterCallback read_reg_callback)243061da546Spatrick void EmulateInstruction::SetReadRegCallback(
244061da546Spatrick     ReadRegisterCallback read_reg_callback) {
245061da546Spatrick   m_read_reg_callback = read_reg_callback;
246061da546Spatrick }
247061da546Spatrick 
SetWriteRegCallback(WriteRegisterCallback write_reg_callback)248061da546Spatrick void EmulateInstruction::SetWriteRegCallback(
249061da546Spatrick     WriteRegisterCallback write_reg_callback) {
250061da546Spatrick   m_write_reg_callback = write_reg_callback;
251061da546Spatrick }
252061da546Spatrick 
253061da546Spatrick //
254061da546Spatrick //  Read & Write Memory and Registers callback functions.
255061da546Spatrick //
256061da546Spatrick 
ReadMemoryFrame(EmulateInstruction * instruction,void * baton,const Context & context,lldb::addr_t addr,void * dst,size_t dst_len)257061da546Spatrick size_t EmulateInstruction::ReadMemoryFrame(EmulateInstruction *instruction,
258061da546Spatrick                                            void *baton, const Context &context,
259061da546Spatrick                                            lldb::addr_t addr, void *dst,
260061da546Spatrick                                            size_t dst_len) {
261061da546Spatrick   if (baton == nullptr || dst == nullptr || dst_len == 0)
262061da546Spatrick     return 0;
263061da546Spatrick 
264061da546Spatrick   StackFrame *frame = (StackFrame *)baton;
265061da546Spatrick 
266061da546Spatrick   ProcessSP process_sp(frame->CalculateProcess());
267061da546Spatrick   if (process_sp) {
268061da546Spatrick     Status error;
269061da546Spatrick     return process_sp->ReadMemory(addr, dst, dst_len, error);
270061da546Spatrick   }
271061da546Spatrick   return 0;
272061da546Spatrick }
273061da546Spatrick 
WriteMemoryFrame(EmulateInstruction * instruction,void * baton,const Context & context,lldb::addr_t addr,const void * src,size_t src_len)274061da546Spatrick size_t EmulateInstruction::WriteMemoryFrame(EmulateInstruction *instruction,
275061da546Spatrick                                             void *baton, const Context &context,
276061da546Spatrick                                             lldb::addr_t addr, const void *src,
277061da546Spatrick                                             size_t src_len) {
278061da546Spatrick   if (baton == nullptr || src == nullptr || src_len == 0)
279061da546Spatrick     return 0;
280061da546Spatrick 
281061da546Spatrick   StackFrame *frame = (StackFrame *)baton;
282061da546Spatrick 
283061da546Spatrick   ProcessSP process_sp(frame->CalculateProcess());
284061da546Spatrick   if (process_sp) {
285061da546Spatrick     Status error;
286061da546Spatrick     return process_sp->WriteMemory(addr, src, src_len, error);
287061da546Spatrick   }
288061da546Spatrick 
289061da546Spatrick   return 0;
290061da546Spatrick }
291061da546Spatrick 
ReadRegisterFrame(EmulateInstruction * instruction,void * baton,const RegisterInfo * reg_info,RegisterValue & reg_value)292061da546Spatrick bool EmulateInstruction::ReadRegisterFrame(EmulateInstruction *instruction,
293061da546Spatrick                                            void *baton,
294061da546Spatrick                                            const RegisterInfo *reg_info,
295061da546Spatrick                                            RegisterValue &reg_value) {
296061da546Spatrick   if (baton == nullptr)
297061da546Spatrick     return false;
298061da546Spatrick 
299061da546Spatrick   StackFrame *frame = (StackFrame *)baton;
300061da546Spatrick   return frame->GetRegisterContext()->ReadRegister(reg_info, reg_value);
301061da546Spatrick }
302061da546Spatrick 
WriteRegisterFrame(EmulateInstruction * instruction,void * baton,const Context & context,const RegisterInfo * reg_info,const RegisterValue & reg_value)303061da546Spatrick bool EmulateInstruction::WriteRegisterFrame(EmulateInstruction *instruction,
304061da546Spatrick                                             void *baton, const Context &context,
305061da546Spatrick                                             const RegisterInfo *reg_info,
306061da546Spatrick                                             const RegisterValue &reg_value) {
307061da546Spatrick   if (baton == nullptr)
308061da546Spatrick     return false;
309061da546Spatrick 
310061da546Spatrick   StackFrame *frame = (StackFrame *)baton;
311061da546Spatrick   return frame->GetRegisterContext()->WriteRegister(reg_info, reg_value);
312061da546Spatrick }
313061da546Spatrick 
ReadMemoryDefault(EmulateInstruction * instruction,void * baton,const Context & context,lldb::addr_t addr,void * dst,size_t length)314061da546Spatrick size_t EmulateInstruction::ReadMemoryDefault(EmulateInstruction *instruction,
315061da546Spatrick                                              void *baton,
316061da546Spatrick                                              const Context &context,
317061da546Spatrick                                              lldb::addr_t addr, void *dst,
318061da546Spatrick                                              size_t length) {
319061da546Spatrick   StreamFile strm(stdout, false);
320061da546Spatrick   strm.Printf("    Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64
321061da546Spatrick               ", context = ",
322061da546Spatrick               addr, (uint64_t)length);
323061da546Spatrick   context.Dump(strm, instruction);
324061da546Spatrick   strm.EOL();
325061da546Spatrick   *((uint64_t *)dst) = 0xdeadbeef;
326061da546Spatrick   return length;
327061da546Spatrick }
328061da546Spatrick 
WriteMemoryDefault(EmulateInstruction * instruction,void * baton,const Context & context,lldb::addr_t addr,const void * dst,size_t length)329061da546Spatrick size_t EmulateInstruction::WriteMemoryDefault(EmulateInstruction *instruction,
330061da546Spatrick                                               void *baton,
331061da546Spatrick                                               const Context &context,
332061da546Spatrick                                               lldb::addr_t addr,
333061da546Spatrick                                               const void *dst, size_t length) {
334061da546Spatrick   StreamFile strm(stdout, false);
335061da546Spatrick   strm.Printf("    Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64
336061da546Spatrick               ", context = ",
337061da546Spatrick               addr, (uint64_t)length);
338061da546Spatrick   context.Dump(strm, instruction);
339061da546Spatrick   strm.EOL();
340061da546Spatrick   return length;
341061da546Spatrick }
342061da546Spatrick 
ReadRegisterDefault(EmulateInstruction * instruction,void * baton,const RegisterInfo * reg_info,RegisterValue & reg_value)343061da546Spatrick bool EmulateInstruction::ReadRegisterDefault(EmulateInstruction *instruction,
344061da546Spatrick                                              void *baton,
345061da546Spatrick                                              const RegisterInfo *reg_info,
346061da546Spatrick                                              RegisterValue &reg_value) {
347061da546Spatrick   StreamFile strm(stdout, false);
348061da546Spatrick   strm.Printf("  Read Register (%s)\n", reg_info->name);
349061da546Spatrick   lldb::RegisterKind reg_kind;
350061da546Spatrick   uint32_t reg_num;
351061da546Spatrick   if (GetBestRegisterKindAndNumber(reg_info, reg_kind, reg_num))
352061da546Spatrick     reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num);
353061da546Spatrick   else
354061da546Spatrick     reg_value.SetUInt64(0);
355061da546Spatrick 
356061da546Spatrick   return true;
357061da546Spatrick }
358061da546Spatrick 
WriteRegisterDefault(EmulateInstruction * instruction,void * baton,const Context & context,const RegisterInfo * reg_info,const RegisterValue & reg_value)359061da546Spatrick bool EmulateInstruction::WriteRegisterDefault(EmulateInstruction *instruction,
360061da546Spatrick                                               void *baton,
361061da546Spatrick                                               const Context &context,
362061da546Spatrick                                               const RegisterInfo *reg_info,
363061da546Spatrick                                               const RegisterValue &reg_value) {
364061da546Spatrick   StreamFile strm(stdout, false);
365061da546Spatrick   strm.Printf("    Write to Register (name = %s, value = ", reg_info->name);
366061da546Spatrick   DumpRegisterValue(reg_value, &strm, reg_info, false, false, eFormatDefault);
367061da546Spatrick   strm.PutCString(", context = ");
368061da546Spatrick   context.Dump(strm, instruction);
369061da546Spatrick   strm.EOL();
370061da546Spatrick   return true;
371061da546Spatrick }
372061da546Spatrick 
Dump(Stream & strm,EmulateInstruction * instruction) const373061da546Spatrick void EmulateInstruction::Context::Dump(Stream &strm,
374061da546Spatrick                                        EmulateInstruction *instruction) const {
375061da546Spatrick   switch (type) {
376061da546Spatrick   case eContextReadOpcode:
377061da546Spatrick     strm.PutCString("reading opcode");
378061da546Spatrick     break;
379061da546Spatrick 
380061da546Spatrick   case eContextImmediate:
381061da546Spatrick     strm.PutCString("immediate");
382061da546Spatrick     break;
383061da546Spatrick 
384061da546Spatrick   case eContextPushRegisterOnStack:
385061da546Spatrick     strm.PutCString("push register");
386061da546Spatrick     break;
387061da546Spatrick 
388061da546Spatrick   case eContextPopRegisterOffStack:
389061da546Spatrick     strm.PutCString("pop register");
390061da546Spatrick     break;
391061da546Spatrick 
392061da546Spatrick   case eContextAdjustStackPointer:
393061da546Spatrick     strm.PutCString("adjust sp");
394061da546Spatrick     break;
395061da546Spatrick 
396061da546Spatrick   case eContextSetFramePointer:
397061da546Spatrick     strm.PutCString("set frame pointer");
398061da546Spatrick     break;
399061da546Spatrick 
400061da546Spatrick   case eContextAdjustBaseRegister:
401061da546Spatrick     strm.PutCString("adjusting (writing value back to) a base register");
402061da546Spatrick     break;
403061da546Spatrick 
404061da546Spatrick   case eContextRegisterPlusOffset:
405061da546Spatrick     strm.PutCString("register + offset");
406061da546Spatrick     break;
407061da546Spatrick 
408061da546Spatrick   case eContextRegisterStore:
409061da546Spatrick     strm.PutCString("store register");
410061da546Spatrick     break;
411061da546Spatrick 
412061da546Spatrick   case eContextRegisterLoad:
413061da546Spatrick     strm.PutCString("load register");
414061da546Spatrick     break;
415061da546Spatrick 
416061da546Spatrick   case eContextRelativeBranchImmediate:
417061da546Spatrick     strm.PutCString("relative branch immediate");
418061da546Spatrick     break;
419061da546Spatrick 
420061da546Spatrick   case eContextAbsoluteBranchRegister:
421061da546Spatrick     strm.PutCString("absolute branch register");
422061da546Spatrick     break;
423061da546Spatrick 
424061da546Spatrick   case eContextSupervisorCall:
425061da546Spatrick     strm.PutCString("supervisor call");
426061da546Spatrick     break;
427061da546Spatrick 
428061da546Spatrick   case eContextTableBranchReadMemory:
429061da546Spatrick     strm.PutCString("table branch read memory");
430061da546Spatrick     break;
431061da546Spatrick 
432061da546Spatrick   case eContextWriteRegisterRandomBits:
433061da546Spatrick     strm.PutCString("write random bits to a register");
434061da546Spatrick     break;
435061da546Spatrick 
436061da546Spatrick   case eContextWriteMemoryRandomBits:
437061da546Spatrick     strm.PutCString("write random bits to a memory address");
438061da546Spatrick     break;
439061da546Spatrick 
440061da546Spatrick   case eContextArithmetic:
441061da546Spatrick     strm.PutCString("arithmetic");
442061da546Spatrick     break;
443061da546Spatrick 
444061da546Spatrick   case eContextReturnFromException:
445061da546Spatrick     strm.PutCString("return from exception");
446061da546Spatrick     break;
447061da546Spatrick 
448061da546Spatrick   default:
449061da546Spatrick     strm.PutCString("unrecognized context.");
450061da546Spatrick     break;
451061da546Spatrick   }
452061da546Spatrick 
453*f6aab3d8Srobert   switch (GetInfoType()) {
454061da546Spatrick   case eInfoTypeRegisterPlusOffset:
455061da546Spatrick     strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")",
456061da546Spatrick                 info.RegisterPlusOffset.reg.name,
457061da546Spatrick                 info.RegisterPlusOffset.signed_offset);
458061da546Spatrick     break;
459061da546Spatrick 
460061da546Spatrick   case eInfoTypeRegisterPlusIndirectOffset:
461061da546Spatrick     strm.Printf(" (reg_plus_reg = %s + %s)",
462061da546Spatrick                 info.RegisterPlusIndirectOffset.base_reg.name,
463061da546Spatrick                 info.RegisterPlusIndirectOffset.offset_reg.name);
464061da546Spatrick     break;
465061da546Spatrick 
466061da546Spatrick   case eInfoTypeRegisterToRegisterPlusOffset:
467061da546Spatrick     strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)",
468061da546Spatrick                 info.RegisterToRegisterPlusOffset.base_reg.name,
469061da546Spatrick                 info.RegisterToRegisterPlusOffset.offset,
470061da546Spatrick                 info.RegisterToRegisterPlusOffset.data_reg.name);
471061da546Spatrick     break;
472061da546Spatrick 
473061da546Spatrick   case eInfoTypeRegisterToRegisterPlusIndirectOffset:
474061da546Spatrick     strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)",
475061da546Spatrick                 info.RegisterToRegisterPlusIndirectOffset.base_reg.name,
476061da546Spatrick                 info.RegisterToRegisterPlusIndirectOffset.offset_reg.name,
477061da546Spatrick                 info.RegisterToRegisterPlusIndirectOffset.data_reg.name);
478061da546Spatrick     break;
479061da546Spatrick 
480061da546Spatrick   case eInfoTypeRegisterRegisterOperands:
481061da546Spatrick     strm.Printf(" (register to register binary op: %s and %s)",
482061da546Spatrick                 info.RegisterRegisterOperands.operand1.name,
483061da546Spatrick                 info.RegisterRegisterOperands.operand2.name);
484061da546Spatrick     break;
485061da546Spatrick 
486061da546Spatrick   case eInfoTypeOffset:
487061da546Spatrick     strm.Printf(" (signed_offset = %+" PRId64 ")", info.signed_offset);
488061da546Spatrick     break;
489061da546Spatrick 
490061da546Spatrick   case eInfoTypeRegister:
491061da546Spatrick     strm.Printf(" (reg = %s)", info.reg.name);
492061da546Spatrick     break;
493061da546Spatrick 
494061da546Spatrick   case eInfoTypeImmediate:
495061da546Spatrick     strm.Printf(" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))",
496061da546Spatrick                 info.unsigned_immediate, info.unsigned_immediate);
497061da546Spatrick     break;
498061da546Spatrick 
499061da546Spatrick   case eInfoTypeImmediateSigned:
500061da546Spatrick     strm.Printf(" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))",
501061da546Spatrick                 info.signed_immediate, info.signed_immediate);
502061da546Spatrick     break;
503061da546Spatrick 
504061da546Spatrick   case eInfoTypeAddress:
505061da546Spatrick     strm.Printf(" (address = 0x%" PRIx64 ")", info.address);
506061da546Spatrick     break;
507061da546Spatrick 
508061da546Spatrick   case eInfoTypeISAAndImmediate:
509061da546Spatrick     strm.Printf(" (isa = %u, unsigned_immediate = %u (0x%8.8x))",
510061da546Spatrick                 info.ISAAndImmediate.isa, info.ISAAndImmediate.unsigned_data32,
511061da546Spatrick                 info.ISAAndImmediate.unsigned_data32);
512061da546Spatrick     break;
513061da546Spatrick 
514061da546Spatrick   case eInfoTypeISAAndImmediateSigned:
515061da546Spatrick     strm.Printf(" (isa = %u, signed_immediate = %i (0x%8.8x))",
516061da546Spatrick                 info.ISAAndImmediateSigned.isa,
517061da546Spatrick                 info.ISAAndImmediateSigned.signed_data32,
518061da546Spatrick                 info.ISAAndImmediateSigned.signed_data32);
519061da546Spatrick     break;
520061da546Spatrick 
521061da546Spatrick   case eInfoTypeISA:
522061da546Spatrick     strm.Printf(" (isa = %u)", info.isa);
523061da546Spatrick     break;
524061da546Spatrick 
525061da546Spatrick   case eInfoTypeNoArgs:
526061da546Spatrick     break;
527061da546Spatrick   }
528061da546Spatrick }
529061da546Spatrick 
SetInstruction(const Opcode & opcode,const Address & inst_addr,Target * target)530061da546Spatrick bool EmulateInstruction::SetInstruction(const Opcode &opcode,
531061da546Spatrick                                         const Address &inst_addr,
532061da546Spatrick                                         Target *target) {
533061da546Spatrick   m_opcode = opcode;
534061da546Spatrick   m_addr = LLDB_INVALID_ADDRESS;
535061da546Spatrick   if (inst_addr.IsValid()) {
536061da546Spatrick     if (target != nullptr)
537061da546Spatrick       m_addr = inst_addr.GetLoadAddress(target);
538061da546Spatrick     if (m_addr == LLDB_INVALID_ADDRESS)
539061da546Spatrick       m_addr = inst_addr.GetFileAddress();
540061da546Spatrick   }
541061da546Spatrick   return true;
542061da546Spatrick }
543061da546Spatrick 
GetBestRegisterKindAndNumber(const RegisterInfo * reg_info,lldb::RegisterKind & reg_kind,uint32_t & reg_num)544061da546Spatrick bool EmulateInstruction::GetBestRegisterKindAndNumber(
545061da546Spatrick     const RegisterInfo *reg_info, lldb::RegisterKind &reg_kind,
546061da546Spatrick     uint32_t &reg_num) {
547061da546Spatrick   // Generic and DWARF should be the two most popular register kinds when
548061da546Spatrick   // emulating instructions since they are the most platform agnostic...
549061da546Spatrick   reg_num = reg_info->kinds[eRegisterKindGeneric];
550061da546Spatrick   if (reg_num != LLDB_INVALID_REGNUM) {
551061da546Spatrick     reg_kind = eRegisterKindGeneric;
552061da546Spatrick     return true;
553061da546Spatrick   }
554061da546Spatrick 
555061da546Spatrick   reg_num = reg_info->kinds[eRegisterKindDWARF];
556061da546Spatrick   if (reg_num != LLDB_INVALID_REGNUM) {
557061da546Spatrick     reg_kind = eRegisterKindDWARF;
558061da546Spatrick     return true;
559061da546Spatrick   }
560061da546Spatrick 
561061da546Spatrick   reg_num = reg_info->kinds[eRegisterKindLLDB];
562061da546Spatrick   if (reg_num != LLDB_INVALID_REGNUM) {
563061da546Spatrick     reg_kind = eRegisterKindLLDB;
564061da546Spatrick     return true;
565061da546Spatrick   }
566061da546Spatrick 
567061da546Spatrick   reg_num = reg_info->kinds[eRegisterKindEHFrame];
568061da546Spatrick   if (reg_num != LLDB_INVALID_REGNUM) {
569061da546Spatrick     reg_kind = eRegisterKindEHFrame;
570061da546Spatrick     return true;
571061da546Spatrick   }
572061da546Spatrick 
573061da546Spatrick   reg_num = reg_info->kinds[eRegisterKindProcessPlugin];
574061da546Spatrick   if (reg_num != LLDB_INVALID_REGNUM) {
575061da546Spatrick     reg_kind = eRegisterKindProcessPlugin;
576061da546Spatrick     return true;
577061da546Spatrick   }
578061da546Spatrick   return false;
579061da546Spatrick }
580061da546Spatrick 
581061da546Spatrick uint32_t
GetInternalRegisterNumber(RegisterContext * reg_ctx,const RegisterInfo & reg_info)582061da546Spatrick EmulateInstruction::GetInternalRegisterNumber(RegisterContext *reg_ctx,
583061da546Spatrick                                               const RegisterInfo &reg_info) {
584061da546Spatrick   lldb::RegisterKind reg_kind;
585061da546Spatrick   uint32_t reg_num;
586061da546Spatrick   if (reg_ctx && GetBestRegisterKindAndNumber(&reg_info, reg_kind, reg_num))
587061da546Spatrick     return reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
588061da546Spatrick   return LLDB_INVALID_REGNUM;
589061da546Spatrick }
590061da546Spatrick 
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)591061da546Spatrick bool EmulateInstruction::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
592061da546Spatrick   unwind_plan.Clear();
593061da546Spatrick   return false;
594061da546Spatrick }
595