1 //===-- NativeRegisterContextLinux.cpp --------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "NativeRegisterContextLinux.h"
11 
12 #include "lldb/Core/RegisterValue.h"
13 #include "lldb/Host/common/NativeProcessProtocol.h"
14 #include "lldb/Host/common/NativeThreadProtocol.h"
15 #include "lldb/Host/linux/Ptrace.h"
16 
17 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
18 
19 using namespace lldb_private;
20 using namespace lldb_private::process_linux;
21 
22 NativeRegisterContextLinux::NativeRegisterContextLinux(NativeThreadProtocol &native_thread,
23                                                        uint32_t concrete_frame_idx,
24                                                        RegisterInfoInterface *reg_info_interface_p) :
25     NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, reg_info_interface_p)
26 {}
27 
28 lldb::ByteOrder
29 NativeRegisterContextLinux::GetByteOrder() const
30 {
31     // Get the target process whose privileged thread was used for the register read.
32     lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
33 
34     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
35     if (!process_sp)
36         return byte_order;
37 
38     if (!process_sp->GetByteOrder (byte_order))
39     {
40         // FIXME log here
41     }
42 
43     return byte_order;
44 }
45 
46 Error
47 NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, RegisterValue &reg_value)
48 {
49     const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
50     if (!reg_info)
51         return Error("register %" PRIu32 " not found", reg_index);
52 
53     NativeProcessProtocolSP process_sp(m_thread.GetProcess());
54     if (!process_sp)
55         return Error("NativeProcessProtocol is NULL");
56 
57     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
58     return process_p->DoOperation([&] {
59         return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, reg_info->byte_size, reg_value);
60     });
61 }
62 
63 Error
64 NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index, const RegisterValue &reg_value)
65 {
66     uint32_t reg_to_write = reg_index;
67     RegisterValue value_to_write = reg_value;
68 
69     // Check if this is a subregister of a full register.
70     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
71     if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
72     {
73         Error error;
74 
75         RegisterValue full_value;
76         uint32_t full_reg = reg_info->invalidate_regs[0];
77         const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
78 
79         // Read the full register.
80         error = ReadRegister(full_reg_info, full_value);
81         if (error.Fail ())
82             return error;
83 
84         lldb::ByteOrder byte_order = GetByteOrder();
85         uint8_t dst[RegisterValue::kMaxRegisterByteSize];
86 
87         // Get the bytes for the full register.
88         const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
89                                                                dst,
90                                                                sizeof(dst),
91                                                                byte_order,
92                                                                error);
93         if (error.Success() && dest_size)
94         {
95             uint8_t src[RegisterValue::kMaxRegisterByteSize];
96 
97             // Get the bytes for the source data.
98             const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
99             if (error.Success() && src_size && (src_size < dest_size))
100             {
101                 // Copy the src bytes to the destination.
102                 memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
103                 // Set this full register as the value to write.
104                 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
105                 value_to_write.SetType(full_reg_info);
106                 reg_to_write = full_reg;
107             }
108         }
109     }
110 
111     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
112     if (!process_sp)
113         return Error("NativeProcessProtocol is NULL");
114 
115     const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
116     assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
117     if (!register_to_write_info_p)
118         return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
119 
120     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
121     return process_p->DoOperation([&] {
122         return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
123     });
124 }
125 
126 Error
127 NativeRegisterContextLinux::ReadGPR()
128 {
129     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
130     if (!process_sp)
131         return Error("NativeProcessProtocol is NULL");
132 
133     void* buf = GetGPRBuffer();
134     if (!buf)
135         return Error("GPR buffer is NULL");
136     size_t buf_size = GetGPRSize();
137 
138     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
139     return process_p->DoOperation([&] { return DoReadGPR(buf, buf_size); });
140 }
141 
142 Error
143 NativeRegisterContextLinux::WriteGPR()
144 {
145     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
146     if (!process_sp)
147         return Error("NativeProcessProtocol is NULL");
148 
149     void* buf = GetGPRBuffer();
150     if (!buf)
151         return Error("GPR buffer is NULL");
152     size_t buf_size = GetGPRSize();
153 
154     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
155     return process_p->DoOperation([&] { return DoWriteGPR(buf, buf_size); });
156 }
157 
158 Error
159 NativeRegisterContextLinux::ReadFPR()
160 {
161     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
162     if (!process_sp)
163         return Error("NativeProcessProtocol is NULL");
164 
165     void* buf = GetFPRBuffer();
166     if (!buf)
167         return Error("GPR buffer is NULL");
168     size_t buf_size = GetFPRSize();
169 
170     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
171     return process_p->DoOperation([&] { return DoReadFPR(buf, buf_size); });
172 }
173 
174 Error
175 NativeRegisterContextLinux::WriteFPR()
176 {
177     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
178     if (!process_sp)
179         return Error("NativeProcessProtocol is NULL");
180 
181     void* buf = GetFPRBuffer();
182     if (!buf)
183         return Error("GPR buffer is NULL");
184     size_t buf_size = GetFPRSize();
185 
186     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
187     return process_p->DoOperation([&] { return DoWriteFPR(buf, buf_size); });
188 }
189 
190 Error
191 NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset)
192 {
193     NativeProcessProtocolSP process_sp (m_thread.GetProcess());
194     if (!process_sp)
195         return Error("NativeProcessProtocol is NULL");
196     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
197 
198     return process_p->DoOperation([&] {
199         return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
200                 static_cast<void *>(&regset), buf, buf_size);
201     });
202 }
203 
204 Error
205 NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset)
206 {
207     NativeProcessProtocolSP process_sp (m_thread.GetProcess());
208     if (!process_sp)
209         return Error("NativeProcessProtocol is NULL");
210     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
211 
212     return process_p->DoOperation([&] {
213         return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
214                 static_cast<void *>(&regset), buf, buf_size);
215     });
216 }
217 
218 Error
219 NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset,
220                                                 const char* reg_name,
221                                                 uint32_t size,
222                                                 RegisterValue &value)
223 {
224     Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
225 
226     long data;
227     Error error = NativeProcessLinux::PtraceWrapper(
228             PTRACE_PEEKUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), nullptr, 0, &data);
229 
230     if (error.Success())
231         // First cast to an unsigned of the same size to avoid sign extension.
232         value.SetUInt64(static_cast<unsigned long>(data));
233 
234     if (log)
235         log->Printf ("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__, reg_name, data);
236 
237     return error;
238 }
239 
240 Error
241 NativeRegisterContextLinux::DoWriteRegisterValue(uint32_t offset,
242                                                  const char* reg_name,
243                                                  const RegisterValue &value)
244 {
245     Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
246 
247     void* buf = reinterpret_cast<void *>(value.GetAsUInt64());
248 
249     if (log)
250         log->Printf ("NativeRegisterContextLinux::%s() reg %s: %p", __FUNCTION__, reg_name, buf);
251 
252     return NativeProcessLinux::PtraceWrapper(
253             PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf);
254 }
255 
256 Error
257 NativeRegisterContextLinux::DoReadGPR(void *buf, size_t buf_size)
258 {
259     return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), nullptr, buf, buf_size);
260 }
261 
262 Error
263 NativeRegisterContextLinux::DoWriteGPR(void *buf, size_t buf_size)
264 {
265     return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), nullptr, buf, buf_size);
266 }
267 
268 Error
269 NativeRegisterContextLinux::DoReadFPR(void *buf, size_t buf_size)
270 {
271     return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(), nullptr, buf, buf_size);
272 }
273 
274 Error
275 NativeRegisterContextLinux::DoWriteFPR(void *buf, size_t buf_size)
276 {
277     return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(), nullptr, buf, buf_size);
278 }
279