GDB (API)
/home/stan/gdb/src/gdb/amd64fbsd-nat.c
Go to the documentation of this file.
00001 /* Native-dependent code for FreeBSD/amd64.
00002 
00003    Copyright (C) 2003-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 "gdb_assert.h"
00026 #include <signal.h>
00027 #include <stddef.h>
00028 #include <sys/types.h>
00029 #include <sys/ptrace.h>
00030 #include <sys/sysctl.h>
00031 #include <machine/reg.h>
00032 
00033 #include "fbsd-nat.h"
00034 #include "amd64-tdep.h"
00035 #include "amd64-nat.h"
00036 #include "amd64bsd-nat.h"
00037 #include "i386-nat.h"
00038 
00039 
00040 /* Offset in `struct reg' where MEMBER is stored.  */
00041 #define REG_OFFSET(member) offsetof (struct reg, member)
00042 
00043 /* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in
00044    `struct reg' location where the GDB register REGNUM is stored.
00045    Unsupported registers are marked with `-1'.  */
00046 static int amd64fbsd64_r_reg_offset[] =
00047 {
00048   REG_OFFSET (r_rax),
00049   REG_OFFSET (r_rbx),
00050   REG_OFFSET (r_rcx),
00051   REG_OFFSET (r_rdx),
00052   REG_OFFSET (r_rsi),
00053   REG_OFFSET (r_rdi),
00054   REG_OFFSET (r_rbp),
00055   REG_OFFSET (r_rsp),
00056   REG_OFFSET (r_r8),
00057   REG_OFFSET (r_r9),
00058   REG_OFFSET (r_r10),
00059   REG_OFFSET (r_r11),
00060   REG_OFFSET (r_r12),
00061   REG_OFFSET (r_r13),
00062   REG_OFFSET (r_r14),
00063   REG_OFFSET (r_r15),
00064   REG_OFFSET (r_rip),
00065   REG_OFFSET (r_rflags),
00066   REG_OFFSET (r_cs),
00067   REG_OFFSET (r_ss),
00068   -1,
00069   -1,
00070   -1,
00071   -1
00072 };
00073 
00074 
00075 /* Mapping between the general-purpose registers in FreeBSD/amd64
00076    `struct reg' format and GDB's register cache layout for
00077    FreeBSD/i386.
00078 
00079    Note that most FreeBSD/amd64 registers are 64-bit, while the
00080    FreeBSD/i386 registers are all 32-bit, but since we're
00081    little-endian we get away with that.  */
00082 
00083 /* From <machine/reg.h>.  */
00084 static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] =
00085 {
00086   14 * 8, 13 * 8,               /* %eax, %ecx */
00087   12 * 8, 11 * 8,               /* %edx, %ebx */
00088   20 * 8, 10 * 8,               /* %esp, %ebp */
00089   9 * 8, 8 * 8,                 /* %esi, %edi */
00090   17 * 8, 19 * 8,               /* %eip, %eflags */
00091   18 * 8, 21 * 8,               /* %cs, %ss */
00092   -1, -1, -1, -1                /* %ds, %es, %fs, %gs */
00093 };
00094 
00095 
00096 /* Support for debugging kernel virtual memory images.  */
00097 
00098 #include <sys/types.h>
00099 #include <machine/pcb.h>
00100 #include <osreldate.h>
00101 
00102 #include "bsd-kvm.h"
00103 
00104 static int
00105 amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
00106 {
00107   /* The following is true for FreeBSD 5.2:
00108 
00109      The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15,
00110      %ds, %es, %fs and %gs.  This accounts for all callee-saved
00111      registers specified by the psABI and then some.  Here %esp
00112      contains the stack pointer at the point just after the call to
00113      cpu_switch().  From this information we reconstruct the register
00114      state as it would like when we just returned from cpu_switch().  */
00115 
00116   /* The stack pointer shouldn't be zero.  */
00117   if (pcb->pcb_rsp == 0)
00118     return 0;
00119 
00120   pcb->pcb_rsp += 8;
00121   regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip);
00122   regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx);
00123   regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp);
00124   regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp);
00125   regcache_raw_supply (regcache, 12, &pcb->pcb_r12);
00126   regcache_raw_supply (regcache, 13, &pcb->pcb_r13);
00127   regcache_raw_supply (regcache, 14, &pcb->pcb_r14);
00128   regcache_raw_supply (regcache, 15, &pcb->pcb_r15);
00129 #if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075)
00130   /* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only
00131      up until __FreeBSD_version 800074: The removal of these fields
00132      occurred on 2009-04-01 while the __FreeBSD_version number was
00133      bumped to 800075 on 2009-04-06.  So 800075 is the closest version
00134      number where we should not try to access these fields.  */
00135   regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds);
00136   regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es);
00137   regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs);
00138   regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs);
00139 #endif
00140 
00141   return 1;
00142 }
00143 
00144 
00145 static void (*super_mourn_inferior) (struct target_ops *ops);
00146 
00147 static void
00148 amd64fbsd_mourn_inferior (struct target_ops *ops)
00149 {
00150 #ifdef HAVE_PT_GETDBREGS
00151   i386_cleanup_dregs ();
00152 #endif
00153   super_mourn_inferior (ops);
00154 }
00155 
00156 /* Provide a prototype to silence -Wmissing-prototypes.  */
00157 void _initialize_amd64fbsd_nat (void);
00158 
00159 void
00160 _initialize_amd64fbsd_nat (void)
00161 {
00162   struct target_ops *t;
00163   int offset;
00164 
00165   amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
00166   amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset;
00167 
00168   /* Add some extra features to the common *BSD/i386 target.  */
00169   t = amd64bsd_target ();
00170 
00171 #ifdef HAVE_PT_GETDBREGS
00172 
00173   i386_use_watchpoints (t);
00174 
00175   i386_dr_low.set_control = amd64bsd_dr_set_control;
00176   i386_dr_low.set_addr = amd64bsd_dr_set_addr;
00177   i386_dr_low.get_addr = amd64bsd_dr_get_addr;
00178   i386_dr_low.get_status = amd64bsd_dr_get_status;
00179   i386_dr_low.get_control = amd64bsd_dr_get_control;
00180   i386_set_debug_register_length (8);
00181 
00182 #endif /* HAVE_PT_GETDBREGS */
00183 
00184   super_mourn_inferior = t->to_mourn_inferior;
00185   t->to_mourn_inferior = amd64fbsd_mourn_inferior;
00186 
00187   t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
00188   t->to_find_memory_regions = fbsd_find_memory_regions;
00189   t->to_make_corefile_notes = fbsd_make_corefile_notes;
00190   add_target (t);
00191 
00192   /* Support debugging kernel virtual memory images.  */
00193   bsd_kvm_add_target (amd64fbsd_supply_pcb);
00194 
00195   /* To support the recognition of signal handlers, i386bsd-tdep.c
00196      hardcodes some constants.  Inclusion of this file means that we
00197      are compiling a native debugger, which means that we can use the
00198      system header files and sysctl(3) to get at the relevant
00199      information.  */
00200 
00201 #define SC_REG_OFFSET amd64fbsd_sc_reg_offset
00202 
00203   /* We only check the program counter, stack pointer and frame
00204      pointer since these members of `struct sigcontext' are essential
00205      for providing backtraces.  */
00206 
00207 #define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM]
00208 #define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM]
00209 #define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM]
00210 
00211   /* Override the default value for the offset of the program counter
00212      in the sigcontext structure.  */
00213   offset = offsetof (struct sigcontext, sc_rip);
00214 
00215   if (SC_RIP_OFFSET != offset)
00216     {
00217       warning (_("\
00218 offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
00219 Please report this to <bug-gdb@gnu.org>."),
00220                offset, SC_RIP_OFFSET);
00221     }
00222 
00223   SC_RIP_OFFSET = offset;
00224 
00225   /* Likewise for the stack pointer.  */
00226   offset = offsetof (struct sigcontext, sc_rsp);
00227 
00228   if (SC_RSP_OFFSET != offset)
00229     {
00230       warning (_("\
00231 offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
00232 Please report this to <bug-gdb@gnu.org>."),
00233                offset, SC_RSP_OFFSET);
00234     }
00235 
00236   SC_RSP_OFFSET = offset;
00237 
00238   /* And the frame pointer.  */
00239   offset = offsetof (struct sigcontext, sc_rbp);
00240 
00241   if (SC_RBP_OFFSET != offset)
00242     {
00243       warning (_("\
00244 offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
00245 Please report this to <bug-gdb@gnu.org>."),
00246                offset, SC_RBP_OFFSET);
00247     }
00248 
00249   SC_RBP_OFFSET = offset;
00250 
00251   /* FreeBSD provides a kern.ps_strings sysctl that we can use to
00252      locate the sigtramp.  That way we can still recognize a sigtramp
00253      if its location is changed in a new kernel.  Of course this is
00254      still based on the assumption that the sigtramp is placed
00255      directly under the location where the program arguments and
00256      environment can be found.  */
00257   {
00258     int mib[2];
00259     long ps_strings;
00260     size_t len;
00261 
00262     mib[0] = CTL_KERN;
00263     mib[1] = KERN_PS_STRINGS;
00264     len = sizeof (ps_strings);
00265     if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
00266       {
00267         amd64fbsd_sigtramp_start_addr = ps_strings - 32;
00268         amd64fbsd_sigtramp_end_addr = ps_strings;
00269       }
00270   }
00271 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines