1 /* GNU/Linux/i386 specific low level interface, for the remote server for GDB. 2 Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2004 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 "server.h" 23 #include "linux-low.h" 24 #include "i387-fp.h" 25 26 /* Correct for all GNU/Linux targets (for quite some time). */ 27 #define GDB_GREGSET_T elf_gregset_t 28 #define GDB_FPREGSET_T elf_fpregset_t 29 30 #ifndef HAVE_ELF_FPREGSET_T 31 /* Make sure we have said types. Not all platforms bring in <linux/elf.h> 32 via <sys/procfs.h>. */ 33 #ifdef HAVE_LINUX_ELF_H 34 #include <linux/elf.h> 35 #endif 36 #endif 37 38 #include "../gdb_proc_service.h" 39 40 #include <sys/ptrace.h> 41 42 #ifdef HAVE_SYS_REG_H 43 #include <sys/reg.h> 44 #endif 45 46 #ifndef PTRACE_GET_THREAD_AREA 47 #define PTRACE_GET_THREAD_AREA 25 48 #endif 49 50 /* This module only supports access to the general purpose registers. */ 51 52 #define i386_num_regs 16 53 54 /* This stuff comes from i386-linux-nat.c. */ 55 56 /* Mapping between the general-purpose registers in `struct user' 57 format and GDB's register array layout. */ 58 static int i386_regmap[] = 59 { 60 EAX * 4, ECX * 4, EDX * 4, EBX * 4, 61 UESP * 4, EBP * 4, ESI * 4, EDI * 4, 62 EIP * 4, EFL * 4, CS * 4, SS * 4, 63 DS * 4, ES * 4, FS * 4, GS * 4 64 }; 65 66 /* Called by libthread_db. */ 67 68 ps_err_e 69 ps_get_thread_area (const struct ps_prochandle *ph, 70 lwpid_t lwpid, int idx, void **base) 71 { 72 unsigned int desc[4]; 73 74 if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, 75 (void *) idx, (unsigned long) &desc) < 0) 76 return PS_ERR; 77 78 *(int *)base = desc[1]; 79 return PS_OK; 80 } 81 82 static int 83 i386_cannot_store_register (int regno) 84 { 85 return (regno >= i386_num_regs); 86 } 87 88 static int 89 i386_cannot_fetch_register (int regno) 90 { 91 return (regno >= i386_num_regs); 92 } 93 94 95 #ifdef HAVE_LINUX_REGSETS 96 #include <sys/procfs.h> 97 #include <sys/ptrace.h> 98 99 static void 100 i386_fill_gregset (void *buf) 101 { 102 int i; 103 104 for (i = 0; i < i386_num_regs; i++) 105 collect_register (i, ((char *) buf) + i386_regmap[i]); 106 107 collect_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4); 108 } 109 110 static void 111 i386_store_gregset (const void *buf) 112 { 113 int i; 114 115 for (i = 0; i < i386_num_regs; i++) 116 supply_register (i, ((char *) buf) + i386_regmap[i]); 117 118 supply_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4); 119 } 120 121 static void 122 i386_fill_fpregset (void *buf) 123 { 124 i387_cache_to_fsave (buf); 125 } 126 127 static void 128 i386_store_fpregset (const void *buf) 129 { 130 i387_fsave_to_cache (buf); 131 } 132 133 static void 134 i386_fill_fpxregset (void *buf) 135 { 136 i387_cache_to_fxsave (buf); 137 } 138 139 static void 140 i386_store_fpxregset (const void *buf) 141 { 142 i387_fxsave_to_cache (buf); 143 } 144 145 146 struct regset_info target_regsets[] = { 147 { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t), 148 GENERAL_REGS, 149 i386_fill_gregset, i386_store_gregset }, 150 #ifdef HAVE_PTRACE_GETFPXREGS 151 { PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, sizeof (elf_fpxregset_t), 152 EXTENDED_REGS, 153 i386_fill_fpxregset, i386_store_fpxregset }, 154 #endif 155 { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t), 156 FP_REGS, 157 i386_fill_fpregset, i386_store_fpregset }, 158 { 0, 0, -1, -1, NULL, NULL } 159 }; 160 161 #endif /* HAVE_LINUX_REGSETS */ 162 163 static const char i386_breakpoint[] = { 0xCC }; 164 #define i386_breakpoint_len 1 165 166 extern int debug_threads; 167 168 static CORE_ADDR 169 i386_get_pc () 170 { 171 unsigned long pc; 172 173 collect_register_by_name ("eip", &pc); 174 175 if (debug_threads) 176 fprintf (stderr, "stop pc (before any decrement) is %08lx\n", pc); 177 return pc; 178 } 179 180 static void 181 i386_set_pc (CORE_ADDR newpc) 182 { 183 if (debug_threads) 184 fprintf (stderr, "set pc to %08lx\n", (long) newpc); 185 supply_register_by_name ("eip", &newpc); 186 } 187 188 static int 189 i386_breakpoint_at (CORE_ADDR pc) 190 { 191 unsigned char c; 192 193 read_inferior_memory (pc, &c, 1); 194 if (c == 0xCC) 195 return 1; 196 197 return 0; 198 } 199 200 struct linux_target_ops the_low_target = { 201 i386_num_regs, 202 i386_regmap, 203 i386_cannot_fetch_register, 204 i386_cannot_store_register, 205 i386_get_pc, 206 i386_set_pc, 207 i386_breakpoint, 208 i386_breakpoint_len, 209 NULL, 210 1, 211 i386_breakpoint_at, 212 }; 213