GDB (API)
|
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 }