This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[RFA]: x86_64 target files


Hello,

This is the related new files for x86-64 target.

Index: ChangeLog
from  Jiri Smid <smid@suse.cz>

	* configure.host: Recognize x86_64-*-linux*.
	* configure.tgt: Likewise.
	* config/i386/x86_64.mh: New file.
	* config/i386/x86_64.mt: New file.
	* config/i386/nm-x86_64.h: New file.
	* config/i386/tm-x86_64.h: New file.
	* config/i386/xm-x86_64.h: New file.
	* x86_64-linux-tdep.c: New file.
	* x86_64-linux-nat.c: New file.
	* x86_64-nat.c: New file.
	* x86_64-tdep.c: New file.

Index: configure.host
===================================================================
RCS file: /cvs/src/src/gdb/configure.host,v
retrieving revision 1.23
diff -c -3 -p -r1.23 configure.host
*** configure.host	2001/07/10 20:41:54	1.23
--- configure.host	2001/08/02 07:38:37
*************** mips*)			gdb_host_cpu=mips ;;
*** 20,25 ****
--- 20,26 ----
  powerpc*)		gdb_host_cpu=powerpc ;;
  sparc64)		gdb_host_cpu=sparc ;;
  s390*)			gdb_host_cpu=s390 ;;
+ x86_64*)		gdb_host_cpu=i386 ;;
  *)			gdb_host_cpu=$host_cpu ;;
  
  esac
*************** xscale-*-*)		gdb_host=arm ;;
*** 162,166 ****
--- 163,169 ----
  vax-*-bsd*)		gdb_host=vaxbsd ;;
  vax-*-ultrix2*)		gdb_host=vaxult2 ;;
  vax-*-ultrix*)		gdb_host=vaxult ;;
+ 
+ x86_64-*-linux*)	gdb_host=x86_64 ;;
  
  esac
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.34
diff -c -3 -p -r1.34 configure.tgt
*** configure.tgt	2001/07/19 05:10:38	1.34
--- configure.tgt	2001/08/02 07:38:37
*************** s390*)			gdb_target_cpu=s390 ;;
*** 27,32 ****
--- 27,33 ----
  strongarm*)		gdb_target_cpu=arm ;;
  xscale*)		gdb_target_cpu=arm ;;
  v850*)			gdb_target_cpu=v850 ;;
+ x86_64*)		gdb_target_cpu=i386 ;;
  *)			gdb_target_cpu=$target_cpu ;;
  
  esac
*************** v850*-*-*)		gdb_target=v850
*** 312,317 ****
--- 313,321 ----
  			;;
  
  # OBSOLETE w65-*-*)		gdb_target=w65 ;;
+ 
+ x86_64-*-linux*)	gdb_target=x86_64
+  		configdirs="${configdirs} gdbserver" ;;
  
  z8k-*-coff*)		gdb_target=z8k ;;
  
