GDB (API)
/home/stan/gdb/src/gdb/i386fbsd-nat.c
Go to the documentation of this file.
00001 /* Native-dependent code for FreeBSD/i386.
00002 
00003    Copyright (C) 2001-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "inferior.h"
00022 #include "regcache.h"
00023 #include "target.h"
00024 
00025 #include <sys/types.h>
00026 #include <sys/ptrace.h>
00027 #include <sys/sysctl.h>
00028 
00029 #include "fbsd-nat.h"
00030 #include "i386-tdep.h"
00031 #include "i386-nat.h"
00032 #include "i386bsd-nat.h"
00033 
00034 /* Resume execution of the inferior process.  If STEP is nonzero,
00035    single-step it.  If SIGNAL is nonzero, give it that signal.  */
00036 
00037 static void
00038 i386fbsd_resume (struct target_ops *ops,
00039                  ptid_t ptid, int step, enum gdb_signal signal)
00040 {
00041   pid_t pid = ptid_get_pid (ptid);
00042   int request = PT_STEP;
00043 
00044   if (pid == -1)
00045     /* Resume all threads.  This only gets used in the non-threaded
00046        case, where "resume all threads" and "resume inferior_ptid" are
00047        the same.  */
00048     pid = ptid_get_pid (inferior_ptid);
00049 
00050   if (!step)
00051     {
00052       struct regcache *regcache = get_current_regcache ();
00053       ULONGEST eflags;
00054 
00055       /* Workaround for a bug in FreeBSD.  Make sure that the trace
00056          flag is off when doing a continue.  There is a code path
00057          through the kernel which leaves the flag set when it should
00058          have been cleared.  If a process has a signal pending (such
00059          as SIGALRM) and we do a PT_STEP, the process never really has
00060          a chance to run because the kernel needs to notify the
00061          debugger that a signal is being sent.  Therefore, the process
00062          never goes through the kernel's trap() function which would
00063          normally clear it.  */
00064 
00065       regcache_cooked_read_unsigned (regcache, I386_EFLAGS_REGNUM,
00066                                      &eflags);
00067       if (eflags & 0x0100)
00068         regcache_cooked_write_unsigned (regcache, I386_EFLAGS_REGNUM,
00069                                         eflags & ~0x0100);
00070 
00071       request = PT_CONTINUE;
00072     }
00073 
00074   /* An addres of (caddr_t) 1 tells ptrace to continue from where it
00075      was.  (If GDB wanted it to start some other way, we have already
00076      written a new PC value to the child.)  */
00077   if (ptrace (request, pid, (caddr_t) 1,
00078               gdb_signal_to_host (signal)) == -1)
00079     perror_with_name (("ptrace"));
00080 }
00081 
00082 
00083 /* Support for debugging kernel virtual memory images.  */
00084 
00085 #include <sys/types.h>
00086 #include <machine/pcb.h>
00087 
00088 #include "bsd-kvm.h"
00089 
00090 static int
00091 i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
00092 {
00093   /* The following is true for FreeBSD 4.7:
00094 
00095      The pcb contains %eip, %ebx, %esp, %ebp, %esi, %edi and %gs.
00096      This accounts for all callee-saved registers specified by the
00097      psABI and then some.  Here %esp contains the stack pointer at the
00098      point just after the call to cpu_switch().  From this information
00099      we reconstruct the register state as it would look when we just
00100      returned from cpu_switch().  */
00101 
00102   /* The stack pointer shouldn't be zero.  */
00103   if (pcb->pcb_esp == 0)
00104     return 0;
00105 
00106   pcb->pcb_esp += 4;
00107   regcache_raw_supply (regcache, I386_EDI_REGNUM, &pcb->pcb_edi);
00108   regcache_raw_supply (regcache, I386_ESI_REGNUM, &pcb->pcb_esi);
00109   regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp);
00110   regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp);
00111   regcache_raw_supply (regcache, I386_EBX_REGNUM, &pcb->pcb_ebx);
00112   regcache_raw_supply (regcache, I386_EIP_REGNUM, &pcb->pcb_eip);
00113   regcache_raw_supply (regcache, I386_GS_REGNUM, &pcb->pcb_gs);
00114 
00115   return 1;
00116 }
00117 
00118 
00119 /* Prevent warning from -Wmissing-prototypes.  */
00120 void _initialize_i386fbsd_nat (void);
00121 
00122 void
00123 _initialize_i386fbsd_nat (void)
00124 {
00125   struct target_ops *t;
00126 
00127   /* Add some extra features to the common *BSD/i386 target.  */
00128   t = i386bsd_target ();
00129 
00130 #ifdef HAVE_PT_GETDBREGS
00131 
00132   i386_use_watchpoints (t);
00133 
00134   i386_dr_low.set_control = i386bsd_dr_set_control;
00135   i386_dr_low.set_addr = i386bsd_dr_set_addr;
00136   i386_dr_low.get_addr = i386bsd_dr_get_addr;
00137   i386_dr_low.get_status = i386bsd_dr_get_status;
00138   i386_dr_low.get_control = i386bsd_dr_get_control;
00139   i386_set_debug_register_length (4);
00140 
00141 #endif /* HAVE_PT_GETDBREGS */
00142 
00143 
00144   t->to_resume = i386fbsd_resume;
00145   t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
00146   t->to_find_memory_regions = fbsd_find_memory_regions;
00147   t->to_make_corefile_notes = fbsd_make_corefile_notes;
00148   add_target (t);
00149 
00150   /* Support debugging kernel virtual memory images.  */
00151   bsd_kvm_add_target (i386fbsd_supply_pcb);
00152 
00153   /* FreeBSD provides a kern.ps_strings sysctl that we can use to
00154      locate the sigtramp.  That way we can still recognize a sigtramp
00155      if its location is changed in a new kernel.  Of course this is
00156      still based on the assumption that the sigtramp is placed
00157      directly under the location where the program arguments and
00158      environment can be found.  */
00159 #ifdef KERN_PS_STRINGS
00160   {
00161     int mib[2];
00162     u_long ps_strings;
00163     size_t len;
00164 
00165     mib[0] = CTL_KERN;
00166     mib[1] = KERN_PS_STRINGS;
00167     len = sizeof (ps_strings);
00168     if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
00169       {
00170         i386fbsd_sigtramp_start_addr = ps_strings - 128;
00171         i386fbsd_sigtramp_end_addr = ps_strings;
00172       }
00173   }
00174 #endif
00175 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines