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 namespace
23 {
24 
25 class ReadRegOperation : public NativeProcessLinux::Operation
26 {
27 public:
28     ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, RegisterValue &value) :
29     	m_tid(tid),
30         m_offset(static_cast<uintptr_t>(offset)),
31         m_reg_name(reg_name),
32         m_value(value)
33     { }
34 
35     void
36     Execute(NativeProcessLinux *monitor) override;
37 
38 private:
39     lldb::tid_t m_tid;
40     uintptr_t m_offset;
41     const char *m_reg_name;
42     RegisterValue &m_value;
43 };
44 
45 class WriteRegOperation : public NativeProcessLinux::Operation
46 {
47 public:
48     WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) :
49     	m_tid(tid),
50         m_offset(offset),
51         m_reg_name(reg_name),
52         m_value(value)
53     { }
54 
55     void
56     Execute(NativeProcessLinux *monitor) override;
57 
58 private:
59     lldb::tid_t m_tid;
60     uintptr_t m_offset;
61     const char *m_reg_name;
62     const RegisterValue &m_value;
63 };
64 
65 class ReadGPROperation : public NativeProcessLinux::Operation
66 {
67 public:
68     ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) :
69     	m_tid(tid), m_buf(buf), m_buf_size(buf_size)
70     { }
71 
72     void Execute(NativeProcessLinux *monitor) override;
73 
74 private:
75     lldb::tid_t m_tid;
76     void *m_buf;
77     size_t m_buf_size;
78 };
79 
80 class WriteGPROperation : public NativeProcessLinux::Operation
81 {
82 public:
83     WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) :
84     	m_tid(tid), m_buf(buf), m_buf_size(buf_size)
85     { }
86 
87     void Execute(NativeProcessLinux *monitor) override;
88 
89 private:
90     lldb::tid_t m_tid;
91     void *m_buf;
92     size_t m_buf_size;
93 };
94 
95 class ReadFPROperation : public NativeProcessLinux::Operation
96 {
97 public:
98     ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) :
99         m_tid(tid), m_buf(buf), m_buf_size(buf_size)
100     { }
101 
102     void Execute(NativeProcessLinux *monitor) override;
103 
104 private:
105     lldb::tid_t m_tid;
106     void *m_buf;
107     size_t m_buf_size;
108 };
109 
110 class WriteFPROperation : public NativeProcessLinux::Operation
111 {
112 public:
113     WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) :
114         m_tid(tid), m_buf(buf), m_buf_size(buf_size)
115     { }
116 
117     void Execute(NativeProcessLinux *monitor) override;
118 
119 private:
120     lldb::tid_t m_tid;
121     void *m_buf;
122     size_t m_buf_size;
123 };
124 
125 class ReadRegisterSetOperation : public NativeProcessLinux::Operation
126 {
127 public:
128     ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) :
129         m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset)
130     { }
131 
132     void Execute(NativeProcessLinux *monitor) override;
133 
134 private:
135     lldb::tid_t m_tid;
136     void *m_buf;
137     size_t m_buf_size;
138     const unsigned int m_regset;
139 };
140 
141 class WriteRegisterSetOperation : public NativeProcessLinux::Operation
142 {
143 public:
144     WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) :
145         m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset)
146     { }
147 
148     void Execute(NativeProcessLinux *monitor) override;
149 
150 private:
151     lldb::tid_t m_tid;
152     void *m_buf;
153     size_t m_buf_size;
154     const unsigned int m_regset;
155 };
156 
157 } // end of anonymous namespace
158 
159 void
160 ReadRegOperation::Execute(NativeProcessLinux *monitor)
161 {
162 	Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
163 
164     lldb::addr_t data = static_cast<unsigned long>(NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSER, m_tid, (void*)m_offset, nullptr, 0, m_error));
165     if (m_error.Success())
166         m_value = data;
167 
168     if (log)
169         log->Printf ("NativeProcessLinux::%s() reg %s: 0x%" PRIx64, __FUNCTION__, m_reg_name, data);
170 }
171 
172 void
173 WriteRegOperation::Execute(NativeProcessLinux *monitor)
174 {
175     Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
176 
177     void* buf = (void*)m_value.GetAsUInt64();
178 
179     if (log)
180         log->Printf ("NativeProcessLinux::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf);
181     NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0, m_error);
182 }
183 
184 void
185 ReadGPROperation::Execute(NativeProcessLinux *monitor)
186 {
187     NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error);
188 }
189 
190 void
191 WriteGPROperation::Execute(NativeProcessLinux *monitor)
192 {
193     NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error);
194 }
195 
196 void
197 ReadFPROperation::Execute(NativeProcessLinux *monitor)
198 {
199     NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error);
200 }
201 
202 void
203 WriteFPROperation::Execute(NativeProcessLinux *monitor)
204 {
205     NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error);
206 }
207 
208 void
209 ReadRegisterSetOperation::Execute(NativeProcessLinux *monitor)
210 {
211     NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error);
212 }
213 
214 void
215 WriteRegisterSetOperation::Execute(NativeProcessLinux *monitor)
216 {
217     NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error);
218 }
219 
220 NativeRegisterContextLinux::NativeRegisterContextLinux(NativeThreadProtocol &native_thread,
221                                                        uint32_t concrete_frame_idx,
222                                                        RegisterInfoInterface *reg_info_interface_p) :
223 	NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, reg_info_interface_p)
224 {}
225 
226 lldb::ByteOrder
227 NativeRegisterContextLinux::GetByteOrder() const
228 {
229     // Get the target process whose privileged thread was used for the register read.
230     lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
231 
232     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
233     if (!process_sp)
234         return byte_order;
235 
236     if (!process_sp->GetByteOrder (byte_order))
237     {
238         // FIXME log here
239     }
240 
241     return byte_order;
242 }
243 
244 Error
245 NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, RegisterValue &reg_value)
246 {
247     const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
248     if (!reg_info)
249     	return Error("register %" PRIu32 " not found", reg_index);
250 
251     NativeProcessProtocolSP process_sp(m_thread.GetProcess());
252     if (!process_sp)
253         return Error("NativeProcessProtocol is NULL");
254 
255     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
256     return process_p->DoOperation(GetReadRegisterValueOperation(reg_info->byte_offset,
257                                                                 reg_info->name,
258                                                                 reg_info->byte_size,
259                                                                 reg_value));
260 }
261 
262 Error
263 NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index, const RegisterValue &reg_value)
264 {
265     uint32_t reg_to_write = reg_index;
266     RegisterValue value_to_write = reg_value;
267 
268     // Check if this is a subregister of a full register.
269     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
270     if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
271     {
272 		Error error;
273 
274         RegisterValue full_value;
275         uint32_t full_reg = reg_info->invalidate_regs[0];
276         const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
277 
278         // Read the full register.
279         error = ReadRegister(full_reg_info, full_value);
280         if (error.Fail ())
281             return error;
282 
283         lldb::ByteOrder byte_order = GetByteOrder();
284         uint8_t dst[RegisterValue::kMaxRegisterByteSize];
285 
286         // Get the bytes for the full register.
287         const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
288                                                                dst,
289                                                                sizeof(dst),
290                                                                byte_order,
291                                                                error);
292         if (error.Success() && dest_size)
293         {
294             uint8_t src[RegisterValue::kMaxRegisterByteSize];
295 
296             // Get the bytes for the source data.
297             const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
298             if (error.Success() && src_size && (src_size < dest_size))
299             {
300                 // Copy the src bytes to the destination.
301                 memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
302                 // Set this full register as the value to write.
303                 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
304                 value_to_write.SetType(full_reg_info);
305                 reg_to_write = full_reg;
306             }
307         }
308     }
309 
310     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
311     if (!process_sp)
312 	    return Error("NativeProcessProtocol is NULL");
313 
314     const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
315     assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
316     if (!register_to_write_info_p)
317         return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
318 
319     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
320     return process_p->DoOperation(GetWriteRegisterValueOperation(reg_info->byte_offset,
321                                                                  reg_info->name,
322                                                                  reg_value));
323 }
324 
325 Error
326 NativeRegisterContextLinux::ReadGPR()
327 {
328 	NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
329     if (!process_sp)
330         return Error("NativeProcessProtocol is NULL");
331 
332     void* buf = GetGPRBuffer();
333     if (!buf)
334     	return Error("GPR buffer is NULL");
335     size_t buf_size = GetGPRSize();
336 
337     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
338     return process_p->DoOperation(GetReadGPROperation(buf, buf_size));
339 }
340 
341 Error
342 NativeRegisterContextLinux::WriteGPR()
343 {
344 	NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
345     if (!process_sp)
346         return Error("NativeProcessProtocol is NULL");
347 
348     void* buf = GetGPRBuffer();
349     if (!buf)
350     	return Error("GPR buffer is NULL");
351     size_t buf_size = GetGPRSize();
352 
353     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
354     return process_p->DoOperation(GetWriteGPROperation(buf, buf_size));
355 }
356 
357 Error
358 NativeRegisterContextLinux::ReadFPR()
359 {
360 	NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
361     if (!process_sp)
362         return Error("NativeProcessProtocol is NULL");
363 
364     void* buf = GetFPRBuffer();
365     if (!buf)
366     	return Error("GPR buffer is NULL");
367     size_t buf_size = GetFPRSize();
368 
369     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
370     return process_p->DoOperation(GetReadFPROperation(buf, buf_size));
371 }
372 
373 Error
374 NativeRegisterContextLinux::WriteFPR()
375 {
376 	NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
377     if (!process_sp)
378         return Error("NativeProcessProtocol is NULL");
379 
380     void* buf = GetFPRBuffer();
381     if (!buf)
382     	return Error("GPR buffer is NULL");
383     size_t buf_size = GetFPRSize();
384 
385     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
386     return process_p->DoOperation(GetWriteFPROperation(buf, buf_size));
387 }
388 
389 Error
390 NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset)
391 {
392     NativeProcessProtocolSP process_sp (m_thread.GetProcess());
393     if (!process_sp)
394         return Error("NativeProcessProtocol is NULL");
395     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
396 
397     ReadRegisterSetOperation op(m_thread.GetID(), buf, buf_size, regset);
398     return process_p->DoOperation(&op);
399 }
400 
401 Error
402 NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset)
403 {
404     NativeProcessProtocolSP process_sp (m_thread.GetProcess());
405     if (!process_sp)
406         return Error("NativeProcessProtocol is NULL");
407     NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
408 
409     WriteRegisterSetOperation op(m_thread.GetID(), buf, buf_size, regset);
410     return process_p->DoOperation(&op);
411 }
412 
413 NativeProcessLinux::OperationUP
414 NativeRegisterContextLinux::GetReadRegisterValueOperation(uint32_t offset,
415                                                           const char* reg_name,
416 	                                                      uint32_t size,
417 	                                                      RegisterValue &value)
418 {
419 	return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value));
420 }
421 
422 NativeProcessLinux::OperationUP
423 NativeRegisterContextLinux::GetWriteRegisterValueOperation(uint32_t offset,
424                                                            const char* reg_name,
425 	                                                       const RegisterValue &value)
426 {
427 	return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value));
428 }
429 
430 NativeProcessLinux::OperationUP
431 NativeRegisterContextLinux::GetReadGPROperation(void *buf, size_t buf_size)
432 {
433 	return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size));
434 }
435 
436 NativeProcessLinux::OperationUP
437 NativeRegisterContextLinux::GetWriteGPROperation(void *buf, size_t buf_size)
438 {
439 	return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size));
440 }
441 
442 NativeProcessLinux::OperationUP
443 NativeRegisterContextLinux::GetReadFPROperation(void *buf, size_t buf_size)
444 {
445 	return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size));
446 }
447 
448 NativeProcessLinux::OperationUP
449 NativeRegisterContextLinux::GetWriteFPROperation(void *buf, size_t buf_size)
450 {
451 	return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size));
452 }
453