198944Sobrien/* Native-dependent code for FreeBSD/i386.
298944Sobrien
3130803Smarcel   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4130803Smarcel
598944Sobrien   This file is part of GDB.
698944Sobrien
798944Sobrien   This program is free software; you can redistribute it and/or modify
898944Sobrien   it under the terms of the GNU General Public License as published by
998944Sobrien   the Free Software Foundation; either version 2 of the License, or
1098944Sobrien   (at your option) any later version.
1198944Sobrien
1298944Sobrien   This program is distributed in the hope that it will be useful,
1398944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1498944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598944Sobrien   GNU General Public License for more details.
1698944Sobrien
1798944Sobrien   You should have received a copy of the GNU General Public License
1898944Sobrien   along with this program; if not, write to the Free Software
1998944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2098944Sobrien   Boston, MA 02111-1307, USA.  */
2198944Sobrien
2298944Sobrien#include "defs.h"
2398944Sobrien#include "inferior.h"
2498944Sobrien#include "regcache.h"
2598944Sobrien
2698944Sobrien#include <sys/types.h>
2798944Sobrien#include <sys/ptrace.h>
2898944Sobrien#include <sys/sysctl.h>
2998944Sobrien
30130803Smarcel#include "i386-tdep.h"
31130803Smarcel
3298944Sobrien/* Prevent warning from -Wmissing-prototypes.  */
3398944Sobrienvoid _initialize_i386fbsd_nat (void);
3498944Sobrien
3598944Sobrien/* Resume execution of the inferior process.
3698944Sobrien   If STEP is nonzero, single-step it.
3798944Sobrien   If SIGNAL is nonzero, give it that signal.  */
3898944Sobrien
3998944Sobrienvoid
4098944Sobrienchild_resume (ptid_t ptid, int step, enum target_signal signal)
4198944Sobrien{
4298944Sobrien  pid_t pid = ptid_get_pid (ptid);
4398944Sobrien  int request = PT_STEP;
4498944Sobrien
4598944Sobrien  if (pid == -1)
4698944Sobrien    /* Resume all threads.  This only gets used in the non-threaded
4798944Sobrien       case, where "resume all threads" and "resume inferior_ptid" are
4898944Sobrien       the same.  */
4998944Sobrien    pid = ptid_get_pid (inferior_ptid);
5098944Sobrien
5198944Sobrien  if (!step)
5298944Sobrien    {
53130803Smarcel      ULONGEST eflags;
5498944Sobrien
5598944Sobrien      /* Workaround for a bug in FreeBSD.  Make sure that the trace
5698944Sobrien 	 flag is off when doing a continue.  There is a code path
5798944Sobrien 	 through the kernel which leaves the flag set when it should
5898944Sobrien 	 have been cleared.  If a process has a signal pending (such
5998944Sobrien 	 as SIGALRM) and we do a PT_STEP, the process never really has
6098944Sobrien 	 a chance to run because the kernel needs to notify the
6198944Sobrien 	 debugger that a signal is being sent.  Therefore, the process
6298944Sobrien 	 never goes through the kernel's trap() function which would
6398944Sobrien 	 normally clear it.  */
6498944Sobrien
65130803Smarcel      regcache_cooked_read_unsigned (current_regcache, I386_EFLAGS_REGNUM,
66130803Smarcel				     &eflags);
6798944Sobrien      if (eflags & 0x0100)
68130803Smarcel	regcache_cooked_write_unsigned (current_regcache, I386_EFLAGS_REGNUM,
69130803Smarcel					eflags & ~0x0100);
7098944Sobrien
7198944Sobrien      request = PT_CONTINUE;
7298944Sobrien    }
7398944Sobrien
7498944Sobrien  /* An addres of (caddr_t) 1 tells ptrace to continue from where it
7598944Sobrien     was.  (If GDB wanted it to start some other way, we have already
7698944Sobrien     written a new PC value to the child.)  */
7798944Sobrien  if (ptrace (request, pid, (caddr_t) 1,
7898944Sobrien	      target_signal_to_host (signal)) == -1)
7998944Sobrien    perror_with_name ("ptrace");
8098944Sobrien}
8198944Sobrien
8298944Sobrienvoid
8398944Sobrien_initialize_i386fbsd_nat (void)
8498944Sobrien{
8598944Sobrien  /* FreeBSD provides a kern.ps_strings sysctl that we can use to
8698944Sobrien     locate the sigtramp.  That way we can still recognize a sigtramp
87130803Smarcel     if its location is changed in a new kernel.  Of course this is
8898944Sobrien     still based on the assumption that the sigtramp is placed
8998944Sobrien     directly under the location where the program arguments and
9098944Sobrien     environment can be found.  */
9198944Sobrien#ifdef KERN_PS_STRINGS
9298944Sobrien  {
9398944Sobrien    int mib[2];
94173619Sobrien    u_long ps_strings;
9598944Sobrien    size_t len;
9698944Sobrien
9798944Sobrien    mib[0] = CTL_KERN;
9898944Sobrien    mib[1] = KERN_PS_STRINGS;
9998944Sobrien    len = sizeof (ps_strings);
10098944Sobrien    if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
10198944Sobrien      {
102130803Smarcel	i386fbsd_sigtramp_start_addr = ps_strings - 128;
103130803Smarcel	i386fbsd_sigtramp_end_addr = ps_strings;
10498944Sobrien      }
10598944Sobrien  }
10698944Sobrien#endif
10798944Sobrien}
108