1/* Native-dependent code for OpenBSD/i386. 2 3 Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "gdbcore.h" 22#include "regcache.h" 23#include "target.h" 24 25#include <sys/param.h> 26#include <sys/sysctl.h> 27#include <machine/frame.h> 28#include <machine/pcb.h> 29 30#include "i386-tdep.h" 31#include "i386bsd-nat.h" 32#include "bsd-kvm.h" 33 34static int 35i386obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) 36{ 37 struct switchframe sf; 38 39 /* The following is true for OpenBSD 3.6: 40 41 The pcb contains %esp and %ebp at the point of the context switch 42 in cpu_switch(). At that point we have a stack frame as 43 described by `struct switchframe', which for OpenBSD 3.6 has the 44 following layout: 45 46 interrupt level 47 %edi 48 %esi 49 %ebx 50 %eip 51 52 we reconstruct the register state as it would look when we just 53 returned from cpu_switch(). */ 54 55 /* The stack pointer shouldn't be zero. */ 56 if (pcb->pcb_esp == 0) 57 return 0; 58 59 /* Read the stack frame, and check its validity. We do this by 60 checking if the saved interrupt priority level in the stack frame 61 looks reasonable.. */ 62 read_memory (pcb->pcb_esp, (char *) &sf, sizeof sf); 63 if ((unsigned int) sf.sf_ppl < 0x100 && (sf.sf_ppl & 0xf) == 0) 64 { 65 /* Yes, we have a frame that matches cpu_switch(). */ 66 pcb->pcb_esp += sizeof (struct switchframe); 67 regcache_raw_supply (regcache, I386_EDI_REGNUM, &sf.sf_edi); 68 regcache_raw_supply (regcache, I386_ESI_REGNUM, &sf.sf_esi); 69 regcache_raw_supply (regcache, I386_EBX_REGNUM, &sf.sf_ebx); 70 regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip); 71 } 72 else 73 { 74 /* No, the pcb must have been last updated by savectx(). */ 75 pcb->pcb_esp += 4; 76 regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf); 77 } 78 79 regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); 80 regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); 81 82 return 1; 83} 84 85 86/* Prevent warning from -Wmissing-prototypes. */ 87void _initialize_i386obsd_nat (void); 88 89void 90_initialize_i386obsd_nat (void) 91{ 92 /* We've got nothing to add to the common *BSD/i386 target. */ 93 add_target (i386bsd_target ()); 94 95 /* Support debugging kernel virtual memory images. */ 96 bsd_kvm_add_target (i386obsd_supply_pcb); 97 98 /* OpenBSD provides a vm.psstrings sysctl that we can use to locate 99 the sigtramp. That way we can still recognize a sigtramp if its 100 location is changed in a new kernel. This is especially 101 important for OpenBSD, since it uses a different memory layout 102 than NetBSD, yet we cannot distinguish between the two. 103 104 Of course this is still based on the assumption that the sigtramp 105 is placed directly under the location where the program arguments 106 and environment can be found. */ 107#ifdef VM_PSSTRINGS 108 { 109 struct _ps_strings _ps; 110 int mib[2]; 111 size_t len; 112 113 mib[0] = CTL_VM; 114 mib[1] = VM_PSSTRINGS; 115 len = sizeof (_ps); 116 if (sysctl (mib, 2, &_ps, &len, NULL, 0) == 0) 117 { 118 i386obsd_sigtramp_start_addr = (u_long) _ps.val - 128; 119 i386obsd_sigtramp_end_addr = (u_long) _ps.val; 120 } 121 } 122#endif 123} 124