xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/i386-obsd-nat.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1699b0f92Schristos /* Native-dependent code for OpenBSD/i386.
2699b0f92Schristos 
3*6881a400Schristos    Copyright (C) 2002-2023 Free Software Foundation, Inc.
4699b0f92Schristos 
5699b0f92Schristos    This file is part of GDB.
6699b0f92Schristos 
7699b0f92Schristos    This program is free software; you can redistribute it and/or modify
8699b0f92Schristos    it under the terms of the GNU General Public License as published by
9699b0f92Schristos    the Free Software Foundation; either version 3 of the License, or
10699b0f92Schristos    (at your option) any later version.
11699b0f92Schristos 
12699b0f92Schristos    This program is distributed in the hope that it will be useful,
13699b0f92Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14699b0f92Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15699b0f92Schristos    GNU General Public License for more details.
16699b0f92Schristos 
17699b0f92Schristos    You should have received a copy of the GNU General Public License
18699b0f92Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19699b0f92Schristos 
20699b0f92Schristos #include "defs.h"
21699b0f92Schristos #include "gdbcore.h"
22699b0f92Schristos #include "regcache.h"
23699b0f92Schristos #include "target.h"
24699b0f92Schristos 
25699b0f92Schristos #include <sys/sysctl.h>
26699b0f92Schristos #include <machine/frame.h>
27699b0f92Schristos #include <machine/pcb.h>
28699b0f92Schristos 
29699b0f92Schristos #include "i386-tdep.h"
30699b0f92Schristos #include "i386-bsd-nat.h"
31699b0f92Schristos #include "obsd-nat.h"
32699b0f92Schristos #include "bsd-kvm.h"
33699b0f92Schristos 
34699b0f92Schristos static int
35699b0f92Schristos i386obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
36699b0f92Schristos {
377f2ac410Schristos   struct gdbarch *gdbarch = regcache->arch ();
38699b0f92Schristos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
39699b0f92Schristos   struct switchframe sf;
40699b0f92Schristos 
41699b0f92Schristos   /* The following is true for OpenBSD 3.6:
42699b0f92Schristos 
43699b0f92Schristos      The pcb contains %esp and %ebp at the point of the context switch
44699b0f92Schristos      in cpu_switch().  At that point we have a stack frame as
45699b0f92Schristos      described by `struct switchframe', which for OpenBSD 3.6 has the
46699b0f92Schristos      following layout:
47699b0f92Schristos 
48699b0f92Schristos      interrupt level
49699b0f92Schristos      %edi
50699b0f92Schristos      %esi
51699b0f92Schristos      %ebx
52699b0f92Schristos      %eip
53699b0f92Schristos 
54699b0f92Schristos      we reconstruct the register state as it would look when we just
55699b0f92Schristos      returned from cpu_switch().  */
56699b0f92Schristos 
57699b0f92Schristos   /* The stack pointer shouldn't be zero.  */
58699b0f92Schristos   if (pcb->pcb_esp == 0)
59699b0f92Schristos     return 0;
60699b0f92Schristos 
61699b0f92Schristos   /* Read the stack frame, and check its validity.  We do this by
62699b0f92Schristos      checking if the saved interrupt priority level in the stack frame
63699b0f92Schristos      looks reasonable..  */
64699b0f92Schristos #ifdef PCB_SAVECTX
65699b0f92Schristos   if ((pcb->pcb_flags & PCB_SAVECTX) == 0)
66699b0f92Schristos     {
67699b0f92Schristos       /* Yes, we have a frame that matches cpu_switch().  */
68699b0f92Schristos       read_memory (pcb->pcb_esp, (gdb_byte *) &sf, sizeof sf);
69699b0f92Schristos       pcb->pcb_esp += sizeof (struct switchframe);
707f2ac410Schristos       regcache->raw_supply (I386_EDI_REGNUM, &sf.sf_edi);
717f2ac410Schristos       regcache->raw_supply (I386_ESI_REGNUM, &sf.sf_esi);
727f2ac410Schristos       regcache->raw_supply (I386_EBX_REGNUM, &sf.sf_ebx);
737f2ac410Schristos       regcache->raw_supply (I386_EIP_REGNUM, &sf.sf_eip);
74699b0f92Schristos     }
75699b0f92Schristos   else
76699b0f92Schristos #endif
77699b0f92Schristos     {
78699b0f92Schristos       /* No, the pcb must have been last updated by savectx().  */
79699b0f92Schristos       pcb->pcb_esp = pcb->pcb_ebp;
80699b0f92Schristos       pcb->pcb_ebp = read_memory_integer(pcb->pcb_esp, 4, byte_order);
81699b0f92Schristos       sf.sf_eip = read_memory_integer(pcb->pcb_esp + 4, 4, byte_order);
827f2ac410Schristos       regcache->raw_supply (I386_EIP_REGNUM, &sf.sf_eip);
83699b0f92Schristos     }
84699b0f92Schristos 
857f2ac410Schristos   regcache->raw_supply (I386_EBP_REGNUM, &pcb->pcb_ebp);
867f2ac410Schristos   regcache->raw_supply (I386_ESP_REGNUM, &pcb->pcb_esp);
87699b0f92Schristos 
88699b0f92Schristos   return 1;
89699b0f92Schristos }
90699b0f92Schristos 
917f2ac410Schristos static i386_bsd_nat_target<obsd_nat_target> the_i386_obsd_nat_target;
92699b0f92Schristos 
937d62b00eSchristos void _initialize_i386obsd_nat ();
94699b0f92Schristos void
957d62b00eSchristos _initialize_i386obsd_nat ()
96699b0f92Schristos {
977f2ac410Schristos   add_inf_child_target (&i386_obsd_nat_target);
98699b0f92Schristos 
99699b0f92Schristos   /* Support debugging kernel virtual memory images.  */
100699b0f92Schristos   bsd_kvm_add_target (i386obsd_supply_pcb);
101699b0f92Schristos 
102699b0f92Schristos   /* OpenBSD provides a vm.psstrings sysctl that we can use to locate
103699b0f92Schristos      the sigtramp.  That way we can still recognize a sigtramp if its
104699b0f92Schristos      location is changed in a new kernel.  This is especially
105699b0f92Schristos      important for OpenBSD, since it uses a different memory layout
106699b0f92Schristos      than NetBSD, yet we cannot distinguish between the two.
107699b0f92Schristos 
108699b0f92Schristos      Of course this is still based on the assumption that the sigtramp
109699b0f92Schristos      is placed directly under the location where the program arguments
110699b0f92Schristos      and environment can be found.  */
111699b0f92Schristos #ifdef VM_PSSTRINGS
112699b0f92Schristos   {
113699b0f92Schristos     struct _ps_strings _ps;
114699b0f92Schristos     int mib[2];
115699b0f92Schristos     size_t len;
116699b0f92Schristos 
117699b0f92Schristos     mib[0] = CTL_VM;
118699b0f92Schristos     mib[1] = VM_PSSTRINGS;
119699b0f92Schristos     len = sizeof (_ps);
120699b0f92Schristos     if (sysctl (mib, 2, &_ps, &len, NULL, 0) == 0)
121699b0f92Schristos       {
122699b0f92Schristos 	i386obsd_sigtramp_start_addr = (u_long) _ps.val - 128;
123699b0f92Schristos 	i386obsd_sigtramp_end_addr = (u_long) _ps.val;
124699b0f92Schristos       }
125699b0f92Schristos   }
126699b0f92Schristos #endif
127699b0f92Schristos }
128