LLDB  mainline
EmulateInstruction.cpp
Go to the documentation of this file.
1 //===-- EmulateInstruction.cpp ----------------------------------*- C++ -*-===//
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 
10 
11 #include "lldb/Core/Address.h"
14 #include "lldb/Core/StreamFile.h"
15 #include "lldb/Symbol/UnwindPlan.h"
16 #include "lldb/Target/Process.h"
18 #include "lldb/Target/StackFrame.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/Utility/Stream.h"
25 #include "lldb/lldb-forward.h"
27 
28 #include "llvm/ADT/StringRef.h"
29 
30 #include <cstring>
31 #include <memory>
32 
33 #include <inttypes.h>
34 #include <stdio.h>
35 
36 namespace lldb_private {
37 class Target;
38 }
39 
40 using namespace lldb;
41 using namespace lldb_private;
42 
45  InstructionType supported_inst_type,
46  const char *plugin_name) {
47  EmulateInstructionCreateInstance create_callback = nullptr;
48  if (plugin_name) {
49  ConstString const_plugin_name(plugin_name);
50  create_callback =
52  const_plugin_name);
53  if (create_callback) {
54  EmulateInstruction *emulate_insn_ptr =
55  create_callback(arch, supported_inst_type);
56  if (emulate_insn_ptr)
57  return emulate_insn_ptr;
58  }
59  } else {
60  for (uint32_t idx = 0;
61  (create_callback =
63  nullptr;
64  ++idx) {
65  EmulateInstruction *emulate_insn_ptr =
66  create_callback(arch, supported_inst_type);
67  if (emulate_insn_ptr)
68  return emulate_insn_ptr;
69  }
70  }
71  return nullptr;
72 }
73 
74 EmulateInstruction::EmulateInstruction(const ArchSpec &arch) : m_arch(arch) {}
75 
76 bool EmulateInstruction::ReadRegister(const RegisterInfo *reg_info,
77  RegisterValue &reg_value) {
78  if (m_read_reg_callback != nullptr)
79  return m_read_reg_callback(this, m_baton, reg_info, reg_value);
80  return false;
81 }
82 
84  uint32_t reg_num,
85  RegisterValue &reg_value) {
86  RegisterInfo reg_info;
87  if (GetRegisterInfo(reg_kind, reg_num, reg_info))
88  return ReadRegister(&reg_info, reg_value);
89  return false;
90 }
91 
93  uint32_t reg_num,
94  uint64_t fail_value,
95  bool *success_ptr) {
96  RegisterValue reg_value;
97  if (ReadRegister(reg_kind, reg_num, reg_value))
98  return reg_value.GetAsUInt64(fail_value, success_ptr);
99  if (success_ptr)
100  *success_ptr = false;
101  return fail_value;
102 }
103 
104 uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo *reg_info,
105  uint64_t fail_value,
106  bool *success_ptr) {
107  RegisterValue reg_value;
108  if (ReadRegister(reg_info, reg_value))
109  return reg_value.GetAsUInt64(fail_value, success_ptr);
110  if (success_ptr)
111  *success_ptr = false;
112  return fail_value;
113 }
114 
116  const RegisterInfo *reg_info,
117  const RegisterValue &reg_value) {
118  if (m_write_reg_callback != nullptr)
119  return m_write_reg_callback(this, m_baton, context, reg_info, reg_value);
120  return false;
121 }
122 
124  lldb::RegisterKind reg_kind,
125  uint32_t reg_num,
126  const RegisterValue &reg_value) {
127  RegisterInfo reg_info;
128  if (GetRegisterInfo(reg_kind, reg_num, reg_info))
129  return WriteRegister(context, &reg_info, reg_value);
130  return false;
131 }
132 
134  lldb::RegisterKind reg_kind,
135  uint32_t reg_num,
136  uint64_t uint_value) {
137  RegisterInfo reg_info;
138  if (GetRegisterInfo(reg_kind, reg_num, reg_info)) {
139  RegisterValue reg_value;
140  if (reg_value.SetUInt(uint_value, reg_info.byte_size))
141  return WriteRegister(context, &reg_info, reg_value);
142  }
143  return false;
144 }
145 
147  const RegisterInfo *reg_info,
148  uint64_t uint_value) {
149  if (reg_info != nullptr) {
150  RegisterValue reg_value;
151  if (reg_value.SetUInt(uint_value, reg_info->byte_size))
152  return WriteRegister(context, reg_info, reg_value);
153  }
154  return false;
155 }
156 
158  void *dst, size_t dst_len) {
159  if (m_read_mem_callback != nullptr)
160  return m_read_mem_callback(this, m_baton, context, addr, dst, dst_len) ==
161  dst_len;
162  return false;
163 }
164 
166  lldb::addr_t addr,
167  size_t byte_size,
168  uint64_t fail_value,
169  bool *success_ptr) {
170  uint64_t uval64 = 0;
171  bool success = false;
172  if (byte_size <= 8) {
173  uint8_t buf[sizeof(uint64_t)];
174  size_t bytes_read =
175  m_read_mem_callback(this, m_baton, context, addr, buf, byte_size);
176  if (bytes_read == byte_size) {
177  lldb::offset_t offset = 0;
178  DataExtractor data(buf, byte_size, GetByteOrder(), GetAddressByteSize());
179  uval64 = data.GetMaxU64(&offset, byte_size);
180  success = true;
181  }
182  }
183 
184  if (success_ptr)
185  *success_ptr = success;
186 
187  if (!success)
188  uval64 = fail_value;
189  return uval64;
190 }
191 
193  lldb::addr_t addr, uint64_t uval,
194  size_t uval_byte_size) {
196  strm.PutMaxHex64(uval, uval_byte_size);
197 
198  size_t bytes_written = m_write_mem_callback(
199  this, m_baton, context, addr, strm.GetString().data(), uval_byte_size);
200  return (bytes_written == uval_byte_size);
201 }
202 
204  const void *src, size_t src_len) {
205  if (m_write_mem_callback != nullptr)
206  return m_write_mem_callback(this, m_baton, context, addr, src, src_len) ==
207  src_len;
208  return false;
209 }
210 
211 void EmulateInstruction::SetBaton(void *baton) { m_baton = baton; }
212 
214  ReadMemoryCallback read_mem_callback,
215  WriteMemoryCallback write_mem_callback,
216  ReadRegisterCallback read_reg_callback,
217  WriteRegisterCallback write_reg_callback) {
218  m_read_mem_callback = read_mem_callback;
219  m_write_mem_callback = write_mem_callback;
220  m_read_reg_callback = read_reg_callback;
221  m_write_reg_callback = write_reg_callback;
222 }
223 
225  ReadMemoryCallback read_mem_callback) {
226  m_read_mem_callback = read_mem_callback;
227 }
228 
230  WriteMemoryCallback write_mem_callback) {
231  m_write_mem_callback = write_mem_callback;
232 }
233 
235  ReadRegisterCallback read_reg_callback) {
236  m_read_reg_callback = read_reg_callback;
237 }
238 
240  WriteRegisterCallback write_reg_callback) {
241  m_write_reg_callback = write_reg_callback;
242 }
243 
244 //
245 // Read & Write Memory and Registers callback functions.
246 //
247 
249  void *baton, const Context &context,
250  lldb::addr_t addr, void *dst,
251  size_t dst_len) {
252  if (baton == nullptr || dst == nullptr || dst_len == 0)
253  return 0;
254 
255  StackFrame *frame = (StackFrame *)baton;
256 
257  ProcessSP process_sp(frame->CalculateProcess());
258  if (process_sp) {
259  Status error;
260  return process_sp->ReadMemory(addr, dst, dst_len, error);
261  }
262  return 0;
263 }
264 
266  void *baton, const Context &context,
267  lldb::addr_t addr, const void *src,
268  size_t src_len) {
269  if (baton == nullptr || src == nullptr || src_len == 0)
270  return 0;
271 
272  StackFrame *frame = (StackFrame *)baton;
273 
274  ProcessSP process_sp(frame->CalculateProcess());
275  if (process_sp) {
276  Status error;
277  return process_sp->WriteMemory(addr, src, src_len, error);
278  }
279 
280  return 0;
281 }
282 
284  void *baton,
285  const RegisterInfo *reg_info,
286  RegisterValue &reg_value) {
287  if (baton == nullptr)
288  return false;
289 
290  StackFrame *frame = (StackFrame *)baton;
291  return frame->GetRegisterContext()->ReadRegister(reg_info, reg_value);
292 }
293 
295  void *baton, const Context &context,
296  const RegisterInfo *reg_info,
297  const RegisterValue &reg_value) {
298  if (baton == nullptr)
299  return false;
300 
301  StackFrame *frame = (StackFrame *)baton;
302  return frame->GetRegisterContext()->WriteRegister(reg_info, reg_value);
303 }
304 
306  void *baton,
307  const Context &context,
308  lldb::addr_t addr, void *dst,
309  size_t length) {
310  StreamFile strm(stdout, false);
311  strm.Printf(" Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64
312  ", context = ",
313  addr, (uint64_t)length);
314  context.Dump(strm, instruction);
315  strm.EOL();
316  *((uint64_t *)dst) = 0xdeadbeef;
317  return length;
318 }
319 
321  void *baton,
322  const Context &context,
323  lldb::addr_t addr,
324  const void *dst, size_t length) {
325  StreamFile strm(stdout, false);
326  strm.Printf(" Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64
327  ", context = ",
328  addr, (uint64_t)length);
329  context.Dump(strm, instruction);
330  strm.EOL();
331  return length;
332 }
333 
335  void *baton,
336  const RegisterInfo *reg_info,
337  RegisterValue &reg_value) {
338  StreamFile strm(stdout, false);
339  strm.Printf(" Read Register (%s)\n", reg_info->name);
340  lldb::RegisterKind reg_kind;
341  uint32_t reg_num;
342  if (GetBestRegisterKindAndNumber(reg_info, reg_kind, reg_num))
343  reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num);
344  else
345  reg_value.SetUInt64(0);
346 
347  return true;
348 }
349 
351  void *baton,
352  const Context &context,
353  const RegisterInfo *reg_info,
354  const RegisterValue &reg_value) {
355  StreamFile strm(stdout, false);
356  strm.Printf(" Write to Register (name = %s, value = ", reg_info->name);
357  DumpRegisterValue(reg_value, &strm, reg_info, false, false, eFormatDefault);
358  strm.PutCString(", context = ");
359  context.Dump(strm, instruction);
360  strm.EOL();
361  return true;
362 }
363 
365  EmulateInstruction *instruction) const {
366  switch (type) {
367  case eContextReadOpcode:
368  strm.PutCString("reading opcode");
369  break;
370 
371  case eContextImmediate:
372  strm.PutCString("immediate");
373  break;
374 
376  strm.PutCString("push register");
377  break;
378 
380  strm.PutCString("pop register");
381  break;
382 
384  strm.PutCString("adjust sp");
385  break;
386 
388  strm.PutCString("set frame pointer");
389  break;
390 
392  strm.PutCString("adjusting (writing value back to) a base register");
393  break;
394 
396  strm.PutCString("register + offset");
397  break;
398 
400  strm.PutCString("store register");
401  break;
402 
404  strm.PutCString("load register");
405  break;
406 
408  strm.PutCString("relative branch immediate");
409  break;
410 
412  strm.PutCString("absolute branch register");
413  break;
414 
416  strm.PutCString("supervisor call");
417  break;
418 
420  strm.PutCString("table branch read memory");
421  break;
422 
424  strm.PutCString("write random bits to a register");
425  break;
426 
428  strm.PutCString("write random bits to a memory address");
429  break;
430 
431  case eContextArithmetic:
432  strm.PutCString("arithmetic");
433  break;
434 
436  strm.PutCString("return from exception");
437  break;
438 
439  default:
440  strm.PutCString("unrecognized context.");
441  break;
442  }
443 
444  switch (info_type) {
446  strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")",
447  info.RegisterPlusOffset.reg.name,
448  info.RegisterPlusOffset.signed_offset);
449  break;
450 
452  strm.Printf(" (reg_plus_reg = %s + %s)",
453  info.RegisterPlusIndirectOffset.base_reg.name,
454  info.RegisterPlusIndirectOffset.offset_reg.name);
455  break;
456 
458  strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)",
459  info.RegisterToRegisterPlusOffset.base_reg.name,
460  info.RegisterToRegisterPlusOffset.offset,
461  info.RegisterToRegisterPlusOffset.data_reg.name);
462  break;
463 
465  strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)",
466  info.RegisterToRegisterPlusIndirectOffset.base_reg.name,
467  info.RegisterToRegisterPlusIndirectOffset.offset_reg.name,
468  info.RegisterToRegisterPlusIndirectOffset.data_reg.name);
469  break;
470 
472  strm.Printf(" (register to register binary op: %s and %s)",
473  info.RegisterRegisterOperands.operand1.name,
474  info.RegisterRegisterOperands.operand2.name);
475  break;
476 
477  case eInfoTypeOffset:
478  strm.Printf(" (signed_offset = %+" PRId64 ")", info.signed_offset);
479  break;
480 
481  case eInfoTypeRegister:
482  strm.Printf(" (reg = %s)", info.reg.name);
483  break;
484 
485  case eInfoTypeImmediate:
486  strm.Printf(" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))",
487  info.unsigned_immediate, info.unsigned_immediate);
488  break;
489 
491  strm.Printf(" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))",
492  info.signed_immediate, info.signed_immediate);
493  break;
494 
495  case eInfoTypeAddress:
496  strm.Printf(" (address = 0x%" PRIx64 ")", info.address);
497  break;
498 
500  strm.Printf(" (isa = %u, unsigned_immediate = %u (0x%8.8x))",
501  info.ISAAndImmediate.isa, info.ISAAndImmediate.unsigned_data32,
502  info.ISAAndImmediate.unsigned_data32);
503  break;
504 
506  strm.Printf(" (isa = %u, signed_immediate = %i (0x%8.8x))",
507  info.ISAAndImmediateSigned.isa,
508  info.ISAAndImmediateSigned.signed_data32,
509  info.ISAAndImmediateSigned.signed_data32);
510  break;
511 
512  case eInfoTypeISA:
513  strm.Printf(" (isa = %u)", info.isa);
514  break;
515 
516  case eInfoTypeNoArgs:
517  break;
518  }
519 }
520 
522  const Address &inst_addr,
523  Target *target) {
524  m_opcode = opcode;
526  if (inst_addr.IsValid()) {
527  if (target != nullptr)
528  m_addr = inst_addr.GetLoadAddress(target);
530  m_addr = inst_addr.GetFileAddress();
531  }
532  return true;
533 }
534 
536  const RegisterInfo *reg_info, lldb::RegisterKind &reg_kind,
537  uint32_t &reg_num) {
538  // Generic and DWARF should be the two most popular register kinds when
539  // emulating instructions since they are the most platform agnostic...
540  reg_num = reg_info->kinds[eRegisterKindGeneric];
541  if (reg_num != LLDB_INVALID_REGNUM) {
542  reg_kind = eRegisterKindGeneric;
543  return true;
544  }
545 
546  reg_num = reg_info->kinds[eRegisterKindDWARF];
547  if (reg_num != LLDB_INVALID_REGNUM) {
548  reg_kind = eRegisterKindDWARF;
549  return true;
550  }
551 
552  reg_num = reg_info->kinds[eRegisterKindLLDB];
553  if (reg_num != LLDB_INVALID_REGNUM) {
554  reg_kind = eRegisterKindLLDB;
555  return true;
556  }
557 
558  reg_num = reg_info->kinds[eRegisterKindEHFrame];
559  if (reg_num != LLDB_INVALID_REGNUM) {
560  reg_kind = eRegisterKindEHFrame;
561  return true;
562  }
563 
564  reg_num = reg_info->kinds[eRegisterKindProcessPlugin];
565  if (reg_num != LLDB_INVALID_REGNUM) {
566  reg_kind = eRegisterKindProcessPlugin;
567  return true;
568  }
569  return false;
570 }
571 
572 uint32_t
574  const RegisterInfo &reg_info) {
575  lldb::RegisterKind reg_kind;
576  uint32_t reg_num;
577  if (reg_ctx && GetBestRegisterKindAndNumber(&reg_info, reg_kind, reg_num))
578  return reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
579  return LLDB_INVALID_REGNUM;
580 }
581 
583  unwind_plan.Clear();
584  return false;
585 }
void SetReadMemCallback(ReadMemoryCallback read_mem_callback)
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
bool WriteMemoryUnsigned(const Context &context, lldb::addr_t addr, uint64_t uval, size_t uval_byte_size)
An data extractor class.
Definition: DataExtractor.h:47
bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)
Get and put data as binary instead of as the default string mode.
Definition: Stream.h:32
EmulateInstruction(const ArchSpec &arch)
static size_t WriteMemoryDefault(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, const void *dst, size_t length)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info, uint64_t fail_value, bool *success_ptr)
void Dump(Stream &s, EmulateInstruction *instruction) const
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition: Address.cpp:292
bool WriteRegister(const Context &context, const RegisterInfo *ref_info, const RegisterValue &reg_value)
virtual bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info)=0
size_t(* WriteMemoryCallback)(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, const void *dst, size_t length)
lldb::ByteOrder GetByteOrder() const
virtual uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num)=0
Convert from a given register numbering scheme to the lldb register numbering scheme.
An architecture specification class.
Definition: ArchSpec.h:32
lldb::addr_t GetFileAddress() const
Get the file address.
Definition: Address.cpp:272
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src, size_t src_len)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
size_t PutMaxHex64(uint64_t uvalue, size_t byte_size, lldb::ByteOrder byte_order=lldb::eByteOrderInvalid)
Definition: Stream.cpp:338
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
static size_t ReadMemoryDefault(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, void *dst, size_t length)
static uint32_t GetInternalRegisterNumber(RegisterContext *reg_ctx, const RegisterInfo &reg_info)
bool SetUInt(uint64_t uint, uint32_t byte_size)
void SetReadRegCallback(ReadRegisterCallback read_reg_callback)
lldb::RegisterContextSP GetRegisterContext()
Get the RegisterContext for this frame, if possible.
bool DumpRegisterValue(const RegisterValue &reg_val, Stream *s, const RegisterInfo *reg_info, bool prefix_with_name, bool prefix_with_alt_name, lldb::Format format, uint32_t reg_name_right_align_at=0)
lldb::ProcessSP CalculateProcess() override
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
size_t ReadMemory(const Context &context, lldb::addr_t addr, void *dst, size_t dst_len)
size_t(* ReadMemoryCallback)(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, void *dst, size_t length)
uint64_t offset_t
Definition: lldb-types.h:87
static bool WriteRegisterDefault(EmulateInstruction *instruction, void *baton, const Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:127
static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton, const Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
static EmulateInstruction * FindPlugin(const ArchSpec &arch, InstructionType supported_inst_type, const char *plugin_name)
llvm::StringRef GetString() const
static size_t WriteMemoryFrame(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, const void *dst, size_t length)
static bool ReadRegisterDefault(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
WriteRegisterCallback m_write_reg_callback
WriteMemoryCallback m_write_mem_callback
static EmulateInstructionCreateInstance GetEmulateInstructionCreateCallbackForPluginName(ConstString name)
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:343
A section + offset based address class.
Definition: Address.h:80
virtual bool SetInstruction(const Opcode &insn_opcode, const Address &inst_addr, Target *target)
static bool ReadRegisterFrame(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
InstructionType
Instruction types.
static EmulateInstructionCreateInstance GetEmulateInstructionCreateCallbackAtIndex(uint32_t idx)
bool(* WriteRegisterCallback)(EmulateInstruction *instruction, void *baton, const Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
static bool GetBestRegisterKindAndNumber(const RegisterInfo *reg_info, lldb::RegisterKind &reg_kind, uint32_t &reg_num)
static size_t ReadMemoryFrame(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, void *dst, size_t length)
uint64_t addr_t
Definition: lldb-types.h:83
A uniqued constant string class.
Definition: ConstString.h:38
Definition: SBAddress.h:15
ReadRegisterCallback m_read_reg_callback
void SetWriteMemCallback(WriteMemoryCallback write_mem_callback)
bool WriteRegisterUnsigned(const Context &context, const RegisterInfo *reg_info, uint64_t reg_value)
bool(* ReadRegisterCallback)(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
This base class provides an interface to stack frames.
Definition: StackFrame.h:40
void SetWriteRegCallback(WriteRegisterCallback write_reg_callback)
void SetCallbacks(ReadMemoryCallback read_mem_callback, WriteMemoryCallback write_mem_callback, ReadRegisterCallback read_reg_callback, WriteRegisterCallback write_reg_callback)
An error handling class.
Definition: Status.h:44
virtual bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan)
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90