1 //===-- NativeRegisterContextLinux_ppc64le.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 // This implementation is related to the OpenPOWER ABI for Power Architecture
11 // 64-bit ELF V2 ABI
12 
13 #if defined(__powerpc64__)
14 
15 #include "NativeRegisterContextLinux_ppc64le.h"
16 
17 #include "lldb/Core/RegisterValue.h"
18 #include "lldb/Host/common/NativeProcessProtocol.h"
19 #include "lldb/Utility/DataBufferHeap.h"
20 #include "lldb/Utility/Log.h"
21 #include "lldb/Utility/Status.h"
22 
23 #include "Plugins/Process/Linux/NativeProcessLinux.h"
24 #include "Plugins/Process/Linux/Procfs.h"
25 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
26 #include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
27 
28 // System includes - They have to be included after framework includes because
29 // they define some
30 // macros which collide with variable names in other modules
31 #include <sys/socket.h>
32 #include <elf.h>
33 #include <asm/ptrace.h>
34 
35 #define REG_CONTEXT_SIZE GetGPRSize()
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 using namespace lldb_private::process_linux;
40 
41 static const uint32_t g_gpr_regnums_ppc64le[] = {
42     gpr_r0_ppc64le,   gpr_r1_ppc64le,  gpr_r2_ppc64le,     gpr_r3_ppc64le,
43     gpr_r4_ppc64le,   gpr_r5_ppc64le,  gpr_r6_ppc64le,     gpr_r7_ppc64le,
44     gpr_r8_ppc64le,   gpr_r9_ppc64le,  gpr_r10_ppc64le,    gpr_r11_ppc64le,
45     gpr_r12_ppc64le,  gpr_r13_ppc64le, gpr_r14_ppc64le,    gpr_r15_ppc64le,
46     gpr_r16_ppc64le,  gpr_r17_ppc64le, gpr_r18_ppc64le,    gpr_r19_ppc64le,
47     gpr_r20_ppc64le,  gpr_r21_ppc64le, gpr_r22_ppc64le,    gpr_r23_ppc64le,
48     gpr_r24_ppc64le,  gpr_r25_ppc64le, gpr_r26_ppc64le,    gpr_r27_ppc64le,
49     gpr_r28_ppc64le,  gpr_r29_ppc64le, gpr_r30_ppc64le,    gpr_r31_ppc64le,
50     gpr_pc_ppc64le,   gpr_msr_ppc64le, gpr_origr3_ppc64le, gpr_ctr_ppc64le,
51     gpr_lr_ppc64le,   gpr_xer_ppc64le, gpr_cr_ppc64le,     gpr_softe_ppc64le,
52     gpr_trap_ppc64le,
53 };
54 
55 namespace {
56 // Number of register sets provided by this context.
57 enum { k_num_register_sets = 1 };
58 }
59 
60 static const RegisterSet g_reg_sets_ppc64le[k_num_register_sets] = {
61     {"General Purpose Registers", "gpr", k_num_gpr_registers_ppc64le,
62      g_gpr_regnums_ppc64le},
63 };
64 
65 NativeRegisterContextLinux *
66 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
67     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
68     uint32_t concrete_frame_idx) {
69   switch (target_arch.GetMachine()) {
70   case llvm::Triple::ppc64le:
71     return new NativeRegisterContextLinux_ppc64le(target_arch, native_thread,
72                                               concrete_frame_idx);
73   default:
74     llvm_unreachable("have no register context for architecture");
75   }
76 }
77 
78 NativeRegisterContextLinux_ppc64le::NativeRegisterContextLinux_ppc64le(
79     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
80     uint32_t concrete_frame_idx)
81     : NativeRegisterContextLinux(native_thread, concrete_frame_idx,
82                                  new RegisterInfoPOSIX_ppc64le(target_arch)) {
83   if (target_arch.GetMachine() != llvm::Triple::ppc64le) {
84     llvm_unreachable("Unhandled target architecture.");
85   }
86 
87   ::memset(&m_gpr_ppc64le, 0, sizeof(m_gpr_ppc64le));
88   ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
89 }
90 
91 uint32_t NativeRegisterContextLinux_ppc64le::GetRegisterSetCount() const {
92   return k_num_register_sets;
93 }
94 
95 const RegisterSet *
96 NativeRegisterContextLinux_ppc64le::GetRegisterSet(uint32_t set_index) const {
97   if (set_index < k_num_register_sets)
98     return &g_reg_sets_ppc64le[set_index];
99 
100   return nullptr;
101 }
102 
103 uint32_t NativeRegisterContextLinux_ppc64le::GetUserRegisterCount() const {
104   uint32_t count = 0;
105   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
106     count += g_reg_sets_ppc64le[set_index].num_registers;
107   return count;
108 }
109 
110 Status NativeRegisterContextLinux_ppc64le::ReadRegister(
111     const RegisterInfo *reg_info, RegisterValue &reg_value) {
112   Status error;
113 
114   if (!reg_info) {
115     error.SetErrorString("reg_info NULL");
116     return error;
117   }
118 
119   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
120 
121   if (IsGPR(reg)) {
122     error = ReadGPR();
123     if (error.Fail())
124       return error;
125 
126     uint8_t *src = (uint8_t *) &m_gpr_ppc64le + reg_info->byte_offset;
127     reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size,
128                                 eByteOrderLittle, error);
129   } else {
130     return Status("failed - register wasn't recognized to be a GPR, "
131                   "read strategy unknown");
132   }
133 
134   return error;
135 }
136 
137 Status NativeRegisterContextLinux_ppc64le::WriteRegister(
138     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
139   Status error;
140   if (!reg_info)
141     return Status("reg_info NULL");
142 
143   const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
144   if (reg_index == LLDB_INVALID_REGNUM)
145     return Status("no lldb regnum for %s", reg_info && reg_info->name
146                                                ? reg_info->name
147                                                : "<unknown register>");
148 
149   if (IsGPR(reg_index)) {
150       error = ReadGPR();
151       if (error.Fail())
152         return error;
153 
154       uint8_t *dst = (uint8_t *) &m_gpr_ppc64le + reg_info->byte_offset;
155       ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize());
156 
157       error = WriteGPR();
158       if (error.Fail())
159         return error;
160 
161       return Status();
162   }
163 
164   return Status("failed - register wasn't recognized to be a GPR, "
165                 "write strategy unknown");
166 }
167 
168 Status NativeRegisterContextLinux_ppc64le::ReadAllRegisterValues(
169     lldb::DataBufferSP &data_sp) {
170   Status error;
171 
172   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
173   if (!data_sp)
174     return Status("failed to allocate DataBufferHeap instance of size %" PRIu64,
175                   REG_CONTEXT_SIZE);
176 
177   error = ReadGPR();
178   if (error.Fail())
179     return error;
180 
181   uint8_t *dst = data_sp->GetBytes();
182   if (dst == nullptr) {
183     error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64
184                                    " returned a null pointer",
185                                    REG_CONTEXT_SIZE);
186     return error;
187   }
188 
189   ::memcpy(dst, &m_gpr_ppc64le, GetGPRSize());
190 
191   return error;
192 }
193 
194 Status NativeRegisterContextLinux_ppc64le::WriteAllRegisterValues(
195     const lldb::DataBufferSP &data_sp) {
196   Status error;
197 
198   if (!data_sp) {
199     error.SetErrorStringWithFormat(
200         "NativeRegisterContextLinux_ppc64le::%s invalid data_sp provided",
201         __FUNCTION__);
202     return error;
203   }
204 
205   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
206     error.SetErrorStringWithFormat(
207         "NativeRegisterContextLinux_ppc64le::%s data_sp contained mismatched "
208         "data size, expected %" PRIu64 ", actual %" PRIu64,
209         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
210     return error;
211   }
212 
213   uint8_t *src = data_sp->GetBytes();
214   if (src == nullptr) {
215     error.SetErrorStringWithFormat("NativeRegisterContextLinux_ppc64le::%s "
216                                    "DataBuffer::GetBytes() returned a null "
217                                    "pointer",
218                                    __FUNCTION__);
219     return error;
220   }
221 
222   ::memcpy(&m_gpr_ppc64le, src, GetGPRSize());
223   error = WriteGPR();
224 
225   return error;
226 }
227 
228 bool NativeRegisterContextLinux_ppc64le::IsGPR(unsigned reg) const {
229   return reg <= k_last_gpr_ppc64le; // GPR's come first.
230 }
231 
232 Status NativeRegisterContextLinux_ppc64le::DoReadGPR(
233     void *buf, size_t buf_size) {
234   int regset = NT_PRSTATUS;
235   return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(),
236                                            &regset, buf, buf_size);
237 }
238 
239 Status NativeRegisterContextLinux_ppc64le::DoWriteGPR(
240     void *buf, size_t buf_size) {
241   int regset = NT_PRSTATUS;
242   return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(),
243                                            &regset, buf, buf_size);
244 }
245 
246 uint32_t NativeRegisterContextLinux_ppc64le::NumSupportedHardwareWatchpoints() {
247   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
248 
249   // Read hardware breakpoint and watchpoint information.
250   Status error = ReadHardwareDebugInfo();
251 
252   if (error.Fail())
253     return 0;
254 
255   LLDB_LOG(log, "{0}", m_max_hwp_supported);
256   return m_max_hwp_supported;
257 }
258 
259 uint32_t NativeRegisterContextLinux_ppc64le::SetHardwareWatchpoint(
260     lldb::addr_t addr, size_t size, uint32_t watch_flags) {
261   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
262   LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
263            watch_flags);
264 
265   // Read hardware breakpoint and watchpoint information.
266   Status error = ReadHardwareDebugInfo();
267 
268   if (error.Fail())
269     return LLDB_INVALID_INDEX32;
270 
271   uint32_t control_value = 0, wp_index = 0;
272   lldb::addr_t real_addr = addr;
273   uint32_t rw_mode = 0;
274 
275   // Check if we are setting watchpoint other than read/write/access
276   // Update watchpoint flag to match ppc64le write-read bit configuration.
277   switch (watch_flags) {
278   case eWatchpointKindWrite:
279     rw_mode = PPC_BREAKPOINT_TRIGGER_WRITE;
280     watch_flags = 2;
281     break;
282   case eWatchpointKindRead:
283     rw_mode = PPC_BREAKPOINT_TRIGGER_READ;
284     watch_flags = 1;
285     break;
286   case (eWatchpointKindRead | eWatchpointKindWrite):
287     rw_mode = PPC_BREAKPOINT_TRIGGER_RW;
288     break;
289   default:
290     return LLDB_INVALID_INDEX32;
291   }
292 
293   // Check if size has a valid hardware watchpoint length.
294   if (size != 1 && size != 2 && size != 4 && size != 8)
295     return LLDB_INVALID_INDEX32;
296 
297   // Check 8-byte alignment for hardware watchpoint target address.
298   // Below is a hack to recalculate address and size in order to
299   // make sure we can watch non 8-byte alligned addresses as well.
300   if (addr & 0x07) {
301 
302     addr_t begin = llvm::alignDown(addr, 8);
303     addr_t end = llvm::alignTo(addr + size, 8);
304     size = llvm::PowerOf2Ceil(end - begin);
305 
306     addr = addr & (~0x07);
307   }
308 
309   // Setup control value
310   control_value = watch_flags << 3;
311   control_value |= ((1 << size) - 1) << 5;
312   control_value |= (2 << 1) | 1;
313 
314   // Iterate over stored watchpoints and find a free wp_index
315   wp_index = LLDB_INVALID_INDEX32;
316   for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
317     if ((m_hwp_regs[i].control & 1) == 0) {
318       wp_index = i; // Mark last free slot
319     } else if (m_hwp_regs[i].address == addr) {
320       return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
321     }
322   }
323 
324   if (wp_index == LLDB_INVALID_INDEX32)
325     return LLDB_INVALID_INDEX32;
326 
327   // Update watchpoint in local cache
328   m_hwp_regs[wp_index].real_addr = real_addr;
329   m_hwp_regs[wp_index].address = addr;
330   m_hwp_regs[wp_index].control = control_value;
331   m_hwp_regs[wp_index].mode = rw_mode;
332 
333   // PTRACE call to set corresponding watchpoint register.
334   error = WriteHardwareDebugRegs();
335 
336   if (error.Fail()) {
337     m_hwp_regs[wp_index].address = 0;
338     m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1);
339 
340     return LLDB_INVALID_INDEX32;
341   }
342 
343   return wp_index;
344 }
345 
346 bool NativeRegisterContextLinux_ppc64le::ClearHardwareWatchpoint(
347     uint32_t wp_index) {
348   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
349   LLDB_LOG(log, "wp_index: {0}", wp_index);
350 
351   // Read hardware breakpoint and watchpoint information.
352   Status error = ReadHardwareDebugInfo();
353 
354   if (error.Fail())
355     return false;
356 
357   if (wp_index >= m_max_hwp_supported)
358     return false;
359 
360   // Create a backup we can revert to in case of failure.
361   lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
362   uint32_t tempControl = m_hwp_regs[wp_index].control;
363   long *tempSlot = reinterpret_cast<long *>(m_hwp_regs[wp_index].slot);
364 
365   // Update watchpoint in local cache
366   m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1);
367   m_hwp_regs[wp_index].address = 0;
368   m_hwp_regs[wp_index].slot = 0;
369   m_hwp_regs[wp_index].mode = 0;
370 
371   // Ptrace call to update hardware debug registers
372   error = NativeProcessLinux::PtraceWrapper(PPC_PTRACE_DELHWDEBUG,
373                                             m_thread.GetID(), 0, tempSlot);
374 
375   if (error.Fail()) {
376     m_hwp_regs[wp_index].control = tempControl;
377     m_hwp_regs[wp_index].address = tempAddr;
378     m_hwp_regs[wp_index].slot = reinterpret_cast<long>(tempSlot);
379 
380     return false;
381   }
382 
383   return true;
384 }
385 
386 uint32_t
387 NativeRegisterContextLinux_ppc64le::GetWatchpointSize(uint32_t wp_index) {
388   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
389   LLDB_LOG(log, "wp_index: {0}", wp_index);
390 
391   unsigned control = (m_hwp_regs[wp_index].control >> 5) & 0xff;
392   assert(llvm::isPowerOf2_32(control + 1));
393   return llvm::countPopulation(control);
394 }
395 
396 bool NativeRegisterContextLinux_ppc64le::WatchpointIsEnabled(
397     uint32_t wp_index) {
398   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
399   LLDB_LOG(log, "wp_index: {0}", wp_index);
400 
401   return !!((m_hwp_regs[wp_index].control & 0x1) == 0x1);
402 }
403 
404 Status NativeRegisterContextLinux_ppc64le::GetWatchpointHitIndex(
405     uint32_t &wp_index, lldb::addr_t trap_addr) {
406   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
407   LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
408 
409   uint32_t watch_size;
410   lldb::addr_t watch_addr;
411 
412   for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
413     watch_size = GetWatchpointSize(wp_index);
414     watch_addr = m_hwp_regs[wp_index].address;
415 
416     if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
417         trap_addr <= watch_addr + watch_size) {
418       m_hwp_regs[wp_index].hit_addr = trap_addr;
419       return Status();
420     }
421   }
422 
423   wp_index = LLDB_INVALID_INDEX32;
424   return Status();
425 }
426 
427 lldb::addr_t
428 NativeRegisterContextLinux_ppc64le::GetWatchpointAddress(uint32_t wp_index) {
429   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
430   LLDB_LOG(log, "wp_index: {0}", wp_index);
431 
432   if (wp_index >= m_max_hwp_supported)
433     return LLDB_INVALID_ADDRESS;
434 
435   if (WatchpointIsEnabled(wp_index))
436     return m_hwp_regs[wp_index].real_addr;
437   else
438     return LLDB_INVALID_ADDRESS;
439 }
440 
441 lldb::addr_t
442 NativeRegisterContextLinux_ppc64le::GetWatchpointHitAddress(uint32_t wp_index) {
443   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
444   LLDB_LOG(log, "wp_index: {0}", wp_index);
445 
446   if (wp_index >= m_max_hwp_supported)
447     return LLDB_INVALID_ADDRESS;
448 
449   if (WatchpointIsEnabled(wp_index))
450     return m_hwp_regs[wp_index].hit_addr;
451 
452   return LLDB_INVALID_ADDRESS;
453 }
454 
455 Status NativeRegisterContextLinux_ppc64le::ReadHardwareDebugInfo() {
456   if (!m_refresh_hwdebug_info) {
457     return Status();
458   }
459 
460   ::pid_t tid = m_thread.GetID();
461 
462   struct ppc_debug_info hwdebug_info;
463   Status error;
464 
465   error = NativeProcessLinux::PtraceWrapper(
466       PPC_PTRACE_GETHWDBGINFO, tid, 0, &hwdebug_info, sizeof(hwdebug_info));
467 
468   if (error.Fail())
469     return error;
470 
471   m_max_hwp_supported = hwdebug_info.num_data_bps;
472   m_max_hbp_supported = hwdebug_info.num_instruction_bps;
473   m_refresh_hwdebug_info = false;
474 
475   return error;
476 }
477 
478 Status NativeRegisterContextLinux_ppc64le::WriteHardwareDebugRegs() {
479   struct ppc_hw_breakpoint reg_state;
480   Status error;
481   long ret;
482 
483   for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
484     reg_state.addr = m_hwp_regs[i].address;
485     reg_state.trigger_type = m_hwp_regs[i].mode;
486     reg_state.version = 1;
487     reg_state.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
488     reg_state.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
489     reg_state.addr2 = 0;
490     reg_state.condition_value = 0;
491 
492     error = NativeProcessLinux::PtraceWrapper(PPC_PTRACE_SETHWDEBUG,
493                                               m_thread.GetID(), 0, &reg_state,
494                                               sizeof(reg_state), &ret);
495 
496     if (error.Fail())
497       return error;
498 
499     m_hwp_regs[i].slot = ret;
500   }
501 
502   return error;
503 }
504 
505 #endif // defined(__powerpc64__)
506