/* Native-dependent code for GNU/Linux x86-64.
- Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "inferior.h"
#include "gdbcore.h"
#include "regcache.h"
#include "linux-nat.h"
+#include "amd64-linux-tdep.h"
#include "gdb_assert.h"
#include "gdb_string.h"
#include "gregset.h"
#include "amd64-tdep.h"
-#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
#include "amd64-nat.h"
RIP * 8, EFLAGS * 8, /* %rip, %eflags */
CS * 8, SS * 8, /* %cs, %ss */
DS * 8, ES * 8, /* %ds, %es */
- FS * 8, GS * 8 /* %fs, %gs */
+ FS * 8, GS * 8, /* %fs, %gs */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ ORIG_RAX * 8
};
\f
-1, -1, -1, -1, -1, -1, -1, -1, -1,
ORIG_RAX * 8 /* "orig_eax" */
};
-
-/* Which ptrace request retrieves which registers?
- These apply to the corresponding SET requests as well. */
-
-#define GETFPREGS_SUPPLIES(regno) \
- (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
\f
/* Transfering the general-purpose registers between GDB, inferiors
amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
}
-/* Fetch all general-purpose registers from process/thread TID and
- store their values in GDB's register cache. */
-
-static void
-fetch_regs (int tid)
-{
- elf_gregset_t regs;
-
- if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0)
- perror_with_name ("Couldn't get registers");
-
- supply_gregset (®s);
-}
-
-/* Store all valid general-purpose registers in GDB's register cache
- into the process/thread specified by TID. */
-
-static void
-store_regs (int tid, int regnum)
-{
- elf_gregset_t regs;
-
- if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0)
- perror_with_name ("Couldn't get registers");
-
- fill_gregset (®s, regnum);
-
- if (ptrace (PTRACE_SETREGS, tid, 0, (long) ®s) < 0)
- perror_with_name ("Couldn't write registers");
-}
-\f
-
/* Transfering floating-point registers between GDB, inferiors and cores. */
/* Fill GDB's register cache with the floating-point and SSE register
void
fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
{
- amd64_fill_fxsave ((char *) fpregsetp, regnum);
-}
-
-/* Fetch all floating-point registers from process/thread TID and store
- thier values in GDB's register cache. */
-
-static void
-fetch_fpregs (int tid)
-{
- elf_fpregset_t fpregs;
-
- if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
- perror_with_name ("Couldn't get floating point status");
-
- supply_fpregset (&fpregs);
-}
-
-/* Store all valid floating-point registers in GDB's register cache
- into the process/thread specified by TID. */
-
-static void
-store_fpregs (int tid, int regnum)
-{
- elf_fpregset_t fpregs;
-
- if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
- perror_with_name ("Couldn't get floating point status");
-
- fill_fpregset (&fpregs, regnum);
-
- if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
- perror_with_name ("Couldn't write floating point status");
+ amd64_collect_fxsave (current_regcache, regnum, fpregsetp);
}
\f
this for all registers (including the floating point and SSE
registers). */
-void
-fetch_inferior_registers (int regnum)
+static void
+amd64_linux_fetch_inferior_registers (int regnum)
{
int tid;
if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
{
- fetch_regs (tid);
+ elf_gregset_t regs;
+
+ if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0)
+ perror_with_name (_("Couldn't get registers"));
+
+ amd64_supply_native_gregset (current_regcache, ®s, -1);
if (regnum != -1)
return;
}
- if (regnum == -1 || GETFPREGS_SUPPLIES (regnum))
+ if (regnum == -1 || !amd64_native_gregset_supplies_p (regnum))
{
- fetch_fpregs (tid);
- return;
- }
+ elf_fpregset_t fpregs;
+
+ if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
+ perror_with_name (_("Couldn't get floating point status"));
- internal_error (__FILE__, __LINE__,
- "Got request for bad register number %d.", regnum);
+ amd64_supply_fxsave (current_regcache, -1, &fpregs);
+ }
}
/* Store register REGNUM back into the child process. If REGNUM is
-1, do this for all registers (including the floating-point and SSE
registers). */
-void
-store_inferior_registers (int regnum)
+static void
+amd64_linux_store_inferior_registers (int regnum)
{
int tid;
if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
{
- store_regs (tid, regnum);
+ elf_gregset_t regs;
+
+ if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0)
+ perror_with_name (_("Couldn't get registers"));
+
+ amd64_collect_native_gregset (current_regcache, ®s, regnum);
+
+ if (ptrace (PTRACE_SETREGS, tid, 0, (long) ®s) < 0)
+ perror_with_name (_("Couldn't write registers"));
+
if (regnum != -1)
return;
}
- if (regnum == -1 || GETFPREGS_SUPPLIES (regnum))
+ if (regnum == -1 || !amd64_native_gregset_supplies_p (regnum))
{
- store_fpregs (tid, regnum);
+ elf_fpregset_t fpregs;
+
+ if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
+ perror_with_name (_("Couldn't get floating point status"));
+
+ amd64_collect_fxsave (current_regcache, regnum, &fpregs);
+
+ if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
+ perror_with_name (_("Couldn't write floating point status"));
+
return;
}
-
- internal_error (__FILE__, __LINE__,
- "Got request to store bad register number %d.", regnum);
}
\f
offsetof (struct user, u_debugreg[regnum]), 0);
if (errno != 0)
#if 0
- perror_with_name ("Couldn't read debug register");
+ perror_with_name (_("Couldn't read debug register"));
#else
return 0;
#endif
errno = 0;
ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
if (errno != 0)
- perror_with_name ("Couldn't write debug register");
+ perror_with_name (_("Couldn't write debug register"));
}
void
}
\f
-void
-child_post_startup_inferior (ptid_t ptid)
+static void (*super_post_startup_inferior) (ptid_t ptid);
+
+static void
+amd64_linux_child_post_startup_inferior (ptid_t ptid)
{
i386_cleanup_dregs ();
- linux_child_post_startup_inferior (ptid);
+ super_post_startup_inferior (ptid);
}
\f
void
_initialize_amd64_linux_nat (void)
{
+ struct target_ops *t;
+
amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset;
+ amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
== amd64_native_gregset32_num_regs);
gdb_assert (ARRAY_SIZE (amd64_linux_gregset64_reg_offset)
== amd64_native_gregset64_num_regs);
+
+ /* Fill in the generic GNU/Linux methods. */
+ t = linux_target ();
+
+ /* Override the GNU/Linux inferior startup hook. */
+ super_post_startup_inferior = t->to_post_startup_inferior;
+ t->to_post_startup_inferior = amd64_linux_child_post_startup_inferior;
+
+ /* Add our register access methods. */
+ t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
+ t->to_store_registers = amd64_linux_store_inferior_registers;
+
+ /* Register the target. */
+ linux_nat_add_target (t);
}