LLDB  mainline
NativeRegisterContextLinux.cpp
Go to the documentation of this file.
1 //===-- NativeRegisterContextLinux.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 
13 #include "lldb/Host/linux/Ptrace.h"
15 
18 
19 using namespace lldb_private;
20 using namespace lldb_private::process_linux;
21 
23  NativeThreadProtocol &native_thread,
24  RegisterInfoInterface *reg_info_interface_p)
25  : NativeRegisterContextRegisterInfo(native_thread, reg_info_interface_p) {}
26 
28  return m_thread.GetProcess().GetByteOrder();
29 }
30 
32  RegisterValue &reg_value) {
33  const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
34  if (!reg_info)
35  return Status("register %" PRIu32 " not found", reg_index);
36 
37  return DoReadRegisterValue(reg_info->byte_offset, reg_info->name,
38  reg_info->byte_size, reg_value);
39 }
40 
41 Status
43  const RegisterValue &reg_value) {
44  uint32_t reg_to_write = reg_index;
45  RegisterValue value_to_write = reg_value;
46 
47  // Check if this is a subregister of a full register.
48  const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
49  if (reg_info->invalidate_regs &&
50  (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
51  Status error;
52 
53  RegisterValue full_value;
54  uint32_t full_reg = reg_info->invalidate_regs[0];
55  const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
56 
57  // Read the full register.
58  error = ReadRegister(full_reg_info, full_value);
59  if (error.Fail())
60  return error;
61 
62  lldb::ByteOrder byte_order = GetByteOrder();
64 
65  // Get the bytes for the full register.
66  const uint32_t dest_size = full_value.GetAsMemoryData(
67  full_reg_info, dst, sizeof(dst), byte_order, error);
68  if (error.Success() && dest_size) {
70 
71  // Get the bytes for the source data.
72  const uint32_t src_size = reg_value.GetAsMemoryData(
73  reg_info, src, sizeof(src), byte_order, error);
74  if (error.Success() && src_size && (src_size < dest_size)) {
75  // Copy the src bytes to the destination.
76  memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
77  // Set this full register as the value to write.
78  value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
79  value_to_write.SetType(full_reg_info);
80  reg_to_write = full_reg;
81  }
82  }
83  }
84 
85  const RegisterInfo *const register_to_write_info_p =
86  GetRegisterInfoAtIndex(reg_to_write);
87  assert(register_to_write_info_p &&
88  "register to write does not have valid RegisterInfo");
89  if (!register_to_write_info_p)
90  return Status("NativeRegisterContextLinux::%s failed to get RegisterInfo "
91  "for write register index %" PRIu32,
92  __FUNCTION__, reg_to_write);
93 
94  return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
95 }
96 
98  void *buf = GetGPRBuffer();
99  if (!buf)
100  return Status("GPR buffer is NULL");
101  size_t buf_size = GetGPRSize();
102 
103  return DoReadGPR(buf, buf_size);
104 }
105 
107  void *buf = GetGPRBuffer();
108  if (!buf)
109  return Status("GPR buffer is NULL");
110  size_t buf_size = GetGPRSize();
111 
112  return DoWriteGPR(buf, buf_size);
113 }
114 
116  void *buf = GetFPRBuffer();
117  if (!buf)
118  return Status("FPR buffer is NULL");
119  size_t buf_size = GetFPRSize();
120 
121  return DoReadFPR(buf, buf_size);
122 }
123 
125  void *buf = GetFPRBuffer();
126  if (!buf)
127  return Status("FPR buffer is NULL");
128  size_t buf_size = GetFPRSize();
129 
130  return DoWriteFPR(buf, buf_size);
131 }
132 
134  unsigned int regset) {
136  static_cast<void *>(&regset), buf,
137  buf_size);
138 }
139 
141  unsigned int regset) {
143  static_cast<void *>(&regset), buf,
144  buf_size);
145 }
146 
148  const char *reg_name,
149  uint32_t size,
150  RegisterValue &value) {
152 
153  long data;
155  PTRACE_PEEKUSER, m_thread.GetID(), reinterpret_cast<void *>(offset),
156  nullptr, 0, &data);
157 
158  if (error.Success())
159  // First cast to an unsigned of the same size to avoid sign extension.
160  value.SetUInt(static_cast<unsigned long>(data), size);
161 
162  LLDB_LOG(log, "{0}: {1:x}", reg_name, data);
163  return error;
164 }
165 
167  uint32_t offset, const char *reg_name, const RegisterValue &value) {
169 
170  void *buf = reinterpret_cast<void *>(value.GetAsUInt64());
171  LLDB_LOG(log, "{0}: {1}", reg_name, buf);
172 
174  PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf);
175 }
176 
177 Status NativeRegisterContextLinux::DoReadGPR(void *buf, size_t buf_size) {
179  nullptr, buf, buf_size);
180 }
181 
182 Status NativeRegisterContextLinux::DoWriteGPR(void *buf, size_t buf_size) {
184  nullptr, buf, buf_size);
185 }
186 
187 Status NativeRegisterContextLinux::DoReadFPR(void *buf, size_t buf_size) {
189  nullptr, buf, buf_size);
190 }
191 
192 Status NativeRegisterContextLinux::DoWriteFPR(void *buf, size_t buf_size) {
194  nullptr, buf, buf_size);
195 }
#define PTRACE_SETREGSET
Definition: Ptrace.h:39
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
NativeRegisterContextLinux(NativeThreadProtocol &native_thread, RegisterInfoInterface *reg_info_interface_p)
RegisterInfo interface to patch RegisterInfo structure for archs.
uint32_t GetAsMemoryData(const RegisterInfo *reg_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
#define LLDB_LOG(log,...)
Definition: Log.h:209
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
virtual Status ReadRegisterRaw(uint32_t reg_index, RegisterValue &reg_value)
virtual Status DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value)
bool SetUInt(uint64_t uint, uint32_t byte_size)
#define PTRACE_GETREGSET
Definition: Ptrace.h:36
#define PTRACE_GETFPREGS
Definition: Ptrace.h:30
#define PTRACE_SETREGS
Definition: Ptrace.h:27
virtual Status ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
virtual Status WriteRegisterRaw(uint32_t reg_index, const RegisterValue &reg_value)
NativeProcessProtocol & GetProcess()
#define POSIX_LOG_REGISTERS
bool Success() const
Test for success condition.
Definition: Status.cpp:287
virtual Status ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset)
#define PTRACE_SETFPREGS
Definition: Ptrace.h:33
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr=nullptr, void *data=nullptr, size_t data_size=0, long *result=nullptr)
const RegisterInfo * GetRegisterInfoAtIndex(uint32_t reg_index) const override
void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order)
#define PTRACE_GETREGS
Definition: Ptrace.h:24
static Log * GetLogIfAllCategoriesSet(uint32_t mask)
virtual Status DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, RegisterValue &value)
void SetType(RegisterValue::Type type)
Definition: RegisterValue.h:83
An error handling class.
Definition: Status.h:44
virtual Status WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset)
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90