1 //===-- NativeRegisterContextLinux.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 "NativeRegisterContextLinux.h"
11 #include "Plugins/Process/Linux/NativeProcessLinux.h"
12 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
13 #include "lldb/Host/HostInfo.h"
14 #include "lldb/Host/common/NativeProcessProtocol.h"
15 #include "lldb/Host/common/NativeThreadProtocol.h"
16 #include "lldb/Host/linux/Ptrace.h"
17 #include "lldb/Utility/RegisterValue.h"
20 using namespace lldb_private
;
21 using namespace lldb_private::process_linux
;
23 lldb::ByteOrder
NativeRegisterContextLinux::GetByteOrder() const {
24 return m_thread
.GetProcess().GetByteOrder();
27 Status
NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index
,
28 RegisterValue
®_value
) {
29 const RegisterInfo
*const reg_info
= GetRegisterInfoAtIndex(reg_index
);
31 return Status::FromErrorStringWithFormat("register %" PRIu32
" not found",
34 return DoReadRegisterValue(GetPtraceOffset(reg_index
), reg_info
->name
,
35 reg_info
->byte_size
, reg_value
);
39 NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index
,
40 const RegisterValue
®_value
) {
41 uint32_t reg_to_write
= reg_index
;
42 RegisterValue value_to_write
= reg_value
;
44 // Check if this is a subregister of a full register.
45 const RegisterInfo
*reg_info
= GetRegisterInfoAtIndex(reg_index
);
46 assert(reg_info
&& "Expected valid register info for reg_index.");
47 if (reg_info
->invalidate_regs
&&
48 (reg_info
->invalidate_regs
[0] != LLDB_INVALID_REGNUM
)) {
51 RegisterValue full_value
;
52 uint32_t full_reg
= reg_info
->invalidate_regs
[0];
53 const RegisterInfo
*full_reg_info
= GetRegisterInfoAtIndex(full_reg
);
55 // Read the full register.
56 error
= ReadRegister(full_reg_info
, full_value
);
58 // full_reg_info was nullptr, or we couldn't read the register.
62 lldb::ByteOrder byte_order
= GetByteOrder();
63 RegisterValue::BytesContainer
dst(full_reg_info
->byte_size
);
65 // Get the bytes for the full register.
66 const uint32_t dest_size
= full_value
.GetAsMemoryData(
67 *full_reg_info
, dst
.data(), dst
.size(), byte_order
, error
);
68 if (error
.Success() && dest_size
) {
69 RegisterValue::BytesContainer
src(reg_info
->byte_size
);
71 // Get the bytes for the source data.
72 const uint32_t src_size
= reg_value
.GetAsMemoryData(
73 *reg_info
, src
.data(), src
.size(), byte_order
, error
);
74 if (error
.Success() && src_size
&& (src_size
< dest_size
)) {
75 // Copy the src bytes to the destination.
76 memcpy(dst
.data() + (reg_info
->byte_offset
& 0x1), src
.data(),
78 // Set this full register as the value to write.
79 value_to_write
.SetBytes(dst
.data(), full_value
.GetByteSize(),
81 value_to_write
.SetType(*full_reg_info
);
82 reg_to_write
= full_reg
;
87 const RegisterInfo
*const register_to_write_info_p
=
88 GetRegisterInfoAtIndex(reg_to_write
);
89 assert(register_to_write_info_p
&&
90 "register to write does not have valid RegisterInfo");
91 if (!register_to_write_info_p
)
92 return Status::FromErrorStringWithFormat(
93 "NativeRegisterContextLinux::%s failed to get RegisterInfo "
94 "for write register index %" PRIu32
,
95 __FUNCTION__
, reg_to_write
);
97 return DoWriteRegisterValue(GetPtraceOffset(reg_index
), reg_info
->name
,
101 Status
NativeRegisterContextLinux::ReadGPR() {
102 return NativeProcessLinux::PtraceWrapper(
103 PTRACE_GETREGS
, m_thread
.GetID(), nullptr, GetGPRBuffer(), GetGPRSize());
106 Status
NativeRegisterContextLinux::WriteGPR() {
107 return NativeProcessLinux::PtraceWrapper(
108 PTRACE_SETREGS
, m_thread
.GetID(), nullptr, GetGPRBuffer(), GetGPRSize());
111 Status
NativeRegisterContextLinux::ReadFPR() {
112 return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS
, m_thread
.GetID(),
113 nullptr, GetFPRBuffer(),
117 Status
NativeRegisterContextLinux::WriteFPR() {
118 return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS
, m_thread
.GetID(),
119 nullptr, GetFPRBuffer(),
123 Status
NativeRegisterContextLinux::ReadRegisterSet(void *buf
, size_t buf_size
,
124 unsigned int regset
) {
125 return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET
, m_thread
.GetID(),
126 static_cast<void *>(®set
), buf
,
130 Status
NativeRegisterContextLinux::WriteRegisterSet(void *buf
, size_t buf_size
,
131 unsigned int regset
) {
132 return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET
, m_thread
.GetID(),
133 static_cast<void *>(®set
), buf
,
137 Status
NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset
,
138 const char *reg_name
,
140 RegisterValue
&value
) {
141 Log
*log
= GetLog(POSIXLog::Registers
);
144 Status error
= NativeProcessLinux::PtraceWrapper(
145 PTRACE_PEEKUSER
, m_thread
.GetID(), reinterpret_cast<void *>(offset
),
149 // First cast to an unsigned of the same size to avoid sign extension.
150 value
.SetUInt(static_cast<unsigned long>(data
), size
);
152 LLDB_LOG(log
, "{0}: {1:x}", reg_name
, data
);
156 Status
NativeRegisterContextLinux::DoWriteRegisterValue(
157 uint32_t offset
, const char *reg_name
, const RegisterValue
&value
) {
158 Log
*log
= GetLog(POSIXLog::Registers
);
160 void *buf
= reinterpret_cast<void *>(value
.GetAsUInt64());
161 LLDB_LOG(log
, "{0}: {1}", reg_name
, buf
);
163 return NativeProcessLinux::PtraceWrapper(
164 PTRACE_POKEUSER
, m_thread
.GetID(), reinterpret_cast<void *>(offset
), buf
);
167 llvm::Expected
<ArchSpec
>
168 NativeRegisterContextLinux::DetermineArchitectureViaGPR(lldb::tid_t tid
,
170 std::unique_ptr
<uint8_t[]> data
= std::make_unique
<uint8_t[]>(gpr64_size
);
172 iov
.iov_base
= data
.get();
173 iov
.iov_len
= gpr64_size
;
174 unsigned int regset
= llvm::ELF::NT_PRSTATUS
;
175 Status ST
= NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET
, tid
, ®set
,
179 return HostInfo::GetArchitecture(
180 iov
.iov_len
< gpr64_size
? HostInfo::eArchKind32
: HostInfo::eArchKind64
);