1 //===-- NativeRegisterContextLinux_mips64.cpp -----------------------------===//
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
9 #if defined(__mips__)
10
11 #include "NativeRegisterContextLinux_mips64.h"
12
13
14 #include "Plugins/Process/Linux/NativeProcessLinux.h"
15 #include "Plugins/Process/Linux/Procfs.h"
16 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
17 #include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
18 #include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
19 #include "lldb/Core/EmulateInstruction.h"
20 #include "lldb/Host/Host.h"
21 #include "lldb/Host/HostInfo.h"
22 #include "lldb/Utility/DataBufferHeap.h"
23 #include "lldb/Utility/LLDBAssert.h"
24 #include "lldb/Utility/Log.h"
25 #include "lldb/Utility/RegisterValue.h"
26 #include "lldb/Utility/Status.h"
27 #include "lldb/lldb-enumerations.h"
28 #include "lldb/lldb-private-enumerations.h"
29 #define NT_MIPS_MSA 0x600
30 #define CONFIG5_FRE (1 << 8)
31 #define SR_FR (1 << 26)
32 #define NUM_REGISTERS 32
33
34 #include <asm/ptrace.h>
35 #include <sys/ptrace.h>
36
37 #ifndef PTRACE_GET_WATCH_REGS
38 enum pt_watch_style { pt_watch_style_mips32, pt_watch_style_mips64 };
39 struct mips32_watch_regs {
40 uint32_t watchlo[8];
41 uint16_t watchhi[8];
42 uint16_t watch_masks[8];
43 uint32_t num_valid;
44 } __attribute__((aligned(8)));
45
46 struct mips64_watch_regs {
47 uint64_t watchlo[8];
48 uint16_t watchhi[8];
49 uint16_t watch_masks[8];
50 uint32_t num_valid;
51 } __attribute__((aligned(8)));
52
53 struct pt_watch_regs {
54 enum pt_watch_style style;
55 union {
56 struct mips32_watch_regs mips32;
57 struct mips64_watch_regs mips64;
58 };
59 };
60
61 #define PTRACE_GET_WATCH_REGS 0xd0
62 #define PTRACE_SET_WATCH_REGS 0xd1
63 #endif
64
65 #define W (1 << 0)
66 #define R (1 << 1)
67 #define I (1 << 2)
68
69 #define IRW (I | R | W)
70
71 #ifndef PTRACE_GETREGSET
72 #define PTRACE_GETREGSET 0x4204
73 #endif
74 struct pt_watch_regs default_watch_regs;
75
76 using namespace lldb_private;
77 using namespace lldb_private::process_linux;
78
79 std::unique_ptr<NativeRegisterContextLinux>
CreateHostNativeRegisterContextLinux(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)80 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
81 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
82 return std::make_unique<NativeRegisterContextLinux_mips64>(target_arch,
83 native_thread);
84 }
85
86 #define REG_CONTEXT_SIZE \
87 (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR_linux_mips) + \
88 sizeof(MSA_linux_mips))
89
90 // NativeRegisterContextLinux_mips64 members.
91
92 static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec & target_arch)93 CreateRegisterInfoInterface(const ArchSpec &target_arch) {
94 if ((target_arch.GetMachine() == llvm::Triple::mips) ||
95 (target_arch.GetMachine() == llvm::Triple::mipsel)) {
96 // 32-bit hosts run with a RegisterContextLinux_mips context.
97 return new RegisterContextLinux_mips(
98 target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable());
99 } else {
100 return new RegisterContextLinux_mips64(
101 target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable());
102 }
103 }
104
NativeRegisterContextLinux_mips64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)105 NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64(
106 const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
107 : NativeRegisterContextRegisterInfo(
108 native_thread, CreateRegisterInfoInterface(target_arch)) {
109 switch (target_arch.GetMachine()) {
110 case llvm::Triple::mips:
111 case llvm::Triple::mipsel:
112 m_reg_info.num_registers = k_num_registers_mips;
113 m_reg_info.num_gpr_registers = k_num_gpr_registers_mips;
114 m_reg_info.num_fpr_registers = k_num_fpr_registers_mips;
115 m_reg_info.last_gpr = k_last_gpr_mips;
116 m_reg_info.first_fpr = k_first_fpr_mips;
117 m_reg_info.last_fpr = k_last_fpr_mips;
118 m_reg_info.first_msa = k_first_msa_mips;
119 m_reg_info.last_msa = k_last_msa_mips;
120 break;
121 case llvm::Triple::mips64:
122 case llvm::Triple::mips64el:
123 m_reg_info.num_registers = k_num_registers_mips64;
124 m_reg_info.num_gpr_registers = k_num_gpr_registers_mips64;
125 m_reg_info.num_fpr_registers = k_num_fpr_registers_mips64;
126 m_reg_info.last_gpr = k_last_gpr_mips64;
127 m_reg_info.first_fpr = k_first_fpr_mips64;
128 m_reg_info.last_fpr = k_last_fpr_mips64;
129 m_reg_info.first_msa = k_first_msa_mips64;
130 m_reg_info.last_msa = k_last_msa_mips64;
131 break;
132 default:
133 assert(false && "Unhandled target architecture.");
134 break;
135 }
136
137 // Initialize m_iovec to point to the buffer and buffer size using the
138 // conventions of Berkeley style UIO structures, as required by PTRACE
139 // extensions.
140 m_iovec.iov_base = &m_msa;
141 m_iovec.iov_len = sizeof(MSA_linux_mips);
142
143 // init h/w watchpoint addr map
144 for (int index = 0; index <= MAX_NUM_WP; index++)
145 hw_addr_map[index] = LLDB_INVALID_ADDRESS;
146
147 ::memset(&m_gpr, 0, sizeof(GPR_linux_mips));
148 ::memset(&m_fpr, 0, sizeof(FPR_linux_mips));
149 ::memset(&m_msa, 0, sizeof(MSA_linux_mips));
150 }
151
GetRegisterSetCount() const152 uint32_t NativeRegisterContextLinux_mips64::GetRegisterSetCount() const {
153 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
154 case llvm::Triple::mips64:
155 case llvm::Triple::mips64el: {
156 const auto context = static_cast<const RegisterContextLinux_mips64 &>
157 (GetRegisterInfoInterface());
158 return context.GetRegisterSetCount();
159 }
160 case llvm::Triple::mips:
161 case llvm::Triple::mipsel: {
162 const auto context = static_cast<const RegisterContextLinux_mips &>
163 (GetRegisterInfoInterface());
164 return context.GetRegisterSetCount();
165 }
166 default:
167 llvm_unreachable("Unhandled target architecture.");
168 }
169 }
170
GetPCfromBreakpointLocation(lldb::addr_t fail_value)171 lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation(
172 lldb::addr_t fail_value) {
173 Status error;
174 RegisterValue pc_value;
175 lldb::addr_t pc = fail_value;
176 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
177 LLDB_LOG(log, "Reading PC from breakpoint location");
178
179 // PC register is at index 34 of the register array
180 const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex(gpr_pc_mips64);
181
182 error = ReadRegister(pc_info_p, pc_value);
183 if (error.Success()) {
184 pc = pc_value.GetAsUInt64();
185
186 // CAUSE register is at index 37 of the register array
187 const RegisterInfo *const cause_info_p =
188 GetRegisterInfoAtIndex(gpr_cause_mips64);
189 RegisterValue cause_value;
190
191 ReadRegister(cause_info_p, cause_value);
192
193 uint64_t cause = cause_value.GetAsUInt64();
194 LLDB_LOG(log, "PC {0:x} cause {1:x}", pc, cause);
195
196 /*
197 * The breakpoint might be in a delay slot. In this case PC points
198 * to the delayed branch instruction rather then the instruction
199 * in the delay slot. If the CAUSE.BD flag is set then adjust the
200 * PC based on the size of the branch instruction.
201 */
202 if ((cause & (1 << 31)) != 0) {
203 lldb::addr_t branch_delay = 0;
204 branch_delay =
205 4; // FIXME - Adjust according to size of branch instruction at PC
206 pc = pc + branch_delay;
207 pc_value.SetUInt64(pc);
208 WriteRegister(pc_info_p, pc_value);
209 LLDB_LOG(log, "New PC {0:x}", pc);
210 }
211 }
212
213 return pc;
214 }
215
216 const RegisterSet *
GetRegisterSet(uint32_t set_index) const217 NativeRegisterContextLinux_mips64::GetRegisterSet(uint32_t set_index) const {
218 if (set_index >= GetRegisterSetCount())
219 return nullptr;
220
221 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
222 case llvm::Triple::mips64:
223 case llvm::Triple::mips64el: {
224 const auto context = static_cast<const RegisterContextLinux_mips64 &>
225 (GetRegisterInfoInterface());
226 return context.GetRegisterSet(set_index);
227 }
228 case llvm::Triple::mips:
229 case llvm::Triple::mipsel: {
230 const auto context = static_cast<const RegisterContextLinux_mips &>
231 (GetRegisterInfoInterface());
232 return context.GetRegisterSet(set_index);
233 }
234 default:
235 llvm_unreachable("Unhandled target architecture.");
236 }
237 }
238
239 lldb_private::Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)240 NativeRegisterContextLinux_mips64::ReadRegister(const RegisterInfo *reg_info,
241 RegisterValue ®_value) {
242 Status error;
243
244 if (!reg_info) {
245 error.SetErrorString("reg_info NULL");
246 return error;
247 }
248
249 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
250 uint8_t byte_size = reg_info->byte_size;
251 if (reg == LLDB_INVALID_REGNUM) {
252 // This is likely an internal register for lldb use only and should not be
253 // directly queried.
254 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
255 "register, cannot read directly",
256 reg_info->name);
257 return error;
258 }
259
260 if (IsMSA(reg) && !IsMSAAvailable()) {
261 error.SetErrorString("MSA not available on this processor");
262 return error;
263 }
264
265 if (IsMSA(reg) || IsFPR(reg)) {
266 uint8_t *src = nullptr;
267 lldbassert(reg_info->byte_offset < sizeof(UserArea));
268
269 error = ReadCP1();
270
271 if (!error.Success()) {
272 error.SetErrorString("failed to read co-processor 1 register");
273 return error;
274 }
275
276 if (IsFPR(reg)) {
277 if (IsFR0() && (byte_size != 4)) {
278 byte_size = 4;
279 uint8_t ptrace_index;
280 ptrace_index = reg_info->kinds[lldb::eRegisterKindProcessPlugin];
281 src = ReturnFPOffset(ptrace_index, reg_info->byte_offset);
282 } else
283 src = (uint8_t *)&m_fpr + reg_info->byte_offset - sizeof(m_gpr);
284 } else
285 src = (uint8_t *)&m_msa + reg_info->byte_offset -
286 (sizeof(m_gpr) + sizeof(m_fpr));
287 switch (byte_size) {
288 case 4:
289 reg_value.SetUInt32(*(uint32_t *)src);
290 break;
291 case 8:
292 reg_value.SetUInt64(*(uint64_t *)src);
293 break;
294 case 16:
295 reg_value.SetBytes((const void *)src, 16, GetByteOrder());
296 break;
297 default:
298 assert(false && "Unhandled data size.");
299 error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
300 reg_info->byte_size);
301 break;
302 }
303 } else {
304 error = ReadRegisterRaw(reg, reg_value);
305 }
306
307 return error;
308 }
309
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)310 lldb_private::Status NativeRegisterContextLinux_mips64::WriteRegister(
311 const RegisterInfo *reg_info, const RegisterValue ®_value) {
312 Status error;
313
314 assert(reg_info && "reg_info is null");
315
316 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
317
318 if (reg_index == LLDB_INVALID_REGNUM)
319 return Status("no lldb regnum for %s", reg_info && reg_info->name
320 ? reg_info->name
321 : "<unknown register>");
322
323 if (IsMSA(reg_index) && !IsMSAAvailable()) {
324 error.SetErrorString("MSA not available on this processor");
325 return error;
326 }
327
328 if (IsFPR(reg_index) || IsMSA(reg_index)) {
329 uint8_t *dst = nullptr;
330 uint64_t *src = nullptr;
331 uint8_t byte_size = reg_info->byte_size;
332 lldbassert(reg_info->byte_offset < sizeof(UserArea));
333
334 // Initialise the FP and MSA buffers by reading all co-processor 1
335 // registers
336 ReadCP1();
337
338 if (IsFPR(reg_index)) {
339 if (IsFR0() && (byte_size != 4)) {
340 byte_size = 4;
341 uint8_t ptrace_index;
342 ptrace_index = reg_info->kinds[lldb::eRegisterKindProcessPlugin];
343 dst = ReturnFPOffset(ptrace_index, reg_info->byte_offset);
344 } else
345 dst = (uint8_t *)&m_fpr + reg_info->byte_offset - sizeof(m_gpr);
346 } else
347 dst = (uint8_t *)&m_msa + reg_info->byte_offset -
348 (sizeof(m_gpr) + sizeof(m_fpr));
349 switch (byte_size) {
350 case 4:
351 *(uint32_t *)dst = reg_value.GetAsUInt32();
352 break;
353 case 8:
354 *(uint64_t *)dst = reg_value.GetAsUInt64();
355 break;
356 case 16:
357 src = (uint64_t *)reg_value.GetBytes();
358 *(uint64_t *)dst = *src;
359 *(uint64_t *)(dst + 8) = *(src + 1);
360 break;
361 default:
362 assert(false && "Unhandled data size.");
363 error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
364 reg_info->byte_size);
365 break;
366 }
367 error = WriteCP1();
368 if (!error.Success()) {
369 error.SetErrorString("failed to write co-processor 1 register");
370 return error;
371 }
372 } else {
373 error = WriteRegisterRaw(reg_index, reg_value);
374 }
375
376 return error;
377 }
378
ReadAllRegisterValues(lldb::DataBufferSP & data_sp)379 Status NativeRegisterContextLinux_mips64::ReadAllRegisterValues(
380 lldb::DataBufferSP &data_sp) {
381 Status error;
382
383 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
384 error = ReadGPR();
385 if (!error.Success()) {
386 error.SetErrorString("ReadGPR() failed");
387 return error;
388 }
389
390 error = ReadCP1();
391 if (!error.Success()) {
392 error.SetErrorString("ReadCP1() failed");
393 return error;
394 }
395
396 uint8_t *dst = data_sp->GetBytes();
397 ::memcpy(dst, &m_gpr, GetRegisterInfoInterface().GetGPRSize());
398 dst += GetRegisterInfoInterface().GetGPRSize();
399
400 ::memcpy(dst, &m_fpr, GetFPRSize());
401 dst += GetFPRSize();
402
403 ::memcpy(dst, &m_msa, sizeof(MSA_linux_mips));
404
405 return error;
406 }
407
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)408 Status NativeRegisterContextLinux_mips64::WriteAllRegisterValues(
409 const lldb::DataBufferSP &data_sp) {
410 Status error;
411
412 if (!data_sp) {
413 error.SetErrorStringWithFormat(
414 "NativeRegisterContextLinux_mips64::%s invalid data_sp provided",
415 __FUNCTION__);
416 return error;
417 }
418
419 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
420 error.SetErrorStringWithFormat(
421 "NativeRegisterContextLinux_mips64::%s data_sp contained mismatched "
422 "data size, expected %" PRIu64 ", actual %" PRIu64,
423 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
424 return error;
425 }
426
427 uint8_t *src = data_sp->GetBytes();
428 if (src == nullptr) {
429 error.SetErrorStringWithFormat("NativeRegisterContextLinux_mips64::%s "
430 "DataBuffer::GetBytes() returned a null "
431 "pointer",
432 __FUNCTION__);
433 return error;
434 }
435
436 ::memcpy(&m_gpr, src, GetRegisterInfoInterface().GetGPRSize());
437 src += GetRegisterInfoInterface().GetGPRSize();
438
439 ::memcpy(&m_fpr, src, GetFPRSize());
440 src += GetFPRSize();
441
442 ::memcpy(&m_msa, src, sizeof(MSA_linux_mips));
443
444 error = WriteGPR();
445 if (!error.Success()) {
446 error.SetErrorStringWithFormat(
447 "NativeRegisterContextLinux_mips64::%s WriteGPR() failed",
448 __FUNCTION__);
449 return error;
450 }
451
452 error = WriteCP1();
453 if (!error.Success()) {
454 error.SetErrorStringWithFormat(
455 "NativeRegisterContextLinux_mips64::%s WriteCP1() failed",
456 __FUNCTION__);
457 return error;
458 }
459
460 return error;
461 }
462
ReadCP1()463 Status NativeRegisterContextLinux_mips64::ReadCP1() {
464 Status error;
465
466 uint8_t *src = nullptr;
467 uint8_t *dst = nullptr;
468
469 lldb::ByteOrder byte_order = GetByteOrder();
470
471 bool IsBigEndian = (byte_order == lldb::eByteOrderBig);
472
473 if (IsMSAAvailable()) {
474 error = NativeRegisterContextLinux::ReadRegisterSet(
475 &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA);
476 src = (uint8_t *)&m_msa + (IsBigEndian * 8);
477 dst = (uint8_t *)&m_fpr;
478 for (int i = 0; i < NUM_REGISTERS; i++) {
479 // Copy fp values from msa buffer fetched via ptrace
480 *(uint64_t *)dst = *(uint64_t *)src;
481 src = src + 16;
482 dst = dst + 8;
483 }
484 m_fpr.fir = m_msa.fir;
485 m_fpr.fcsr = m_msa.fcsr;
486 m_fpr.config5 = m_msa.config5;
487 } else {
488 error = NativeRegisterContextLinux::ReadFPR();
489 }
490 return error;
491 }
492
493 uint8_t *
ReturnFPOffset(uint8_t reg_index,uint32_t byte_offset)494 NativeRegisterContextLinux_mips64::ReturnFPOffset(uint8_t reg_index,
495 uint32_t byte_offset) {
496
497 uint8_t *fp_buffer_ptr = nullptr;
498 lldb::ByteOrder byte_order = GetByteOrder();
499 bool IsBigEndian = (byte_order == lldb::eByteOrderBig);
500 if (reg_index % 2) {
501 uint8_t offset_diff = (IsBigEndian) ? 8 : 4;
502 fp_buffer_ptr =
503 (uint8_t *)&m_fpr + byte_offset - offset_diff - sizeof(m_gpr);
504 } else {
505 fp_buffer_ptr =
506 (uint8_t *)&m_fpr + byte_offset + 4 * (IsBigEndian) - sizeof(m_gpr);
507 }
508 return fp_buffer_ptr;
509 }
510
WriteCP1()511 Status NativeRegisterContextLinux_mips64::WriteCP1() {
512 Status error;
513
514 uint8_t *src = nullptr;
515 uint8_t *dst = nullptr;
516
517 lldb::ByteOrder byte_order = GetByteOrder();
518
519 bool IsBigEndian = (byte_order == lldb::eByteOrderBig);
520
521 if (IsMSAAvailable()) {
522 dst = (uint8_t *)&m_msa + (IsBigEndian * 8);
523 src = (uint8_t *)&m_fpr;
524 for (int i = 0; i < NUM_REGISTERS; i++) {
525 // Copy fp values to msa buffer for ptrace
526 *(uint64_t *)dst = *(uint64_t *)src;
527 dst = dst + 16;
528 src = src + 8;
529 }
530 m_msa.fir = m_fpr.fir;
531 m_msa.fcsr = m_fpr.fcsr;
532 m_msa.config5 = m_fpr.config5;
533 error = NativeRegisterContextLinux::WriteRegisterSet(
534 &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA);
535 } else {
536 error = NativeRegisterContextLinux::WriteFPR();
537 }
538
539 return error;
540 }
541
IsFR0()542 bool NativeRegisterContextLinux_mips64::IsFR0() {
543 const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex(gpr_sr_mips64);
544
545 RegisterValue reg_value;
546 ReadRegister(reg_info_p, reg_value);
547
548 uint64_t value = reg_value.GetAsUInt64();
549
550 return (!(value & SR_FR));
551 }
552
IsFRE()553 bool NativeRegisterContextLinux_mips64::IsFRE() {
554 const RegisterInfo *const reg_info_p =
555 GetRegisterInfoAtIndex(gpr_config5_mips64);
556
557 RegisterValue reg_value;
558 ReadRegister(reg_info_p, reg_value);
559
560 uint64_t config5 = reg_value.GetAsUInt64();
561
562 return (config5 & CONFIG5_FRE);
563 }
564
IsFPR(uint32_t reg_index) const565 bool NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const {
566 return (m_reg_info.first_fpr <= reg_index &&
567 reg_index <= m_reg_info.last_fpr);
568 }
569
GetWatchHi(struct pt_watch_regs * regs,uint32_t index)570 static uint32_t GetWatchHi(struct pt_watch_regs *regs, uint32_t index) {
571 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
572 if (regs->style == pt_watch_style_mips32)
573 return regs->mips32.watchhi[index];
574 else if (regs->style == pt_watch_style_mips64)
575 return regs->mips64.watchhi[index];
576 LLDB_LOG(log, "Invalid watch register style");
577 return 0;
578 }
579
SetWatchHi(struct pt_watch_regs * regs,uint32_t index,uint16_t value)580 static void SetWatchHi(struct pt_watch_regs *regs, uint32_t index,
581 uint16_t value) {
582 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
583 if (regs->style == pt_watch_style_mips32)
584 regs->mips32.watchhi[index] = value;
585 else if (regs->style == pt_watch_style_mips64)
586 regs->mips64.watchhi[index] = value;
587 LLDB_LOG(log, "Invalid watch register style");
588 return;
589 }
590
GetWatchLo(struct pt_watch_regs * regs,uint32_t index)591 static lldb::addr_t GetWatchLo(struct pt_watch_regs *regs, uint32_t index) {
592 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
593 if (regs->style == pt_watch_style_mips32)
594 return regs->mips32.watchlo[index];
595 else if (regs->style == pt_watch_style_mips64)
596 return regs->mips64.watchlo[index];
597 LLDB_LOG(log, "Invalid watch register style");
598 return LLDB_INVALID_ADDRESS;
599 }
600
SetWatchLo(struct pt_watch_regs * regs,uint32_t index,uint64_t value)601 static void SetWatchLo(struct pt_watch_regs *regs, uint32_t index,
602 uint64_t value) {
603 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
604 if (regs->style == pt_watch_style_mips32)
605 regs->mips32.watchlo[index] = (uint32_t)value;
606 else if (regs->style == pt_watch_style_mips64)
607 regs->mips64.watchlo[index] = value;
608 else
609 LLDB_LOG(log, "Invalid watch register style");
610 }
611
GetIRWMask(struct pt_watch_regs * regs,uint32_t index)612 static uint32_t GetIRWMask(struct pt_watch_regs *regs, uint32_t index) {
613 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
614 if (regs->style == pt_watch_style_mips32)
615 return regs->mips32.watch_masks[index] & IRW;
616 else if (regs->style == pt_watch_style_mips64)
617 return regs->mips64.watch_masks[index] & IRW;
618 LLDB_LOG(log, "Invalid watch register style");
619 return 0;
620 }
621
GetRegMask(struct pt_watch_regs * regs,uint32_t index)622 static uint32_t GetRegMask(struct pt_watch_regs *regs, uint32_t index) {
623 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
624 if (regs->style == pt_watch_style_mips32)
625 return regs->mips32.watch_masks[index] & ~IRW;
626 else if (regs->style == pt_watch_style_mips64)
627 return regs->mips64.watch_masks[index] & ~IRW;
628 LLDB_LOG(log, "Invalid watch register style");
629 return 0;
630 }
631
GetRangeMask(lldb::addr_t mask)632 static lldb::addr_t GetRangeMask(lldb::addr_t mask) {
633 lldb::addr_t mask_bit = 1;
634 while (mask_bit < mask) {
635 mask = mask | mask_bit;
636 mask_bit <<= 1;
637 }
638 return mask;
639 }
640
GetVacantWatchIndex(struct pt_watch_regs * regs,lldb::addr_t addr,uint32_t size,uint32_t irw,uint32_t num_valid)641 static int GetVacantWatchIndex(struct pt_watch_regs *regs, lldb::addr_t addr,
642 uint32_t size, uint32_t irw,
643 uint32_t num_valid) {
644 lldb::addr_t last_byte = addr + size - 1;
645 lldb::addr_t mask = GetRangeMask(addr ^ last_byte) | IRW;
646 lldb::addr_t base_addr = addr & ~mask;
647
648 // Check if this address is already watched by previous watch points.
649 lldb::addr_t lo;
650 uint16_t hi;
651 uint32_t vacant_watches = 0;
652 for (uint32_t index = 0; index < num_valid; index++) {
653 lo = GetWatchLo(regs, index);
654 if (lo != 0 && irw == ((uint32_t)lo & irw)) {
655 hi = GetWatchHi(regs, index) | IRW;
656 lo &= ~(lldb::addr_t)hi;
657 if (addr >= lo && last_byte <= (lo + hi))
658 return index;
659 } else
660 vacant_watches++;
661 }
662
663 // Now try to find a vacant index
664 if (vacant_watches > 0) {
665 vacant_watches = 0;
666 for (uint32_t index = 0; index < num_valid; index++) {
667 lo = GetWatchLo(regs, index);
668 if (lo == 0 && irw == (GetIRWMask(regs, index) & irw)) {
669 if (mask <= (GetRegMask(regs, index) | IRW)) {
670 // It fits, we can use it.
671 SetWatchLo(regs, index, base_addr | irw);
672 SetWatchHi(regs, index, mask & ~IRW);
673 return index;
674 } else {
675 // It doesn't fit, but has the proper IRW capabilities
676 vacant_watches++;
677 }
678 }
679 }
680
681 if (vacant_watches > 1) {
682 // Split this watchpoint across several registers
683 struct pt_watch_regs regs_copy;
684 regs_copy = *regs;
685 lldb::addr_t break_addr;
686 uint32_t segment_size;
687 for (uint32_t index = 0; index < num_valid; index++) {
688 lo = GetWatchLo(®s_copy, index);
689 hi = GetRegMask(®s_copy, index) | IRW;
690 if (lo == 0 && irw == (hi & irw)) {
691 lo = addr & ~(lldb::addr_t)hi;
692 break_addr = lo + hi + 1;
693 if (break_addr >= addr + size)
694 segment_size = size;
695 else
696 segment_size = break_addr - addr;
697 mask = GetRangeMask(addr ^ (addr + segment_size - 1));
698 SetWatchLo(®s_copy, index, (addr & ~mask) | irw);
699 SetWatchHi(®s_copy, index, mask & ~IRW);
700 if (break_addr >= addr + size) {
701 *regs = regs_copy;
702 return index;
703 }
704 size = addr + size - break_addr;
705 addr = break_addr;
706 }
707 }
708 }
709 }
710 return LLDB_INVALID_INDEX32;
711 }
712
IsMSA(uint32_t reg_index) const713 bool NativeRegisterContextLinux_mips64::IsMSA(uint32_t reg_index) const {
714 return (m_reg_info.first_msa <= reg_index &&
715 reg_index <= m_reg_info.last_msa);
716 }
717
IsMSAAvailable()718 bool NativeRegisterContextLinux_mips64::IsMSAAvailable() {
719 MSA_linux_mips msa_buf;
720 unsigned int regset = NT_MIPS_MSA;
721
722 Status error = NativeProcessLinux::PtraceWrapper(
723 PTRACE_GETREGSET, Host::GetCurrentProcessID(),
724 static_cast<void *>(®set), &msa_buf, sizeof(MSA_linux_mips));
725
726 if (error.Success() && msa_buf.mir) {
727 return true;
728 }
729
730 return false;
731 }
732
IsWatchpointHit(uint32_t wp_index,bool & is_hit)733 Status NativeRegisterContextLinux_mips64::IsWatchpointHit(uint32_t wp_index,
734 bool &is_hit) {
735 if (wp_index >= NumSupportedHardwareWatchpoints())
736 return Status("Watchpoint index out of range");
737
738 // reading the current state of watch regs
739 struct pt_watch_regs watch_readback;
740 Status error = DoReadWatchPointRegisterValue(
741 m_thread.GetID(), static_cast<void *>(&watch_readback));
742
743 if (GetWatchHi(&watch_readback, wp_index) & (IRW)) {
744 // clear hit flag in watchhi
745 SetWatchHi(&watch_readback, wp_index,
746 (GetWatchHi(&watch_readback, wp_index) & ~(IRW)));
747 DoWriteWatchPointRegisterValue(m_thread.GetID(),
748 static_cast<void *>(&watch_readback));
749
750 is_hit = true;
751 return error;
752 }
753 is_hit = false;
754 return error;
755 }
756
GetWatchpointHitIndex(uint32_t & wp_index,lldb::addr_t trap_addr)757 Status NativeRegisterContextLinux_mips64::GetWatchpointHitIndex(
758 uint32_t &wp_index, lldb::addr_t trap_addr) {
759 uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
760 for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
761 bool is_hit;
762 Status error = IsWatchpointHit(wp_index, is_hit);
763 if (error.Fail()) {
764 wp_index = LLDB_INVALID_INDEX32;
765 } else if (is_hit) {
766 return error;
767 }
768 }
769 wp_index = LLDB_INVALID_INDEX32;
770 return Status();
771 }
772
IsWatchpointVacant(uint32_t wp_index,bool & is_vacant)773 Status NativeRegisterContextLinux_mips64::IsWatchpointVacant(uint32_t wp_index,
774 bool &is_vacant) {
775 is_vacant = false;
776 return Status("MIPS TODO: "
777 "NativeRegisterContextLinux_mips64::IsWatchpointVacant not "
778 "implemented");
779 }
780
ClearHardwareWatchpoint(uint32_t wp_index)781 bool NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint(
782 uint32_t wp_index) {
783 if (wp_index >= NumSupportedHardwareWatchpoints())
784 return false;
785
786 struct pt_watch_regs regs;
787 // First reading the current state of watch regs
788 DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
789
790 if (regs.style == pt_watch_style_mips32) {
791 regs.mips32.watchlo[wp_index] = default_watch_regs.mips32.watchlo[wp_index];
792 regs.mips32.watchhi[wp_index] = default_watch_regs.mips32.watchhi[wp_index];
793 regs.mips32.watch_masks[wp_index] =
794 default_watch_regs.mips32.watch_masks[wp_index];
795 } else // pt_watch_style_mips64
796 {
797 regs.mips64.watchlo[wp_index] = default_watch_regs.mips64.watchlo[wp_index];
798 regs.mips64.watchhi[wp_index] = default_watch_regs.mips64.watchhi[wp_index];
799 regs.mips64.watch_masks[wp_index] =
800 default_watch_regs.mips64.watch_masks[wp_index];
801 }
802
803 Status error = DoWriteWatchPointRegisterValue(m_thread.GetID(),
804 static_cast<void *>(®s));
805 if (!error.Fail()) {
806 hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS;
807 return true;
808 }
809 return false;
810 }
811
ClearAllHardwareWatchpoints()812 Status NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints() {
813 return DoWriteWatchPointRegisterValue(
814 m_thread.GetID(), static_cast<void *>(&default_watch_regs));
815 }
816
SetHardwareWatchpointWithIndex(lldb::addr_t addr,size_t size,uint32_t watch_flags,uint32_t wp_index)817 Status NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex(
818 lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
819 Status error;
820 error.SetErrorString("MIPS TODO: "
821 "NativeRegisterContextLinux_mips64::"
822 "SetHardwareWatchpointWithIndex not implemented");
823 return error;
824 }
825
SetHardwareWatchpoint(lldb::addr_t addr,size_t size,uint32_t watch_flags)826 uint32_t NativeRegisterContextLinux_mips64::SetHardwareWatchpoint(
827 lldb::addr_t addr, size_t size, uint32_t watch_flags) {
828 struct pt_watch_regs regs;
829
830 // First reading the current state of watch regs
831 DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
832
833 // Try if a new watch point fits in this state
834 int index = GetVacantWatchIndex(®s, addr, size, watch_flags,
835 NumSupportedHardwareWatchpoints());
836
837 // New watchpoint doesn't fit
838 if (index == LLDB_INVALID_INDEX32)
839 return LLDB_INVALID_INDEX32;
840
841 // It fits, so we go ahead with updating the state of watch regs
842 DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
843
844 // Storing exact address
845 hw_addr_map[index] = addr;
846 return index;
847 }
848
849 lldb::addr_t
GetWatchpointAddress(uint32_t wp_index)850 NativeRegisterContextLinux_mips64::GetWatchpointAddress(uint32_t wp_index) {
851 if (wp_index >= NumSupportedHardwareWatchpoints())
852 return LLDB_INVALID_ADDRESS;
853
854 return hw_addr_map[wp_index];
855 }
856
857 struct EmulatorBaton {
858 lldb::addr_t m_watch_hit_addr;
859 NativeProcessLinux *m_process;
860 NativeRegisterContext *m_reg_context;
861
EmulatorBatonEmulatorBaton862 EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context)
863 : m_watch_hit_addr(LLDB_INVALID_ADDRESS), m_process(process),
864 m_reg_context(reg_context) {}
865 };
866
ReadMemoryCallback(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,void * dst,size_t length)867 static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
868 const EmulateInstruction::Context &context,
869 lldb::addr_t addr, void *dst, size_t length) {
870 size_t bytes_read;
871 EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
872 emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read);
873 return bytes_read;
874 }
875
WriteMemoryCallback(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,const void * dst,size_t length)876 static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
877 const EmulateInstruction::Context &context,
878 lldb::addr_t addr, const void *dst,
879 size_t length) {
880 return length;
881 }
882
ReadRegisterCallback(EmulateInstruction * instruction,void * baton,const RegisterInfo * reg_info,RegisterValue & reg_value)883 static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
884 const RegisterInfo *reg_info,
885 RegisterValue ®_value) {
886 EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
887
888 const RegisterInfo *full_reg_info =
889 emulator_baton->m_reg_context->GetRegisterInfo(
890 lldb::eRegisterKindDWARF, reg_info->kinds[lldb::eRegisterKindDWARF]);
891
892 Status error =
893 emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
894 if (error.Success())
895 return true;
896
897 return false;
898 }
899
WriteRegisterCallback(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,const RegisterInfo * reg_info,const RegisterValue & reg_value)900 static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
901 const EmulateInstruction::Context &context,
902 const RegisterInfo *reg_info,
903 const RegisterValue ®_value) {
904 if (reg_info->kinds[lldb::eRegisterKindDWARF] == dwarf_bad_mips64) {
905 EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
906 emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64();
907 }
908
909 return true;
910 }
911
912 /*
913 * MIPS Linux kernel returns a masked address (last 3bits are masked)
914 * when a HW watchpoint is hit. However user may not have set a watchpoint
915 * on this address. Emulate instruction at PC and find the base address of
916 * the load/store instruction. This will give the exact address used to
917 * read/write the variable. Send this exact address to client so that
918 * it can decide to stop or continue the thread.
919 */
920 lldb::addr_t
GetWatchpointHitAddress(uint32_t wp_index)921 NativeRegisterContextLinux_mips64::GetWatchpointHitAddress(uint32_t wp_index) {
922 if (wp_index >= NumSupportedHardwareWatchpoints())
923 return LLDB_INVALID_ADDRESS;
924
925 lldb_private::ArchSpec arch;
926 arch = GetRegisterInfoInterface().GetTargetArchitecture();
927 std::unique_ptr<EmulateInstruction> emulator_up(
928 EmulateInstruction::FindPlugin(arch, lldb_private::eInstructionTypeAny,
929 nullptr));
930
931 if (emulator_up == nullptr)
932 return LLDB_INVALID_ADDRESS;
933
934 EmulatorBaton baton(
935 static_cast<NativeProcessLinux *>(&m_thread.GetProcess()), this);
936 emulator_up->SetBaton(&baton);
937 emulator_up->SetReadMemCallback(&ReadMemoryCallback);
938 emulator_up->SetReadRegCallback(&ReadRegisterCallback);
939 emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
940 emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
941
942 if (!emulator_up->ReadInstruction())
943 return LLDB_INVALID_ADDRESS;
944
945 if (emulator_up->EvaluateInstruction(lldb::eEmulateInstructionOptionNone))
946 return baton.m_watch_hit_addr;
947
948 return LLDB_INVALID_ADDRESS;
949 }
950
NumSupportedHardwareWatchpoints()951 uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() {
952 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
953 struct pt_watch_regs regs;
954 static int num_valid = 0;
955 if (!num_valid) {
956 DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
957 default_watch_regs =
958 regs; // Keeping default watch regs values for future use
959 switch (regs.style) {
960 case pt_watch_style_mips32:
961 num_valid = regs.mips32.num_valid; // Using num_valid as cache
962 return num_valid;
963 case pt_watch_style_mips64:
964 num_valid = regs.mips64.num_valid;
965 return num_valid;
966 }
967 LLDB_LOG(log, "Invalid watch register style");
968 return 0;
969 }
970 return num_valid;
971 }
972
973 Status
ReadRegisterRaw(uint32_t reg_index,RegisterValue & value)974 NativeRegisterContextLinux_mips64::ReadRegisterRaw(uint32_t reg_index,
975 RegisterValue &value) {
976 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
977
978 if (!reg_info)
979 return Status("register %" PRIu32 " not found", reg_index);
980
981 uint32_t offset = reg_info->kinds[lldb::eRegisterKindProcessPlugin];
982
983 if ((offset == ptrace_sr_mips) || (offset == ptrace_config5_mips))
984 return Read_SR_Config(reg_info->byte_offset, reg_info->name,
985 reg_info->byte_size, value);
986
987 return DoReadRegisterValue(offset, reg_info->name, reg_info->byte_size,
988 value);
989 }
990
WriteRegisterRaw(uint32_t reg_index,const RegisterValue & value)991 Status NativeRegisterContextLinux_mips64::WriteRegisterRaw(
992 uint32_t reg_index, const RegisterValue &value) {
993 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
994
995 if (!reg_info)
996 return Status("register %" PRIu32 " not found", reg_index);
997
998 if (reg_info->invalidate_regs)
999 lldbassert(false && "reg_info->invalidate_regs is unhandled");
1000
1001 uint32_t offset = reg_info->kinds[lldb::eRegisterKindProcessPlugin];
1002 return DoWriteRegisterValue(offset, reg_info->name, value);
1003 }
1004
Read_SR_Config(uint32_t offset,const char * reg_name,uint32_t size,RegisterValue & value)1005 Status NativeRegisterContextLinux_mips64::Read_SR_Config(uint32_t offset,
1006 const char *reg_name,
1007 uint32_t size,
1008 RegisterValue &value) {
1009 GPR_linux_mips regs;
1010 ::memset(®s, 0, sizeof(GPR_linux_mips));
1011
1012 Status error = NativeProcessLinux::PtraceWrapper(
1013 PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs);
1014 if (error.Success()) {
1015 const lldb_private::ArchSpec &arch =
1016 m_thread.GetProcess().GetArchitecture();
1017 void *target_address = ((uint8_t *)®s) + offset +
1018 4 * (arch.GetMachine() == llvm::Triple::mips);
1019 value.SetUInt(*(uint32_t *)target_address, size);
1020 }
1021 return error;
1022 }
1023
DoReadWatchPointRegisterValue(lldb::tid_t tid,void * watch_readback)1024 Status NativeRegisterContextLinux_mips64::DoReadWatchPointRegisterValue(
1025 lldb::tid_t tid, void *watch_readback) {
1026 return NativeProcessLinux::PtraceWrapper(PTRACE_GET_WATCH_REGS,
1027 m_thread.GetID(), watch_readback);
1028 }
1029
DoWriteWatchPointRegisterValue(lldb::tid_t tid,void * watch_reg_value)1030 Status NativeRegisterContextLinux_mips64::DoWriteWatchPointRegisterValue(
1031 lldb::tid_t tid, void *watch_reg_value) {
1032 return NativeProcessLinux::PtraceWrapper(PTRACE_SET_WATCH_REGS,
1033 m_thread.GetID(), watch_reg_value);
1034 }
1035
1036 #endif // defined (__mips__)
1037