loongarch-linux-nat.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* Native-dependent code for GNU/Linux on LoongArch processors.
  2. Copyright (C) 2022 Free Software Foundation, Inc.
  3. Contributed by Loongson Ltd.
  4. This file is part of GDB.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. #include "defs.h"
  16. #include "elf/common.h"
  17. #include "gregset.h"
  18. #include "inferior.h"
  19. #include "linux-nat-trad.h"
  20. #include "loongarch-tdep.h"
  21. #include "nat/gdb_ptrace.h"
  22. #include "target-descriptions.h"
  23. #include <asm/ptrace.h>
  24. /* LoongArch Linux native additions to the default Linux support. */
  25. class loongarch_linux_nat_target final : public linux_nat_trad_target
  26. {
  27. public:
  28. /* Add our register access methods. */
  29. void fetch_registers (struct regcache *, int) override;
  30. void store_registers (struct regcache *, int) override;
  31. protected:
  32. /* Override linux_nat_trad_target methods. */
  33. CORE_ADDR register_u_offset (struct gdbarch *gdbarch, int regno,
  34. int store_p) override;
  35. };
  36. /* Fill GDB's register array with the general-purpose, pc and badv
  37. register values from the current thread. */
  38. static void
  39. fetch_gregs_from_thread (struct regcache *regcache, int regno, pid_t tid)
  40. {
  41. loongarch_gdbarch_tdep *tdep
  42. = (loongarch_gdbarch_tdep *) gdbarch_tdep (regcache->arch ());
  43. auto regs = tdep->regs;
  44. elf_gregset_t regset;
  45. if (regno == -1 || (regs.r <= regno && regno < regs.r + 32)
  46. || regs.pc == regno || regs.badv == regno)
  47. {
  48. struct iovec iov;
  49. iov.iov_base = &regset;
  50. iov.iov_len = sizeof (regset);
  51. if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (long) &iov) < 0)
  52. perror_with_name (_("Couldn't get NT_PRSTATUS registers"));
  53. else
  54. loongarch_gregset.supply_regset (nullptr, regcache, regno,
  55. &regset, sizeof (regset));
  56. }
  57. }
  58. /* Store to the current thread the valid general-purpose, pc and badv
  59. register values in the GDB's register array. */
  60. static void
  61. store_gregs_to_thread (struct regcache *regcache, int regno, pid_t tid)
  62. {
  63. loongarch_gdbarch_tdep *tdep
  64. = (loongarch_gdbarch_tdep *) gdbarch_tdep (regcache->arch ());
  65. auto regs = tdep->regs;
  66. elf_gregset_t regset;
  67. if (regno == -1 || (regs.r <= regno && regno < regs.r + 32)
  68. || regs.pc == regno || regs.badv == regno)
  69. {
  70. struct iovec iov;
  71. iov.iov_base = &regset;
  72. iov.iov_len = sizeof (regset);
  73. if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (long) &iov) < 0)
  74. perror_with_name (_("Couldn't get NT_PRSTATUS registers"));
  75. else
  76. {
  77. loongarch_gregset.collect_regset (nullptr, regcache, regno,
  78. &regset, sizeof (regset));
  79. if (ptrace (PTRACE_SETREGSET, tid, NT_PRSTATUS, (long) &iov) < 0)
  80. perror_with_name (_("Couldn't set NT_PRSTATUS registers"));
  81. }
  82. }
  83. }
  84. /* Implement the "fetch_registers" target_ops method. */
  85. void
  86. loongarch_linux_nat_target::fetch_registers (struct regcache *regcache,
  87. int regno)
  88. {
  89. pid_t tid = get_ptrace_pid (regcache->ptid ());
  90. fetch_gregs_from_thread(regcache, regno, tid);
  91. }
  92. /* Implement the "store_registers" target_ops method. */
  93. void
  94. loongarch_linux_nat_target::store_registers (struct regcache *regcache,
  95. int regno)
  96. {
  97. pid_t tid = get_ptrace_pid (regcache->ptid ());
  98. store_gregs_to_thread (regcache, regno, tid);
  99. }
  100. /* Return the address in the core dump or inferior of register REGNO. */
  101. CORE_ADDR
  102. loongarch_linux_nat_target::register_u_offset (struct gdbarch *gdbarch,
  103. int regno, int store_p)
  104. {
  105. loongarch_gdbarch_tdep *tdep
  106. = (loongarch_gdbarch_tdep *) gdbarch_tdep (gdbarch);
  107. auto regs = tdep->regs;
  108. /* According to <asm/ptrace.h> */
  109. if (0 <= regs.r && regs.r <= regno && regno < regs.r + GPR_NUM)
  110. return GPR_BASE + regno - regs.r;
  111. else if (regs.pc == regno)
  112. return PC;
  113. else
  114. return -1;
  115. }
  116. static loongarch_linux_nat_target the_loongarch_linux_nat_target;
  117. /* Wrapper functions. These are only used by libthread_db. */
  118. void
  119. supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregset)
  120. {
  121. loongarch_gregset.supply_regset (nullptr, regcache, -1, gregset,
  122. sizeof (gdb_gregset_t));
  123. }
  124. void
  125. fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregset,
  126. int regno)
  127. {
  128. loongarch_gregset.collect_regset (nullptr, regcache, regno, gregset,
  129. sizeof (gdb_gregset_t));
  130. }
  131. void
  132. supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregset)
  133. {
  134. }
  135. void
  136. fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregset,
  137. int regno)
  138. {
  139. }
  140. /* Initialize LoongArch Linux native support. */
  141. void _initialize_loongarch_linux_nat ();
  142. void
  143. _initialize_loongarch_linux_nat ()
  144. {
  145. linux_target = &the_loongarch_linux_nat_target;
  146. add_inf_child_target (&the_loongarch_linux_nat_target);
  147. }