1 //===-- EmulateInstruction.cpp --------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Core/EmulateInstruction.h"
11 #include "lldb/Core/Address.h"
12 #include "lldb/Core/DumpRegisterValue.h"
13 #include "lldb/Core/PluginManager.h"
14 #include "lldb/Host/StreamFile.h"
15 #include "lldb/Symbol/UnwindPlan.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/RegisterContext.h"
18 #include "lldb/Target/StackFrame.h"
19 #include "lldb/Utility/ConstString.h"
20 #include "lldb/Utility/DataExtractor.h"
21 #include "lldb/Utility/RegisterValue.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/Utility/Stream.h"
24 #include "lldb/Utility/StreamString.h"
25 #include "lldb/lldb-forward.h"
26 #include "lldb/lldb-private-interfaces.h"
28 #include "llvm/ADT/StringRef.h"
37 namespace lldb_private
{
42 using namespace lldb_private
;
45 EmulateInstruction::FindPlugin(const ArchSpec
&arch
,
46 InstructionType supported_inst_type
,
47 const char *plugin_name
) {
48 EmulateInstructionCreateInstance create_callback
= nullptr;
51 PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
53 if (create_callback
) {
54 EmulateInstruction
*emulate_insn_ptr
=
55 create_callback(arch
, supported_inst_type
);
57 return emulate_insn_ptr
;
60 for (uint32_t idx
= 0;
62 PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx
)) !=
65 EmulateInstruction
*emulate_insn_ptr
=
66 create_callback(arch
, supported_inst_type
);
68 return emulate_insn_ptr
;
74 EmulateInstruction::EmulateInstruction(const ArchSpec
&arch
) : m_arch(arch
) {}
76 std::optional
<RegisterValue
>
77 EmulateInstruction::ReadRegister(const RegisterInfo
®_info
) {
78 if (m_read_reg_callback
== nullptr)
81 RegisterValue reg_value
;
82 bool success
= m_read_reg_callback(this, m_baton
, ®_info
, reg_value
);
88 bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind
,
90 RegisterValue
®_value
) {
91 std::optional
<RegisterInfo
> reg_info
= GetRegisterInfo(reg_kind
, reg_num
);
95 std::optional
<RegisterValue
> value
= ReadRegister(*reg_info
);
98 return value
.has_value();
101 uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind
,
105 RegisterValue reg_value
;
106 if (ReadRegister(reg_kind
, reg_num
, reg_value
))
107 return reg_value
.GetAsUInt64(fail_value
, success_ptr
);
109 *success_ptr
= false;
113 uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo
®_info
,
116 std::optional
<RegisterValue
> reg_value
= ReadRegister(reg_info
);
119 *success_ptr
= false;
123 return reg_value
->GetAsUInt64(fail_value
, success_ptr
);
126 bool EmulateInstruction::WriteRegister(const Context
&context
,
127 const RegisterInfo
®_info
,
128 const RegisterValue
®_value
) {
129 if (m_write_reg_callback
!= nullptr)
130 return m_write_reg_callback(this, m_baton
, context
, ®_info
, reg_value
);
134 bool EmulateInstruction::WriteRegister(const Context
&context
,
135 lldb::RegisterKind reg_kind
,
137 const RegisterValue
®_value
) {
138 std::optional
<RegisterInfo
> reg_info
= GetRegisterInfo(reg_kind
, reg_num
);
140 return WriteRegister(context
, *reg_info
, reg_value
);
144 bool EmulateInstruction::WriteRegisterUnsigned(const Context
&context
,
145 lldb::RegisterKind reg_kind
,
147 uint64_t uint_value
) {
148 std::optional
<RegisterInfo
> reg_info
= GetRegisterInfo(reg_kind
, reg_num
);
150 RegisterValue reg_value
;
151 if (reg_value
.SetUInt(uint_value
, reg_info
->byte_size
))
152 return WriteRegister(context
, *reg_info
, reg_value
);
157 bool EmulateInstruction::WriteRegisterUnsigned(const Context
&context
,
158 const RegisterInfo
®_info
,
159 uint64_t uint_value
) {
160 RegisterValue reg_value
;
161 if (reg_value
.SetUInt(uint_value
, reg_info
.byte_size
))
162 return WriteRegister(context
, reg_info
, reg_value
);
166 size_t EmulateInstruction::ReadMemory(const Context
&context
, lldb::addr_t addr
,
167 void *dst
, size_t dst_len
) {
168 if (m_read_mem_callback
!= nullptr)
169 return m_read_mem_callback(this, m_baton
, context
, addr
, dst
, dst_len
) ==
174 uint64_t EmulateInstruction::ReadMemoryUnsigned(const Context
&context
,
180 bool success
= false;
181 if (byte_size
<= 8) {
182 uint8_t buf
[sizeof(uint64_t)];
184 m_read_mem_callback(this, m_baton
, context
, addr
, buf
, byte_size
);
185 if (bytes_read
== byte_size
) {
186 lldb::offset_t offset
= 0;
187 DataExtractor
data(buf
, byte_size
, GetByteOrder(), GetAddressByteSize());
188 uval64
= data
.GetMaxU64(&offset
, byte_size
);
194 *success_ptr
= success
;
201 bool EmulateInstruction::WriteMemoryUnsigned(const Context
&context
,
202 lldb::addr_t addr
, uint64_t uval
,
203 size_t uval_byte_size
) {
204 StreamString
strm(Stream::eBinary
, GetAddressByteSize(), GetByteOrder());
205 strm
.PutMaxHex64(uval
, uval_byte_size
);
207 size_t bytes_written
= m_write_mem_callback(
208 this, m_baton
, context
, addr
, strm
.GetString().data(), uval_byte_size
);
209 return (bytes_written
== uval_byte_size
);
212 bool EmulateInstruction::WriteMemory(const Context
&context
, lldb::addr_t addr
,
213 const void *src
, size_t src_len
) {
214 if (m_write_mem_callback
!= nullptr)
215 return m_write_mem_callback(this, m_baton
, context
, addr
, src
, src_len
) ==
220 void EmulateInstruction::SetBaton(void *baton
) { m_baton
= baton
; }
222 void EmulateInstruction::SetCallbacks(
223 ReadMemoryCallback read_mem_callback
,
224 WriteMemoryCallback write_mem_callback
,
225 ReadRegisterCallback read_reg_callback
,
226 WriteRegisterCallback write_reg_callback
) {
227 m_read_mem_callback
= read_mem_callback
;
228 m_write_mem_callback
= write_mem_callback
;
229 m_read_reg_callback
= read_reg_callback
;
230 m_write_reg_callback
= write_reg_callback
;
233 void EmulateInstruction::SetReadMemCallback(
234 ReadMemoryCallback read_mem_callback
) {
235 m_read_mem_callback
= read_mem_callback
;
238 void EmulateInstruction::SetWriteMemCallback(
239 WriteMemoryCallback write_mem_callback
) {
240 m_write_mem_callback
= write_mem_callback
;
243 void EmulateInstruction::SetReadRegCallback(
244 ReadRegisterCallback read_reg_callback
) {
245 m_read_reg_callback
= read_reg_callback
;
248 void EmulateInstruction::SetWriteRegCallback(
249 WriteRegisterCallback write_reg_callback
) {
250 m_write_reg_callback
= write_reg_callback
;
254 // Read & Write Memory and Registers callback functions.
257 size_t EmulateInstruction::ReadMemoryFrame(EmulateInstruction
*instruction
,
258 void *baton
, const Context
&context
,
259 lldb::addr_t addr
, void *dst
,
261 if (baton
== nullptr || dst
== nullptr || dst_len
== 0)
264 StackFrame
*frame
= (StackFrame
*)baton
;
266 ProcessSP
process_sp(frame
->CalculateProcess());
269 return process_sp
->ReadMemory(addr
, dst
, dst_len
, error
);
274 size_t EmulateInstruction::WriteMemoryFrame(EmulateInstruction
*instruction
,
275 void *baton
, const Context
&context
,
276 lldb::addr_t addr
, const void *src
,
278 if (baton
== nullptr || src
== nullptr || src_len
== 0)
281 StackFrame
*frame
= (StackFrame
*)baton
;
283 ProcessSP
process_sp(frame
->CalculateProcess());
286 return process_sp
->WriteMemory(addr
, src
, src_len
, error
);
292 bool EmulateInstruction::ReadRegisterFrame(EmulateInstruction
*instruction
,
294 const RegisterInfo
*reg_info
,
295 RegisterValue
®_value
) {
296 if (baton
== nullptr)
299 StackFrame
*frame
= (StackFrame
*)baton
;
300 return frame
->GetRegisterContext()->ReadRegister(reg_info
, reg_value
);
303 bool EmulateInstruction::WriteRegisterFrame(EmulateInstruction
*instruction
,
304 void *baton
, const Context
&context
,
305 const RegisterInfo
*reg_info
,
306 const RegisterValue
®_value
) {
307 if (baton
== nullptr)
310 StackFrame
*frame
= (StackFrame
*)baton
;
311 return frame
->GetRegisterContext()->WriteRegister(reg_info
, reg_value
);
314 size_t EmulateInstruction::ReadMemoryDefault(EmulateInstruction
*instruction
,
316 const Context
&context
,
317 lldb::addr_t addr
, void *dst
,
319 StreamFile
strm(stdout
, false);
320 strm
.Printf(" Read from Memory (address = 0x%" PRIx64
", length = %" PRIu64
322 addr
, (uint64_t)length
);
323 context
.Dump(strm
, instruction
);
325 *((uint64_t *)dst
) = 0xdeadbeef;
329 size_t EmulateInstruction::WriteMemoryDefault(EmulateInstruction
*instruction
,
331 const Context
&context
,
333 const void *dst
, size_t length
) {
334 StreamFile
strm(stdout
, false);
335 strm
.Printf(" Write to Memory (address = 0x%" PRIx64
", length = %" PRIu64
337 addr
, (uint64_t)length
);
338 context
.Dump(strm
, instruction
);
343 bool EmulateInstruction::ReadRegisterDefault(EmulateInstruction
*instruction
,
345 const RegisterInfo
*reg_info
,
346 RegisterValue
®_value
) {
347 StreamFile
strm(stdout
, false);
348 strm
.Printf(" Read Register (%s)\n", reg_info
->name
);
349 lldb::RegisterKind reg_kind
;
351 if (GetBestRegisterKindAndNumber(reg_info
, reg_kind
, reg_num
))
352 reg_value
.SetUInt64((uint64_t)reg_kind
<< 24 | reg_num
);
354 reg_value
.SetUInt64(0);
359 bool EmulateInstruction::WriteRegisterDefault(EmulateInstruction
*instruction
,
361 const Context
&context
,
362 const RegisterInfo
*reg_info
,
363 const RegisterValue
®_value
) {
364 StreamFile
strm(stdout
, false);
365 strm
.Printf(" Write to Register (name = %s, value = ", reg_info
->name
);
366 DumpRegisterValue(reg_value
, strm
, *reg_info
, false, false, eFormatDefault
);
367 strm
.PutCString(", context = ");
368 context
.Dump(strm
, instruction
);
373 void EmulateInstruction::Context::Dump(Stream
&strm
,
374 EmulateInstruction
*instruction
) const {
376 case eContextReadOpcode
:
377 strm
.PutCString("reading opcode");
380 case eContextImmediate
:
381 strm
.PutCString("immediate");
384 case eContextPushRegisterOnStack
:
385 strm
.PutCString("push register");
388 case eContextPopRegisterOffStack
:
389 strm
.PutCString("pop register");
392 case eContextAdjustStackPointer
:
393 strm
.PutCString("adjust sp");
396 case eContextSetFramePointer
:
397 strm
.PutCString("set frame pointer");
400 case eContextAdjustBaseRegister
:
401 strm
.PutCString("adjusting (writing value back to) a base register");
404 case eContextRegisterPlusOffset
:
405 strm
.PutCString("register + offset");
408 case eContextRegisterStore
:
409 strm
.PutCString("store register");
412 case eContextRegisterLoad
:
413 strm
.PutCString("load register");
416 case eContextRelativeBranchImmediate
:
417 strm
.PutCString("relative branch immediate");
420 case eContextAbsoluteBranchRegister
:
421 strm
.PutCString("absolute branch register");
424 case eContextSupervisorCall
:
425 strm
.PutCString("supervisor call");
428 case eContextTableBranchReadMemory
:
429 strm
.PutCString("table branch read memory");
432 case eContextWriteRegisterRandomBits
:
433 strm
.PutCString("write random bits to a register");
436 case eContextWriteMemoryRandomBits
:
437 strm
.PutCString("write random bits to a memory address");
440 case eContextArithmetic
:
441 strm
.PutCString("arithmetic");
444 case eContextReturnFromException
:
445 strm
.PutCString("return from exception");
449 strm
.PutCString("unrecognized context.");
453 switch (GetInfoType()) {
454 case eInfoTypeRegisterPlusOffset
:
455 strm
.Printf(" (reg_plus_offset = %s%+" PRId64
")",
456 info
.RegisterPlusOffset
.reg
.name
,
457 info
.RegisterPlusOffset
.signed_offset
);
460 case eInfoTypeRegisterPlusIndirectOffset
:
461 strm
.Printf(" (reg_plus_reg = %s + %s)",
462 info
.RegisterPlusIndirectOffset
.base_reg
.name
,
463 info
.RegisterPlusIndirectOffset
.offset_reg
.name
);
466 case eInfoTypeRegisterToRegisterPlusOffset
:
467 strm
.Printf(" (base_and_imm_offset = %s%+" PRId64
", data_reg = %s)",
468 info
.RegisterToRegisterPlusOffset
.base_reg
.name
,
469 info
.RegisterToRegisterPlusOffset
.offset
,
470 info
.RegisterToRegisterPlusOffset
.data_reg
.name
);
473 case eInfoTypeRegisterToRegisterPlusIndirectOffset
:
474 strm
.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)",
475 info
.RegisterToRegisterPlusIndirectOffset
.base_reg
.name
,
476 info
.RegisterToRegisterPlusIndirectOffset
.offset_reg
.name
,
477 info
.RegisterToRegisterPlusIndirectOffset
.data_reg
.name
);
480 case eInfoTypeRegisterRegisterOperands
:
481 strm
.Printf(" (register to register binary op: %s and %s)",
482 info
.RegisterRegisterOperands
.operand1
.name
,
483 info
.RegisterRegisterOperands
.operand2
.name
);
486 case eInfoTypeOffset
:
487 strm
.Printf(" (signed_offset = %+" PRId64
")", info
.signed_offset
);
490 case eInfoTypeRegister
:
491 strm
.Printf(" (reg = %s)", info
.reg
.name
);
494 case eInfoTypeImmediate
:
495 strm
.Printf(" (unsigned_immediate = %" PRIu64
" (0x%16.16" PRIx64
"))",
496 info
.unsigned_immediate
, info
.unsigned_immediate
);
499 case eInfoTypeImmediateSigned
:
500 strm
.Printf(" (signed_immediate = %+" PRId64
" (0x%16.16" PRIx64
"))",
501 info
.signed_immediate
, info
.signed_immediate
);
504 case eInfoTypeAddress
:
505 strm
.Printf(" (address = 0x%" PRIx64
")", info
.address
);
508 case eInfoTypeISAAndImmediate
:
509 strm
.Printf(" (isa = %u, unsigned_immediate = %u (0x%8.8x))",
510 info
.ISAAndImmediate
.isa
, info
.ISAAndImmediate
.unsigned_data32
,
511 info
.ISAAndImmediate
.unsigned_data32
);
514 case eInfoTypeISAAndImmediateSigned
:
515 strm
.Printf(" (isa = %u, signed_immediate = %i (0x%8.8x))",
516 info
.ISAAndImmediateSigned
.isa
,
517 info
.ISAAndImmediateSigned
.signed_data32
,
518 info
.ISAAndImmediateSigned
.signed_data32
);
522 strm
.Printf(" (isa = %u)", info
.isa
);
525 case eInfoTypeNoArgs
:
530 bool EmulateInstruction::SetInstruction(const Opcode
&opcode
,
531 const Address
&inst_addr
,
534 m_addr
= LLDB_INVALID_ADDRESS
;
535 if (inst_addr
.IsValid()) {
536 if (target
!= nullptr)
537 m_addr
= inst_addr
.GetLoadAddress(target
);
538 if (m_addr
== LLDB_INVALID_ADDRESS
)
539 m_addr
= inst_addr
.GetFileAddress();
544 bool EmulateInstruction::GetBestRegisterKindAndNumber(
545 const RegisterInfo
*reg_info
, lldb::RegisterKind
®_kind
,
547 // Generic and DWARF should be the two most popular register kinds when
548 // emulating instructions since they are the most platform agnostic...
549 reg_num
= reg_info
->kinds
[eRegisterKindGeneric
];
550 if (reg_num
!= LLDB_INVALID_REGNUM
) {
551 reg_kind
= eRegisterKindGeneric
;
555 reg_num
= reg_info
->kinds
[eRegisterKindDWARF
];
556 if (reg_num
!= LLDB_INVALID_REGNUM
) {
557 reg_kind
= eRegisterKindDWARF
;
561 reg_num
= reg_info
->kinds
[eRegisterKindLLDB
];
562 if (reg_num
!= LLDB_INVALID_REGNUM
) {
563 reg_kind
= eRegisterKindLLDB
;
567 reg_num
= reg_info
->kinds
[eRegisterKindEHFrame
];
568 if (reg_num
!= LLDB_INVALID_REGNUM
) {
569 reg_kind
= eRegisterKindEHFrame
;
573 reg_num
= reg_info
->kinds
[eRegisterKindProcessPlugin
];
574 if (reg_num
!= LLDB_INVALID_REGNUM
) {
575 reg_kind
= eRegisterKindProcessPlugin
;
582 EmulateInstruction::GetInternalRegisterNumber(RegisterContext
*reg_ctx
,
583 const RegisterInfo
®_info
) {
584 lldb::RegisterKind reg_kind
;
586 if (reg_ctx
&& GetBestRegisterKindAndNumber(®_info
, reg_kind
, reg_num
))
587 return reg_ctx
->ConvertRegisterKindToRegisterNumber(reg_kind
, reg_num
);
588 return LLDB_INVALID_REGNUM
;
591 bool EmulateInstruction::CreateFunctionEntryUnwind(UnwindPlan
&unwind_plan
) {