[lldb][Process] Introduce LoongArch64 hw break/watchpoint support · llvm/llvm-project@6c4e70f (original) (raw)

`@@ -11,6 +11,7 @@

`

11

11

`#include "NativeRegisterContextLinux_loongarch64.h"

`

12

12

``

13

13

`#include "lldb/Host/HostInfo.h"

`

``

14

`+

#include "lldb/Host/linux/Ptrace.h"

`

14

15

`#include "lldb/Utility/DataBufferHeap.h"

`

15

16

`#include "lldb/Utility/Log.h"

`

16

17

`#include "lldb/Utility/RegisterValue.h"

`

`@@ -62,6 +63,16 @@ NativeRegisterContextLinux_loongarch64::NativeRegisterContextLinux_loongarch64(

`

62

63

`::memset(&m_fpr, 0, sizeof(m_fpr));

`

63

64

`::memset(&m_gpr, 0, sizeof(m_gpr));

`

64

65

``

``

66

`+

::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));

`

``

67

`+

::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));

`

``

68

+

``

69

`+

// Refer to:

`

``

70

`+

// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#control-and-status-registers-related-to-watchpoints

`

``

71

`+

// 14 is just a maximum value, query hardware for actual watchpoint count.

`

``

72

`+

m_max_hwp_supported = 14;

`

``

73

`+

m_max_hbp_supported = 14;

`

``

74

`+

m_refresh_hwdebug_info = true;

`

``

75

+

65

76

` m_gpr_is_valid = false;

`

66

77

` m_fpu_is_valid = false;

`

67

78

`}

`

`@@ -337,4 +348,73 @@ NativeRegisterContextLinux_loongarch64::GetExpeditedRegisters(

`

337

348

`return expedited_reg_nums;

`

338

349

`}

`

339

350

``

``

351

`+

llvm::Error NativeRegisterContextLinux_loongarch64::ReadHardwareDebugInfo() {

`

``

352

`+

if (!m_refresh_hwdebug_info)

`

``

353

`+

return llvm::Error::success();

`

``

354

+

``

355

`+

::pid_t tid = m_thread.GetID();

`

``

356

+

``

357

`+

int regset = NT_LOONGARCH_HW_WATCH;

`

``

358

`+

struct iovec ioVec;

`

``

359

`+

struct user_watch_state dreg_state;

`

``

360

`+

Status error;

`

``

361

+

``

362

`+

ioVec.iov_base = &dreg_state;

`

``

363

`+

ioVec.iov_len = sizeof(dreg_state);

`

``

364

`+

error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,

`

``

365

`+

&ioVec, ioVec.iov_len);

`

``

366

`+

if (error.Fail())

`

``

367

`+

return error.ToError();

`

``

368

+

``

369

`+

m_max_hwp_supported = dreg_state.dbg_info & 0x3f;

`

``

370

+

``

371

`+

regset = NT_LOONGARCH_HW_BREAK;

`

``

372

`+

error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,

`

``

373

`+

&ioVec, ioVec.iov_len);

`

``

374

`+

if (error.Fail())

`

``

375

`+

return error.ToError();

`

``

376

+

``

377

`+

m_max_hbp_supported = dreg_state.dbg_info & 0x3f;

`

``

378

+

``

379

`+

m_refresh_hwdebug_info = false;

`

``

380

+

``

381

`+

return llvm::Error::success();

`

``

382

`+

}

`

``

383

+

``

384

`+

llvm::Error NativeRegisterContextLinux_loongarch64::WriteHardwareDebugRegs(

`

``

385

`+

DREGType hwbType) {

`

``

386

`+

struct iovec ioVec;

`

``

387

`+

struct user_watch_state dreg_state;

`

``

388

`+

int regset;

`

``

389

+

``

390

`+

memset(&dreg_state, 0, sizeof(dreg_state));

`

``

391

`+

ioVec.iov_base = &dreg_state;

`

``

392

+

``

393

`+

switch (hwbType) {

`

``

394

`+

case eDREGTypeWATCH:

`

``

395

`+

regset = NT_LOONGARCH_HW_WATCH;

`

``

396

`+

ioVec.iov_len = sizeof(dreg_state.dbg_info) +

`

``

397

`+

(sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);

`

``

398

+

``

399

`+

for (uint32_t i = 0; i < m_max_hwp_supported; i++) {

`

``

400

`+

dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;

`

``

401

`+

dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;

`

``

402

`+

}

`

``

403

`+

break;

`

``

404

`+

case eDREGTypeBREAK:

`

``

405

`+

regset = NT_LOONGARCH_HW_BREAK;

`

``

406

`+

ioVec.iov_len = sizeof(dreg_state.dbg_info) +

`

``

407

`+

(sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);

`

``

408

+

``

409

`+

for (uint32_t i = 0; i < m_max_hbp_supported; i++) {

`

``

410

`+

dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;

`

``

411

`+

dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;

`

``

412

`+

}

`

``

413

`+

break;

`

``

414

`+

}

`

``

415

+

``

416

`+

return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),

`

``

417

`+

&regset, &ioVec, ioVec.iov_len)

`

``

418

`+

.ToError();

`

``

419

`+

}

`

340

420

`#endif // defined(loongarch) && __loongarch_grlen == 64

`