i386-fbsd-nat.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /* Native-dependent code for FreeBSD/i386.
  2. Copyright (C) 2001-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #include "defs.h"
  15. #include "inferior.h"
  16. #include "regcache.h"
  17. #include "target.h"
  18. #include <sys/types.h>
  19. #include <sys/ptrace.h>
  20. #include <sys/sysctl.h>
  21. #include <sys/user.h>
  22. #include "i386-tdep.h"
  23. #include "i386-fbsd-tdep.h"
  24. #include "i387-tdep.h"
  25. #include "x86-nat.h"
  26. #include "gdbsupport/x86-xstate.h"
  27. #include "x86-fbsd-nat.h"
  28. class i386_fbsd_nat_target final : public x86_fbsd_nat_target
  29. {
  30. public:
  31. void fetch_registers (struct regcache *, int) override;
  32. void store_registers (struct regcache *, int) override;
  33. const struct target_desc *read_description () override;
  34. void resume (ptid_t, int, enum gdb_signal) override;
  35. };
  36. static i386_fbsd_nat_target the_i386_fbsd_nat_target;
  37. #ifdef PT_GETXSTATE_INFO
  38. static size_t xsave_len;
  39. #endif
  40. static int have_ptrace_xmmregs;
  41. /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
  42. for all registers. */
  43. void
  44. i386_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
  45. {
  46. struct gdbarch *gdbarch = regcache->arch ();
  47. #if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
  48. const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  49. #endif
  50. pid_t pid = get_ptrace_pid (regcache->ptid ());
  51. if (fetch_register_set<struct reg> (regcache, regnum, PT_GETREGS,
  52. &i386_fbsd_gregset))
  53. {
  54. if (regnum != -1)
  55. return;
  56. }
  57. #ifdef PT_GETFSBASE
  58. if (regnum == -1 || regnum == I386_FSBASE_REGNUM)
  59. {
  60. register_t base;
  61. if (ptrace (PT_GETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
  62. perror_with_name (_("Couldn't get segment register fs_base"));
  63. regcache->raw_supply (I386_FSBASE_REGNUM, &base);
  64. if (regnum != -1)
  65. return;
  66. }
  67. #endif
  68. #ifdef PT_GETGSBASE
  69. if (regnum == -1 || regnum == I386_GSBASE_REGNUM)
  70. {
  71. register_t base;
  72. if (ptrace (PT_GETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
  73. perror_with_name (_("Couldn't get segment register gs_base"));
  74. regcache->raw_supply (I386_GSBASE_REGNUM, &base);
  75. if (regnum != -1)
  76. return;
  77. }
  78. #endif
  79. /* There is no i386_fxsave_supplies or i386_xsave_supplies.
  80. Instead, the earlier register sets return early if the request
  81. was for a specific register that was already satisified to avoid
  82. fetching the FPU/XSAVE state unnecessarily. */
  83. #ifdef PT_GETXSTATE_INFO
  84. if (xsave_len != 0)
  85. {
  86. void *xstateregs = alloca (xsave_len);
  87. if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
  88. perror_with_name (_("Couldn't get extended state status"));
  89. i387_supply_xsave (regcache, regnum, xstateregs);
  90. return;
  91. }
  92. #endif
  93. if (have_ptrace_xmmregs != 0)
  94. {
  95. char xmmregs[I387_SIZEOF_FXSAVE];
  96. if (ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
  97. perror_with_name (_("Couldn't get XMM registers"));
  98. i387_supply_fxsave (regcache, regnum, xmmregs);
  99. return;
  100. }
  101. struct fpreg fpregs;
  102. if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
  103. perror_with_name (_("Couldn't get floating point status"));
  104. i387_supply_fsave (regcache, regnum, &fpregs);
  105. }
  106. /* Store register REGNUM back into the inferior. If REGNUM is -1, do
  107. this for all registers. */
  108. void
  109. i386_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
  110. {
  111. struct gdbarch *gdbarch = regcache->arch ();
  112. #if defined(PT_GETFSBASE) || defined(PT_GETGSBASE)
  113. const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  114. #endif
  115. pid_t pid = get_ptrace_pid (regcache->ptid ());
  116. if (store_register_set<struct reg> (regcache, regnum, PT_GETREGS, PT_SETREGS,
  117. &i386_fbsd_gregset))
  118. {
  119. if (regnum != -1)
  120. return;
  121. }
  122. #ifdef PT_SETFSBASE
  123. if (regnum == -1 || regnum == I386_FSBASE_REGNUM)
  124. {
  125. register_t base;
  126. regcache->raw_collect (I386_FSBASE_REGNUM, &base);
  127. if (ptrace (PT_SETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
  128. perror_with_name (_("Couldn't write segment register fs_base"));
  129. if (regnum != -1)
  130. return;
  131. }
  132. #endif
  133. #ifdef PT_SETGSBASE
  134. if (regnum == -1 || regnum == I386_GSBASE_REGNUM)
  135. {
  136. register_t base;
  137. regcache->raw_collect (I386_GSBASE_REGNUM, &base);
  138. if (ptrace (PT_SETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1)
  139. perror_with_name (_("Couldn't write segment register gs_base"));
  140. if (regnum != -1)
  141. return;
  142. }
  143. #endif
  144. /* There is no i386_fxsave_supplies or i386_xsave_supplies.
  145. Instead, the earlier register sets return early if the request
  146. was for a specific register that was already satisified to avoid
  147. fetching the FPU/XSAVE state unnecessarily. */
  148. #ifdef PT_GETXSTATE_INFO
  149. if (xsave_len != 0)
  150. {
  151. void *xstateregs = alloca (xsave_len);
  152. if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
  153. perror_with_name (_("Couldn't get extended state status"));
  154. i387_collect_xsave (regcache, regnum, xstateregs, 0);
  155. if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, xsave_len)
  156. == -1)
  157. perror_with_name (_("Couldn't write extended state status"));
  158. return;
  159. }
  160. #endif
  161. if (have_ptrace_xmmregs != 0)
  162. {
  163. char xmmregs[I387_SIZEOF_FXSAVE];
  164. if (ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
  165. perror_with_name (_("Couldn't get XMM registers"));
  166. i387_collect_fxsave (regcache, regnum, xmmregs);
  167. if (ptrace (PT_SETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
  168. perror_with_name (_("Couldn't write XMM registers"));
  169. return;
  170. }
  171. struct fpreg fpregs;
  172. if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
  173. perror_with_name (_("Couldn't get floating point status"));
  174. i387_collect_fsave (regcache, regnum, &fpregs);
  175. if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
  176. perror_with_name (_("Couldn't write floating point status"));
  177. }
  178. /* Resume execution of the inferior process. If STEP is nonzero,
  179. single-step it. If SIGNAL is nonzero, give it that signal. */
  180. void
  181. i386_fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
  182. {
  183. pid_t pid = ptid.pid ();
  184. int request = PT_STEP;
  185. if (pid == -1)
  186. /* Resume all threads. This only gets used in the non-threaded
  187. case, where "resume all threads" and "resume inferior_ptid" are
  188. the same. */
  189. pid = inferior_ptid.pid ();
  190. if (!step)
  191. {
  192. struct regcache *regcache = get_current_regcache ();
  193. ULONGEST eflags;
  194. /* Workaround for a bug in FreeBSD. Make sure that the trace
  195. flag is off when doing a continue. There is a code path
  196. through the kernel which leaves the flag set when it should
  197. have been cleared. If a process has a signal pending (such
  198. as SIGALRM) and we do a PT_STEP, the process never really has
  199. a chance to run because the kernel needs to notify the
  200. debugger that a signal is being sent. Therefore, the process
  201. never goes through the kernel's trap() function which would
  202. normally clear it. */
  203. regcache_cooked_read_unsigned (regcache, I386_EFLAGS_REGNUM,
  204. &eflags);
  205. if (eflags & 0x0100)
  206. regcache_cooked_write_unsigned (regcache, I386_EFLAGS_REGNUM,
  207. eflags & ~0x0100);
  208. request = PT_CONTINUE;
  209. }
  210. /* An addres of (caddr_t) 1 tells ptrace to continue from where it
  211. was. (If GDB wanted it to start some other way, we have already
  212. written a new PC value to the child.) */
  213. if (ptrace (request, pid, (caddr_t) 1,
  214. gdb_signal_to_host (signal)) == -1)
  215. perror_with_name (("ptrace"));
  216. }
  217. /* Support for debugging kernel virtual memory images. */
  218. #include <machine/pcb.h>
  219. #include "bsd-kvm.h"
  220. static int
  221. i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
  222. {
  223. /* The following is true for FreeBSD 4.7:
  224. The pcb contains %eip, %ebx, %esp, %ebp, %esi, %edi and %gs.
  225. This accounts for all callee-saved registers specified by the
  226. psABI and then some. Here %esp contains the stack pointer at the
  227. point just after the call to cpu_switch(). From this information
  228. we reconstruct the register state as it would look when we just
  229. returned from cpu_switch(). */
  230. /* The stack pointer shouldn't be zero. */
  231. if (pcb->pcb_esp == 0)
  232. return 0;
  233. pcb->pcb_esp += 4;
  234. regcache->raw_supply (I386_EDI_REGNUM, &pcb->pcb_edi);
  235. regcache->raw_supply (I386_ESI_REGNUM, &pcb->pcb_esi);
  236. regcache->raw_supply (I386_EBP_REGNUM, &pcb->pcb_ebp);
  237. regcache->raw_supply (I386_ESP_REGNUM, &pcb->pcb_esp);
  238. regcache->raw_supply (I386_EBX_REGNUM, &pcb->pcb_ebx);
  239. regcache->raw_supply (I386_EIP_REGNUM, &pcb->pcb_eip);
  240. regcache->raw_supply (I386_GS_REGNUM, &pcb->pcb_gs);
  241. return 1;
  242. }
  243. /* Implement the read_description method. */
  244. const struct target_desc *
  245. i386_fbsd_nat_target::read_description ()
  246. {
  247. #ifdef PT_GETXSTATE_INFO
  248. static int xsave_probed;
  249. static uint64_t xcr0;
  250. #endif
  251. static int xmm_probed;
  252. #ifdef PT_GETXSTATE_INFO
  253. if (!xsave_probed)
  254. {
  255. struct ptrace_xstate_info info;
  256. if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (),
  257. (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0)
  258. {
  259. xsave_len = info.xsave_len;
  260. xcr0 = info.xsave_mask;
  261. }
  262. xsave_probed = 1;
  263. }
  264. if (xsave_len != 0)
  265. return i386_target_description (xcr0, true);
  266. #endif
  267. if (!xmm_probed)
  268. {
  269. char xmmregs[I387_SIZEOF_FXSAVE];
  270. if (ptrace (PT_GETXMMREGS, inferior_ptid.pid (),
  271. (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
  272. have_ptrace_xmmregs = 1;
  273. xmm_probed = 1;
  274. }
  275. if (have_ptrace_xmmregs)
  276. return i386_target_description (X86_XSTATE_SSE_MASK, true);
  277. return i386_target_description (X86_XSTATE_X87_MASK, true);
  278. }
  279. void _initialize_i386fbsd_nat ();
  280. void
  281. _initialize_i386fbsd_nat ()
  282. {
  283. add_inf_child_target (&the_i386_fbsd_nat_target);
  284. /* Support debugging kernel virtual memory images. */
  285. bsd_kvm_add_target (i386fbsd_supply_pcb);
  286. }