1/* GNU/FreeBSD/amd64 specific low level interface, for the remote server for GDB. 2 Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002 3 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 2 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, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22#include <sys/cdefs.h> 23__FBSDID("$FreeBSD$"); 24 25#include "server.h" 26#include "fbsd-low.h" 27#include "i387-fp.h" 28 29#include <sys/stddef.h> 30#include <sys/types.h> 31#include <sys/ptrace.h> 32#include <machine/reg.h> 33 34/* Mapping between the general-purpose registers in `struct user' 35 format and GDB's register array layout. */ 36static int amd64_regmap[] = { 37 offsetof(struct reg, r_rax), 38 offsetof(struct reg, r_rbx), 39 offsetof(struct reg, r_rcx), 40 offsetof(struct reg, r_rdx), 41 offsetof(struct reg, r_rsi), 42 offsetof(struct reg, r_rdi), 43 offsetof(struct reg, r_rbp), 44 offsetof(struct reg, r_rsp), 45 offsetof(struct reg, r_r8), 46 offsetof(struct reg, r_r9), 47 offsetof(struct reg, r_r10), 48 offsetof(struct reg, r_r11), 49 offsetof(struct reg, r_r12), 50 offsetof(struct reg, r_r13), 51 offsetof(struct reg, r_r14), 52 offsetof(struct reg, r_r15), 53 offsetof(struct reg, r_rip), 54 offsetof(struct reg, r_rflags), /* XXX 64-bit */ 55 offsetof(struct reg, r_cs), 56 offsetof(struct reg, r_ss), 57 offsetof(struct reg, r_ds), 58 offsetof(struct reg, r_es), 59 offsetof(struct reg, r_fs), 60 offsetof(struct reg, r_gs), 61}; 62#define AMD64_NUM_REGS (sizeof(amd64_regmap) / sizeof(amd64_regmap[0])) 63 64static const char amd64_breakpoint[] = { 0xCC }; 65#define AMD64_BP_LEN 1 66 67extern int debug_threads; 68 69static int 70amd64_cannot_store_register(int regno) 71{ 72 73 return (regno >= AMD64_NUM_REGS); 74} 75 76static int 77amd64_cannot_fetch_register(int regno) 78{ 79 80 return (regno >= AMD64_NUM_REGS); 81} 82 83static void 84amd64_fill_gregset(void *buf) 85{ 86 int i; 87 88 for (i = 0; i < AMD64_NUM_REGS; i++) 89 collect_register(i, ((char *)buf) + amd64_regmap[i]); 90} 91 92static void 93amd64_store_gregset(const void *buf) 94{ 95 int i; 96 97 for (i = 0; i < AMD64_NUM_REGS; i++) 98 supply_register(i, ((char *)buf) + amd64_regmap[i]); 99} 100 101static void 102amd64_fill_fpregset(void *buf) 103{ 104 105 i387_cache_to_fsave(buf); 106} 107 108static void 109amd64_store_fpregset(const void *buf) 110{ 111 112 i387_fsave_to_cache(buf); 113} 114 115static void 116amd64_fill_fpxregset(void *buf) 117{ 118 119 i387_cache_to_fxsave(buf); 120} 121 122static void 123amd64_store_fpxregset(const void *buf) 124{ 125 126 i387_fxsave_to_cache(buf); 127} 128 129 130struct regset_info target_regsets[] = { 131 { 132 PT_GETREGS, 133 PT_SETREGS, 134 sizeof(struct reg), 135 GENERAL_REGS, 136 amd64_fill_gregset, 137 amd64_store_gregset, 138 }, 139#ifdef HAVE_PTRACE_GETFPXREGS 140 { 141 PTRACE_GETFPXREGS, 142 PTRACE_SETFPXREGS, 143 sizeof(elf_fpxregset_t), 144 EXTENDED_REGS, 145 amd64_fill_fpxregset, 146 amd64_store_fpxregset, 147 }, 148#endif 149 { 150 PT_GETFPREGS, 151 PT_SETFPREGS, 152 sizeof(struct fpreg), 153 FP_REGS, 154 amd64_fill_fpregset, 155 amd64_store_fpregset, 156 }, 157 { 158 0, 159 0, 160 -1, 161 -1, 162 NULL, 163 NULL, 164 } 165}; 166 167static CORE_ADDR 168amd64_get_pc(void) 169{ 170 unsigned long pc; 171 172 collect_register_by_name("rip", &pc); 173 174 if (debug_threads) 175 fprintf(stderr, "stop pc (before any decrement) is %016lx\n", pc); 176 177 return (pc); 178} 179 180static void 181amd64_set_pc(CORE_ADDR newpc) 182{ 183 184 if (debug_threads) 185 fprintf(stderr, "set pc to %016lx\n", (long)newpc); 186 supply_register_by_name("rip", &newpc); 187} 188 189static int 190amd64_breakpoint_at(CORE_ADDR pc) 191{ 192 unsigned char c; 193 194 read_inferior_memory(pc, &c, 1); 195 if (c == 0xCC) 196 return (1); 197 198 return (0); 199} 200 201struct fbsd_target_ops the_low_target = { 202 AMD64_NUM_REGS, 203 amd64_regmap, 204 amd64_cannot_fetch_register, 205 amd64_cannot_store_register, 206 amd64_get_pc, 207 amd64_set_pc, 208 amd64_breakpoint, 209 AMD64_BP_LEN, 210 NULL, 211 1, 212 amd64_breakpoint_at, 213}; 214