LLDB  mainline
NativeProcessSoftwareSingleStep.cpp
Go to the documentation of this file.
1 //===-- NativeProcessSoftwareSingleStep.cpp -------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
14 
15 #include <unordered_map>
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 namespace {
21 
22 struct EmulatorBaton {
23  NativeProcessProtocol &m_process;
24  NativeRegisterContext &m_reg_context;
25 
26  // eRegisterKindDWARF -> RegsiterValue
27  std::unordered_map<uint32_t, RegisterValue> m_register_values;
28 
29  EmulatorBaton(NativeProcessProtocol &process,
30  NativeRegisterContext &reg_context)
31  : m_process(process), m_reg_context(reg_context) {}
32 };
33 
34 } // anonymous namespace
35 
36 static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
37  const EmulateInstruction::Context &context,
38  lldb::addr_t addr, void *dst, size_t length) {
39  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
40 
41  size_t bytes_read;
42  emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read);
43  return bytes_read;
44 }
45 
46 static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
47  const RegisterInfo *reg_info,
48  RegisterValue &reg_value) {
49  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
50 
51  auto it = emulator_baton->m_register_values.find(
52  reg_info->kinds[eRegisterKindDWARF]);
53  if (it != emulator_baton->m_register_values.end()) {
54  reg_value = it->second;
55  return true;
56  }
57 
58  // The emulator only fill in the dwarf regsiter numbers (and in some case the
59  // generic register numbers). Get the full register info from the register
60  // context based on the dwarf register numbers.
61  const RegisterInfo *full_reg_info =
62  emulator_baton->m_reg_context.GetRegisterInfo(
63  eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
64 
65  Status error =
66  emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value);
67  if (error.Success())
68  return true;
69 
70  return false;
71 }
72 
73 static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
74  const EmulateInstruction::Context &context,
75  const RegisterInfo *reg_info,
76  const RegisterValue &reg_value) {
77  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
78  emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =
79  reg_value;
80  return true;
81 }
82 
83 static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
84  const EmulateInstruction::Context &context,
85  lldb::addr_t addr, const void *dst,
86  size_t length) {
87  return length;
88 }
89 
90 static lldb::addr_t ReadFlags(NativeRegisterContext &regsiter_context) {
91  const RegisterInfo *flags_info = regsiter_context.GetRegisterInfo(
93  return regsiter_context.ReadRegisterAsUnsigned(flags_info,
95 }
96 
97 Status NativeProcessSoftwareSingleStep::SetupSoftwareSingleStepping(
98  NativeThreadProtocol &thread) {
99  Status error;
100  NativeProcessProtocol &process = thread.GetProcess();
101  NativeRegisterContext &register_context = thread.GetRegisterContext();
102  const ArchSpec &arch = process.GetArchitecture();
103 
104  std::unique_ptr<EmulateInstruction> emulator_up(
105  EmulateInstruction::FindPlugin(arch, eInstructionTypePCModifying,
106  nullptr));
107 
108  if (emulator_up == nullptr)
109  return Status("Instruction emulator not found!");
110 
111  EmulatorBaton baton(process, register_context);
112  emulator_up->SetBaton(&baton);
113  emulator_up->SetReadMemCallback(&ReadMemoryCallback);
114  emulator_up->SetReadRegCallback(&ReadRegisterCallback);
115  emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
116  emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
117 
118  if (!emulator_up->ReadInstruction())
119  return Status("Read instruction failed!");
120 
121  bool emulation_result =
122  emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
123 
124  const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo(
126  const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo(
128 
129  auto pc_it =
130  baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
131  auto flags_it =
132  baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]);
133 
134  lldb::addr_t next_pc;
135  lldb::addr_t next_flags;
136  if (emulation_result) {
137  assert(pc_it != baton.m_register_values.end() &&
138  "Emulation was successfull but PC wasn't updated");
139  next_pc = pc_it->second.GetAsUInt64();
140 
141  if (flags_it != baton.m_register_values.end())
142  next_flags = flags_it->second.GetAsUInt64();
143  else
144  next_flags = ReadFlags(register_context);
145  } else if (pc_it == baton.m_register_values.end()) {
146  // Emulate instruction failed and it haven't changed PC. Advance PC with
147  // the size of the current opcode because the emulation of all
148  // PC modifying instruction should be successful. The failure most
149  // likely caused by a not supported instruction which don't modify PC.
150  next_pc = register_context.GetPC() + emulator_up->GetOpcode().GetByteSize();
151  next_flags = ReadFlags(register_context);
152  } else {
153  // The instruction emulation failed after it modified the PC. It is an
154  // unknown error where we can't continue because the next instruction is
155  // modifying the PC but we don't know how.
156  return Status("Instruction emulation failed unexpectedly.");
157  }
158 
159  int size_hint = 0;
160  if (arch.GetMachine() == llvm::Triple::arm) {
161  if (next_flags & 0x20) {
162  // Thumb mode
163  size_hint = 2;
164  } else {
165  // Arm mode
166  size_hint = 4;
167  }
168  } else if (arch.IsMIPS() || arch.GetTriple().isPPC64())
169  size_hint = 4;
170  error = process.SetBreakpoint(next_pc, size_hint, /*hardware=*/false);
171 
172  // If setting the breakpoint fails because next_pc is out of the address
173  // space, ignore it and let the debugee segfault.
174  if (error.GetError() == EIO || error.GetError() == EFAULT) {
175  return Status();
176  } else if (error.Fail())
177  return error;
178 
179  m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc});
180 
181  return Status();
182 }
lldb_private::eInstructionTypePCModifying
@ eInstructionTypePCModifying
Definition: lldb-private-enumerations.h:123
lldb_private::ArchSpec
Definition: ArchSpec.h:33
lldb_private::ArchSpec::IsMIPS
bool IsMIPS() const
if MIPS architecture return true.
Definition: ArchSpec.cpp:545
x20
@ x20
Definition: CompactUnwindInfo.cpp:1237
lldb_private::ArchSpec::GetMachine
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:667
lldb_private::RegisterValue
Definition: RegisterValue.h:28
lldb_private::NativeThreadProtocol
Definition: NativeThreadProtocol.h:20
lldb::eRegisterKindDWARF
@ eRegisterKindDWARF
the register numbers seen DWARF
Definition: lldb-enumerations.h:229
lldb::eRegisterKindGeneric
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
Definition: lldb-enumerations.h:230
lldb_private::EmulateInstruction::Context
Definition: EmulateInstruction.h:184
WriteRegisterCallback
static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
Definition: NativeProcessSoftwareSingleStep.cpp:73
lldb_private::NativeThreadProtocol::GetProcess
NativeProcessProtocol & GetProcess()
Definition: NativeThreadProtocol.h:37
RegisterValue.h
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:444
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::NativeRegisterContext::ReadRegisterAsUnsigned
lldb::addr_t ReadRegisterAsUnsigned(uint32_t reg, lldb::addr_t fail_value)
Definition: NativeRegisterContext.cpp:190
lldb_private::NativeRegisterContext::GetRegisterInfo
const RegisterInfo * GetRegisterInfo(uint32_t reg_kind, uint32_t reg_num)
Definition: NativeRegisterContext.cpp:82
LLDB_REGNUM_GENERIC_FLAGS
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:67
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
EmulateInstruction.h
lldb_private::NativeThreadProtocol::GetRegisterContext
virtual NativeRegisterContext & GetRegisterContext()=0
lldb_private::Status
Definition: Status.h:44
WriteMemoryCallback
static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, lldb::addr_t addr, const void *dst, size_t length)
Definition: NativeProcessSoftwareSingleStep.cpp:83
lldb_private::EmulateInstruction
Definition: EmulateInstruction.h:93
lldb_private::NativeProcessProtocol
Definition: NativeProcessProtocol.h:47
lldb_private::NativeThreadProtocol::GetID
lldb::tid_t GetID() const
Definition: NativeThreadProtocol.h:35
lldb_private::NativeProcessProtocol::SetBreakpoint
virtual Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware)=0
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:86
lldb_private::NativeRegisterContext::GetPC
lldb::addr_t GetPC(lldb::addr_t fail_value=LLDB_INVALID_ADDRESS)
Definition: NativeRegisterContext.cpp:124
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:63
ReadRegisterCallback
static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
Definition: NativeProcessSoftwareSingleStep.cpp:46
lldb_private::NativeRegisterContext
Definition: NativeRegisterContext.h:21
NativeProcessSoftwareSingleStep.h
lldb
Definition: SBAddress.h:15
NativeRegisterContext.h
ReadMemoryCallback
static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst, size_t length)
Definition: NativeProcessSoftwareSingleStep.cpp:36
ReadFlags
static lldb::addr_t ReadFlags(NativeRegisterContext &regsiter_context)
Definition: NativeProcessSoftwareSingleStep.cpp:90
lldb_private::NativeProcessProtocol::GetArchitecture
virtual const ArchSpec & GetArchitecture() const =0