Index: x86_64-linux-nat.c
===================================================================
RCS file: x86_64-linux-nat.c
diff -N x86_64-linux-nat.c
*** /dev/null	Tue May  5 13:32:27 1998
--- x86_64-linux-nat.c	Thu Aug  2 00:38:40 2001
***************
*** 0 ****
--- 1,739 ----
+ /* Native-dependent code for Linux/x86-64.
+    Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    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.  */
+ 
+ #include "defs.h"
+ #include "inferior.h"
+ #include "gdbcore.h"
+ #include "regcache.h"
+ 
+ #include <asm/unistd.h>
+ #include <sys/ptrace.h>
+ #include <sys/user.h>
+ #include <sys/procfs.h>
+ 
+ #ifdef HAVE_SYS_REG_H
+ #include <sys/reg.h>
+ #endif
+ 
+ /* Prototypes for supply_gregset etc.  */
+ #include "gregset.h"
+ 
+ /* Prototypes for i387_supply_fsave etc.  */
+ #include "i387-nat.h"
+ 
+ 
+ /* The register sets used in Linux ELF core-dumps are identical to the
+    register sets in `struct user' that is used for a.out core-dumps,
+    and is also used by `ptrace'.  The corresponding types are
+    `elf_gregset_t' for the general-purpose registers (with
+    `elf_greg_t' the type of a single GP register) and `elf_fpregset_t'
+    for the floating-point registers.
+ 
+    Those types used to be available under the names `gregset_t' and
+    `fpregset_t' too, and this file used those names in the past.  But
+    those names are now used for the register sets used in the
+    `mcontext_t' type, and have a different size and layout.  */
+ 
+ /* Mapping between the general-purpose registers in `struct user'
+    format and GDB's register array layout.  */
+ 
+ static int regmap[] =
+ {
+   RAX, RDX, RCX, RBX,
+   RSI, RDI, RBP, RSP,
+   R8, R9, R10, R11,
+   R12, R13, R14, R15,
+   RIP, EFLAGS
+ };
+ 
+ /* Which ptrace request retrieves which registers?
+    These apply to the corresponding SET requests as well.  */
+ #define GETREGS_SUPPLIES(regno) \
+   (0 <= (regno) && (regno) <= 17)
+ #define GETFPREGS_SUPPLIES(regno) \
+   (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
+ 
+ /* Does the current host support the GETREGS request?  */
+ int have_ptrace_getregs =
+ #ifdef HAVE_PTRACE_GETREGS
+   1
+ #else
+   0
+ #endif
+ ;
+ 
+ 
+ 
+ /* Fetching registers directly from the U area, one at a time.  */
+ 
+ /* FIXME: kettenis/2000-03-05: This duplicates code from `inptrace.c'.
+    The problem is that we define FETCH_INFERIOR_REGISTERS since we
+    want to use our own versions of {fetch,store}_inferior_registers
+    that use the GETREGS request.  This means that the code in
+    `infptrace.c' is #ifdef'd out.  But we need to fall back on that
+    code when GDB is running on top of a kernel that doesn't support
+    the GETREGS request.  I want to avoid changing `infptrace.c' right
+    now.  */
+ 
+ #ifndef PT_READ_U
+ #define PT_READ_U PTRACE_PEEKUSR
+ #endif
+ #ifndef PT_WRITE_U
+ #define PT_WRITE_U PTRACE_POKEUSR
+ #endif
+ 
+ /* Default the type of the ptrace transfer to int.  */
+ #ifndef PTRACE_XFER_TYPE
+ #define PTRACE_XFER_TYPE unsigned long
+ #endif
+ 
+ /* Registers we shouldn't try to fetch.  */
+ #define OLD_CANNOT_FETCH_REGISTER(regno) ((regno) >= NUM_GREGS)
+ 
+ /* Fetch one register.  */
+ 
+ static void
+ fetch_register (int regno)
+ {
+   /* This isn't really an address.  But ptrace thinks of it as one.  */
+   CORE_ADDR regaddr;
+   char mess[128];		/* For messages */
+   register int i;
+   unsigned int offset;		/* Offset of registers within the u area.  */
+   char buf[MAX_REGISTER_RAW_SIZE];
+   int tid;
+ 
+   if (OLD_CANNOT_FETCH_REGISTER (regno))
+     {
+       memset (buf, '\0', REGISTER_RAW_SIZE (regno));	/* Supply zeroes */
+       supply_register (regno, buf);
+       return;
+     }
+ 
+   /* Overload thread id onto process id */
+   if ((tid = TIDGET (inferior_ptid)) == 0)
+     tid = PIDGET (inferior_ptid);		/* no thread id, just use process id */
+ 
+   offset = U_REGS_OFFSET;
+ 
+   regaddr = register_addr (regno, offset);
+   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+     {
+       errno = 0;
+       ptrace (PT_READ_U, tid, (PTRACE_ARG3_TYPE) regaddr, ((PTRACE_XFER_TYPE *) buf) + i );
+       regaddr += sizeof (PTRACE_XFER_TYPE);
+       if (errno != 0)
+ 	{
+ 	  sprintf (mess, "reading register %s (#%d)",
+ 		   REGISTER_NAME (regno), regno);
+ 	  perror_with_name (mess);
+ 	}
+     }
+   supply_register (regno, buf);
+ }
+ 
+ /* Fetch register values from the inferior.
+    If REGNO is negative, do this for all registers.
+    Otherwise, REGNO specifies which register (so we can save time). */
+ 
+ void
+ old_fetch_inferior_registers (int regno)
+ {
+  if (regno >= 0)
+     {
+       fetch_register (regno);
+     }
+   else
+     {
+       for (regno = 0; regno < NUM_REGS; regno++)
+ 	{
+ 	  fetch_register (regno);
+ 	}
+     }
+ }
+ 
+ /* Registers we shouldn't try to store.  */
+ #define OLD_CANNOT_STORE_REGISTER(regno) ((regno) >= NUM_GREGS)
+ 
+ /* Store one register. */
+ 
+ static void
+ store_register (int regno)
+ {
+   /* This isn't really an address.  But ptrace thinks of it as one.  */
+   CORE_ADDR regaddr;
+   char mess[128];		/* For messages */
+   register int i;
+   unsigned int offset;		/* Offset of registers within the u area.  */
+   int tid;
+ 
+   if (OLD_CANNOT_STORE_REGISTER (regno))
+     {
+       return;
+     }
+ 
+   /* Overload thread id onto process id */
+   if ((tid = TIDGET (inferior_ptid)) == 0)
+     tid = PIDGET (inferior_ptid);		/* no thread id, just use process id */
+ 
+   offset = U_REGS_OFFSET;
+ 
+   regaddr = register_addr (regno, offset);
+   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+     {
+       errno = 0;
+       ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+ 	      *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]);
+       regaddr += sizeof (PTRACE_XFER_TYPE);
+       if (errno != 0)
+ 	{
+ 	  sprintf (mess, "writing register %s (#%d)",
+ 		   REGISTER_NAME (regno), regno);
+ 	  perror_with_name (mess);
+ 	}
+     }
+ }
+ 
+ /* Store our register values back into the inferior.
+    If REGNO is negative, do this for all registers.
+    Otherwise, REGNO specifies which register (so we can save time).  */
+ 
+ void
+ old_store_inferior_registers (int regno)
+ {
+   if (regno >= 0)
+     {
+       store_register (regno);
+     }
+   else
+     {
+       for (regno = 0; regno < NUM_REGS; regno++)
+ 	{
+ 	  store_register (regno);
+ 	}
+     }
+ }
+ 
+ 
+ /* Transfering the general-purpose registers between GDB, inferiors
+    and core files.  */
+ 
+ /* Fill GDB's register array with the general-purpose register values
+    in *GREGSETP.  */
+ 
+ void
+ supply_gregset (elf_gregset_t *gregsetp)
+ {
+   elf_greg_t *regp = (elf_greg_t *) gregsetp;
+   int i;
+ 
+   for (i = 0; i < NUM_GREGS; i++)
+     supply_register (i, (char *) (regp + regmap[i]));
+ }
+ 
+ /* Fill register REGNO (if it is a general-purpose register) in
+    *GREGSETPS with the value in GDB's register array.  If REGNO is -1,
+    do this for all registers.  */
+ 
+ void
+ fill_gregset (elf_gregset_t *gregsetp, int regno)
+ {
+   elf_greg_t *regp = (elf_greg_t *) gregsetp;
+   int i;
+ 
+   for (i = 0; i < NUM_GREGS; i++)
+     if ((regno == -1 || regno == i))
+       *(regp + regmap[i]) = *(elf_greg_t *) &registers[REGISTER_BYTE (i)];
+ }
+ 
+ #ifdef HAVE_PTRACE_GETREGS
+ 
+ /* Fetch all general-purpose registers from process/thread TID and
+    store their values in GDB's register array.  */
+ 
+ static void
+ fetch_regs (int tid)
+ {
+   elf_gregset_t regs;
+ 
+   if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
+     {
+       if (errno == EIO)
+ 	{
+ 	  /* The kernel we're running on doesn't support the GETREGS
+ 	     request.  Reset `have_ptrace_getregs'.  */
+ 	  have_ptrace_getregs = 0;
+ 	  return;
+ 	}
+ 
+       perror_with_name ("Couldn't get registers");
+     }
+ 
+   supply_gregset (&regs);
+ }
+ 
+ /* Store all valid general-purpose registers in GDB's register array
+    into the process/thread specified by TID.  */
+ 
+ static void
+ store_regs (int tid, int regno)
+ {
+   elf_gregset_t regs;
+ 
+   if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
+     perror_with_name ("Couldn't get registers");
+ 
+   fill_gregset (&regs, regno);
+ 
+   if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
+     perror_with_name ("Couldn't write registers");
+ }
+ 
+ #else
+ 
+ static void fetch_regs (int tid) {}
+ static void store_regs (int tid, int regno) {}
+ 
+ #endif
+ 
+ 
+ /* Transfering floating-point registers between GDB, inferiors and cores.  */
+ 
+ /* Fill GDB's register array with the floating-point register values in
+    *FPREGSETP.  */
+ 
+ void
+ supply_fpregset (elf_fpregset_t *fpregsetp)
+ {
+   i387_supply_fxsave ((char *) fpregsetp);
+ }
+ 
+ /* Fill register REGNO (if it is a floating-point register) in
+    *FPREGSETP with the value in GDB's register array.  If REGNO is -1,
+    do this for all registers.  */
+ 
+ void
+ fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
+ {
+   i387_fill_fxsave ((char *) fpregsetp, regno);
+ }
+ 
+ #ifdef HAVE_PTRACE_GETREGS
+ 
+ /* Fetch all floating-point registers from process/thread TID and store
+    thier values in GDB's register array.  */
+ 
+ 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 array
+    into the process/thread specified by TID.  */
+ 
+ static void
+ store_fpregs (int tid, int regno)
+ {
+   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, regno);
+ 
+   if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
+     perror_with_name ("Couldn't write floating point status");
+ }
+ 
+ #else
+ 
+ static void fetch_fpregs (int tid) {}
+ static void store_fpregs (int tid, int regno) {}
+ 
+ #endif
+ 
+ 
+ /* Transferring arbitrary registers between GDB and inferior.  */
+ 
+ /* Check if register REGNO in the child process is accessible.
+    If we are accessing registers directly via the U area, only the
+    general-purpose registers are available.
+    All registers should be accessible if we have GETREGS support.  */
+ 
+ int
+ cannot_fetch_register (int regno)
+ {
+   if (! have_ptrace_getregs)
+     return OLD_CANNOT_FETCH_REGISTER (regno);
+   return 0;
+ }
+ int
+ cannot_store_register (int regno)
+ {
+   if (! have_ptrace_getregs)
+     return OLD_CANNOT_STORE_REGISTER (regno);
+   return 0;
+ }
+ 
+ /* Fetch register REGNO from the child process.  If REGNO is -1, do
+    this for all registers (including the floating point and SSE
+    registers).  */
+ 
+ void
+ fetch_inferior_registers (int regno)
+ {
+   int tid;
+ 
+   /* Use the old method of peeking around in `struct user' if the
+      GETREGS request isn't available.  */
+   if (! have_ptrace_getregs)
+     {
+       old_fetch_inferior_registers (regno);
+       return;
+     }
+ 
+   /* Linux LWP ID's are process ID's.  */
+   if ((tid = TIDGET (inferior_ptid)) == 0)
+     tid = PIDGET (inferior_ptid);		/* Not a threaded program.  */
+ 
+   if (regno == -1)
+     {
+       fetch_regs (tid);
+ 
+       /* The call above might reset `have_ptrace_getregs'.  */
+       if (! have_ptrace_getregs)
+ 	{
+ 	  old_fetch_inferior_registers (-1);
+ 	  return;
+ 	}
+ 
+       fetch_fpregs (tid);
+       return;
+     }
+ 
+   if (GETREGS_SUPPLIES (regno))
+     {
+       fetch_regs (tid);
+       return;
+     }
+ 
+   if (GETFPREGS_SUPPLIES (regno))
+     {
+       fetch_fpregs (tid);
+       return;
+     }
+ 
+   internal_error (__FILE__, __LINE__,
+ 		  "Got request for bad register number %d.", regno);
+ }
+ 
+ /* Store register REGNO back into the child process.  If REGNO is -1,
+    do this for all registers (including the floating point and SSE
+    registers).  */
+ void
+ store_inferior_registers (int regno)
+ {
+   int tid;
+ 
+   /* Use the old method of poking around in `struct user' if the
+      SETREGS request isn't available.  */
+   if (! have_ptrace_getregs)
+     {
+       old_store_inferior_registers (regno);
+       return;
+     }
+ 
+   /* Linux LWP ID's are process ID's.  */
+   if ((tid = TIDGET (inferior_ptid)) == 0)
+     tid = PIDGET (inferior_ptid);		/* Not a threaded program.  */
+ 
+   /* Use the PTRACE_SETFPXREGS requests whenever possible, since it
+      transfers more registers in one system call.  But remember that
+      store_fpxregs can fail, and return zero.  */
+   if (regno == -1)
+     {
+       store_regs (tid, regno);
+       store_fpregs (tid, regno);
+       return;
+     }
+ 
+   if (GETREGS_SUPPLIES (regno))
+     {
+       store_regs (tid, regno);
+       return;
+     }
+ 
+   if (GETFPREGS_SUPPLIES (regno))
+     {
+       store_fpregs (tid, regno);
+       return;
+     }
+ 
+   internal_error (__FILE__, __LINE__,
+ 		  "Got request to store bad register number %d.", regno);
+ }
+ 
+ 
+ static const unsigned char linux_syscall[] = { 0x0f, 0x05 };
+ 
+ #define LINUX_SYSCALL_LEN (sizeof linux_syscall)
+ 
+ /* The system call number is stored in the %rax register.  */
+ #define LINUX_SYSCALL_REGNUM 0	/* %rax */
+ 
+ /* We are specifically interested in the sigreturn and rt_sigreturn
+    system calls.  */
+ 
+ #ifndef SYS_sigreturn
+ #define SYS_sigreturn		__NR_sigreturn
+ #endif
+ #ifndef SYS_rt_sigreturn
+ #define SYS_rt_sigreturn	__NR_rt_sigreturn
+ #endif
+ 
+ /* Offset to saved processor flags, from <asm/sigcontext.h>.  */
+ #define LINUX_SIGCONTEXT_EFLAGS_OFFSET (152)
+ /* Offset to saved processor registers from <asm/ucontext.h> */
+ #define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36)
+ 
+ /* Resume execution of the inferior process.
+    If STEP is nonzero, single-step it.
+    If SIGNAL is nonzero, give it that signal.  */
+ 
+ void
+ child_resume (ptid_t ptid, int step, enum target_signal signal)
+ {
+   int pid = PIDGET (ptid);
+   int request = PTRACE_CONT;
+ 
+   if ( pid == -1)
+     /* Resume all threads.  */
+     /* I think this only gets used in the non-threaded case, where "resume
+        all threads" and "resume inferior_ptid" are the same.  */
+     pid = PIDGET (inferior_ptid);
+ 
+   if (step)
+     {
+       CORE_ADDR pc = read_pc_pid (pid_to_ptid (pid));
+       unsigned char buf[LINUX_SYSCALL_LEN];
+ 
+       request = PTRACE_SINGLESTEP;
+ 
+       /* Returning from a signal trampoline is done by calling a
+ 	 special system call (sigreturn or rt_sigreturn, see
+ 	 i386-linux-tdep.c for more information).  This system call
+ 	 restores the registers that were saved when the signal was
+ 	 raised, including %eflags.  That means that single-stepping
+ 	 won't work.  Instead, we'll have to modify the signal context
+ 	 that's about to be restored, and set the trace flag there.  */
+ 
+       /* First check if PC is at a system call.  */
+       if (read_memory_nobpt (pc, (char *) buf, LINUX_SYSCALL_LEN) == 0
+ 	  && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0)
+ 	{
+ 	  int syscall = read_register_pid (LINUX_SYSCALL_REGNUM, pid_to_ptid (pid));
+ 
+ 	  /* Then check the system call number.  */
+ 	  if (syscall == SYS_rt_sigreturn)
+ 	    {
+ 	      CORE_ADDR sp = read_register (SP_REGNUM);
+ 	      CORE_ADDR addr = sp;
+ 	      unsigned long int eflags;
+ 
+ 	      addr += sizeof(struct siginfo) + LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+ 
+ 	      /* Set the trace flag in the context that's about to be
+ 		 restored.  */
+ 	      addr += LINUX_SIGCONTEXT_EFLAGS_OFFSET;
+ 	      read_memory (addr, (char *) &eflags, 8);
+ 	      eflags |= 0x0100;
+ 	      write_memory (addr, (char *) &eflags, 8);
+ 	    }
+ 	}
+     }
+ 
+   if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1)
+     perror_with_name ("ptrace");
+ }
+ 
+ 
+ /* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+    to debugger memory starting at MYADDR.   Copy to inferior if
+    WRITE is nonzero.  TARGET is ignored.
+ 
+    Returns the length copied, which is either the LEN argument or zero.
+    This xfer function does not do partial moves, since child_ops
+    doesn't allow memory operations to cross below us in the target stack
+    anyway.  */
+ 
+ int
+ child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+ 		   struct mem_attrib *attrib ATTRIBUTE_UNUSED,
+ 		   struct target_ops *target)
+ {
+   register int i;
+   /* Round starting address down to longword boundary.  */
+   register CORE_ADDR addr = memaddr & -sizeof (PTRACE_XFER_TYPE);
+   /* Round ending address up; get number of longwords that makes.  */
+   register int count
+   = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+   / sizeof (PTRACE_XFER_TYPE);
+   /* Allocate buffer of that many longwords.  */
+   register PTRACE_XFER_TYPE *buffer
+   = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+ 
+   if (write)
+     {
+       /* Fill start and end extra bytes of buffer with existing memory data.  */
+       if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE))
+ 	{
+ 	  /* Need part of initial word -- fetch it.  */
+ 	  ptrace (PT_READ_I, PIDGET (inferior_ptid),
+ 		  (PTRACE_ARG3_TYPE) addr, buffer);
+ 	}
+ 
+       if (count > 1)		/* FIXME, avoid if even boundary */
+ 	{
+ 	  ptrace (PT_READ_I, PIDGET (inferior_ptid),
+ 		  ((PTRACE_ARG3_TYPE)
+ 		   (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE))),
+ 		  buffer + count - 1);
+ 	}
+ 
+       /* Copy data to be written over corresponding part of buffer */
+ 
+       memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ 	      myaddr,
+ 	      len);
+ 
+       /* Write the entire buffer.  */
+ 
+       for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ 	{
+ 	  errno = 0;
+ 	  ptrace (PT_WRITE_D, PIDGET (inferior_ptid),
+ 		  (PTRACE_ARG3_TYPE) addr, buffer[i]);
+ 	  if (errno)
+ 	    {
+ 	      /* Using the appropriate one (I or D) is necessary for
+ 		 Gould NP1, at least.  */
+ 	      errno = 0;
+ 	      ptrace (PT_WRITE_I, PIDGET (inferior_ptid),
+ 		      (PTRACE_ARG3_TYPE) addr, buffer[i]);
+ 	    }
+ 	  if (errno)
+ 	    return 0;
+ 	}
+ #ifdef CLEAR_INSN_CACHE
+       CLEAR_INSN_CACHE ();
+ #endif
+     }
+   else
+     {
+       /* Read all the longwords */
+       for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+        {
+ 	 errno = 0;
+ 	 ptrace (PT_READ_I, PIDGET (inferior_ptid),
+ 		 (PTRACE_ARG3_TYPE) addr, buffer + i);
+ 	 if (errno)
+ 	   return 0;
+        }
+ 
+       /* Copy appropriate bytes out of the buffer.  */
+       memcpy (myaddr,
+ 	      (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ 	      len);
+     }
+   return len;
+ }
+ 
+ /* Interpreting register set info found in core files.  */
+ 
+ /* Provide registers to GDB from a core file.
+ 
+    CORE_REG_SECT points to an array of bytes, which are the contents
+    of a `note' from a core file which BFD thinks might contain
+    register contents.  CORE_REG_SIZE is its size.
+ 
+    WHICH says which register set corelow suspects this is:
+      0 --- the general-purpose register set, in elf_gregset_t format
+      2 --- the floating-point register set, in elf_fpregset_t format
+ 
+    REG_ADDR isn't used on Linux.  */
+ 
+ static void
+ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
+ 		      int which, CORE_ADDR reg_addr)
+ {
+   elf_gregset_t gregset;
+   elf_fpregset_t fpregset;
+   switch (which)
+     {
+     case 0:
+       if (core_reg_size != sizeof (gregset))
+ 	warning ("Wrong size gregset in core file.");
+       else
+ 	{
+ 	  memcpy (&gregset, core_reg_sect, sizeof (gregset));
+ 	  supply_gregset (&gregset);
+ 	}
+       break;
+ 
+     case 2:
+       if (core_reg_size != sizeof (fpregset))
+ 	warning ("Wrong size fpregset in core file.");
+       else
+ 	{
+ 	  memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
+ 	  supply_fpregset (&fpregset);
+ 	}
+       break;
+ 
+     default:
+       /* We've covered all the kinds of registers we know about here,
+ 	 so this must be something we wouldn't know what to do with
+ 	 anyway.  Just ignore it.  */
+       break;
+     }
+ }
+ 
+ /* Register that we are able to handle Linux ELF core file formats.  */
+ 
+ static struct core_fns linux_elf_core_fns =
+ {
+   bfd_target_elf_flavour,		/* core_flavour */
+   default_check_format,			/* check_format */
+   default_core_sniffer,			/* core_sniffer */
+   fetch_core_registers,			/* core_read_registers */
+   NULL					/* next */
+ };
+ 
+ void
+ _initialize_i386_linux_nat (void)
+ {
+  add_core_fns (&linux_elf_core_fns);
+ }
Index: x86_64-linux-tdep.c
===================================================================
RCS file: x86_64-linux-tdep.c
diff -N x86_64-linux-tdep.c
*** /dev/null	Tue May  5 13:32:27 1998
--- x86_64-linux-tdep.c	Thu Aug  2 00:38:40 2001
***************
*** 0 ****
--- 1,298 ----
+ /* Target-dependent code for Linux running on x86-64, for GDB.
+    Copyright 2000, 2001 Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    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.  */
+ 
+ #include "defs.h"
+ #include "gdbcore.h"
+ #include "frame.h"
+ #include "value.h"
+ #include "regcache.h"
+ 
+ /* For x86_64_linux_skip_solib_resolver.  */
+ #include "symtab.h"
+ #include "symfile.h"
+ #include "objfiles.h"
+ 
+ #include "solib-svr4.h"		/* For struct link_map_offsets.  */
+ 
+ 
+ /* Recognizing signal handler frames.  */
+ 
+ #define STRUCT_OFFSET(struct_type, member)    \
+     ((long) ((char*) &((struct_type*) 0)->member))
+ 
+ #define LINUX_SIGTRAMP_INSN0 (0x48)	/* mov $NNNNNNNN,%rax */
+ #define LINUX_SIGTRAMP_OFFSET0 (0)
+ #define LINUX_SIGTRAMP_INSN1 (0x0f)	/* syscall */
+ #define LINUX_SIGTRAMP_OFFSET1 (7)
+ 
+ static const unsigned char linux_sigtramp_code[] =
+ {
+   LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, /*  mov $0x89,%rax */
+   LINUX_SIGTRAMP_INSN1, 0x05		                /* syscall */
+ };
+ 
+ #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
+ 
+ /* If PC is in a sigtramp routine, return the address of the start of
+    the routine.  Otherwise, return 0.  */
+ 
+ static CORE_ADDR
+ x86_64_linux_sigtramp_start (CORE_ADDR pc)
+ {
+   unsigned char buf[LINUX_SIGTRAMP_LEN];
+ /* We only recognize a signal trampoline if PC is at the start of
+      one of the two instructions.  We optimize for finding the PC at
+      the start, as will be the case when the trampoline is not the
+      first frame on the stack.  We assume that in the case where the
+      PC is not at the start of the instruction sequence, there will be
+      a few trailing readable bytes on the stack.  */
+ 
+   if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+     return 0;
+ 
+   if (buf[0] != LINUX_SIGTRAMP_INSN0)
+     {
+       if (buf[0] != LINUX_SIGTRAMP_INSN1)
+ 	return 0;
+ 
+       pc -= LINUX_SIGTRAMP_OFFSET1;
+ 
+       if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
+ 	return 0;
+     }
+ 
+   if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
+     return 0;
+ 
+   return pc;
+ }
+ 
+ /* Return whether PC is in a Linux sigtramp routine.  */
+ 
+ int
+ x86_64_linux_in_sigtramp (CORE_ADDR pc, char *name)
+ {
+  if (name)
+     return STREQ ("__restore_rt", name);
+ 
+  return x86_64_linux_sigtramp_start (pc);
+ }
+ 
+ /* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>.  */
+ #define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36)
+ 
+ /* Assuming FRAME is for a Linux sigtramp routine, return the address
+    of the associated sigcontext structure.  */
+ 
+ /* FIXME */
+ CORE_ADDR
+ x86_64_linux_sigcontext_addr (struct frame_info *frame)
+ {
+   CORE_ADDR pc;
+ 
+   pc = x86_64_linux_sigtramp_start (frame->pc);
+   if (pc)
+     {
+       if (frame->next)
+ 	/* If this isn't the top frame, the next frame must be for the
+ 	   signal handler itself.  The sigcontext structure is part of
+ 	   the user context. */
+ 	return frame->next->frame + sizeof(struct siginfo) +
+ 	       LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+ 
+ 
+       /* This is the top frame. */
+       return read_register (SP_REGNUM) + sizeof(struct siginfo) +
+ 	     LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
+ 
+     }
+ 
+   error ("Couldn't recognize signal trampoline.");
+   return 0;
+ }
+ 
+ /* Offset to saved PC in sigcontext, from <asm/sigcontext.h>.  */
+ #define LINUX_SIGCONTEXT_PC_OFFSET (136)
+ 
+ /* Assuming FRAME is for a Linux sigtramp routine, return the saved
+    program counter.  */
+ 
+ CORE_ADDR
+ x86_64_linux_sigtramp_saved_pc (struct frame_info *frame)
+ {
+   CORE_ADDR addr;
+ 
+   addr = x86_64_linux_sigcontext_addr (frame);
+   return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 8);
+ }
+ 
+ /* Offset to saved SP in sigcontext, from <asm/sigcontext.h>.  */
+ #define LINUX_SIGCONTEXT_SP_OFFSET (208)
+ 
+ /* Assuming FRAME is for a Linux sigtramp routine, return the saved
+    stack pointer.  */
+ 
+ CORE_ADDR
+ x86_64_linux_sigtramp_saved_sp (struct frame_info *frame)
+ {
+   CORE_ADDR addr;
+ 
+   addr = x86_64_linux_sigcontext_addr (frame);
+   return read_memory_integer (addr + LINUX_SIGCONTEXT_SP_OFFSET, 8);
+ }
+ 
+ /* Immediately after a function call, return the saved pc.  */
+ 
+ CORE_ADDR
+ x86_64_linux_saved_pc_after_call (struct frame_info *frame)
+ {
+  if (frame->signal_handler_caller)
+     return x86_64_linux_sigtramp_saved_pc (frame);
+ 
+   return read_memory_integer (read_register (SP_REGNUM), 8);
+ }
+ 
+ 
+ 
+ /* Calling functions in shared libraries.  */
+ /* Find the minimal symbol named NAME, and return both the minsym
+    struct and its objfile.  This probably ought to be in minsym.c, but
+    everything there is trying to deal with things like C++ and
+    SOFUN_ADDRESS_MAYBE_TURQUOISE, ...  Since this is so simple, it may
+    be considered too special-purpose for general consumption.  */
+ 
+ static struct minimal_symbol *
+ find_minsym_and_objfile (char *name, struct objfile **objfile_p)
+ {
+   struct objfile *objfile;
+ 
+   ALL_OBJFILES (objfile)
+     {
+       struct minimal_symbol *msym;
+ 
+       ALL_OBJFILE_MSYMBOLS (objfile, msym)
+ 	{
+ 	  if (SYMBOL_NAME (msym)
+ 	      && STREQ (SYMBOL_NAME (msym), name))
+ 	    {
+ 	      *objfile_p = objfile;
+ 	      return msym;
+ 	    }
+ 	}
+     }
+ 
+   return 0;
+ }
+ 
+ static CORE_ADDR
+ skip_hurd_resolver (CORE_ADDR pc)
+ {
+ /* The HURD dynamic linker is part of the GNU C library, so many
+      GNU/Linux distributions use it.  (All ELF versions, as far as I
+      know.)  An unresolved PLT entry points to "_dl_runtime_resolve",
+      which calls "fixup" to patch the PLT, and then passes control to
+      the function.
+ 
+      We look for the symbol `_dl_runtime_resolve', and find `fixup' in
+      the same objfile.  If we are at the entry point of `fixup', then
+      we set a breakpoint at the return address (at the top of the
+      stack), and continue.
+ 
+      It's kind of gross to do all these checks every time we're
+      called, since they don't change once the executable has gotten
+      started.  But this is only a temporary hack --- upcoming versions
+      of Linux will provide a portable, efficient interface for
+      debugging programs that use shared libraries.  */
+ 
+   struct objfile *objfile;
+   struct minimal_symbol *resolver
+     = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile);
+ 
+   if (resolver)
+     {
+       struct minimal_symbol *fixup
+ 	= lookup_minimal_symbol ("fixup", 0, objfile);
+ 
+       if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
+ 	return (SAVED_PC_AFTER_CALL (get_current_frame ()));
+     }
+ 
+   return 0;
+ }
+ 
+ /* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c.
+    This function:
+    1) decides whether a PLT has sent us into the linker to resolve
+       a function reference, and
+    2) if so, tells us where to set a temporary breakpoint that will
+       trigger when the dynamic linker is done.  */
+ 
+ CORE_ADDR
+ x86_64_linux_skip_solib_resolver (CORE_ADDR pc)
+ {
+   CORE_ADDR result;
+ 
+   /* Plug in functions for other kinds of resolvers here.  */
+   result = skip_hurd_resolver (pc);
+   if (result)
+     return result;
+ 
+   return 0;
+ }
+ 
+ /* Fetch (and possibly build) an appropriate link_map_offsets
+    structure for native Linux/x86 targets using the struct offsets
+    defined in link.h (but without actual reference to that file).
+ 
+    This makes it possible to access Linux/x86 shared libraries from a
+    GDB that was not built on an Linux/x86 host (for cross debugging).  */
+ 
+ struct link_map_offsets *
+ x86_64_linux_svr4_fetch_link_map_offsets (void)
+ {
+   static struct link_map_offsets lmo;
+   static struct link_map_offsets *lmp = NULL;
+ 
+   if (lmp == NULL)
+     {
+       lmp = &lmo;
+ 
+       lmo.r_debug_size = 12;	/* The actual size is 32 bytes, but
+ 				   this is all we need.  */
+       lmo.r_map_offset = 8;
+       lmo.r_map_size   = 8;
+ 
+       lmo.link_map_size = 40;
+ 
+       lmo.l_addr_offset = 0;
+       lmo.l_addr_size   = 8;
+ 
+       lmo.l_name_offset = 8;
+       lmo.l_name_size   = 8;
+ 
+       lmo.l_next_offset = 24;
+       lmo.l_next_size   = 8;
+ 
+       lmo.l_prev_offset = 32;
+       lmo.l_prev_size   = 8;
+     }
+ 
+   return lmp;
+ }
Index: x86_64-nat.c
===================================================================
RCS file: x86_64-nat.c
diff -N x86_64-nat.c
*** /dev/null	Tue May  5 13:32:27 1998
--- x86_64-nat.c	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,276 ----
+ /* AMD x86_64 native support.
+    Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
+    2000 Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    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.  */
+ 
+ #include "defs.h"
+ 
+ #ifdef HAVE_PTRACE_H
+ #include <ptrace.h>
+ #else
+ #ifdef HAVE_SYS_PTRACE_H
+ #include <sys/ptrace.h>
+ #endif
+ #endif
+ 
+ #include "frame.h"
+ #include "inferior.h"
+ #include "language.h"
+ #include "gdbcore.h"
+ 
+ #ifdef USG
+ #include <sys/types.h>
+ #endif
+ 
+ #include <sys/param.h>
+ #include <sys/dir.h>
+ #include <signal.h>
+ #include <sys/user.h>
+ #include <sys/ioctl.h>
+ #include <fcntl.h>
+ #include <asm/debugreg.h>
+ 
+ #include <sys/file.h>
+ #include "gdb_stat.h"
+ 
+ #ifdef HAVE_SYS_REG_H
+ #include <sys/reg.h>
+ #endif
+ 
+ #include "floatformat.h"
+ 
+ #include "target.h"
+ 
+ 
+ /* This table must line up with REGISTER_NAMES in tm-x86_64.h
+    symbols like 'RAX' come from <sys/reg.h>.  */
+ static int regmap[] = {
+   RAX, RDX, RCX, RBX,
+   RSI, RDI, RBP, RSP,
+   R8, R9, R10, R11,
+   R12, R13, R14, R15,
+   RIP, EFLAGS
+ };
+ 
+ /* blockend is the value of u.u_ar0, and points to the
+    place where GS is stored.  */
+ 
+ CORE_ADDR
+ x86_64_register_u_addr (CORE_ADDR blockend, int regnum)
+ {
+   struct user u;
+   CORE_ADDR fpstate;
+   CORE_ADDR ubase;
+   ubase = blockend;
+   if (IS_FP_REGNUM (regnum))
+     {
+       fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
+       return (fpstate + 16 * (regnum - FP0_REGNUM));
+     }
+   else if (IS_SSE_REGNUM (regnum))
+     {
+       fpstate = ubase + ((char *) &u.i387.xmm_space - (char *) &u);
+       return (fpstate + 16 * (regnum - XMM0_REGNUM));
+     }
+   else
+     return (ubase + 8 * regmap[regnum]);
+ }
+ 
+ 
+ 
+ int
+ kernel_u_size (void)
+ {
+   return (sizeof (struct user));
+ }
+ 
+ #if !defined (offsetof)
+ #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+ #endif
+ 
+ /* Record the value of the debug control register.  */
+ static long debug_control_mirror;
+ 
+ /* Record which address associates with which register.  */
+ static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
+ 
+ static int
+ x86_64_insert_aligned_watchpoint (ptid_t, CORE_ADDR, CORE_ADDR, int, int);
+ 
+ static int
+ x86_64_insert_nonaligned_watchpoint (ptid_t, CORE_ADDR, CORE_ADDR, int, int);
+ 
+ /* Insert a watchpoint.  */
+ 
+ int
+ x86_64_insert_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
+ {
+   return x86_64_insert_aligned_watchpoint (ptid, addr, addr, len, rw);
+ }
+ 
+ static int
+ x86_64_insert_aligned_watchpoint (ptid_t ptid, CORE_ADDR waddr, CORE_ADDR addr,
+ 				  int len, int rw)
+ {
+   int i;
+   int read_write_bits, len_bits;
+   int free_debug_register;
+   int register_number;
+ 
+   /* Look for a free debug register.  */
+   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+     {
+       if (address_lookup[i - DR_FIRSTADDR] == 0)
+ 	break;
+     }
+ 
+   /* No more debug registers!  */
+   if (i > DR_LASTADDR)
+     return -1;
+ 
+   read_write_bits = (rw & 1) ? DR_RW_READ : DR_RW_WRITE;
+ 
+   if (len == 1)
+     len_bits = DR_LEN_1;
+   else if (len == 2)
+     {
+       if (addr % 2)
+ 	return x86_64_insert_nonaligned_watchpoint (ptid, waddr, addr, len,
+ 						    rw);
+       len_bits = DR_LEN_2;
+     }
+   else if (len == 4)
+     {
+       if (addr % 4)
+ 	return x86_64_insert_nonaligned_watchpoint (ptid, waddr, addr, len,
+ 						    rw);
+       len_bits = DR_LEN_4;
+     }
+   else if (len == 8)
+     {
+       if (addr % 8)
+ 	return x86_64_insert_nonaligned_watchpoint (ptid, waddr, addr, len,
+ 						    rw);
+       len_bits = DR_LEN_8;
+     }
+   else
+     return x86_64_insert_nonaligned_watchpoint (ptid, waddr, addr, len, rw);
+ 
+   free_debug_register = i;
+   register_number = free_debug_register - DR_FIRSTADDR;
+   debug_control_mirror |=
+     ((read_write_bits | len_bits)
+      << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
+   debug_control_mirror |=
+     (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+   debug_control_mirror |= DR_LOCAL_SLOWDOWN;
+   debug_control_mirror &= ~DR_CONTROL_RESERVED;
+ 
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_CONTROL]),
+ 	  debug_control_mirror);
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[free_debug_register]),
+ 	  addr);
+ 
+   /* Record where we came from.  */
+   address_lookup[register_number] = addr;
+   return 0;
+ }
+ 
+ static int
+ x86_64_insert_nonaligned_watchpoint (ptid_t ptid, CORE_ADDR waddr, CORE_ADDR addr,
+ 				     int len, int rw)
+ {
+   int align;
+   int size;
+   int rv;
+ 
+   static int size_try_array[8][8] = {
+     {1, 1, 1, 1, 1, 1, 1, 1},	/* trying size one */
+     {2, 1, 2, 1, 2, 1, 2, 1},	/* trying size two */
+     {2, 1, 2, 1, 2, 1, 2, 1},	/* trying size three */
+     {4, 1, 2, 1, 4, 1, 2, 1},	/* trying size four */
+     {4, 1, 2, 1, 4, 1, 2, 1},	/* trying size five */
+     {4, 1, 2, 1, 4, 1, 2, 1},	/* trying size six */
+     {4, 1, 2, 1, 4, 1, 2, 1},	/* trying size seven */
+     {8, 1, 2, 1, 4, 1, 2, 1},	/* trying size eight */
+   };
+ 
+   rv = 0;
+   while (len > 0)
+     {
+       align = addr % 8;
+       /* Eight is the maximum length for x86-64.  */
+       size = size_try_array[len > 8 ? 7 : len - 1][align];
+ 
+       rv = x86_64_insert_aligned_watchpoint (ptid, waddr, addr, size, rw);
+       if (rv)
+ 	{
+ 	  x86_64_remove_watchpoint (ptid, waddr, size);
+ 	  return rv;
+ 	}
+       addr += size;
+       len -= size;
+     }
+   return rv;
+ }
+ 
+ /* Remove a watchpoint.  */
+ 
+ int
+ x86_64_remove_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
+ {
+   int i;
+   int register_number;
+ 
+   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+     {
+       register_number = i - DR_FIRSTADDR;
+       if (address_lookup[register_number] == addr)
+ 	{
+ 	  debug_control_mirror &=
+ 	    ~(1 <<
+ 	      (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+ 	  address_lookup[register_number] = 0;
+ 	}
+     }
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_CONTROL]),
+ 	  debug_control_mirror);
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+ 
+   return 0;
+ }
+ 
+ /* Check if stopped by a watchpoint.  */
+ 
+ CORE_ADDR
+ x86_64_stopped_by_watchpoint (ptid_t ptid)
+ {
+   int i;
+   int status;
+ 
+   status = ptrace (3, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+   ptrace (6, PIDGET (ptid), offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+ 
+   for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+     {
+       if (status & (1 << (i - DR_FIRSTADDR)))
+ 	return address_lookup[i - DR_FIRSTADDR];
+     }
+   return 0;
+ }
Index: x86_64-tdep.c
===================================================================
RCS file: x86_64-tdep.c
diff -N x86_64-tdep.c
*** /dev/null	Tue May  5 13:32:27 1998
--- x86_64-tdep.c	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,763 ----
+ /* AMD x86-64 target-dependent stuff.
+    Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+    1998, 1999, 2000, 2001
+    Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    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.  */
+ 
+ #include "defs.h"
+ #include "gdb_string.h"
+ #include "frame.h"
+ #include "inferior.h"
+ #include "gdbcore.h"
+ #include "target.h"
+ #include "floatformat.h"
+ #include "symtab.h"
+ #include "gdbcmd.h"
+ #include "command.h"
+ #include "arch-utils.h"
+ #include "regcache.h"
+ 
+ /* x86_64_register_byte[i] is the offset into the register file of the
+    start of register number i.  We initialize this from
+    x86_64_register_raw_size.  */
+ int x86_64_register_byte[NUM_REGS];
+ 
+ /* x86_64_register_raw_size[i] is the number of bytes of storage in
+    GDB's register array occupied by register i.  */
+ 
+ int x86_64_register_raw_size[NUM_REGS] = {
+   8, 8, 8, 8,
+   8, 8, 8, 8,
+   8, 8, 8, 8,
+   8, 8, 8, 8,
+   8, 4,
+   10, 10, 10, 10,
+   10, 10, 10, 10,
+   4, 4, 4, 4,
+   4, 4, 4, 4,
+   16, 16, 16, 16,
+   16, 16, 16, 16,
+   16, 16, 16, 16,
+   16, 16, 16, 16,
+   4
+ };
+ 
+ /* x86_64_register_virtual_size[i] is the size in bytes of the virtual
+    type of register i.  */
+ int x86_64_register_virtual_size[NUM_REGS];
+ 
+ 
+ /* This is the variable that is set with "set disassembly-flavor", and
+    its legitimate values.  */
+ static const char att_flavor[] = "att";
+ static const char intel_flavor[] = "intel";
+ static const char *valid_flavors[] = {
+   att_flavor,
+   intel_flavor,
+   NULL
+ };
+ static const char *disassembly_flavor = att_flavor;
+ 
+ /* This is used to keep the bfd arch_info in sync with the disassembly
+    flavor.  */
+ static void set_disassembly_flavor_sfunc (char *, int,
+ 					  struct cmd_list_element *);
+ static void set_disassembly_flavor (void);
+ 
+ 
+ /* Stdio style buffering was used to minimize calls to ptrace, but
+    this buffering did not take into account that the code section
+    being accessed may not be an even number of buffers long (even if
+    the buffer is only sizeof(int) long).  In cases where the code
+    section size happened to be a non-integral number of buffers long,
+    attempting to read the last buffer would fail.  Simply using
+    target_read_memory and ignoring errors, rather than read_memory, is
+    not the correct solution, since legitimate access errors would then
+    be totally ignored.  To properly handle this situation and continue
+    to use buffering would require that this code be able to determine
+    the minimum code section size granularity (not the alignment of the
+    section itself, since the actual failing case that pointed out this
+    problem had a section alignment of 4 but was not a multiple of 4
+    bytes long), on a target by target basis, and then adjust it's
+    buffer size accordingly.  This is messy, but potentially feasible.
+    It probably needs the bfd library's help and support.  For now, the
+    buffer size is set to 1.  (FIXME -fnf) */
+ 
+ #define CODESTREAM_BUFSIZ 1	/* Was sizeof(int), see note above */
+ static CORE_ADDR codestream_next_addr;
+ static CORE_ADDR codestream_addr;
+ static unsigned char codestream_buf[CODESTREAM_BUFSIZ];
+ static int codestream_off;
+ static int codestream_cnt;
+ 
+ #define codestream_tell() (codestream_addr + codestream_off)
+ #define codestream_peek() \
+   (codestream_cnt == 0 ? \
+    codestream_fill(1) : codestream_buf[codestream_off])
+ #define codestream_get() \
+   (codestream_cnt-- == 0 ? \
+    codestream_fill(0) : codestream_buf[codestream_off++])
+ 
+ static unsigned char
+ codestream_fill (int peek_flag)
+ {
+   codestream_addr = codestream_next_addr;
+   codestream_next_addr += CODESTREAM_BUFSIZ;
+   codestream_off = 0;
+   codestream_cnt = CODESTREAM_BUFSIZ;
+   read_memory (codestream_addr, (char *) codestream_buf, CODESTREAM_BUFSIZ);
+ 
+   if (peek_flag)
+     return (codestream_peek ());
+   else
+     return (codestream_get ());
+ }
+ 
+ static void
+ codestream_seek (CORE_ADDR place)
+ {
+   codestream_next_addr = place / CODESTREAM_BUFSIZ;
+   codestream_next_addr *= CODESTREAM_BUFSIZ;
+   codestream_cnt = 0;
+   codestream_fill (1);
+   while (codestream_tell () != place)
+     codestream_get ();
+ }
+ 
+ static void
+ codestream_read (unsigned char *buf, int count)
+ {
+   unsigned char *p;
+   int i;
+ 
+   p = buf;
+   for (i = 0; i < count; i++)
+     *p++ = codestream_get ();
+ }
+ 
+ void
+ x86_64_push_dummy_frame (void)
+ {
+   CORE_ADDR sp = read_register (SP_REGNUM);
+   int regnum;
+   char regbuf[MAX_REGISTER_RAW_SIZE];
+ 
+   for (regnum = 0; regnum < NUM_REGS; regnum++)
+     {
+       read_register_gen (regnum, regbuf);
+       sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum));
+     }
+   write_register (SP_REGNUM, sp);
+ }
+ 
+ /* Insert the function address into the call sequence
+    stored at DUMMY.  */
+ void
+ uw_create_dummy_fde (CORE_ADDR initial_location, CORE_ADDR address_range);
+ 
+ void
+ x86_64_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+ 		       value_ptr * args, struct type *type, int gcc_p)
+ {
+   int i;
+   long to = (long) (fun);
+ 
+   *(dummy + 3) = (to & 0xff);
+   *(dummy + 4) = ((to >> 8) & 0xff);
+   *(dummy + 5) = ((to >> 16) & 0xff);
+   *(dummy + 6) = ((to >> 24) & 0xff);
+   *(dummy + 7) = ((to >> 32) & 0xff);
+   *(dummy + 8) = ((to >> 40) & 0xff);
+   *(dummy + 9) = ((to >> 48) & 0xff);
+   *(dummy + 10) = ((to >> 52) & 0xff);
+ 
+   uw_create_dummy_fde (pc, CALL_DUMMY_LENGTH);
+ }
+ 
+ #ifdef GET_LONGJMP_TARGET
+ 
+ /* Figure out where the longjmp will land.  Slurp the args out of the
+    stack.  We expect the first arg to be a pointer to the jmp_buf
+    structure from which we extract the pc (JB_PC) that we will land
+    at.  The pc is copied into PC.  This routine returns true on
+    success.  */
+ 
+ int
+ get_longjmp_target (CORE_ADDR * pc)
+ {
+   char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+   CORE_ADDR sp, jb_addr;
+ 
+   sp = read_register (SP_REGNUM);
+ 
+   if (target_read_memory (sp + 8,	/* Offset of first arg on stack.  */
+ 			  buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
+     return 0;
+ 
+   jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ 
+   if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
+ 			  TARGET_PTR_BIT / TARGET_CHAR_BIT))
+     return 0;
+ 
+   *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ 
+   return 1;
+ }
+ 
+ #endif /* GET_LONGJMP_TARGET */
+ 
+ /* The returning of values is done according to the special algorithm.
+    Some types are returned in registers an some (big structures) in memory.
+    See ABI for details.
+  */
+ 
+ #define MAX_CLASSES 4
+ 
+ enum x86_64_reg_class
+ {
+   X86_64_NO_CLASS,
+   X86_64_INTEGER_CLASS,
+   X86_64_INTEGERSI_CLASS,
+   X86_64_SSE_CLASS,
+   X86_64_SSESF_CLASS,
+   X86_64_SSEDF_CLASS,
+   X86_64_SSEUP_CLASS,
+   X86_64_X87_CLASS,
+   X86_64_X87UP_CLASS,
+   X86_64_MEMORY_CLASS
+ };
+ 
+ /* Return the union class of CLASS1 and CLASS2.
+    See the x86-64 ABI for details.  */
+ 
+ static enum x86_64_reg_class
+ merge_classes (class1, class2)
+      enum x86_64_reg_class class1, class2;
+ {
+   /* Rule #1: If both classes are equal, this is the resulting class.  */
+   if (class1 == class2)
+     return class1;
+ 
+   /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
+      the other class.  */
+   if (class1 == X86_64_NO_CLASS)
+     return class2;
+   if (class2 == X86_64_NO_CLASS)
+     return class1;
+ 
+   /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
+   if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
+     return X86_64_MEMORY_CLASS;
+ 
+   /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
+   if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
+       || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
+     return X86_64_INTEGERSI_CLASS;
+   if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
+       || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
+     return X86_64_INTEGER_CLASS;
+ 
+   /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used.  */
+   if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
+       || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
+     return X86_64_MEMORY_CLASS;
+ 
+   /* Rule #6: Otherwise class SSE is used.  */
+   return X86_64_SSE_CLASS;
+ }
+ 
+ 
+ /* Classify the argument type.
+    CLASSES will be filled by the register class used to pass each word
+    of the operand.  The number of words is returned.  In case the parameter
+    should be passed in memory, 0 is returned. As a special case for zero
+    sized containers, classes[0] will be NO_CLASS and 1 is returned.
+ 
+    See the x86-64 PS ABI for details.
+ */
+ 
+ static int
+ classify_argument (struct type *type,
+ 		   enum x86_64_reg_class classes[MAX_CLASSES], int bit_offset)
+ {
+   int bytes = TYPE_LENGTH (type);
+   int words = (bytes + 8 - 1) / 8;
+ 
+   switch (TYPE_CODE (type))
+     {
+     case TYPE_CODE_ARRAY:
+     case TYPE_CODE_STRUCT:
+     case TYPE_CODE_UNION:
+       {
+ 	int i;
+ 	enum x86_64_reg_class subclasses[MAX_CLASSES];
+ 
+ 	/* On x86-64 we pass structures larger than 16 bytes on the stack.  */
+ 	if (bytes > 16)
+ 	  return 0;
+ 
+ 	for (i = 0; i < words; i++)
+ 	  classes[i] = X86_64_NO_CLASS;
+ 
+ 	/* Zero sized arrays or structures are NO_CLASS.  We return 0 to
+ 	   signalize memory class, so handle it as special case.  */
+ 	if (!words)
+ 	  {
+ 	    classes[0] = X86_64_NO_CLASS;
+ 	    return 1;
+ 	  }
+ 	switch (TYPE_CODE (type))
+ 	  {
+ 	  case TYPE_CODE_STRUCT:
+ 	    {
+ 	      int j;
+ 	      for (j = 0; j < type->nfields; ++j)
+ 		{
+ 		  int num = classify_argument (type->fields[j].type,
+ 					       subclasses,
+ 					       (type->fields[j].loc.bitpos
+ 						+ bit_offset) % 256);
+ 		  if (!num)
+ 		    return 0;
+ 		  for (i = 0; i < num; i++)
+ 		    {
+ 		      int pos =
+ 			(type->fields[j].loc.bitpos + bit_offset) / 8 / 8;
+ 		      classes[i + pos] =
+ 			merge_classes (subclasses[i], classes[i + pos]);
+ 		    }
+ 		}
+ 	    }
+ 	    break;
+ 	  case TYPE_CODE_ARRAY:
+ 	    {
+ 	      int num;
+ 
+ 	      num = classify_argument (type->target_type,
+ 				       subclasses, bit_offset);
+ 	      if (!num)
+ 		return 0;
+ 
+ 	      /* The partial classes are now full classes.  */
+ 	      if (subclasses[0] == X86_64_SSESF_CLASS && bytes != 4)
+ 		subclasses[0] = X86_64_SSE_CLASS;
+ 	      if (subclasses[0] == X86_64_INTEGERSI_CLASS && bytes != 4)
+ 		subclasses[0] = X86_64_INTEGER_CLASS;
+ 
+ 	      for (i = 0; i < words; i++)
+ 		classes[i] = subclasses[i % num];
+ 	    }
+ 	    break;
+ 	  case TYPE_CODE_UNION:
+ 	    {
+ 	      int j;
+ 	      {
+ 		for (j = 0; j < type->nfields; ++j)
+ 		  {
+ 		    int num;
+ 		    num = classify_argument (type->fields[j].type,
+ 					     subclasses, bit_offset);
+ 		    if (!num)
+ 		      return 0;
+ 		    for (i = 0; i < num; i++)
+ 		      classes[i] = merge_classes (subclasses[i], classes[i]);
+ 		  }
+ 	      }
+ 	    }
+ 	    break;
+ 	  }
+ 	/* Final merger cleanup.  */
+ 	for (i = 0; i < words; i++)
+ 	  {
+ 	    /* If one class is MEMORY, everything should be passed in
+ 	       memory.  */
+ 	    if (classes[i] == X86_64_MEMORY_CLASS)
+ 	      return 0;
+ 
+ 	    /* The X86_64_SSEUP_CLASS should be always preceeded by
+ 	       X86_64_SSE_CLASS.  */
+ 	    if (classes[i] == X86_64_SSEUP_CLASS
+ 		&& (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
+ 	      classes[i] = X86_64_SSE_CLASS;
+ 
+ 	    /*  X86_64_X87UP_CLASS should be preceeded by X86_64_X87_CLASS.  */
+ 	    if (classes[i] == X86_64_X87UP_CLASS
+ 		&& (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
+ 	      classes[i] = X86_64_SSE_CLASS;
+ 	  }
+ 	return words;
+       }
+       break;
+     case TYPE_CODE_FLT:
+       switch (bytes)
+ 	{
+ 	case 4:
+ 	  if (!(bit_offset % 64))
+ 	    classes[0] = X86_64_SSESF_CLASS;
+ 	  else
+ 	    classes[0] = X86_64_SSE_CLASS;
+ 	  return 1;
+ 	case 8:
+ 	  classes[0] = X86_64_SSEDF_CLASS;
+ 	  return 1;
+ 	case 16:
+ 	  classes[0] = X86_64_X87_CLASS;
+ 	  classes[1] = X86_64_X87UP_CLASS;
+ 	  return 2;
+ 	}
+       break;
+     case TYPE_CODE_INT:
+     case TYPE_CODE_PTR:
+       switch (bytes)
+ 	{
+ 	case 1:
+ 	case 2:
+ 	case 4:
+ 	case 8:
+ 	  if (bytes * 8 + bit_offset <= 32)
+ 	    classes[0] = X86_64_INTEGERSI_CLASS;
+ 	  else
+ 	    classes[0] = X86_64_INTEGER_CLASS;
+ 	  return 1;
+ 	case 16:
+ 	  classes[0] = classes[1] = X86_64_INTEGER_CLASS;
+ 	  return 2;
+ 	default:
+ 	  break;
+ 	}
+     }
+   internal_error (__FILE__, __LINE__, "Unknown argument type");
+ }
+ 
+ /* Examine the argument and return set number of register required in each
+    class.  Return 0 ifif parameter should be passed in memory.  */
+ 
+ static int
+ examine_argument (enum x86_64_reg_class classes[MAX_CLASSES],
+ 		  int n, int *int_nregs, int *sse_nregs)
+ {
+   *int_nregs = 0;
+   *sse_nregs = 0;
+   if (!n)
+     return 0;
+   for (n--; n >= 0; n--)
+     switch (classes[n])
+       {
+       case X86_64_INTEGER_CLASS:
+       case X86_64_INTEGERSI_CLASS:
+ 	(*int_nregs)++;
+ 	break;
+       case X86_64_SSE_CLASS:
+       case X86_64_SSESF_CLASS:
+       case X86_64_SSEDF_CLASS:
+ 	(*sse_nregs)++;
+ 	break;
+       case X86_64_NO_CLASS:
+       case X86_64_SSEUP_CLASS:
+       case X86_64_X87_CLASS:
+       case X86_64_X87UP_CLASS:
+ 	break;
+       case X86_64_MEMORY_CLASS:
+ 	internal_error (__FILE__, __LINE__, "Unexpected memory class");
+       }
+   return 1;
+ }
+ 
+ #define RET_INT_REGS 2
+ #define RET_SSE_REGS 2
+ int ret_int_r[RET_INT_REGS] = {
+   RAX_REGNUM, RDX_REGNUM
+ };
+ int ret_sse_r[RET_SSE_REGS] = {
+   XMM0_REGNUM, XMM1_REGNUM
+ };
+ 
+ /* Check if the structure in value_type is returned in registers or in
+    memory. If this function returns 1, gdb will call STORE_STRUCT_RETURN and
+    EXTRACT_STRUCT_VALUE_ADDRESS else STORE_RETURN_VALUE and EXTRACT_RETURN_VALUE
+    will be used.  */
+ int
+ x86_64_use_struct_convention (struct type *value_type)
+ {
+   enum x86_64_reg_class class[MAX_CLASSES];
+   int n = classify_argument (value_type, class, 0);
+   int needed_intregs;
+   int needed_sseregs;
+ 
+   return  (!n ||
+ 	   !examine_argument (class, n, &needed_intregs, &needed_sseregs) ||
+ 	   needed_intregs > RET_INT_REGS || needed_sseregs > RET_SSE_REGS);
+ }
+ 
+ 
+ /* Extract from an array REGBUF containing the (raw) register state, a
+    function return value of TYPE, and copy that, in virtual format,
+    into VALBUF.  */
+ 
+ void
+ x86_64_extract_return_value (struct type *type, char *regbuf, char *valbuf)
+ {
+   enum x86_64_reg_class class[MAX_CLASSES];
+   int n = classify_argument (type, class, 0);
+   int needed_intregs;
+   int needed_sseregs;
+   int intreg = 0;
+   int ssereg = 0;
+   int offset = 0;
+ 
+   printf ("Argument classify n=%d\n", n);
+ 
+   if (!n ||
+       !examine_argument (class, n, &needed_intregs, &needed_sseregs) ||
+       needed_intregs > RET_INT_REGS || needed_sseregs > RET_SSE_REGS)
+     {				/* memory class */
+       CORE_ADDR addr;
+       memcpy (&addr, regbuf, REGISTER_RAW_SIZE (RAX_REGNUM));
+       read_memory (addr, valbuf, TYPE_LENGTH (type));
+       return;
+     }
+   else
+     {
+       int i;
+       for (i = 0; i < n; i++)
+ 	{
+ 	  switch (class[i])
+ 	    {
+ 	    case X86_64_NO_CLASS:
+ 	      printf ("X86_64_NO_CLASS\n");
+ 	      break;
+ 	    case X86_64_INTEGER_CLASS:
+ 	      printf ("X86_64_INTEGER_CLASS %d %d\n",
+ 		      ret_int_r[(intreg + 1) / 2],
+ 		      regbuf + REGISTER_BYTE (ret_int_r[(intreg + 1) / 2]));
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (ret_int_r[(intreg + 1) / 2]),
+ 		      8);
+ 	      offset += 8;
+ 	      intreg += 2;
+ 	      break;
+ 	    case X86_64_INTEGERSI_CLASS:
+ 	      printf ("X86_64_INTEGERSI_CLASS\n");
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (ret_int_r[intreg / 2]), 4);
+ 	      offset += 8;
+ 	      intreg++;
+ 	      break;
+ 	    case X86_64_SSEDF_CLASS:
+ 	    case X86_64_SSESF_CLASS:
+ 	    case X86_64_SSE_CLASS:
+ 	      printf ("X86_64_SSE_CLASS\n");
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (ret_sse_r[(ssereg + 1) / 2]),
+ 		      8);
+ 	      offset += 8;
+ 	      ssereg += 2;
+ 	      break;
+ 	    case X86_64_SSEUP_CLASS:
+ 	      printf ("X86_64_SSEUP_CLASS\n");
+ 	      memcpy (valbuf + offset + 8,
+ 		      regbuf + REGISTER_BYTE (ret_sse_r[ssereg / 2]), 8);
+ 	      offset += 8;
+ 	      ssereg++;
+ 	      break;
+ 	    case X86_64_X87_CLASS:
+ 	      printf ("X86_64_X87_CLASS\n");
+ 	      memcpy (valbuf + offset, regbuf + REGISTER_BYTE (FP0_REGNUM),
+ 		      8);
+ 	      offset += 8;
+ 	      break;
+ 	    case X86_64_X87UP_CLASS:
+ 	      printf ("X86_64_X87UP_CLASS\n");
+ 	      memcpy (valbuf + offset,
+ 		      regbuf + REGISTER_BYTE (FP0_REGNUM) + 8, 8);
+ 	      offset += 8;
+ 	      break;
+ 	    case X86_64_MEMORY_CLASS:
+ 	    default:
+ 	      internal_error (__FILE__, __LINE__,
+ 			      "Unexpected argument class");
+ 	    }
+ 	}
+     }
+ }
+ 
+ /* Write into the appropriate registers a function return value stored
+    in VALBUF of type TYPE, given in virtual format.  */
+ void
+ x86_64_store_return_value (struct type *type, char *valbuf)
+ {
+   int len = TYPE_LENGTH (type);
+ 
+   if (TYPE_CODE_FLT == TYPE_CODE (type))
+     {
+       if (NUM_FREGS == 0)
+ 	{
+ 	  warning ("Cannot set floating-point return value.");
+ 	  return;
+ 	}
+ 
+       /* Floating-point return values can be found in %st(0).  */
+       if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT
+ 	  && TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext)
+ 	{
+ 	  /* Copy straight over.  */
+ 	  write_register_bytes (REGISTER_BYTE (FP0_REGNUM), valbuf,
+ 				FPU_REG_RAW_SIZE);
+ 	}
+       else
+ 	{
+ 	  char buf[FPU_REG_RAW_SIZE];
+ 	  DOUBLEST val;
+ 
+ 	  /* Convert the value found in VALBUF to the extended
+ 	     floating point format used by the FPU.  This is probably
+ 	     not exactly how it would happen on the target itself, but
+ 	     it is the best we can do.  */
+ 	  val = extract_floating (valbuf, TYPE_LENGTH (type));
+ 	  floatformat_from_doublest (&floatformat_i387_ext, &val, buf);
+ 	  write_register_bytes (REGISTER_BYTE (FP0_REGNUM), buf,
+ 				FPU_REG_RAW_SIZE);
+ 	}
+     }
+   else
+     {
+       int low_size = REGISTER_RAW_SIZE (0);
+       int high_size = REGISTER_RAW_SIZE (1);
+ 
+       if (len <= low_size)
+ 	write_register_bytes (REGISTER_BYTE (0), valbuf, len);
+       else if (len <= (low_size + high_size))
+ 	{
+ 	  write_register_bytes (REGISTER_BYTE (0), valbuf, low_size);
+ 	  write_register_bytes (REGISTER_BYTE (1),
+ 				valbuf + low_size, len - low_size);
+ 	}
+       else
+ 	internal_error (__FILE__, __LINE__,
+ 			"Cannot store return value of %d bytes long.", len);
+     }
+ }
+ 
+ /* Convert data from raw format for register REGNUM in buffer FROM to
+    virtual format with type TYPE in buffer TO.  In principle both
+    formats are identical except that the virtual format has two extra
+    bytes appended that aren't used.  We set these to zero.  */
+ void
+ x86_64_register_convert_to_virtual (int regnum, struct type *type,
+ 				    char *from, char *to)
+ {
+ /* Copy straight over, but take care of the padding.  */
+   memcpy (to, from, FPU_REG_RAW_SIZE);
+   memset (to + FPU_REG_RAW_SIZE, 0, TYPE_LENGTH (type) - FPU_REG_RAW_SIZE);
+ }
+ 
+ /* Convert data from virtual format with type TYPE in buffer FROM to
+    raw format for register REGNUM in buffer TO.  Simply omit the two
+    unused bytes.  */
+ 
+ void
+ x86_64_register_convert_to_raw (struct type *type, int regnum,
+ 				char *from, char *to)
+ {
+   memcpy (to, from, FPU_REG_RAW_SIZE);
+ }
+ 
+ 
+ /* We have two flavours of disassembly.  The machinery on this page
+    deals with switching between those.  */
+ 
+ static int
+ gdb_print_insn_x86_64 (bfd_vma memaddr, disassemble_info * info)
+ {
+   if (disassembly_flavor == att_flavor)
+     return print_insn_i386_att (memaddr, info);
+   else if (disassembly_flavor == intel_flavor)
+     return print_insn_i386_intel (memaddr, info);
+   /* Never reached -- disassembly_flavour is always either att_flavor
+      or intel_flavor.  */
+   internal_error (__FILE__, __LINE__, "failed internal consistency check");
+ }
+ 
+ /* If the disassembly mode is intel, we have to also switch the bfd
+    mach_type.  This function is run in the set disassembly_flavor
+    command, and does that.  */
+ 
+ static void
+ set_disassembly_flavor_sfunc (char *args, int from_tty,
+ 			      struct cmd_list_element *c)
+ {
+   set_disassembly_flavor ();
+ }
+ 
+ static void
+ set_disassembly_flavor (void)
+ {
+   if (disassembly_flavor == att_flavor)
+     set_architecture_from_arch_mach (bfd_arch_i386, bfd_mach_x86_64);
+   else if (disassembly_flavor == intel_flavor)
+     set_architecture_from_arch_mach (bfd_arch_i386,
+ 				     bfd_mach_x86_64_intel_syntax);
+ }
+ 
+ 
+ void
+ _initialize_x86_64_tdep (void)
+ {
+ /* Initialize the table saying where each register starts in the
+      register file.  */
+   {
+     int i, offset;
+ 
+     offset = 0;
+     for (i = 0; i < NUM_REGS; i++)
+       {
+ 	x86_64_register_byte[i] = offset;
+ 	offset += x86_64_register_raw_size[i];
+       }
+   }
+ 
+   /* Initialize the table of virtual register sizes.  */
+   {
+     int i;
+ 
+     for (i = 0; i < NUM_REGS; i++)
+       x86_64_register_virtual_size[i] =
+ 	TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (i));
+   }
+ 
+   tm_print_insn = gdb_print_insn_x86_64;
+   tm_print_insn_info.mach = bfd_lookup_arch (bfd_arch_i386, 3)->mach;
+ 
+   /* Add the variable that controls the disassembly flavor.  */
+   {
+     struct cmd_list_element *new_cmd;
+ 
+     new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
+ 				valid_flavors, &disassembly_flavor, "\
+ Set the disassembly flavor, the valid values are \"att\" and \"intel\", \
+ and the default value is \"att\".", &setlist);
+     new_cmd->function.sfunc = set_disassembly_flavor_sfunc;
+     add_show_from_set (new_cmd, &showlist);
+   }
+ 
+   /* Finally, initialize the disassembly flavor to the default given
+      in the disassembly_flavor variable.  */
+   set_disassembly_flavor ();
+ }
Index: config/i386/nm-x86_64.h
===================================================================
RCS file: nm-x86_64.h
diff -N nm-x86_64.h
*** /dev/null	Tue May  5 13:32:27 1998
--- nm-x86_64.h	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,109 ----
+ /* Native support for Linux/x86-64.
+    Copyright 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+    1999, 2000, 2001
+    Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    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.  */
+ 
+ #ifndef NM_X86_64_H
+ #define NM_X86_64_H
+ 
+ #include "nm-linux.h"
+ 
+ 
+ #define REGISTER_U_ADDR(addr, blockend, regno) \
+ 	(addr) = x86_64_register_u_addr ((blockend),(regno));
+ CORE_ADDR x86_64_register_u_addr (CORE_ADDR, int);
+ 
+ /* Return the size of the user struct.  */
+ #define KERNEL_U_SIZE kernel_u_size()
+ extern int kernel_u_size (void);
+ 
+ /* Offset of the registers within the user area.  */
+ #define U_REGS_OFFSET 0
+ 
+ /* This is the amount to subtract from u.u_ar0
+    to get the offset in the core file of the register values.  */
+ #define KERNEL_U_ADDR 0x0
+ 
+ /* FIXME use special child_xfer_memory.  */
+ #define CHILD_XFER_MEMORY
+ 
+ #define PTRACE_ARG3_TYPE void*
+ 
+ /* GNU/Linux supports the x86_64 hardware debugging registers.  */
+ 
+ #define TARGET_HAS_HARDWARE_WATCHPOINTS
+ 
+ #define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
+ 
+ /* After a watchpoint trap, the PC points to the instruction after
+    the one that caused the trap.  Therefore we don't need to step over it.
+    But we do need to reset the status register to avoid another trap.  */
+ #define HAVE_CONTINUABLE_WATCHPOINT
+ 
+ #define STOPPED_BY_WATCHPOINT(W)  \
+   x86_64_stopped_by_watchpoint (inferior_ptid)
+ CORE_ADDR x86_64_stopped_by_watchpoint (ptid_t);
+ 
+ /* Use these macros for watchpoint insertion/removal.  */
+ 
+ #define target_insert_watchpoint(addr, len, type)  \
+   x86_64_insert_watchpoint (inferior_ptid, addr, len, type)
+ int x86_64_insert_watchpoint (ptid_t pid, CORE_ADDR addr, int len, int rw);
+ 
+ #define target_remove_watchpoint(addr, len, type)  \
+   x86_64_remove_watchpoint (inferior_ptid, addr, len)
+ int x86_64_remove_watchpoint (ptid_t pid, CORE_ADDR addr, int len);
+ 
+ /* We define this if link.h is available, because with ELF we use SVR4 style
+    shared libraries. */
+ 
+ #ifdef HAVE_LINK_H
+ #define SVR4_SHARED_LIBS
+ #include "solib.h"		/* Support for shared libraries. */
+ #endif
+ 
+ /* Override copies of {fetch,store}_inferior_registers in `infptrace.c'.  */
+ #define FETCH_INFERIOR_REGISTERS
+ 
+ /* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we might fall
+    back on the code `infptrace.c' (well a copy of that code in
+    `i386-linux-nat.c' for now) and we can access only the
+    general-purpose registers in that way.  */
+ extern int cannot_fetch_register (int regno);
+ extern int cannot_store_register (int regno);
+ #define CANNOT_FETCH_REGISTER(regno) cannot_store_register (regno)
+ #define CANNOT_STORE_REGISTER(regno) cannot_fetch_register (regno)
+ 
+ /* Override child_resume in `infptrace.c'.  */
+ #define CHILD_RESUME
+ 
+ extern int lin_lwp_prepare_to_proceed (void);
+ #undef PREPARE_TO_PROCEED
+ #define PREPARE_TO_PROCEED(select_it) lin_lwp_prepare_to_proceed ()
+ 
+ extern void lin_lwp_attach_lwp (ptid_t pid, int verbose);
+ #define ATTACH_LWP(pid, verbose) lin_lwp_attach_lwp ((pid), (verbose))
+ 
+ #include <signal.h>
+ 
+ extern void lin_thread_get_thread_signals (sigset_t * mask);
+ #define GET_THREAD_SIGNALS(mask) lin_thread_get_thread_signals (mask)
+ 
+ #endif /* NM_X86_64.h */
Index: config/i386/tm-x86_64.h
===================================================================
RCS file: tm-x86_64.h
diff -N tm-x86_64.h
*** /dev/null	Tue May  5 13:32:27 1998
--- tm-x86_64.h	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,462 ----
+ /* Definitions to target GDB to GNU/Linux on x86-64.
+    Copyright 1992, 1993, 1995, 1996, 1998, 1999, 2000, 2001
+    Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    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.  */
+ 
+ #ifndef TM_X86_64_H
+ #define TM_X86_64_H
+ 
+ #define X86_64_GNULINUX_TARGET
+ #define ARCH_64BIT
+ #define TARGET_LONG_BIT 64
+ #define TARGET_LONG_LONG_BIT 64
+ #define TARGET_PTR_BIT 64
+ #define DWARF2_USE_CFI
+ 
+ #include "tm-linux.h"
+ #include "regcache.h"
+ 
+ /* Forward declarations for prototypes.  */
+ struct frame_info;
+ struct frame_saved_regs;
+ struct value;
+ struct type;
+ 
+ #define TARGET_BYTE_ORDER LITTLE_ENDIAN
+ 
+ /* The format used for `long double' is the i387 extended floating-point
+    format.  */
+ #define TARGET_LONG_DOUBLE_FORMAT &floatformat_i387_ext
+ 
+ /* Although the x86-64 extended floating-point has only 80 significant
+    bits, a `long double' actually takes up 128, to enforce
+    alignment.  */
+ 
+ #define TARGET_LONG_DOUBLE_BIT 128
+ 
+ /* Used for example in valprint.c:print_floating() to enable checking
+    for NaN's.  */
+ 
+ #define IEEE_FLOAT (1)
+ 
+ /* Number of traps that happen between exec'ing the shell to run an
+    inferior, and when we finally get to the inferior code.  This is 2
+    on most implementations.  */
+ 
+ #define START_INFERIOR_TRAPS_EXPECTED 2
+ 
+ /* Offset from address of function to start of its code.
+    Zero on most machines.  */
+ 
+ #define FUNCTION_START_OFFSET 0
+ 
+ /* On x86_64 there are no reasonable prologs.  */
+ 
+ #define SKIP_PROLOGUE(frompc)   (frompc)
+ 
+ /* Immediately after a function call, return the saved pc.  */
+ 
+ #define SAVED_PC_AFTER_CALL(frame) x86_64_linux_saved_pc_after_call (frame)
+ extern CORE_ADDR x86_64_linux_saved_pc_after_call (struct frame_info *);
+ 
+ /* Stack grows downward.  */
+ 
+ #define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+ 
+ /* Sequence of bytes for breakpoint instruction.  */
+ 
+ #define BREAKPOINT {0xcc}
+ 
+ /* Amount PC must be decremented by after a breakpoint.  This is often the
+    number of bytes in BREAKPOINT but not always.  */
+ 
+ #define DECR_PC_AFTER_BREAK 1
+ 
+ /* Say how long (ordinary) registers are.  This is a piece of bogosity
+    used in push_word and a few other places; REGISTER_RAW_SIZE is the
+    real way to know how big a register is.  */
+ 
+ #define REGISTER_SIZE 8
+ 
+ /* Number of general registers.  */
+ #define NUM_GREGS (18)
+ 
+ /* Number of floating-point unit registers.  */
+ #define NUM_FREGS (16)
+ 
+ /* Number of SSE registers.
+    There are 16 xmm registers and 1 Control and Status Register (mxcsr).  */
+ #define NUM_SSE_REGS (17)
+ 
+ /* Number of all registers.  */
+ #define NUM_REGS (NUM_GREGS + NUM_FREGS + NUM_SSE_REGS)
+ 
+ /* Initializer for an array of names of registers.  There should be at least
+    NUM_REGS strings in this initializer.  Any excess ones are simply ignored.  */
+ 
+ #define REGISTER_NAMES { "rax",   "rdx",    "rcx",   "rbx",	\
+ 			 "rsi",   "rdi",    "rbp",   "rsp",	\
+ 			 "r8",    "r9",     "r10",   "r11",	\
+ 			 "r12",   "r13",    "r14",   "r15",	\
+ 			 "rip",   "eflags",                     \
+ 			 "st0",   "st1",    "st2",   "st3",	\
+ 			 "st4",   "st5",    "st6",   "st7",	\
+ 			 "fctrl", "fstat",  "ftag",  "fiseg",	\
+ 			 "fioff", "foseg",  "fooff", "fop",	\
+ 			 "xmm0",  "xmm1",   "xmm2",  "xmm3",	\
+ 			 "xmm4",  "xmm5",   "xmm6",  "xmm7",	\
+ 			 "xmm8",  "xmm9",   "xmm10", "xmm11",	\
+ 			 "xmm12", "xmm13",  "xmm14", "xmm15",	\
+ 			 "mxcsr"				\
+ 		       }
+ 
+ /* Register numbers of various important registers.  */
+ #define FP_REGNUM 6		/* (rbp) */
+ #define SP_REGNUM 7		/* (rsp) Contains address of top of stack.  */
+ #define PC_REGNUM 16		/* (rip) Contains program counter.  */
+ #define PS_REGNUM 17		/* (ps)  Contains processor status.  */
+ 
+ #define RAX_REGNUM    0		/* First return register.  */
+ #define RDX_REGNUM    1		/* Second return register.  */
+ #define RDI_REGNUM    5
+ 
+ /* Floating point registers. FP0 .. FP7 are consecutive register numbers.  */
+ #define FP0_REGNUM   18		/* First FPU floating-point register.  */
+ #define FP7_REGNUM   25		/* Last  FPU floating-point register.  */
+ 
+ /* All of these control registers (except for FCOFF and FDOFF) are
+    sixteen bits long (at most) in the FPU, but are zero-extended to
+    thirty-two bits in GDB's register file.  This makes it easier to
+    compute the size of the control register file, and somewhat easier
+    to convert to and from the FSAVE instruction's 32-bit format.  */
+ 
+ #define FIRST_FPU_CTRL_REGNUM 26
+ #define FCTRL_REGNUM 26		/* FPU control word.  */
+ #define FPC_REGNUM   26		/* old name for FCTRL_REGNUM.  */
+ #define FSTAT_REGNUM 27		/* FPU status word.  */
+ #define FTAG_REGNUM  28		/* FPU register tag word.  */
+ #define FCS_REGNUM   29		/* FPU instruction's code segment selector
+ 				   16 bits, called "FPU Instruction Pointer
+ 				   Selector" in the x86 manuals.  */
+ #define FCOFF_REGNUM 30		/* FPU instruction's offset within segment
+ 				   ("Fpu Code OFFset").  */
+ #define FDS_REGNUM   31		/* FPU operand's data segment.  */
+ #define FDOFF_REGNUM 32		/* FPU operand's offset within segment.  */
+ #define FOP_REGNUM   33		/* FPU opcode, bottom eleven bits.  */
+ #define LAST_FPU_CTRL_REGNUM 33
+ 
+ /* SSE registers. XMM0 .. XMM15  are consecutive register numbers.   */
+ #define XMM0_REGNUM  34		/* First SSE data register.  */
+ #define XMM1_REGNUM  35
+ #define XMM15_REGNUM 49		/* Last  SSE2 data register.  */
+ #define MXCSR_REGNUM 50		/* Streaming SIMD Extension control/status.  */
+ 
+ #define IS_FP_REGNUM(n) (FP0_REGNUM <= (n) && (n) <= FP7_REGNUM)
+ #define IS_FPU_CTRL_REGNUM(n) (FIRST_FPU_CTRL_REGNUM <= (n) && (n) <= LAST_FPU_CTRL_REGNUM)
+ #define IS_SSE_REGNUM(n) (XMM0_REGNUM <= (n) && (n) <= XMM15_REGNUM)
+ 
+ #define FPU_REG_RAW_SIZE (10)
+ 
+ /* Sizes of individual register sets.  These cover the entire register
+    file, so summing up the sizes of those portions actually present
+    yields REGISTER_BYTES.  */
+ #define SIZEOF_GREGS (NUM_GREGS * REGISTER_SIZE)
+ #define SIZEOF_FPU_REGS (8 * FPU_REG_RAW_SIZE)
+ #define SIZEOF_FPU_CTRL_REGS \
+   ((LAST_FPU_CTRL_REGNUM - FIRST_FPU_CTRL_REGNUM + 1) * 4)
+ #define SIZEOF_SSE_REGS (8 * 16 + 4)
+ 
+ /* Total amount of space needed to store our copies of the machine's register
+    state, the array `registers'.  */
+ #define REGISTER_BYTES \
+   (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS)
+ 
+ /* Index within `registers' of the first byte of the space for register N.  */
+ #define REGISTER_BYTE(n) (x86_64_register_byte[(n)])
+ extern int x86_64_register_byte[];
+ 
+ /* Number of bytes of storage in the actual machine representation for
+    register N.  */
+ #define REGISTER_RAW_SIZE(n) (x86_64_register_raw_size[(n)])
+ extern int x86_64_register_raw_size[];
+ 
+ /* Number of bytes of storage in the program's representation
+    for register N.  */
+ #define REGISTER_VIRTUAL_SIZE(n) (x86_64_register_virtual_size[(n)])
+ extern int x86_64_register_virtual_size[];
+ 
+ /* Largest value REGISTER_RAW_SIZE can have.  */
+ #define MAX_REGISTER_RAW_SIZE 16
+ 
+ /* Return the GDB type object for the "standard" data type of data in
+    register N.  Perhaps si and di should go here, but potentially they
+    could be used for things other than address.  */
+ 
+ #undef  REGISTER_VIRTUAL_TYPE
+ #define REGISTER_VIRTUAL_TYPE(N)				\
+   (((N) == PC_REGNUM || (N) == SP_REGNUM)	\
+    ? lookup_pointer_type (builtin_type_void)			\
+    : IS_FP_REGNUM(N) ? builtin_type_long_double			\
+    : IS_SSE_REGNUM(N) ? builtin_type_v4sf			\
+    : IS_FPU_CTRL_REGNUM(N) || N==MXCSR_REGNUM || N==PS_REGNUM   \
+    ? builtin_type_int : builtin_type_long)
+ 
+ /* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+ #define MAX_REGISTER_VIRTUAL_SIZE 16
+ 
+ /* REGISTER_CONVERTIBLE(N) is true iff register N's virtual format is
+    different from its raw format.  Note that this definition assumes
+    that the host supports IEEE 32-bit floats, since it doesn't say
+    that SSE registers need conversion.  Even if we can't find a
+    counterexample, this is still sloppy.  */
+ #define REGISTER_CONVERTIBLE(n) (IS_FP_REGNUM (n))
+ 
+ /* Convert data from raw format for register REGNUM in buffer FROM to
+    virtual format with type TYPE in buffer TO.  */
+ #define REGISTER_CONVERT_TO_VIRTUAL(regnum, type, from, to) \
+   x86_64_register_convert_to_virtual ((regnum), (type), (from), (to))
+ extern void x86_64_register_convert_to_virtual (int regnum, struct type *type,
+ 						char *from, char *to);
+ 
+ /* Convert data from virtual format with type TYPE in buffer FROM to
+    raw format for register REGNUM in buffer TO.  */
+ #define REGISTER_CONVERT_TO_RAW(type, regnum, from, to) \
+   x86_64_register_convert_to_raw ((type), (regnum), (from), (to))
+ extern void x86_64_register_convert_to_raw (struct type *type, int regnum,
+ 					    char *from, char *to);
+ 
+ /* Print out the i387 floating point state.  */
+ #define FLOAT_INFO { i387_float_info (); }
+ extern void i387_float_info (void);
+ 
+ /* Don't use default structure extract routine */
+ #undef EXTRACT_STRUCT_VALUE_ADDRESS
+ 
+ /* If USE_STRUCT_CONVENTION retruns 0, then gdb uses STORE_RETURN_VALUE
+    and EXTRACT_RETURN_VALUE to store/fetch the functions return value.  It is
+    the case when structure is returned in registers.  */
+ #define USE_STRUCT_CONVENTION(gcc_p, type) x86_64_use_struct_convention (type)
+ extern int x86_64_use_struct_convention (struct type *value_type);
+ 
+ /* Store the address of the place in which to copy the structure the
+    subroutine will return.  This is called from call_function. */
+ #define STORE_STRUCT_RETURN(ADDR, SP) write_register (RDI_REGNUM, ADDR);
+ 
+ /* Extract from an array REGBUF containing the (raw) register state
+    a function return value of type TYPE, and copy that, in virtual format,
+    into VALBUF.  */
+ 
+ #define EXTRACT_RETURN_VALUE(type, regbuf, valbuf) \
+   x86_64_extract_return_value ((type), (regbuf), (valbuf))
+ extern void x86_64_extract_return_value (struct type *type, char *regbuf,
+ 					 char *valbuf);
+ 
+ /* Write into the appropriate registers a function return value stored
+    in VALBUF of type TYPE, given in virtual format.  */
+ #define STORE_RETURN_VALUE(type, valbuf) \
+   x86_64_store_return_value ((type), (valbuf))
+ extern void x86_64_store_return_value (struct type *type, char *valbuf);
+ 
+ /* FRAME_CHAIN takes a frame's nominal address and produces the frame's
+    chain-pointer.  */
+ #define FRAME_CHAIN(FRAME) uw_frame_chain(FRAME)
+ extern CORE_ADDR uw_frame_chain (struct frame_info *thisframe);
+ 
+ /* A macro that tells us whether the function invocation represented
+    by FI does not have a frame on the stack associated with it.  If it
+    does not, FRAMELESS is set to 1, else 0.  */
+ #define FRAMELESS_FUNCTION_INVOCATION(FI) (0)
+ 
+ /* Saved Pc.  Get it from sigcontext if within sigtramp.  */
+ #define FRAME_SAVED_PC(FRAME)					\
+   ((FRAME)->signal_handler_caller				\
+    ? sigtramp_saved_pc (FRAME)					\
+    : (FRAMELESS_SIGNAL (FRAME)					\
+       ? read_memory_integer (x86_64_linux_sigtramp_saved_sp ((FRAME)->next), 8) \
+       : uw_get_ra (FRAME)))
+ extern CORE_ADDR uw_get_ra (struct frame_info *fi);
+ extern CORE_ADDR sigtramp_saved_pc (struct frame_info *);
+ 
+ #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+ 
+ #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+ 
+ /* Return number of args passed to a frame. -1, means no way to tell.  */
+ #define FRAME_NUM_ARGS(fi) (-1)
+ 
+ /* Return number of bytes at start of arglist that are not really args.  */
+ 
+ #define FRAME_ARGS_SKIP 8
+ 
+ /* Handled by unwind informations.  */
+ #define FRAME_INIT_SAVED_REGS(fi)
+ 
+ /* Frame pc initialization is handled by unwind informations.  */
+ #define INIT_FRAME_PC(fromleaf, prev) \
+ 	uw_init_frame_pc (fromleaf, prev)
+ extern void uw_init_frame_pc (int, struct frame_info *fi);
+ 
+ /* Unwind informations context is in frame info. */
+ #define EXTRA_FRAME_INFO \
+ 	struct unwind_context *context;
+ 
+ /* Initialization of unwind informations.  */
+ #define INIT_EXTRA_FRAME_INFO(fromleaf, fi) uw_init_extra_frame_info(fromleaf, fi)
+ extern void uw_init_extra_frame_info (int fromleaf, struct frame_info *fi);
+ 
+ /* Getting saved registers is handled by unwind informations.  */
+ #define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \
+    uw_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ extern void uw_get_saved_register (char *raw_buffer,
+ 				   int *optimized,
+ 				   CORE_ADDR * addrp,
+ 				   struct frame_info *frame,
+ 				   int regnum, enum lval_type *lval);
+ #undef FRAME_INIT_SAVED_REGS
+ #define FRAME_INIT_SAVED_REGS(fi)
+ 
+ #define TARGET_READ_FP() uw_read_fp()
+ extern CORE_ADDR uw_read_fp ();
+ 
+ #define TARGET_WRITE_FP(val) uw_write_fp(val)
+ extern void uw_write_fp (CORE_ADDR val);
+ 
+ /* Cons up virtual frame pointer for trace */
+ #define TARGET_VIRTUAL_FRAME_POINTER(PC, REGP, OFFP) \
+ 	uw_virtual_frame_pointer ((PC), (REGP), (OFFP))
+ extern void uw_virtual_frame_pointer (CORE_ADDR, long *, long *);
+ 
+ /* Things needed for making the inferior call functions.  */
+ 
+ /* "An argument's size is increased, if necessary, to make it a
+    multiple of [32 bit] words.  This may require tail padding,
+    depending on the size of the argument" - from the x86 ABI.  */
+ #define PARM_BOUNDARY 32
+ 
+ /* Push an empty stack frame, to record the current PC, etc.  */
+ 
+ #define PUSH_DUMMY_FRAME { x86_64_push_dummy_frame (); }
+ extern void x86_64_push_dummy_frame (void);
+ 
+ /* Discard from the stack the innermost frame, restoring all registers.  */
+ #define POP_FRAME  { uw_pop_frame (); }
+ extern void uw_pop_frame (void);
+ 
+ /* this is
+  *   mov    $0x................,%r14
+  *   callq  *(%r14)
+  *   int3
+  */
+ #define CALL_DUMMY { 0x000000000000be49, 0x00000000cc16ff49 }
+ 
+ #define CALL_DUMMY_LENGTH 16
+ 
+ #define CALL_DUMMY_START_OFFSET 0	/* Start execution at beginning of dummy.  */
+ 
+ #define CALL_DUMMY_BREAKPOINT_OFFSET 12
+ 
+ /* Insert the specified number of args and function address
+    into a call sequence of the above form stored at DUMMYNAME.  */
+ #define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+   x86_64_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
+ extern void x86_64_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+ 				   int nargs, struct value **args,
+ 				   struct type *type, int gcc_p);
+ 
+ /* Use target_specific function to define link map offsets.  */
+ extern struct link_map_offsets
+   *x86_64_linux_svr4_fetch_link_map_offsets (void);
+ #define SVR4_FETCH_LINK_MAP_OFFSETS() x86_64_linux_svr4_fetch_link_map_offsets ()
+ 
+ /* The following works around a problem with /usr/include/sys/procfs.h  */
+ #define sys_quotactl 1
+ 
+ /* When the x86-64 Linux kernel calls a signal handler, the return
+    address points to a bit of code on the stack.  These definitions
+    are used to identify this bit of code as a signal trampoline in
+    order to support backtracing through calls to signal handlers.  */
+ 
+ #define IN_SIGTRAMP(pc, name) x86_64_linux_in_sigtramp (pc, name)
+ extern int x86_64_linux_in_sigtramp (CORE_ADDR, char *);
+ 
+ /* We need our own version of sigtramp_saved_pc to get the saved PC in
+    a sigtramp routine.  */
+ 
+ #define sigtramp_saved_pc x86_64_linux_sigtramp_saved_pc
+ extern CORE_ADDR x86_64_linux_sigtramp_saved_pc (struct frame_info *);
+ 
+ /* Signal trampolines don't have a meaningful frame.  As in tm-i386.h,
+    the frame pointer value we use is actually the frame pointer of the
+    calling frame--that is, the frame which was in progress when the
+    signal trampoline was entered.  gdb mostly treats this frame
+    pointer value as a magic cookie.  We detect the case of a signal
+    trampoline by looking at the SIGNAL_HANDLER_CALLER field, which is
+    set based on IN_SIGTRAMP.
+ 
+    When a signal trampoline is invoked from a frameless function, we
+    essentially have two frameless functions in a row.  In this case,
+    we use the same magic cookie for three frames in a row.  We detect
+    this case by seeing whether the next frame has
+    SIGNAL_HANDLER_CALLER set, and, if it does, checking whether the
+    current frame is actually frameless.  In this case, we need to get
+    the PC by looking at the SP register value stored in the signal
+    context.
+ 
+    This should work in most cases except in horrible situations where
+    a signal occurs just as we enter a function but before the frame
+    has been set up.  */
+ 
+ #define FRAMELESS_SIGNAL(FRAME)					\
+   ((FRAME)->next != NULL					\
+    && (FRAME)->next->signal_handler_caller			\
+    && frameless_look_for_prologue (FRAME))
+ 
+ extern CORE_ADDR x86_64_linux_sigtramp_saved_sp (struct frame_info *);
+ 
+ 
+ /* When we call a function in a shared library, and the PLT sends us
+    into the dynamic linker to find the function's real address, we
+    need to skip over the dynamic linker call.  This function decides
+    when to skip, and where to skip to.  See the comments for
+    SKIP_SOLIB_RESOLVER at the top of infrun.c.  */
+ #define SKIP_SOLIB_RESOLVER x86_64_linux_skip_solib_resolver
+ extern CORE_ADDR x86_64_linux_skip_solib_resolver (CORE_ADDR pc);
+ 
+ /* N_FUN symbols in shared libaries have 0 for their values and need
+    to be relocated. */
+ #define SOFUN_ADDRESS_MAYBE_MISSING
+ 
+ 
+ /* Support for longjmp.  */
+ 
+ /* Details about jmp_buf.  It's supposed to be an array of integers.  */
+ 
+ #define JB_ELEMENT_SIZE 4	/* Size of elements in jmp_buf.  */
+ #define JB_PC		5	/* Array index of saved PC.  */
+ 
+ /* Figure out where the longjmp will land.  Slurp the args out of the
+    stack.  We expect the first arg to be a pointer to the jmp_buf
+    structure from which we extract the pc (JB_PC) that we will land
+    at.  The pc is copied into ADDR.  This routine returns true on
+    success.  */
+ 
+ #define GET_LONGJMP_TARGET(addr) get_longjmp_target (addr)
+ extern int get_longjmp_target (CORE_ADDR * addr);
+ 
+ #endif /* ifndef TM_X86_64_H */
Index: config/i386/x86_64.mh
===================================================================
RCS file: x86_64.mh
diff -N x86_64.mh
*** /dev/null	Tue May  5 13:32:27 1998
--- x86_64.mh	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,11 ----
+ # Host: AMD x86-64 running GNU/Linux
+ 
+ XM_FILE= xm-x86_64.h
+ XDEPFILES=
+ 
+ NAT_FILE= nm-x86_64.h
+ NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
+ 	core-aout.o x86_64-nat.o x86_64-linux-nat.o i387-nat.o \
+ 	proc-service.o thread-db.o lin-lwp.o
+ 
+ LOADLIBES = -ldl -rdynamic
Index: config/i386/x86_64.mt
===================================================================
RCS file: x86_64.mt
diff -N x86_64.mt
*** /dev/null	Tue May  5 13:32:27 1998
--- x86_64.mt	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,6 ----
+ # Target: AMD x86-64 running GNU/Linux
+ TDEPFILES= x86_64-tdep.o x86_64-linux-tdep.o i387-tdep.o \
+ 	solib.o solib-svr4.o solib-legacy.o
+ TM_FILE= tm-x86_64.h
+ 
+ GDBSERVER_DEPFILES= low-linux.o
Index: config/i386/xm-x86_64.h
===================================================================
RCS file: xm-x86_64.h
diff -N xm-x86_64.h
*** /dev/null	Tue May  5 13:32:27 1998
--- xm-x86_64.h	Thu Aug  2 00:38:41 2001
***************
*** 0 ****
--- 1,32 ----
+ /* Native support for GNU/Linux, for GDB, the GNU debugger.
+    Copyright 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001
+    Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    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.  */
+ 
+ #ifndef XM_X86_64_H
+ #define XM_X86_64_H
+ 
+ #define HOST_BYTE_ORDER LITTLE_ENDIAN
+ 
+ #define HOST_LONG_DOUBLE_FORMAT &floatformat_i387_ext
+ 
+ /* Need R_OK etc, but USG isn't defined.  */
+ #include <unistd.h>
+ 
+ #endif /* #ifndef XM_X86_64_H */

-- 
Jiri Smid

---------------------------------------------------------------------
SuSE CR, s.r.o.                                 e-mail: smid@suse.cz
Drahobejlova 27                                tel:+420 2 83095 373
190 00 Praha 9                                 fax:+420 2 83095 374
Ceska republika                                http://www.suse.cz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]