1204335Sjkim/* GNU/FreeBSD/amd64 specific low level interface, for the remote server for GDB. 2204335Sjkim Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002 3204335Sjkim Free Software Foundation, Inc. 4204335Sjkim 5204335Sjkim This file is part of GDB. 6204335Sjkim 7204335Sjkim This program is free software; you can redistribute it and/or modify 8204335Sjkim it under the terms of the GNU General Public License as published by 9204335Sjkim the Free Software Foundation; either version 2 of the License, or 10204335Sjkim (at your option) any later version. 11204335Sjkim 12204335Sjkim This program is distributed in the hope that it will be useful, 13204335Sjkim but WITHOUT ANY WARRANTY; without even the implied warranty of 14204335Sjkim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15204335Sjkim GNU General Public License for more details. 16204335Sjkim 17204335Sjkim You should have received a copy of the GNU General Public License 18204335Sjkim along with this program; if not, write to the Free Software 19204335Sjkim Foundation, Inc., 59 Temple Place - Suite 330, 20204335Sjkim Boston, MA 02111-1307, USA. */ 21204335Sjkim 22204335Sjkim#include <sys/cdefs.h> 23204335Sjkim__FBSDID("$FreeBSD$"); 24204335Sjkim 25204335Sjkim#include "server.h" 26204335Sjkim#include "fbsd-low.h" 27204335Sjkim#include "i387-fp.h" 28204335Sjkim 29204335Sjkim#include <sys/stddef.h> 30204335Sjkim#include <sys/types.h> 31204335Sjkim#include <sys/ptrace.h> 32204335Sjkim#include <machine/reg.h> 33204335Sjkim 34204335Sjkim/* Mapping between the general-purpose registers in `struct user' 35204335Sjkim format and GDB's register array layout. */ 36204335Sjkimstatic int amd64_regmap[] = { 37204335Sjkim offsetof(struct reg, r_rax), 38204335Sjkim offsetof(struct reg, r_rbx), 39204335Sjkim offsetof(struct reg, r_rcx), 40204335Sjkim offsetof(struct reg, r_rdx), 41204335Sjkim offsetof(struct reg, r_rsi), 42204335Sjkim offsetof(struct reg, r_rdi), 43204335Sjkim offsetof(struct reg, r_rbp), 44204335Sjkim offsetof(struct reg, r_rsp), 45204335Sjkim offsetof(struct reg, r_r8), 46204335Sjkim offsetof(struct reg, r_r9), 47204335Sjkim offsetof(struct reg, r_r10), 48204335Sjkim offsetof(struct reg, r_r11), 49204335Sjkim offsetof(struct reg, r_r12), 50204335Sjkim offsetof(struct reg, r_r13), 51204335Sjkim offsetof(struct reg, r_r14), 52204335Sjkim offsetof(struct reg, r_r15), 53204335Sjkim offsetof(struct reg, r_rip), 54204335Sjkim offsetof(struct reg, r_rflags), /* XXX 64-bit */ 55204335Sjkim offsetof(struct reg, r_cs), 56204335Sjkim offsetof(struct reg, r_ss), 57204335Sjkim offsetof(struct reg, r_ds), 58204335Sjkim offsetof(struct reg, r_es), 59204335Sjkim offsetof(struct reg, r_fs), 60204335Sjkim offsetof(struct reg, r_gs), 61204335Sjkim}; 62204335Sjkim#define AMD64_NUM_REGS (sizeof(amd64_regmap) / sizeof(amd64_regmap[0])) 63204335Sjkim 64204335Sjkimstatic const char amd64_breakpoint[] = { 0xCC }; 65204335Sjkim#define AMD64_BP_LEN 1 66204335Sjkim 67204335Sjkimextern int debug_threads; 68204335Sjkim 69204335Sjkimstatic int 70204335Sjkimamd64_cannot_store_register(int regno) 71204335Sjkim{ 72204335Sjkim 73204335Sjkim return (regno >= AMD64_NUM_REGS); 74204335Sjkim} 75204335Sjkim 76204335Sjkimstatic int 77204335Sjkimamd64_cannot_fetch_register(int regno) 78204335Sjkim{ 79204335Sjkim 80204335Sjkim return (regno >= AMD64_NUM_REGS); 81204335Sjkim} 82204335Sjkim 83204335Sjkimstatic void 84204335Sjkimamd64_fill_gregset(void *buf) 85204335Sjkim{ 86204335Sjkim int i; 87204335Sjkim 88204335Sjkim for (i = 0; i < AMD64_NUM_REGS; i++) 89204335Sjkim collect_register(i, ((char *)buf) + amd64_regmap[i]); 90204335Sjkim} 91204335Sjkim 92204335Sjkimstatic void 93204335Sjkimamd64_store_gregset(const void *buf) 94204335Sjkim{ 95204335Sjkim int i; 96204335Sjkim 97204335Sjkim for (i = 0; i < AMD64_NUM_REGS; i++) 98204335Sjkim supply_register(i, ((char *)buf) + amd64_regmap[i]); 99204335Sjkim} 100204335Sjkim 101204335Sjkimstatic void 102204335Sjkimamd64_fill_fpregset(void *buf) 103204335Sjkim{ 104204335Sjkim 105204335Sjkim i387_cache_to_fsave(buf); 106204335Sjkim} 107204335Sjkim 108204335Sjkimstatic void 109204335Sjkimamd64_store_fpregset(const void *buf) 110204335Sjkim{ 111204335Sjkim 112204335Sjkim i387_fsave_to_cache(buf); 113204335Sjkim} 114204335Sjkim 115204335Sjkimstatic void 116204335Sjkimamd64_fill_fpxregset(void *buf) 117204335Sjkim{ 118204335Sjkim 119204335Sjkim i387_cache_to_fxsave(buf); 120204335Sjkim} 121204335Sjkim 122204335Sjkimstatic void 123204335Sjkimamd64_store_fpxregset(const void *buf) 124204335Sjkim{ 125204335Sjkim 126204335Sjkim i387_fxsave_to_cache(buf); 127204335Sjkim} 128204335Sjkim 129204335Sjkim 130204335Sjkimstruct regset_info target_regsets[] = { 131204335Sjkim { 132204335Sjkim PT_GETREGS, 133204335Sjkim PT_SETREGS, 134204335Sjkim sizeof(struct reg), 135204335Sjkim GENERAL_REGS, 136204335Sjkim amd64_fill_gregset, 137204335Sjkim amd64_store_gregset, 138204335Sjkim }, 139204335Sjkim#ifdef HAVE_PTRACE_GETFPXREGS 140204335Sjkim { 141204335Sjkim PTRACE_GETFPXREGS, 142204335Sjkim PTRACE_SETFPXREGS, 143204335Sjkim sizeof(elf_fpxregset_t), 144204335Sjkim EXTENDED_REGS, 145204335Sjkim amd64_fill_fpxregset, 146204335Sjkim amd64_store_fpxregset, 147204335Sjkim }, 148204335Sjkim#endif 149204335Sjkim { 150204335Sjkim PT_GETFPREGS, 151204335Sjkim PT_SETFPREGS, 152204335Sjkim sizeof(struct fpreg), 153204335Sjkim FP_REGS, 154204335Sjkim amd64_fill_fpregset, 155204335Sjkim amd64_store_fpregset, 156204335Sjkim }, 157204335Sjkim { 158204335Sjkim 0, 159204335Sjkim 0, 160204335Sjkim -1, 161204335Sjkim -1, 162204335Sjkim NULL, 163204335Sjkim NULL, 164204335Sjkim } 165204335Sjkim}; 166204335Sjkim 167204335Sjkimstatic CORE_ADDR 168204335Sjkimamd64_get_pc(void) 169204335Sjkim{ 170204335Sjkim unsigned long pc; 171204335Sjkim 172204335Sjkim collect_register_by_name("rip", &pc); 173204335Sjkim 174204335Sjkim if (debug_threads) 175204335Sjkim fprintf(stderr, "stop pc (before any decrement) is %016lx\n", pc); 176204335Sjkim 177204335Sjkim return (pc); 178204335Sjkim} 179204335Sjkim 180204335Sjkimstatic void 181204335Sjkimamd64_set_pc(CORE_ADDR newpc) 182204335Sjkim{ 183204335Sjkim 184204335Sjkim if (debug_threads) 185204335Sjkim fprintf(stderr, "set pc to %016lx\n", (long)newpc); 186204335Sjkim supply_register_by_name("rip", &newpc); 187204335Sjkim} 188204335Sjkim 189204335Sjkimstatic int 190204335Sjkimamd64_breakpoint_at(CORE_ADDR pc) 191204335Sjkim{ 192204335Sjkim unsigned char c; 193204335Sjkim 194204335Sjkim read_inferior_memory(pc, &c, 1); 195204335Sjkim if (c == 0xCC) 196204335Sjkim return (1); 197204335Sjkim 198204335Sjkim return (0); 199204335Sjkim} 200204335Sjkim 201204335Sjkimstruct fbsd_target_ops the_low_target = { 202204335Sjkim AMD64_NUM_REGS, 203204335Sjkim amd64_regmap, 204204335Sjkim amd64_cannot_fetch_register, 205204335Sjkim amd64_cannot_store_register, 206204335Sjkim amd64_get_pc, 207204335Sjkim amd64_set_pc, 208204335Sjkim amd64_breakpoint, 209204335Sjkim AMD64_BP_LEN, 210204335Sjkim NULL, 211204335Sjkim 1, 212204335Sjkim amd64_breakpoint_at, 213204335Sjkim}; 214