1 /* Native-dependent code for GNU/Linux x86-64. 2 3 Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. 4 Contributed by Jiri Smid, SuSE Labs. 5 6 This file is part of GDB. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place - Suite 330, 21 Boston, MA 02111-1307, USA. */ 22 23 #include "defs.h" 24 #include "inferior.h" 25 #include "gdbcore.h" 26 #include "regcache.h" 27 #include "linux-nat.h" 28 29 #include "gdb_assert.h" 30 #include "gdb_string.h" 31 #include <sys/ptrace.h> 32 #include <sys/debugreg.h> 33 #include <sys/syscall.h> 34 #include <sys/procfs.h> 35 #include <asm/prctl.h> 36 /* FIXME ezannoni-2003-07-09: we need <sys/reg.h> to be included after 37 <asm/ptrace.h> because the latter redefines FS and GS for no apparent 38 reason, and those definitions don't match the ones that libpthread_db 39 uses, which come from <sys/reg.h>. */ 40 /* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have 41 been removed from ptrace.h in the kernel. However, better safe than 42 sorry. */ 43 #include <asm/ptrace.h> 44 #include <sys/reg.h> 45 #include "gdb_proc_service.h" 46 47 /* Prototypes for supply_gregset etc. */ 48 #include "gregset.h" 49 50 #include "amd64-tdep.h" 51 #include "i386-linux-tdep.h" 52 #include "amd64-nat.h" 53 54 /* Mapping between the general-purpose registers in GNU/Linux x86-64 55 `struct user' format and GDB's register cache layout. */ 56 57 static int amd64_linux_gregset64_reg_offset[] = 58 { 59 RAX * 8, RBX * 8, /* %rax, %rbx */ 60 RCX * 8, RDX * 8, /* %rcx, %rdx */ 61 RSI * 8, RDI * 8, /* %rsi, %rdi */ 62 RBP * 8, RSP * 8, /* %rbp, %rsp */ 63 R8 * 8, R9 * 8, /* %r8 ... */ 64 R10 * 8, R11 * 8, 65 R12 * 8, R13 * 8, 66 R14 * 8, R15 * 8, /* ... %r15 */ 67 RIP * 8, EFLAGS * 8, /* %rip, %eflags */ 68 CS * 8, SS * 8, /* %cs, %ss */ 69 DS * 8, ES * 8, /* %ds, %es */ 70 FS * 8, GS * 8 /* %fs, %gs */ 71 }; 72 73 74 /* Mapping between the general-purpose registers in GNU/Linux x86-64 75 `struct user' format and GDB's register cache layout for GNU/Linux 76 i386. 77 78 Note that most GNU/Linux x86-64 registers are 64-bit, while the 79 GNU/Linux i386 registers are all 32-bit, but since we're 80 little-endian we get away with that. */ 81 82 /* From <sys/reg.h> on GNU/Linux i386. */ 83 static int amd64_linux_gregset32_reg_offset[] = 84 { 85 RAX * 8, RCX * 8, /* %eax, %ecx */ 86 RDX * 8, RBX * 8, /* %edx, %ebx */ 87 RSP * 8, RBP * 8, /* %esp, %ebp */ 88 RSI * 8, RDI * 8, /* %esi, %edi */ 89 RIP * 8, EFLAGS * 8, /* %eip, %eflags */ 90 CS * 8, SS * 8, /* %cs, %ss */ 91 DS * 8, ES * 8, /* %ds, %es */ 92 FS * 8, GS * 8, /* %fs, %gs */ 93 -1, -1, -1, -1, -1, -1, -1, -1, 94 -1, -1, -1, -1, -1, -1, -1, -1, 95 -1, -1, -1, -1, -1, -1, -1, -1, -1, 96 ORIG_RAX * 8 /* "orig_eax" */ 97 }; 98 99 100 /* Transfering the general-purpose registers between GDB, inferiors 101 and core files. */ 102 103 /* Fill GDB's register cache with the general-purpose register values 104 in *GREGSETP. */ 105 106 void 107 supply_gregset (elf_gregset_t *gregsetp) 108 { 109 amd64_supply_native_gregset (current_regcache, gregsetp, -1); 110 } 111 112 /* Fill register REGNUM (if it is a general-purpose register) in 113 *GREGSETP with the value in GDB's register cache. If REGNUM is -1, 114 do this for all registers. */ 115 116 void 117 fill_gregset (elf_gregset_t *gregsetp, int regnum) 118 { 119 amd64_collect_native_gregset (current_regcache, gregsetp, regnum); 120 } 121 122 /* Transfering floating-point registers between GDB, inferiors and cores. */ 123 124 /* Fill GDB's register cache with the floating-point and SSE register 125 values in *FPREGSETP. */ 126 127 void 128 supply_fpregset (elf_fpregset_t *fpregsetp) 129 { 130 amd64_supply_fxsave (current_regcache, -1, fpregsetp); 131 } 132 133 /* Fill register REGNUM (if it is a floating-point or SSE register) in 134 *FPREGSETP with the value in GDB's register cache. If REGNUM is 135 -1, do this for all registers. */ 136 137 void 138 fill_fpregset (elf_fpregset_t *fpregsetp, int regnum) 139 { 140 amd64_collect_fxsave (current_regcache, regnum, fpregsetp); 141 } 142 143 144 /* Transferring arbitrary registers between GDB and inferior. */ 145 146 /* Fetch register REGNUM from the child process. If REGNUM is -1, do 147 this for all registers (including the floating point and SSE 148 registers). */ 149 150 void 151 fetch_inferior_registers (int regnum) 152 { 153 int tid; 154 155 /* GNU/Linux LWP ID's are process ID's. */ 156 tid = TIDGET (inferior_ptid); 157 if (tid == 0) 158 tid = PIDGET (inferior_ptid); /* Not a threaded program. */ 159 160 if (regnum == -1 || amd64_native_gregset_supplies_p (regnum)) 161 { 162 elf_gregset_t regs; 163 164 if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0) 165 perror_with_name ("Couldn't get registers"); 166 167 amd64_supply_native_gregset (current_regcache, ®s, -1); 168 if (regnum != -1) 169 return; 170 } 171 172 if (regnum == -1 || !amd64_native_gregset_supplies_p (regnum)) 173 { 174 elf_fpregset_t fpregs; 175 176 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0) 177 perror_with_name ("Couldn't get floating point status"); 178 179 amd64_supply_fxsave (current_regcache, -1, &fpregs); 180 } 181 } 182 183 /* Store register REGNUM back into the child process. If REGNUM is 184 -1, do this for all registers (including the floating-point and SSE 185 registers). */ 186 187 void 188 store_inferior_registers (int regnum) 189 { 190 int tid; 191 192 /* GNU/Linux LWP ID's are process ID's. */ 193 tid = TIDGET (inferior_ptid); 194 if (tid == 0) 195 tid = PIDGET (inferior_ptid); /* Not a threaded program. */ 196 197 if (regnum == -1 || amd64_native_gregset_supplies_p (regnum)) 198 { 199 elf_gregset_t regs; 200 201 if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0) 202 perror_with_name ("Couldn't get registers"); 203 204 amd64_collect_native_gregset (current_regcache, ®s, regnum); 205 206 if (ptrace (PTRACE_SETREGS, tid, 0, (long) ®s) < 0) 207 perror_with_name ("Couldn't write registers"); 208 209 if (regnum != -1) 210 return; 211 } 212 213 if (regnum == -1 || !amd64_native_gregset_supplies_p (regnum)) 214 { 215 elf_fpregset_t fpregs; 216 217 if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0) 218 perror_with_name ("Couldn't get floating point status"); 219 220 amd64_collect_fxsave (current_regcache, regnum, &fpregs); 221 222 if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0) 223 perror_with_name ("Couldn't write floating point status"); 224 225 return; 226 } 227 } 228 229 230 static unsigned long 231 amd64_linux_dr_get (int regnum) 232 { 233 int tid; 234 unsigned long value; 235 236 /* FIXME: kettenis/2001-01-29: It's not clear what we should do with 237 multi-threaded processes here. For now, pretend there is just 238 one thread. */ 239 tid = PIDGET (inferior_ptid); 240 241 /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the 242 ptrace call fails breaks debugging remote targets. The correct 243 way to fix this is to add the hardware breakpoint and watchpoint 244 stuff to the target vectore. For now, just return zero if the 245 ptrace call fails. */ 246 errno = 0; 247 value = ptrace (PT_READ_U, tid, 248 offsetof (struct user, u_debugreg[regnum]), 0); 249 if (errno != 0) 250 #if 0 251 perror_with_name ("Couldn't read debug register"); 252 #else 253 return 0; 254 #endif 255 256 return value; 257 } 258 259 static void 260 amd64_linux_dr_set (int regnum, unsigned long value) 261 { 262 int tid; 263 264 /* FIXME: kettenis/2001-01-29: It's not clear what we should do with 265 multi-threaded processes here. For now, pretend there is just 266 one thread. */ 267 tid = PIDGET (inferior_ptid); 268 269 errno = 0; 270 ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value); 271 if (errno != 0) 272 perror_with_name ("Couldn't write debug register"); 273 } 274 275 void 276 amd64_linux_dr_set_control (unsigned long control) 277 { 278 amd64_linux_dr_set (DR_CONTROL, control); 279 } 280 281 void 282 amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr) 283 { 284 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); 285 286 amd64_linux_dr_set (DR_FIRSTADDR + regnum, addr); 287 } 288 289 void 290 amd64_linux_dr_reset_addr (int regnum) 291 { 292 gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); 293 294 amd64_linux_dr_set (DR_FIRSTADDR + regnum, 0L); 295 } 296 297 unsigned long 298 amd64_linux_dr_get_status (void) 299 { 300 return amd64_linux_dr_get (DR_STATUS); 301 } 302 303 304 /* This function is called by libthread_db as part of its handling of 305 a request for a thread's local storage address. */ 306 307 ps_err_e 308 ps_get_thread_area (const struct ps_prochandle *ph, 309 lwpid_t lwpid, int idx, void **base) 310 { 311 if (gdbarch_ptr_bit (current_gdbarch) == 32) 312 { 313 /* The full structure is found in <asm-i386/ldt.h>. The second 314 integer is the LDT's base_address and that is used to locate 315 the thread's local storage. See i386-linux-nat.c more 316 info. */ 317 unsigned int desc[4]; 318 319 /* This code assumes that "int" is 32 bits and that 320 GET_THREAD_AREA returns no more than 4 int values. */ 321 gdb_assert (sizeof (int) == 4); 322 #ifndef PTRACE_GET_THREAD_AREA 323 #define PTRACE_GET_THREAD_AREA 25 324 #endif 325 if (ptrace (PTRACE_GET_THREAD_AREA, 326 lwpid, (void *) (long) idx, (unsigned long) &desc) < 0) 327 return PS_ERR; 328 329 /* Extend the value to 64 bits. Here it's assumed that a "long" 330 and a "void *" are the same. */ 331 (*base) = (void *) (long) desc[1]; 332 return PS_OK; 333 } 334 else 335 { 336 /* This definition comes from prctl.h, but some kernels may not 337 have it. */ 338 #ifndef PTRACE_ARCH_PRCTL 339 #define PTRACE_ARCH_PRCTL 30 340 #endif 341 /* FIXME: ezannoni-2003-07-09 see comment above about include 342 file order. We could be getting bogus values for these two. */ 343 gdb_assert (FS < ELF_NGREG); 344 gdb_assert (GS < ELF_NGREG); 345 switch (idx) 346 { 347 case FS: 348 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0) 349 return PS_OK; 350 break; 351 case GS: 352 if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0) 353 return PS_OK; 354 break; 355 default: /* Should not happen. */ 356 return PS_BADADDR; 357 } 358 } 359 return PS_ERR; /* ptrace failed. */ 360 } 361 362 363 void 364 child_post_startup_inferior (ptid_t ptid) 365 { 366 i386_cleanup_dregs (); 367 linux_child_post_startup_inferior (ptid); 368 } 369 370 371 /* Provide a prototype to silence -Wmissing-prototypes. */ 372 void _initialize_amd64_linux_nat (void); 373 374 void 375 _initialize_amd64_linux_nat (void) 376 { 377 amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset; 378 amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS; 379 amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset; 380 381 gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset) 382 == amd64_native_gregset32_num_regs); 383 gdb_assert (ARRAY_SIZE (amd64_linux_gregset64_reg_offset) 384 == amd64_native_gregset64_num_regs); 385 } 386