* [PATCH/i386newframe] amd64newframe
@ 2003-05-17 15:19 Mark Kettenis
2003-05-19 15:31 ` Elena Zannoni
0 siblings, 1 reply; 14+ messages in thread
From: Mark Kettenis @ 2003-05-17 15:19 UTC (permalink / raw)
To: gdb-patches, mludvig; +Cc: aj
Folks,
I've checked in on my i386newframe branch a major overhaul of the
x86-64 (sub)target to make it fit into the new frame unwindig
framework. I've tried very hard to reduce the gratuitous differences
between the i386 and x86_64 stuff, and cleaned things up quite a bit.
However, this code is *untested*. The code compiles, that is, I can
build a x86_64-linux cross-debugger on my i386-unknown-freebsd4.7
system (actually I can't since the final link fails because of a
problem with the way we do our shared library support). It would be
great if someone could provide me with access to an amd64 system. If
it's running *BSD, I can probably add the necessary support for it to
GDB. Otherwise I'd appreciate it if someone could test this code on
x86_64-linux.
Mark
Index: ChangeLog
from Mark Kettenis <kettenis@gnu.org>
Revise the x86_64 (sub)taget.
* x86-64-tdep.c, x86-64-linux-tdep.c, x86-64-linux-nat.c,
config/i386/tm-x86-64linux.h, config/i386/nm-x86-64linux.h,
config/i386/x86-64-linux.mt, config/i386/x86-64linux.mh: Extensive
changes.
Index: x86-64-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-linux-nat.c,v
retrieving revision 1.21
diff -u -p -r1.21 x86-64-linux-nat.c
--- x86-64-linux-nat.c 11 Feb 2003 23:09:59 -0000 1.21
+++ x86-64-linux-nat.c 17 May 2003 14:58:42 -0000
@@ -25,20 +25,30 @@
#include "inferior.h"
#include "gdbcore.h"
#include "regcache.h"
+
#include "gdb_assert.h"
#include "gdb_string.h"
-#include "x86-64-tdep.h"
-
#include <sys/ptrace.h>
#include <sys/debugreg.h>
#include <sys/syscall.h>
#include <sys/procfs.h>
#include <sys/reg.h>
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
+
+#include "x86-64-tdep.h"
+
+/* The register sets used in GNU/Linux ELF core-dumps are identical to
+ the register sets 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.
+
/* Mapping between the general-purpose registers in `struct user'
format and GDB's register array layout. */
-
-static int x86_64_regmap[] = {
+static int regmap[] =
+{
RAX, RBX, RCX, RDX,
RSI, RDI, RBP, RSP,
R8, R9, R10, R11,
@@ -47,85 +57,12 @@ static int x86_64_regmap[] = {
DS, ES, FS, GS
};
-static unsigned long
-x86_64_linux_dr_get (int regnum)
-{
- int tid;
- unsigned long value;
-
- /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
- multi-threaded processes here. For now, pretend there is just
- one thread. */
- tid = PIDGET (inferior_ptid);
-
- /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
- ptrace call fails breaks debugging remote targets. The correct
- way to fix this is to add the hardware breakpoint and watchpoint
- stuff to the target vectore. For now, just return zero if the
- ptrace call fails. */
- errno = 0;
- value = ptrace (PT_READ_U, tid,
- offsetof (struct user, u_debugreg[regnum]), 0);
- if (errno != 0)
-#if 0
- perror_with_name ("Couldn't read debug register");
-#else
- return 0;
-#endif
-
- return value;
-}
-
-static void
-x86_64_linux_dr_set (int regnum, unsigned long value)
-{
- int tid;
-
- /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
- multi-threaded processes here. For now, pretend there is just
- one thread. */
- tid = PIDGET (inferior_ptid);
-
- 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");
-}
-
-void
-x86_64_linux_dr_set_control (unsigned long control)
-{
- x86_64_linux_dr_set (DR_CONTROL, control);
-}
-
-void
-x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
-{
- gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
-
- x86_64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
-}
-
-void
-x86_64_linux_dr_reset_addr (int regnum)
-{
- gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
-
- x86_64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
-}
-
-unsigned long
-x86_64_linux_dr_get_status (void)
-{
- return x86_64_linux_dr_get (DR_STATUS);
-}
-\f
-
-/* The register sets used in GNU/Linux ELF core-dumps are identical to
- the register sets used by `ptrace'. */
+/* Which ptrace request retrieves which registers?
+ These apply to the corresponding SET requests as well. */
#define GETREGS_SUPPLIES(regno) \
- (0 <= (regno) && (regno) < x86_64_num_gregs)
+ (0 <= (regno) && (regno) < X86_64_NUM_GREGS)
+
#define GETFPREGS_SUPPLIES(regno) \
(FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
\f
@@ -137,13 +74,13 @@ x86_64_linux_dr_get_status (void)
in *GREGSETP. */
void
-supply_gregset (elf_gregset_t * gregsetp)
+supply_gregset (elf_gregset_t *gregsetp)
{
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;
- for (i = 0; i < x86_64_num_gregs; i++)
- supply_register (i, (char *) (regp + x86_64_regmap[i]));
+ for (i = 0; i < X86_64_NUM_GREGS; i++)
+ supply_register (i, regp + regmap[i]);
}
/* Fill register REGNO (if it is a general-purpose register) in
@@ -151,14 +88,14 @@ supply_gregset (elf_gregset_t * gregsetp
do this for all registers. */
void
-fill_gregset (elf_gregset_t * gregsetp, int regno)
+fill_gregset (elf_gregset_t *gregsetp, int regno)
{
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;
- for (i = 0; i < x86_64_num_gregs; i++)
- if ((regno == -1 || regno == i))
- regcache_collect (i, (char *) (regp + x86_64_regmap[i]));
+ for (i = 0; i < X86_64_NUM_GREGS; i++)
+ if (regno == -1 || regno == i)
+ regcache_collect (i, regp + regmap[i]);
}
/* Fetch all general-purpose registers from process/thread TID and
@@ -195,73 +132,23 @@ store_regs (int tid, int regno)
/* Transfering floating-point registers between GDB, inferiors and cores. */
-static void *
-x86_64_fxsave_offset (elf_fpregset_t * fxsave, int regnum)
-{
- const char *reg_name;
- int reg_index;
-
- gdb_assert (x86_64_num_gregs - 1 < regnum && regnum < x86_64_num_regs);
-
- reg_name = x86_64_register_name (regnum);
-
- if (reg_name[0] == 's' && reg_name[1] == 't')
- {
- reg_index = reg_name[2] - '0';
- return &fxsave->st_space[reg_index * 2];
- }
-
- if (reg_name[0] == 'x' && reg_name[1] == 'm' && reg_name[2] == 'm')
- {
- reg_index = reg_name[3] - '0';
- return &fxsave->xmm_space[reg_index * 4];
- }
-
- if (strcmp (reg_name, "mxcsr") == 0)
- return &fxsave->mxcsr;
-
- return NULL;
-}
-
/* Fill GDB's register array with the floating-point and SSE register
- values in *FXSAVE. This function masks off any of the reserved
- bits in *FXSAVE. */
+ values in *FPREGSETP. */
void
-supply_fpregset (elf_fpregset_t * fxsave)
+supply_fpregset (elf_fpregset_t *fpregsetp)
{
- int i, reg_st0, reg_mxcsr;
-
- reg_st0 = x86_64_register_number ("st0");
- reg_mxcsr = x86_64_register_number ("mxcsr");
-
- gdb_assert (reg_st0 > 0 && reg_mxcsr > reg_st0);
-
- for (i = reg_st0; i <= reg_mxcsr; i++)
- supply_register (i, x86_64_fxsave_offset (fxsave, i));
+ x86_64_supply_fxsave ((char *) fpregsetp);
}
/* Fill register REGNUM (if it is a floating-point or SSE register) in
- *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
- this for all registers. This function doesn't touch any of the
- reserved bits in *FXSAVE. */
+ *FPREGSETP with the value in GDB's register array. If REGNUM is
+ -1, do this for all registers. */
void
-fill_fpregset (elf_fpregset_t * fxsave, int regnum)
+fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
{
- int i, last_regnum = MXCSR_REGNUM;
- void *ptr;
-
- if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
- last_regnum = FOP_REGNUM;
-
- for (i = FP0_REGNUM; i <= last_regnum; i++)
- if (regnum == -1 || regnum == i)
- {
- ptr = x86_64_fxsave_offset (fxsave, i);
- if (ptr)
- regcache_collect (i, ptr);
- }
+ x86_64_fill_fxsave ((char *) fpregsetp, regnum);
}
/* Fetch all floating-point registers from process/thread TID and store
@@ -308,8 +195,9 @@ fetch_inferior_registers (int regno)
int tid;
/* GNU/Linux LWP ID's are process ID's. */
- if ((tid = TIDGET (inferior_ptid)) == 0)
- tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+ tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid); /* Not a threaded program. */
if (regno == -1)
{
@@ -335,16 +223,18 @@ fetch_inferior_registers (int regno)
}
/* Store register REGNO back into the child process. If REGNO is -1,
- do this for all registers (including the floating point and SSE
+ do this for all registers (including the floating-point and SSE
registers). */
+
void
store_inferior_registers (int regno)
{
int tid;
/* GNU/Linux LWP ID's are process ID's. */
- if ((tid = TIDGET (inferior_ptid)) == 0)
- tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+ tid = TIDGET (inferior_ptid);
+ if (tid == 0)
+ tid = PIDGET (inferior_ptid); /* Not a threaded program. */
if (regno == -1)
{
@@ -370,123 +260,75 @@ store_inferior_registers (int regno)
}
\f
-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 */
+static unsigned long
+x86_64_linux_dr_get (int regnum)
+{
+ int tid;
+ unsigned long value;
-/* We are specifically interested in the sigreturn and rt_sigreturn
- system calls. */
+ /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
+ multi-threaded processes here. For now, pretend there is just
+ one thread. */
+ tid = PIDGET (inferior_ptid);
-#ifndef SYS_sigreturn
-#define SYS_sigreturn __NR_sigreturn
-#endif
-#ifndef SYS_rt_sigreturn
-#define SYS_rt_sigreturn __NR_rt_sigreturn
+ /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
+ ptrace call fails breaks debugging remote targets. The correct
+ way to fix this is to add the hardware breakpoint and watchpoint
+ stuff to the target vectore. For now, just return zero if the
+ ptrace call fails. */
+ errno = 0;
+ value = ptrace (PT_READ_U, tid,
+ offsetof (struct user, u_debugreg[regnum]), 0);
+ if (errno != 0)
+#if 0
+ perror_with_name ("Couldn't read debug register");
+#else
+ return 0;
#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)
-
-/* 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 GNU/Linux. */
+ return value;
+}
static void
-fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
- int which, CORE_ADDR reg_addr)
+x86_64_linux_dr_set (int regnum, unsigned long value)
{
- 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;
- }
-}
+ int tid;
-/* Register that we are able to handle GNU/Linux ELF core file formats. */
+ /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
+ multi-threaded processes here. For now, pretend there is just
+ one thread. */
+ tid = PIDGET (inferior_ptid);
-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 */
-};
-\f
+ 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");
+}
-#if !defined (offsetof)
-#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
-#endif
+void
+x86_64_linux_dr_set_control (unsigned long control)
+{
+ x86_64_linux_dr_set (DR_CONTROL, control);
+}
-/* Return the address of register REGNUM. BLOCKEND is the value of
- u.u_ar0, which should point to the registers. */
-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 * x86_64_regmap[regnum]);
+void
+x86_64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+{
+ gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
+
+ x86_64_linux_dr_set (DR_FIRSTADDR + regnum, addr);
}
void
-_initialize_x86_64_linux_nat (void)
+x86_64_linux_dr_reset_addr (int regnum)
{
- add_core_fns (&linux_elf_core_fns);
+ gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
+
+ x86_64_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
}
-int
-kernel_u_size (void)
+unsigned long
+x86_64_linux_dr_get_status (void)
{
- return (sizeof (struct user));
+ return x86_64_linux_dr_get (DR_STATUS);
}
Index: x86-64-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-linux-tdep.c,v
retrieving revision 1.17
diff -u -p -r1.17 x86-64-linux-tdep.c
--- x86-64-linux-tdep.c 14 Jan 2003 00:49:04 -0000 1.17
+++ x86-64-linux-tdep.c 17 May 2003 14:58:42 -0000
@@ -24,19 +24,21 @@
#include "defs.h"
#include "inferior.h"
#include "gdbcore.h"
-#include "gdb_string.h"
#include "regcache.h"
-#include "x86-64-tdep.h"
-#include "dwarf2cfi.h"
#include "osabi.h"
-#define LINUX_SIGTRAMP_INSN0 (0x48) /* mov $NNNNNNNN,%rax */
-#define LINUX_SIGTRAMP_OFFSET0 (0)
-#define LINUX_SIGTRAMP_INSN1 (0x0f) /* syscall */
-#define LINUX_SIGTRAMP_OFFSET1 (7)
+#include "gdb_string.h"
-static const unsigned char linux_sigtramp_code[] = {
- /* mov $__NR_rt_sigreturn,%rax */
+#include "x86-64-tdep.h"
+
+#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[] =
+{
+ /* mov $__NR_rt_sigreturn, %rax */
LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00,
/* syscall */
LINUX_SIGTRAMP_INSN1, 0x05
@@ -51,6 +53,14 @@ 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;
@@ -71,133 +81,60 @@ x86_64_linux_sigtramp_start (CORE_ADDR p
return pc;
}
-#define LINUX_SIGINFO_SIZE 0
-
-/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
-#define LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40
-
-/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>. */
-#define LINUX_SIGCONTEXT_PC_OFFSET 128
-#define LINUX_SIGCONTEXT_FP_OFFSET 120
-
-/* Assuming FRAME is for a GNU/Linux sigtramp routine, return the
- address of the associated sigcontext structure. */
-static CORE_ADDR
-x86_64_linux_sigcontext_addr (struct frame_info *frame)
-{
- CORE_ADDR pc;
- ULONGEST rsp;
-
- pc = x86_64_linux_sigtramp_start (get_frame_pc (frame));
- if (pc)
- {
- if (get_next_frame (frame))
- /* 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 get_frame_base (get_next_frame (frame)) + LINUX_SIGINFO_SIZE +
- LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
-
-
- /* This is the top frame. */
- rsp = read_register (SP_REGNUM);
- return rsp + LINUX_SIGINFO_SIZE + LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
-
- }
-
- error ("Couldn't recognize signal trampoline.");
- return 0;
-}
-
-/* Assuming FRAME is for a GNU/Linux sigtramp routine, return the
- saved program counter. */
-
-static 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);
-}
-
-/* Immediately after a function call, return the saved pc. */
-
-CORE_ADDR
-x86_64_linux_saved_pc_after_call (struct frame_info *frame)
-{
- if ((get_frame_type (frame) == SIGTRAMP_FRAME))
- return x86_64_linux_sigtramp_saved_pc (frame);
-
- return read_memory_integer (read_register (SP_REGNUM), 8);
-}
-
-/* Saved Pc. Get it from sigcontext if within sigtramp. */
-CORE_ADDR
-x86_64_linux_frame_saved_pc (struct frame_info *frame)
-{
- if ((get_frame_type (frame) == SIGTRAMP_FRAME))
- return x86_64_linux_sigtramp_saved_pc (frame);
- return cfi_get_ra (frame);
-}
-
/* Return whether PC is in a GNU/Linux sigtramp routine. */
-int
-x86_64_linux_in_sigtramp (CORE_ADDR pc, char *name)
+static int
+x86_64_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
- if (name)
- return strcmp ("__restore_rt", name) == 0;
+ /* If we have NAME, we can optimize the search. The trampoline is
+ named __restore_rt. However, it isn't dynamically exported from
+ the shared C library, so the trampoline may appear to be part of
+ the preceding function. This should always be sigaction,
+ __sigaction, or __libc_sigaction (all aliases to the same
+ function). */
+ if (name == NULL || strstr (name, "sigaction") != NULL)
+ return (x86_64_linux_sigtramp_start (pc) != 0);
- return (x86_64_linux_sigtramp_start (pc) != 0);
+ return (strcmp ("__restore_rt", name) == 0);
}
-CORE_ADDR
-x86_64_linux_frame_chain (struct frame_info *fi)
-{
- ULONGEST addr;
- CORE_ADDR fp, pc;
-
- if (!(get_frame_type (fi) == SIGTRAMP_FRAME))
- {
- fp = cfi_frame_chain (fi);
- if (fp)
- return fp;
- else
- addr = get_frame_base (fi);
- }
- else
- addr = get_frame_base (get_next_frame (fi));
-
- addr += LINUX_SIGINFO_SIZE + LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
-
- fp = read_memory_integer (addr + LINUX_SIGCONTEXT_FP_OFFSET, 8) + 8;
+/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
+#define X86_64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40
- return fp;
-}
+/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
+ routine, return the address of the associated sigcontext structure. */
-CORE_ADDR
-x86_64_init_frame_pc (int fromleaf, struct frame_info *fi)
+static CORE_ADDR
+x86_64_linux_sigcontext_addr (struct frame_info *next_frame)
{
- CORE_ADDR addr;
+ CORE_ADDR sp, ucontext_addr;
+ char buf[8];
- if (get_next_frame (fi)
- && (get_frame_type (get_next_frame (fi)) == SIGTRAMP_FRAME))
- {
- addr = get_frame_base (get_next_frame (get_next_frame (fi)))
- + LINUX_SIGINFO_SIZE + LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
- return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 8);
- }
- else
- return cfi_init_frame_pc (fromleaf, fi);
+ frame_unwind_register (next_frame, SP_REGNUM, buf);
+ sp = extract_unsigned_integer (buf, 8);
+
+ /* The sigcontext structure is part of the user context. A pointer
+ to the user context is passed as the third argument to the signal
+ handler. */
+ read_memory (sp + 16, buf, 8);
+ ucontext_addr = extract_unsigned_integer (buf, 8);
+ return ucontext_addr + X86_64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
}
\f
static void
x86_64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
x86_64_init_abi (info, gdbarch);
+
+ set_gdbarch_pc_in_sigtramp (gdbarch, x86_64_linux_pc_in_sigtramp);
+
+ tdep->sigcontext_addr = x86_64_linux_sigcontext_addr;
+ tdep->sc_pc_offset = 16 * 8; /* From <asm/sigcontext.h>. */
+ tdep->sc_sp_offset = 15 * 8;
}
+\f
/* Provide a prototype to silence -Wmissing-prototypes. */
extern void _initialize_x86_64_linux_tdep (void);
Index: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.67.2.1
diff -u -p -r1.67.2.1 x86-64-tdep.c
--- x86-64-tdep.c 4 May 2003 11:37:46 -0000 1.67.2.1
+++ x86-64-tdep.c 17 May 2003 14:58:43 -0000
@@ -21,249 +21,202 @@
Boston, MA 02111-1307, USA. */
#include "defs.h"
+#include "arch-utils.h"
+#include "block.h"
+#include "dummy-frame.h"
+#include "dwarf-frame.h"
+#include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
#include "inferior.h"
-#include "gdbcore.h"
#include "gdbcmd.h"
-#include "arch-utils.h"
+#include "gdbcore.h"
+#include "objfiles.h"
#include "regcache.h"
#include "symfile.h"
-#include "objfiles.h"
-#include "x86-64-tdep.h"
-#include "dwarf2cfi.h"
+
#include "gdb_assert.h"
-#include "block.h"
+
+#include "x86-64-tdep.h"
+#include "i387-tdep.h"
/* Register numbers of various important registers. */
-#define RAX_REGNUM 0
-#define RDX_REGNUM 3
-#define RDI_REGNUM 5
-#define EFLAGS_REGNUM 17
-#define ST0_REGNUM 22
-#define XMM1_REGNUM 39
-struct register_info
+#define X86_64_RAX_REGNUM 0 /* %rax */
+#define X86_64_RDX_REGNUM 3 /* %rdx */
+#define X86_64_RDI_REGNUM 5 /* %rdi */
+#define X86_64_RBP_REGNUM 6 /* %rbp */
+#define X86_64_RSP_REGNUM 7 /* %rsp */
+#define X86_64_RIP_REGNUM 16 /* %rip */
+#define X86_64_EFLAGS_REGNUM 17 /* %eflags */
+#define X86_64_ST0_REGNUM 22 /* %st0 */
+#define X86_64_XMM0_REGNUM 38 /* %xmm0 */
+#define X86_64_XMM1_REGNUM 39 /* %xmm1 */
+
+struct x86_64_register_info
{
- int size;
char *name;
struct type **type;
};
-/* x86_64_register_raw_size_table[i] is the number of bytes of storage in
- GDB's register array occupied by register i. */
-static struct register_info x86_64_register_info_table[] = {
- /* 0 */ {8, "rax", &builtin_type_int64},
- /* 1 */ {8, "rbx", &builtin_type_int64},
- /* 2 */ {8, "rcx", &builtin_type_int64},
- /* 3 */ {8, "rdx", &builtin_type_int64},
- /* 4 */ {8, "rsi", &builtin_type_int64},
- /* 5 */ {8, "rdi", &builtin_type_int64},
- /* 6 */ {8, "rbp", &builtin_type_void_func_ptr},
- /* 7 */ {8, "rsp", &builtin_type_void_func_ptr},
- /* 8 */ {8, "r8", &builtin_type_int64},
- /* 9 */ {8, "r9", &builtin_type_int64},
- /* 10 */ {8, "r10", &builtin_type_int64},
- /* 11 */ {8, "r11", &builtin_type_int64},
- /* 12 */ {8, "r12", &builtin_type_int64},
- /* 13 */ {8, "r13", &builtin_type_int64},
- /* 14 */ {8, "r14", &builtin_type_int64},
- /* 15 */ {8, "r15", &builtin_type_int64},
- /* 16 */ {8, "rip", &builtin_type_void_func_ptr},
- /* 17 */ {4, "eflags", &builtin_type_int32},
- /* 18 */ {4, "ds", &builtin_type_int32},
- /* 19 */ {4, "es", &builtin_type_int32},
- /* 20 */ {4, "fs", &builtin_type_int32},
- /* 21 */ {4, "gs", &builtin_type_int32},
- /* 22 */ {10, "st0", &builtin_type_i387_ext},
- /* 23 */ {10, "st1", &builtin_type_i387_ext},
- /* 24 */ {10, "st2", &builtin_type_i387_ext},
- /* 25 */ {10, "st3", &builtin_type_i387_ext},
- /* 26 */ {10, "st4", &builtin_type_i387_ext},
- /* 27 */ {10, "st5", &builtin_type_i387_ext},
- /* 28 */ {10, "st6", &builtin_type_i387_ext},
- /* 29 */ {10, "st7", &builtin_type_i387_ext},
- /* 30 */ {4, "fctrl", &builtin_type_int32},
- /* 31 */ {4, "fstat", &builtin_type_int32},
- /* 32 */ {4, "ftag", &builtin_type_int32},
- /* 33 */ {4, "fiseg", &builtin_type_int32},
- /* 34 */ {4, "fioff", &builtin_type_int32},
- /* 35 */ {4, "foseg", &builtin_type_int32},
- /* 36 */ {4, "fooff", &builtin_type_int32},
- /* 37 */ {4, "fop", &builtin_type_int32},
- /* 38 */ {16, "xmm0", &builtin_type_v4sf},
- /* 39 */ {16, "xmm1", &builtin_type_v4sf},
- /* 40 */ {16, "xmm2", &builtin_type_v4sf},
- /* 41 */ {16, "xmm3", &builtin_type_v4sf},
- /* 42 */ {16, "xmm4", &builtin_type_v4sf},
- /* 43 */ {16, "xmm5", &builtin_type_v4sf},
- /* 44 */ {16, "xmm6", &builtin_type_v4sf},
- /* 45 */ {16, "xmm7", &builtin_type_v4sf},
- /* 46 */ {16, "xmm8", &builtin_type_v4sf},
- /* 47 */ {16, "xmm9", &builtin_type_v4sf},
- /* 48 */ {16, "xmm10", &builtin_type_v4sf},
- /* 49 */ {16, "xmm11", &builtin_type_v4sf},
- /* 50 */ {16, "xmm12", &builtin_type_v4sf},
- /* 51 */ {16, "xmm13", &builtin_type_v4sf},
- /* 52 */ {16, "xmm14", &builtin_type_v4sf},
- /* 53 */ {16, "xmm15", &builtin_type_v4sf},
- /* 54 */ {4, "mxcsr", &builtin_type_int32}
-};
-
-/* This array is a mapping from Dwarf-2 register
- numbering to GDB's one. Dwarf-2 numbering is
- defined in x86-64 ABI, section 3.6. */
-static int x86_64_dwarf2gdb_regno_map[] = {
- 0, 1, 2, 3, /* RAX - RDX */
- 4, 5, 6, 7, /* RSI, RDI, RBP, RSP */
- 8, 9, 10, 11, /* R8 - R11 */
- 12, 13, 14, 15, /* R12 - R15 */
- -1, /* RA - not mapped */
- XMM1_REGNUM - 1, XMM1_REGNUM, /* XMM0 ... */
- XMM1_REGNUM + 1, XMM1_REGNUM + 2,
- XMM1_REGNUM + 3, XMM1_REGNUM + 4,
- XMM1_REGNUM + 5, XMM1_REGNUM + 6,
- XMM1_REGNUM + 7, XMM1_REGNUM + 8,
- XMM1_REGNUM + 9, XMM1_REGNUM + 10,
- XMM1_REGNUM + 11, XMM1_REGNUM + 12,
- XMM1_REGNUM + 13, XMM1_REGNUM + 14, /* ... XMM15 */
- ST0_REGNUM + 0, ST0_REGNUM + 1, /* ST0 ... */
- ST0_REGNUM + 2, ST0_REGNUM + 3,
- ST0_REGNUM + 4, ST0_REGNUM + 5,
- ST0_REGNUM + 6, ST0_REGNUM + 7 /* ... ST7 */
+static struct x86_64_register_info x86_64_register_info[] =
+{
+ { "rax", &builtin_type_int64 },
+ { "rbx", &builtin_type_int64 },
+ { "rcx", &builtin_type_int64 },
+ { "rdx", &builtin_type_int64 },
+ { "rsi", &builtin_type_int64 },
+ { "rdi", &builtin_type_int64 },
+ { "rbp", &builtin_type_void_data_ptr },
+ { "rsp", &builtin_type_void_data_ptr },
+
+ /* %r8 is indeed register number 8. */
+ { "r8", &builtin_type_int64 },
+ { "r9", &builtin_type_int64 },
+ { "r10", &builtin_type_int64 },
+ { "r11", &builtin_type_int64 },
+ { "r12", &builtin_type_int64 },
+ { "r13", &builtin_type_int64 },
+ { "r14", &builtin_type_int64 },
+ { "r15", &builtin_type_int64 },
+ { "rip", &builtin_type_void_func_ptr },
+ { "eflags", &builtin_type_int32 },
+ { "ds", &builtin_type_int32 },
+ { "es", &builtin_type_int32 },
+ { "fs", &builtin_type_int32 },
+ { "gs", &builtin_type_int32 },
+
+ /* %st0 is register number 22. */
+ { "st0", &builtin_type_i387_ext },
+ { "st1", &builtin_type_i387_ext },
+ { "st2", &builtin_type_i387_ext },
+ { "st3", &builtin_type_i387_ext },
+ { "st4", &builtin_type_i387_ext },
+ { "st5", &builtin_type_i387_ext },
+ { "st6", &builtin_type_i387_ext },
+ { "st7", &builtin_type_i387_ext },
+ { "fctrl", &builtin_type_int32 },
+ { "fstat", &builtin_type_int32 },
+ { "ftag", &builtin_type_int32 },
+ { "fiseg", &builtin_type_int32 },
+ { "fioff", &builtin_type_int32 },
+ { "foseg", &builtin_type_int32 },
+ { "fooff", &builtin_type_int32 },
+ { "fop", &builtin_type_int32 },
+
+ /* %xmm0 is register number 38. */
+ { "xmm0", &builtin_type_v4sf },
+ { "xmm1", &builtin_type_v4sf },
+ { "xmm2", &builtin_type_v4sf },
+ { "xmm3", &builtin_type_v4sf },
+ { "xmm4", &builtin_type_v4sf },
+ { "xmm5", &builtin_type_v4sf },
+ { "xmm6", &builtin_type_v4sf },
+ { "xmm7", &builtin_type_v4sf },
+ { "xmm8", &builtin_type_v4sf },
+ { "xmm9", &builtin_type_v4sf },
+ { "xmm10", &builtin_type_v4sf },
+ { "xmm11", &builtin_type_v4sf },
+ { "xmm12", &builtin_type_v4sf },
+ { "xmm13", &builtin_type_v4sf },
+ { "xmm14", &builtin_type_v4sf },
+ { "xmm15", &builtin_type_v4sf },
+ { "mxcsr", &builtin_type_int32 }
};
-static int x86_64_dwarf2gdb_regno_map_length =
- sizeof (x86_64_dwarf2gdb_regno_map) /
- sizeof (x86_64_dwarf2gdb_regno_map[0]);
-
-/* Number of all registers */
-#define X86_64_NUM_REGS (sizeof (x86_64_register_info_table) / \
- sizeof (x86_64_register_info_table[0]))
+/* Total number of registers. */
+#define X86_64_NUM_REGS \
+ (sizeof (x86_64_register_info) / sizeof (x86_64_register_info[0]))
-/* Number of general registers. */
-#define X86_64_NUM_GREGS (22)
+/* Size of the register buffer. */
+static int x86_64_register_bytes;
-int x86_64_num_regs = X86_64_NUM_REGS;
-int x86_64_num_gregs = X86_64_NUM_GREGS;
+/* Return the name of register REGNUM. */
-/* Did we already print a note about frame pointer? */
-int omit_fp_note_printed = 0;
-
-/* Number of bytes of storage in the actual machine representation for
- register REGNO. */
-int
-x86_64_register_raw_size (int regno)
+static const char *
+x86_64_register_name (int regnum)
{
- return x86_64_register_info_table[regno].size;
-}
+ if (regnum >= 0 && regnum < X86_64_NUM_REGS)
+ return x86_64_register_info[regnum].name;
-/* x86_64_register_byte_table[i] is the offset into the register file of the
- start of register number i. We initialize this from
- x86_64_register_info_table. */
-int x86_64_register_byte_table[X86_64_NUM_REGS];
-
-/* Index within `registers' of the first byte of the space for register REGNO. */
-int
-x86_64_register_byte (int regno)
-{
- return x86_64_register_byte_table[regno];
+ return NULL;
}
/* Return the GDB type object for the "standard" data type of data in
- register N. */
+ register REGNUM. */
+
static struct type *
-x86_64_register_virtual_type (int regno)
+x86_64_register_type (struct gdbarch *gdbarch, int regnum)
{
- return *x86_64_register_info_table[regno].type;
-}
+ gdb_assert (regnum >= 0 && regnum < X86_64_NUM_REGS);
-/* x86_64_register_convertible is true if 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. */
-int
-x86_64_register_convertible (int regno)
-{
- return IS_FP_REGNUM (regno);
+ return *x86_64_register_info[regnum].type;
}
-/* 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)
+/* DWARF Register Number Mapping as defined in the System V psABI,
+ section 3.6. */
+
+static int x86_64_dwarf_regmap[] =
{
- char buf[12];
+ /* General Purpose Registers RAX, RDX, RCX, RBX, RSI, RDI. */
+ X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, 3, 2,
+ 4, X86_64_RDI_REGNUM,
- /* We only support floating-point values. */
- if (TYPE_CODE (type) != TYPE_CODE_FLT)
- {
- warning ("Cannot convert floating-point register value "
- "to non-floating-point type.");
- memset (to, 0, TYPE_LENGTH (type));
- return;
- }
- /* First add the necessary padding. */
- memcpy (buf, from, FPU_REG_RAW_SIZE);
- memset (buf + FPU_REG_RAW_SIZE, 0, sizeof buf - FPU_REG_RAW_SIZE);
- /* Convert to TYPE. This should be a no-op, if TYPE is equivalent
- to the extended floating-point format used by the FPU. */
- convert_typed_floating (to, type, buf,
- x86_64_register_virtual_type (regnum));
-}
+ /* Frame Pointer Register RBP. */
+ X86_64_RBP_REGNUM,
-/* 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. */
+ /* Stack Pointer Register RSP. */
+ X86_64_RSP_REGNUM,
-void
-x86_64_register_convert_to_raw (struct type *type, int regnum,
- char *from, char *to)
-{
- gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 12);
- /* Simply omit the two unused bytes. */
- memcpy (to, from, FPU_REG_RAW_SIZE);
-}
+ /* Extended Integer Registers 8 - 15. */
+ 8, 9, 10, 11, 12, 13, 14, 15,
-/* Dwarf-2 <-> GDB register numbers mapping. */
-int
-x86_64_dwarf2_reg_to_regnum (int dw_reg)
-{
- if (dw_reg < 0 || dw_reg > x86_64_dwarf2gdb_regno_map_length)
- {
- warning ("Dwarf-2 uses unmapped register #%d\n", dw_reg);
- return dw_reg;
- }
+ /* Return Address RA. Not mapped. */
+ -1,
- return x86_64_dwarf2gdb_regno_map[dw_reg];
-}
+ /* SSE Registers 0 - 7. */
+ X86_64_XMM0_REGNUM + 0, X86_64_XMM1_REGNUM,
+ X86_64_XMM0_REGNUM + 2, X86_64_XMM0_REGNUM + 3,
+ X86_64_XMM0_REGNUM + 4, X86_64_XMM0_REGNUM + 5,
+ X86_64_XMM0_REGNUM + 6, X86_64_XMM0_REGNUM + 7,
-/* Push the return address (pointing to the call dummy) onto the stack
- and return the new value for the stack pointer. */
+ /* Extended SSE Registers 8 - 15. */
+ X86_64_XMM0_REGNUM + 8, X86_64_XMM0_REGNUM + 9,
+ X86_64_XMM0_REGNUM + 10, X86_64_XMM0_REGNUM + 11,
+ X86_64_XMM0_REGNUM + 12, X86_64_XMM0_REGNUM + 13,
+ X86_64_XMM0_REGNUM + 14, X86_64_XMM0_REGNUM + 15,
-static CORE_ADDR
-x86_64_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
-{
- char buf[8];
+ /* Floating Point Registers 0-7. */
+ X86_64_ST0_REGNUM + 0, X86_64_ST0_REGNUM + 1,
+ X86_64_ST0_REGNUM + 2, X86_64_ST0_REGNUM + 3,
+ X86_64_ST0_REGNUM + 4, X86_64_ST0_REGNUM + 5,
+ X86_64_ST0_REGNUM + 6, X86_64_ST0_REGNUM + 7
+};
- store_unsigned_integer (buf, 8, CALL_DUMMY_ADDRESS ());
- write_memory (sp - 8, buf, 8);
- return sp - 8;
-}
+static const int x86_64_dwarf_regmap_len =
+ (sizeof (x86_64_dwarf_regmap) / sizeof (x86_64_dwarf_regmap[0]));
-static void
-x86_64_pop_frame (void)
+/* Convert DWARF register number REG to the appropriate register
+ number used by GDB. */
+
+static int
+x86_64_dwarf_reg_to_regnum (int reg)
{
- generic_pop_current_frame (cfi_pop_frame);
+ int regnum = -1;
+
+ if (reg >= 0 || reg < x86_64_dwarf_regmap_len)
+ regnum = x86_64_dwarf_regmap[reg];
+
+ if (regnum == -1)
+ warning ("Unmapped DWARF Register #%d encountered\n", reg);
+
+ return regnum;
}
\f
/* 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.
- */
+ Some types are returned in registers an some (big structures) in
+ memory. See the System V psABI for details. */
#define MAX_CLASSES 4
@@ -282,27 +235,27 @@ enum x86_64_reg_class
};
/* Return the union class of CLASS1 and CLASS2.
- See the x86-64 ABI for details. */
+ See the System V psABI for details. */
static enum x86_64_reg_class
merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
{
- /* Rule #1: If both classes are equal, this is the resulting class. */
+ /* Rule (a): 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
+ /* Rule (b): 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. */
+ /* Rule (c): 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. */
+ /* Rule (d): 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;
@@ -310,12 +263,13 @@ merge_classes (enum x86_64_reg_class cla
|| 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. */
+ /* Rule (e): If one of the classes is X87 or X87UP class, MEMORY is
+ used as class. */
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. */
+ /* Rule (f): Otherwise class SSE is used. */
return X86_64_SSE_CLASS;
}
@@ -325,7 +279,7 @@ merge_classes (enum x86_64_reg_class cla
is returned. As a special case for zero sized containers,
classes[0] will be NO_CLASS and 1 is returned.
- See the x86-64 psABI for details. */
+ See the System V psABI for details. */
static int
classify_argument (struct type *type,
@@ -533,7 +487,8 @@ examine_argument (enum x86_64_reg_class
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
+
+static int
x86_64_use_struct_convention (int gcc_p, struct type *value_type)
{
enum x86_64_reg_class class[MAX_CLASSES];
@@ -550,7 +505,7 @@ x86_64_use_struct_convention (int gcc_p,
function return value of TYPE, and copy that, in virtual format,
into VALBUF. */
-void
+static void
x86_64_extract_return_value (struct type *type, struct regcache *regcache,
void *valbuf)
{
@@ -561,15 +516,15 @@ x86_64_extract_return_value (struct type
int intreg = 0;
int ssereg = 0;
int offset = 0;
- int ret_int_r[RET_INT_REGS] = { RAX_REGNUM, RDX_REGNUM };
- int ret_sse_r[RET_SSE_REGS] = { XMM0_REGNUM, XMM1_REGNUM };
+ int ret_int_r[RET_INT_REGS] = { X86_64_RAX_REGNUM, X86_64_RDX_REGNUM };
+ int ret_sse_r[RET_SSE_REGS] = { X86_64_XMM0_REGNUM, X86_64_XMM1_REGNUM };
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;
- regcache_cooked_read (regcache, RAX_REGNUM, &addr);
+ regcache_cooked_read (regcache, X86_64_RAX_REGNUM, &addr);
read_memory (addr, valbuf, TYPE_LENGTH (type));
return;
}
@@ -610,12 +565,12 @@ x86_64_extract_return_value (struct type
ssereg++;
break;
case X86_64_X87_CLASS:
- regcache_cooked_read_part (regcache, FP0_REGNUM,
+ regcache_cooked_read_part (regcache, X86_64_ST0_REGNUM,
0, 8, (char *) valbuf + offset);
offset += 8;
break;
case X86_64_X87UP_CLASS:
- regcache_cooked_read_part (regcache, FP0_REGNUM,
+ regcache_cooked_read_part (regcache, X86_64_ST0_REGNUM,
8, 2, (char *) valbuf + offset);
offset += 8;
break;
@@ -628,33 +583,29 @@ x86_64_extract_return_value (struct type
}
}
-static void
-x86_64_frame_init_saved_regs (struct frame_info *fi)
-{
- /* Do nothing. Everything is handled by the stack unwinding code. */
-}
-
#define INT_REGS 6
-#define SSE_REGS 16
+#define SSE_REGS 8
-CORE_ADDR
-x86_64_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+static CORE_ADDR
+x86_64_push_arguments (struct regcache *regcache, int nargs,
+ struct value **args, CORE_ADDR sp)
{
int intreg = 0;
int ssereg = 0;
int i;
- static int int_parameter_registers[INT_REGS] = {
- 5 /* RDI */ , 4 /* RSI */ ,
- 3 /* RDX */ , 2 /* RCX */ ,
- 8 /* R8 */ , 9 /* R9 */
+ static int int_parameter_registers[INT_REGS] =
+ {
+ X86_64_RDI_REGNUM, 4, /* %rdi, %rsi */
+ X86_64_RDX_REGNUM, 2, /* %rdx, %rcx */
+ 8, 9 /* %r8, %r9 */
};
- /* XMM0 - XMM15 */
- static int sse_parameter_registers[SSE_REGS] = {
- XMM1_REGNUM - 1, XMM1_REGNUM, XMM1_REGNUM + 1, XMM1_REGNUM + 2,
- XMM1_REGNUM + 3, XMM1_REGNUM + 4, XMM1_REGNUM + 5, XMM1_REGNUM + 6,
- XMM1_REGNUM + 7, XMM1_REGNUM + 8, XMM1_REGNUM + 9, XMM1_REGNUM + 10,
- XMM1_REGNUM + 11, XMM1_REGNUM + 12, XMM1_REGNUM + 13, XMM1_REGNUM + 14
+ /* %xmm0 - %xmm7 */
+ static int sse_parameter_registers[SSE_REGS] =
+ {
+ X86_64_XMM0_REGNUM + 0, X86_64_XMM1_REGNUM,
+ X86_64_XMM0_REGNUM + 2, X86_64_XMM0_REGNUM + 3,
+ X86_64_XMM0_REGNUM + 4, X86_64_XMM0_REGNUM + 5,
+ X86_64_XMM0_REGNUM + 6, X86_64_XMM0_REGNUM + 7,
};
int stack_values_count = 0;
int *stack_values;
@@ -684,19 +635,18 @@ x86_64_push_arguments (int nargs, struct
case X86_64_NO_CLASS:
break;
case X86_64_INTEGER_CLASS:
- deprecated_write_register_gen (int_parameter_registers
- [(intreg + 1) / 2],
- VALUE_CONTENTS_ALL (args[i]) + offset);
+ regcache_cooked_write
+ (regcache, int_parameter_registers[(intreg + 1) / 2],
+ VALUE_CONTENTS_ALL (args[i]) + offset);
offset += 8;
intreg += 2;
break;
case X86_64_INTEGERSI_CLASS:
{
- LONGEST num
- = extract_signed_integer (VALUE_CONTENTS_ALL (args[i])
- + offset, 4);
- regcache_raw_write_signed (current_regcache,
- int_parameter_registers[intreg / 2], num);
+ LONGEST val = extract_signed_integer
+ (VALUE_CONTENTS_ALL (args[i]) + offset, 4);
+ regcache_cooked_write_signed
+ (regcache, int_parameter_registers[intreg / 2], val);
offset += 8;
intreg++;
@@ -705,15 +655,16 @@ x86_64_push_arguments (int nargs, struct
case X86_64_SSEDF_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSE_CLASS:
- deprecated_write_register_gen (sse_parameter_registers
- [(ssereg + 1) / 2],
- VALUE_CONTENTS_ALL (args[i]) + offset);
+ regcache_cooked_write
+ (regcache, sse_parameter_registers[(ssereg + 1) / 2],
+ VALUE_CONTENTS_ALL (args[i]) + offset);
offset += 8;
ssereg += 2;
break;
case X86_64_SSEUP_CLASS:
- deprecated_write_register_gen (sse_parameter_registers[ssereg / 2],
- VALUE_CONTENTS_ALL (args[i]) + offset);
+ regcache_cooked_write
+ (regcache, sse_parameter_registers[ssereg / 2],
+ VALUE_CONTENTS_ALL (args[i]) + offset);
offset += 8;
ssereg++;
break;
@@ -732,21 +683,25 @@ x86_64_push_arguments (int nargs, struct
}
}
}
+
+ /* Push any remaining arguments onto the stack. */
while (--stack_values_count >= 0)
{
struct value *arg = args[stack_values[stack_values_count]];
int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg));
- len += 7;
- len -= len % 8;
- sp -= len;
+
+ /* Make sure the stack stays eightbyte-aligned. */
+ sp -= (len + 7) & ~7;
write_memory (sp, VALUE_CONTENTS_ALL (arg), len);
}
+
return sp;
}
/* Write into the appropriate registers a function return value stored
in VALBUF of type TYPE, given in virtual format. */
-void
+
+static void
x86_64_store_return_value (struct type *type, struct regcache *regcache,
const void *valbuf)
{
@@ -754,27 +709,32 @@ x86_64_store_return_value (struct type *
if (TYPE_CODE_FLT == TYPE_CODE (type))
{
- /* 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. */
- regcache_cooked_write (regcache, FP0_REGNUM, valbuf);
- }
- else
- {
- char buf[FPU_REG_RAW_SIZE];
- DOUBLEST val;
+ ULONGEST fstat;
+ char buf[FPU_REG_RAW_SIZE];
- /* 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 = deprecated_extract_floating (valbuf, TYPE_LENGTH (type));
- floatformat_from_doublest (&floatformat_i387_ext, &val, buf);
- regcache_cooked_write_part (regcache, FP0_REGNUM,
- 0, FPU_REG_RAW_SIZE, buf);
- }
+ /* Returning floating-point values is a bit tricky. Apart from
+ storing the return value in %st(0), we have to simulate the
+ state of the FPU at function return point. */
+
+ /* 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. */
+ convert_typed_floating (valbuf, type, buf, builtin_type_i387_ext);
+ regcache_raw_write (regcache, X86_64_ST0_REGNUM, buf);
+
+ /* Set the top of the floating-point register stack to 7. The
+ actual value doesn't really matter, but 7 is what a normal
+ function return would end up with if the program started out
+ with a freshly initialized FPU. */
+ regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat);
+ fstat |= (7 << 11);
+ regcache_raw_write_unsigned (regcache, FSTAT_REGNUM, fstat);
+
+ /* Mark %st(1) through %st(7) as empty. Since we set the top of
+ the floating-point register stack to 7, the appropriate value
+ for the tag word is 0x3fff. */
+ regcache_raw_write_unsigned (regcache, FTAG_REGNUM, 0x3fff);
}
else
{
@@ -797,119 +757,385 @@ x86_64_store_return_value (struct type *
}
\f
-const char *
-x86_64_register_name (int reg_nr)
+static CORE_ADDR
+x86_64_push_dummy_call (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR dummy_addr, int nargs, struct value **args,
+ CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr)
{
- if (reg_nr < 0 || reg_nr >= X86_64_NUM_REGS)
- return NULL;
- return x86_64_register_info_table[reg_nr].name;
+ char buf[8];
+
+ /* Pass arguments. */
+ sp = x86_64_push_arguments (regcache, nargs, args, sp);
+
+ /* Pass "hidden" argument". */
+ if (struct_return)
+ {
+ store_address (buf, 8, struct_addr);
+ regcache_cooked_write (regcache, X86_64_RDI_REGNUM, buf);
+ }
+
+ /* Store return address. */
+ sp -= 8;
+ store_address (buf, 8, dummy_addr);
+ write_memory (sp, buf, 8);
+
+ /* Finally, update the stack pointer... */
+ store_address (buf, 8, sp);
+ regcache_cooked_write (regcache, X86_64_RSP_REGNUM, buf);
+
+ /* ...and fake a frame pointer. */
+ regcache_cooked_write (regcache, X86_64_RBP_REGNUM, buf);
+
+ return sp;
}
+\f
-int
-x86_64_register_number (const char *name)
+/* The maximum number of saved registers. This should include %rip. */
+#define X86_64_NUM_SAVED_REGS 17
+
+struct x86_64_frame_cache
{
- int reg_nr;
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR sp_offset;
+ CORE_ADDR pc;
+
+ /* Saved registers. */
+ CORE_ADDR saved_regs[X86_64_NUM_SAVED_REGS];
+ CORE_ADDR saved_sp;
+
+ /* Do we have a frame? */
+ int frameless_p;
+};
+
+/* Allocate and initialize a frame cache. */
+
+static struct x86_64_frame_cache *
+x86_64_alloc_frame_cache (void)
+{
+ struct x86_64_frame_cache *cache;
+ int i;
- for (reg_nr = 0; reg_nr < X86_64_NUM_REGS; reg_nr++)
- if (strcmp (name, x86_64_register_info_table[reg_nr].name) == 0)
- return reg_nr;
- return -1;
+ cache = FRAME_OBSTACK_ZALLOC (struct x86_64_frame_cache);
+
+ /* Base address. */
+ cache->base = 0;
+ cache->sp_offset = -8;
+ cache->pc = 0;
+
+ /* Saved registers. We initialize these to -1 since zero is a valid
+ offset (that's where %rbp is supposed to be stored). */
+ for (i = 0; i < X86_64_NUM_SAVED_REGS; i++)
+ cache->saved_regs[i] = -1;
+ cache->saved_sp = 0;
+
+ /* Frameless until proven otherwise. */
+ cache->frameless_p = 1;
+
+ return cache;
}
-\f
-/* Store the address of the place in which to copy the structure the
- subroutine will return. This is called from call_function. */
-void
-x86_64_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+/* Do a limited analysis of the prologue at PC and update CACHE
+ accordingly. Bail out early if CURRENT_PC is reached. Return the
+ address where the analysis stopped.
+
+ We will handle only functions beginning with:
+
+ pushq %rbp 0x55
+ movq %rsp, %rbp 0x48 0x89 0xe5
+
+ Any function that doesn't start with this sequence will be assumed
+ to have no prologue and thus no valid frame pointer in %rbp. */
+
+static CORE_ADDR
+x86_64_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
+ struct x86_64_frame_cache *cache)
{
- write_register (RDI_REGNUM, addr);
+ static unsigned char proto[3] = { 0x48, 0x89, 0xe5 };
+ unsigned char buf[3];
+ unsigned char op;
+
+ if (current_pc <= pc)
+ return current_pc;
+
+ op = read_memory_unsigned_integer (pc, 1);
+
+ if (op == 0x55) /* pushq %rbp */
+ {
+ /* Take into account that we've executed the `pushq %rbp' that
+ starts this instruction sequence. */
+ cache->saved_regs[X86_64_RBP_REGNUM] = 0;
+ cache->sp_offset += 8;
+
+ /* If that's all, return now. */
+ if (current_pc <= pc + 1)
+ return current_pc;
+
+ /* Check for `movq %rsp, %rbp'. */
+ read_memory (pc + 1, buf, 3);
+ if (memcmp (buf, proto, 3) != 0)
+ return pc + 1;
+
+ /* OK, we actually have a frame. */
+ cache->frameless_p = 0;
+ return pc + 4;
+ }
+
+ return pc;
}
-int
-x86_64_frameless_function_invocation (struct frame_info *frame)
+/* Return PC of first real instruction. */
+
+static CORE_ADDR
+x86_64_skip_prologue (CORE_ADDR start_pc)
{
- return 0;
+ struct x86_64_frame_cache cache;
+ CORE_ADDR pc;
+
+ pc = x86_64_analyze_prologue (start_pc, 0xffffffffffffffff, &cache);
+ if (cache.frameless_p)
+ return start_pc;
+
+ return pc;
}
+\f
-/* We will handle only functions beginning with:
- 55 pushq %rbp
- 48 89 e5 movq %rsp,%rbp
- Any function that doesn't start with this sequence
- will be assumed to have no prologue and thus no valid
- frame pointer in %rbp. */
-#define PROLOG_BUFSIZE 4
-int
-x86_64_function_has_prologue (CORE_ADDR pc)
+/* Normal frames. */
+
+static struct x86_64_frame_cache *
+x86_64_frame_cache (struct frame_info *next_frame, void **this_cache)
{
+ struct x86_64_frame_cache *cache;
+ char buf[8];
int i;
- unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 },
- prolog_buf[PROLOG_BUFSIZE];
- read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE);
+ if (*this_cache)
+ return *this_cache;
- /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */
- for (i = 0; i < PROLOG_BUFSIZE; i++)
- if (prolog_expect[i] != prolog_buf[i])
- return 0; /* ... no, it doesn't. Nothing to skip. */
-
- return 1;
+ cache = x86_64_alloc_frame_cache ();
+
+ frame_unwind_register (next_frame, X86_64_RBP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 8);
+ if (cache->base == 0)
+ return cache;
+
+ /* For normal frames, %rip is stored at 8(%rbp). */
+ cache->saved_regs[X86_64_RIP_REGNUM] = 8;
+
+ cache->pc = frame_func_unwind (next_frame);
+ if (cache->pc != 0)
+ x86_64_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
+
+ if (cache->frameless_p)
+ {
+ /* We didn't find a valid frame, which means that CACHE->base
+ currently holds the frame pointer for our calling frame. If
+ we're at the start of a function, or somewhere half-way its
+ prologue, the function's frame probably hasn't been fully
+ setup yet. Try to reconstruct the base address for the stack
+ frame by looking at the stack pointer. For truly "frameless"
+ functions this might work too. */
+
+ frame_unwind_register (next_frame, X86_64_RSP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 8) + cache->sp_offset;
+ }
+
+ /* Now that we have the base address for the stack frame we can
+ calculate the value of %rsp in the calling frame. */
+ cache->saved_sp = cache->base + 16;
+
+ /* Adjust all the saved registers such that they contain addresses
+ instead of offsets. */
+ for (i = 0; i < X86_64_NUM_SAVED_REGS; i++)
+ if (cache->saved_regs[i] != -1)
+ cache->saved_regs[i] += cache->base;
+
+ return cache;
}
-/* If a function with debugging information and known beginning
- is detected, we will return pc of the next line in the source
- code. With this approach we effectively skip the prolog. */
+static void
+x86_64_frame_this_id (struct frame_info *next_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ struct x86_64_frame_cache *cache =
+ x86_64_frame_cache (next_frame, this_cache);
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return;
-CORE_ADDR
-x86_64_skip_prologue (CORE_ADDR pc)
+ /* This is meant to halt the backtrace at "_start". */
+ if (inside_entry_file (cache->pc))
+ return;
+
+ (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static void
+x86_64_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realnump, void *valuep)
{
- int i;
- struct symtab_and_line v_sal;
- struct symbol *v_function;
- CORE_ADDR endaddr;
-
- if (! x86_64_function_has_prologue (pc))
- return pc;
-
- /* OK, we have found the prologue and want PC of the first
- non-prologue instruction. */
- pc += PROLOG_BUFSIZE;
-
- v_function = find_pc_function (pc);
- v_sal = find_pc_line (pc, 0);
-
- /* If pc doesn't point to a function with debuginfo, some of the
- following may be NULL. */
- if (!v_function || !v_function->ginfo.value.block || !v_sal.symtab)
- return pc;
-
- endaddr = BLOCK_END (SYMBOL_BLOCK_VALUE (v_function));
-
- for (i = 0; i < v_sal.symtab->linetable->nitems; i++)
- if (v_sal.symtab->linetable->item[i].pc >= pc
- && v_sal.symtab->linetable->item[i].pc < endaddr)
- {
- pc = v_sal.symtab->linetable->item[i].pc;
- break;
- }
+ struct x86_64_frame_cache *cache =
+ x86_64_frame_cache (next_frame, this_cache);
- return pc;
+ gdb_assert (regnum >= 0);
+
+ if (regnum == SP_REGNUM && cache->saved_sp)
+ {
+ *optimizedp = 0;
+ *lvalp = not_lval;
+ *addrp = 0;
+ *realnump = -1;
+ if (valuep)
+ {
+ /* Store the value. */
+ store_address (valuep, 8, cache->saved_sp);
+ }
+ return;
+ }
+
+ if (regnum < X86_64_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1)
+ {
+ *optimizedp = 0;
+ *lvalp = lval_memory;
+ *addrp = cache->saved_regs[regnum];
+ *realnump = -1;
+ if (valuep)
+ {
+ /* Read the value in from memory. */
+ read_memory (*addrp, valuep,
+ register_size (current_gdbarch, regnum));
+ }
+ return;
+ }
+
+ frame_register_unwind (next_frame, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind x86_64_frame_unwind =
+{
+ NORMAL_FRAME,
+ x86_64_frame_this_id,
+ x86_64_frame_prev_register
+};
+
+static const struct frame_unwind *
+x86_64_frame_p (CORE_ADDR pc)
+{
+ return &x86_64_frame_unwind;
+}
+\f
+
+/* Signal trampolines. */
+
+/* FIXME: kettenis/20030419: Perhaps, we can unify the 32-bit and
+ 64-bit variants. This would require using identical frame caches
+ on both platforms. */
+
+static struct x86_64_frame_cache *
+x86_64_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+ struct x86_64_frame_cache *cache;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ CORE_ADDR addr;
+ char buf[8];
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = x86_64_alloc_frame_cache ();
+
+ frame_unwind_register (next_frame, X86_64_RSP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 8) - 8;
+
+ addr = tdep->sigcontext_addr (next_frame);
+ cache->saved_regs[X86_64_RIP_REGNUM] = addr + tdep->sc_pc_offset;
+ cache->saved_regs[X86_64_RSP_REGNUM] = addr + tdep->sc_sp_offset;
+
+ *this_cache = cache;
+ return cache;
+}
+
+static void
+x86_64_sigtramp_frame_this_id (struct frame_info *next_frame,
+ void **this_cache, struct frame_id *this_id)
+{
+ struct x86_64_frame_cache *cache =
+ x86_64_sigtramp_frame_cache (next_frame, this_cache);
+
+ (*this_id) = frame_id_build (cache->base, frame_pc_unwind (next_frame));
}
static void
+x86_64_sigtramp_frame_prev_register (struct frame_info *next_frame,
+ void **this_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realnump, void *valuep)
+{
+ /* Make sure we've initialized the cache. */
+ x86_64_sigtramp_frame_cache (next_frame, this_cache);
+
+ x86_64_frame_prev_register (next_frame, this_cache, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind x86_64_sigtramp_frame_unwind =
+{
+ SIGTRAMP_FRAME,
+ x86_64_sigtramp_frame_this_id,
+ x86_64_sigtramp_frame_prev_register
+};
+
+static const struct frame_unwind *
+x86_64_sigtramp_frame_p (CORE_ADDR pc)
+{
+ char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ if (PC_IN_SIGTRAMP (pc, name))
+ return &x86_64_sigtramp_frame_unwind;
+
+ return NULL;
+}
+\f
+
+static CORE_ADDR
+x86_64_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+ struct x86_64_frame_cache *cache =
+ x86_64_frame_cache (next_frame, this_cache);
+
+ return cache->base;
+}
+
+static const struct frame_base x86_64_frame_base =
+{
+ &x86_64_frame_unwind,
+ x86_64_frame_base_address,
+ x86_64_frame_base_address,
+ x86_64_frame_base_address
+};
+
+static void
x86_64_save_dummy_frame_tos (CORE_ADDR sp)
{
- /* We must add the size of the return address that is already
- put on the stack. */
- generic_save_dummy_frame_tos (sp +
- TYPE_LENGTH (builtin_type_void_func_ptr));
+ generic_save_dummy_frame_tos (sp + 16);
}
static struct frame_id
-x86_64_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *frame)
+x86_64_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- CORE_ADDR base;
- frame_unwind_unsigned_register (frame, SP_REGNUM, &base);
- return frame_id_build (base, frame_pc_unwind (frame));
+ char buf[8];
+ CORE_ADDR fp;
+
+ frame_unwind_register (next_frame, X86_64_RBP_REGNUM, buf);
+ fp = extract_unsigned_integer (buf, 8);
+
+ return frame_id_build (fp, frame_pc_unwind (next_frame));
}
void
@@ -932,115 +1158,107 @@ x86_64_init_abi (struct gdbarch_info inf
set_gdbarch_long_double_bit (gdbarch, 128);
set_gdbarch_num_regs (gdbarch, X86_64_NUM_REGS);
+ set_gdbarch_register_bytes (gdbarch, x86_64_register_bytes);
+ set_gdbarch_register_name (gdbarch, x86_64_register_name);
+ set_gdbarch_register_size (gdbarch, 8);
+ set_gdbarch_register_type (gdbarch, x86_64_register_type);
/* Register numbers of various important registers. */
- set_gdbarch_sp_regnum (gdbarch, 7); /* %rsp */
- set_gdbarch_deprecated_fp_regnum (gdbarch, 6); /* %rbp */
- set_gdbarch_pc_regnum (gdbarch, 16); /* %rip */
- set_gdbarch_ps_regnum (gdbarch, 17); /* %eflags */
- set_gdbarch_fp0_regnum (gdbarch, X86_64_NUM_GREGS); /* %st(0) */
+ set_gdbarch_sp_regnum (gdbarch, X86_64_RSP_REGNUM); /* %rsp */
+ set_gdbarch_pc_regnum (gdbarch, X86_64_RIP_REGNUM); /* %rip */
+ set_gdbarch_ps_regnum (gdbarch, X86_64_EFLAGS_REGNUM); /* %eflags */
+ set_gdbarch_fp0_regnum (gdbarch, X86_64_ST0_REGNUM); /* %st(0) */
/* The "default" register numbering scheme for the x86-64 is
- referred to as the "DWARF register number mapping" in the psABI.
- The preferred debugging format for all known x86-64 targets is
- actually DWARF2, and GCC doesn't seem to support DWARF (that is
- DWARF-1), but we provide the same mapping just in case. This
- mapping is also used for stabs, which GCC does support. */
- set_gdbarch_stab_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum);
- set_gdbarch_dwarf_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum);
- set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum);
+ referred to as the "DWARF Register Number Mapping" in the System
+ V psABI. The preferred debugging format for all known x86-64
+ targets is actually DWARF2, and GCC doesn't seem to support DWARF
+ (that is DWARF-1), but we provide the same mapping just in case.
+ This mapping is also used for stabs, which GCC does support. */
+ set_gdbarch_stab_reg_to_regnum (gdbarch, x86_64_dwarf_reg_to_regnum);
+ set_gdbarch_dwarf_reg_to_regnum (gdbarch, x86_64_dwarf_reg_to_regnum);
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf_reg_to_regnum);
- /* We don't override SDB_REG_RO_REGNUM, sice COFF doesn't seem to be
- in use on any of the supported x86-64 targets. */
+ /* We don't override SDB_REG_RO_REGNUM, since COFF doesn't seem to
+ be in use on any of the supported x86-64 targets. */
- set_gdbarch_register_name (gdbarch, x86_64_register_name);
- set_gdbarch_register_size (gdbarch, 8);
-
- /* Total amount of space needed to store our copies of the machine's
- register (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS +
- SIZEOF_SSE_REGS) */
- for (i = 0, sum = 0; i < X86_64_NUM_REGS; i++)
- sum += x86_64_register_info_table[i].size;
- set_gdbarch_register_bytes (gdbarch, sum);
-
- set_gdbarch_register_raw_size (gdbarch, x86_64_register_raw_size);
- set_gdbarch_register_byte (gdbarch, x86_64_register_byte);
- set_gdbarch_register_virtual_type (gdbarch, x86_64_register_virtual_type);
-
- set_gdbarch_register_convertible (gdbarch, x86_64_register_convertible);
- set_gdbarch_register_convert_to_virtual (gdbarch,
- x86_64_register_convert_to_virtual);
- set_gdbarch_register_convert_to_raw (gdbarch,
- x86_64_register_convert_to_raw);
-
- /* Getting saved registers is handled by unwind information. */
- set_gdbarch_deprecated_get_saved_register (gdbarch, cfi_get_saved_register);
-
- /* FIXME: kettenis/20021026: Should we set parm_boundary to 64 here? */
- set_gdbarch_deprecated_target_read_fp (gdbarch, cfi_read_fp);
+ /* Call dummy code. */
+ set_gdbarch_push_dummy_call (gdbarch, x86_64_push_dummy_call);
set_gdbarch_extract_return_value (gdbarch, x86_64_extract_return_value);
-
- set_gdbarch_deprecated_push_arguments (gdbarch, x86_64_push_arguments);
- set_gdbarch_deprecated_push_return_address (gdbarch, x86_64_push_return_address);
- set_gdbarch_deprecated_pop_frame (gdbarch, x86_64_pop_frame);
- set_gdbarch_deprecated_store_struct_return (gdbarch, x86_64_store_struct_return);
set_gdbarch_store_return_value (gdbarch, x86_64_store_return_value);
/* Override, since this is handled by x86_64_extract_return_value. */
set_gdbarch_extract_struct_value_address (gdbarch, NULL);
set_gdbarch_use_struct_convention (gdbarch, x86_64_use_struct_convention);
- set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, x86_64_frame_init_saved_regs);
set_gdbarch_skip_prologue (gdbarch, x86_64_skip_prologue);
- set_gdbarch_deprecated_frame_chain (gdbarch, x86_64_linux_frame_chain);
- set_gdbarch_frameless_function_invocation (gdbarch,
- x86_64_frameless_function_invocation);
- /* FIXME: kettenis/20021026: These two are GNU/Linux-specific and
- should be moved elsewhere. */
- set_gdbarch_deprecated_frame_saved_pc (gdbarch, x86_64_linux_frame_saved_pc);
- set_gdbarch_deprecated_saved_pc_after_call (gdbarch, x86_64_linux_saved_pc_after_call);
- set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
- /* FIXME: kettenis/20021026: This one is GNU/Linux-specific too. */
- set_gdbarch_pc_in_sigtramp (gdbarch, x86_64_linux_in_sigtramp);
-
+ /* Avoid wiring in the MMX registers for now. */
set_gdbarch_num_pseudo_regs (gdbarch, 0);
- /* Build call frame information (CFI) from DWARF2 frame debug info. */
- set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info);
-
- /* Initialization of per-frame CFI. */
- set_gdbarch_deprecated_init_extra_frame_info (gdbarch, cfi_init_extra_frame_info);
-
- /* Frame PC initialization is handled by using CFI. */
- set_gdbarch_deprecated_init_frame_pc (gdbarch, x86_64_init_frame_pc);
-
- /* Cons up virtual frame pointer for trace. */
- set_gdbarch_virtual_frame_pointer (gdbarch, cfi_virtual_frame_pointer);
+ set_gdbarch_unwind_dummy_id (gdbarch, x86_64_unwind_dummy_id);
+ set_gdbarch_save_dummy_frame_tos (gdbarch, x86_64_save_dummy_frame_tos);
/* FIXME: kettenis/20021026: This is ELF-specific. Fine for now,
since all supported x86-64 targets are ELF, but that might change
in the future. */
set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
-
- /* Dummy frame helper functions. */
- set_gdbarch_save_dummy_frame_tos (gdbarch, x86_64_save_dummy_frame_tos);
- set_gdbarch_unwind_dummy_id (gdbarch, x86_64_unwind_dummy_id);
+
+ frame_unwind_append_predicate (gdbarch, x86_64_sigtramp_frame_p);
+ frame_unwind_append_predicate (gdbarch, x86_64_frame_p);
+ frame_base_set_default (gdbarch, &x86_64_frame_base);
}
void
_initialize_x86_64_tdep (void)
{
- /* Initialize the table saying where each register starts in the
- register file. */
- {
- int i, offset;
+ int i;
- offset = 0;
- for (i = 0; i < X86_64_NUM_REGS; i++)
- {
- x86_64_register_byte_table[i] = offset;
- offset += x86_64_register_info_table[i].size;
- }
- }
+ /* Total amount of space needed to store our copies of the machine's
+ registers. */
+ for (i = 0; i < X86_64_NUM_REGS; i++)
+ x86_64_register_bytes += TYPE_LENGTH (*x86_64_register_info[i].type);
+}
+\f
+
+#define I387_FISEG_REGNUM FISEG_REGNUM
+#define I387_FOSEG_REGNUM FOSEG_REGNUM
+
+/* The 64-bit FXSAVE format differs from the 32-bit format in the
+ sense that the instruction pointer and data pointer are simply
+ 64-bit offsets into the code segment and the data segment instead
+ of a selector offset pair. The functions below store the upper 32
+ bits of these pointers (instead of just the 16-bits of the segment
+ selector). */
+
+/* Fill GDB's register array with the floating-point and SSE register
+ values in *FXSAVE. This function masks off any of the reserved
+ bits in *FXSAVE. */
+
+void
+x86_64_supply_fxsave (char *fxsave)
+{
+ i387_supply_fxsave (fxsave);
+
+ if (fxsave)
+ {
+ supply_register (I387_FISEG_REGNUM, fxsave + 12);
+ supply_register (I387_FOSEG_REGNUM, fxsave + 20);
+ }
+}
+
+/* Fill register REGNUM (if it is a floating-point or SSE register) in
+ *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
+ this for all registers. This function doesn't touch any of the
+ reserved bits in *FXSAVE. */
+
+void
+x86_64_fill_fxsave (char *fxsave, int regnum)
+{
+ i387_fill_fxsave (fxsave, regnum);
+
+ if (regnum == -1 || regnum == I387_FISEG_REGNUM)
+ regcache_collect (regnum, fxsave + 12);
+ if (regnum == -1 || regnum == I387_FOSEG_REGNUM)
+ regcache_collect (regnum, fxsave + 20);
}
Index: x86-64-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.h,v
retrieving revision 1.14
diff -u -p -r1.14 x86-64-tdep.h
--- x86-64-tdep.h 12 Apr 2003 17:41:26 -0000 1.14
+++ x86-64-tdep.h 17 May 2003 14:58:43 -0000
@@ -1,6 +1,8 @@
-/* Target-dependent code for GDB, the GNU debugger.
- Copyright 2001
+/* Target-dependent code for the x86-64.
+
+ Copyright 2001, 2003
Free Software Foundation, Inc.
+
Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
@@ -28,19 +30,22 @@ struct frame_info;
#include "i386-tdep.h"
-extern int x86_64_num_regs;
-extern int x86_64_num_gregs;
+/* Number of general purpose registers. */
+#define X86_64_NUM_GREGS 22
+
+void x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
-int x86_64_register_number (const char *name);
-const char *x86_64_register_name (int reg_nr);
+/* Fill GDB's register array with the floating-point and SSE register
+ values in *FXSAVE. This function masks off any of the reserved
+ bits in *FXSAVE. */
-gdbarch_deprecated_frame_saved_pc_ftype x86_64_linux_frame_saved_pc;
-gdbarch_deprecated_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call;
-gdbarch_pc_in_sigtramp_ftype x86_64_linux_in_sigtramp;
-CORE_ADDR x86_64_linux_frame_chain (struct frame_info *fi);
-CORE_ADDR x86_64_init_frame_pc (int fromleaf, struct frame_info *fi);
-int x86_64_function_has_prologue (CORE_ADDR pc);
+void x86_64_supply_fxsave (char *fxsave);
-void x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
+/* Fill register REGNUM (if it is a floating-point or SSE register) in
+ *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
+ this for all registers. This function doesn't touch any of the
+ reserved bits in *FXSAVE. */
+
+void x86_64_fill_fxsave (char *fxsave, int regnum);
-#endif
+#endif /* x86-64-tdep.h */
Index: config/i386/nm-x86-64linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/nm-x86-64linux.h,v
retrieving revision 1.1
diff -u -p -r1.1 nm-x86-64linux.h
--- config/i386/nm-x86-64linux.h 1 Jul 2002 22:09:52 -0000 1.1
+++ config/i386/nm-x86-64linux.h 17 May 2003 14:58:43 -0000
@@ -1,7 +1,8 @@
/* Native support for GNU/Linux x86-64.
- Copyright 2001, 2002 Free Software Foundation, Inc. Contributed by
- Jiri Smid, SuSE Labs.
+ Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
@@ -20,13 +21,14 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#ifndef NM_X86_64_H
-#define NM_X86_64_H
-
-#include "config/nm-linux.h"
+#ifndef NM_X86_64_LINUX_H
+#define NM_X86_64_LINUX_H
+/* GNU/Linux supports the i386 hradware debugging registers. */
#define I386_USE_GENERIC_WATCHPOINTS
+
#include "i386/nm-i386.h"
+#include "config/nm-linux.h"
/* Support for 8-byte wide hw watchpoints. */
#define TARGET_HAS_DR_LEN_8 1
@@ -50,41 +52,17 @@ extern unsigned long x86_64_linux_dr_get
x86_64_linux_dr_get_status ()
\f
-#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
+/* Type of the third argument to the `ptrace' system call. */
+#define PTRACE_ARG3_TYPE long
-#define PTRACE_ARG3_TYPE void*
-#define PTRACE_XFER_TYPE unsigned long
-\f
-
-/* 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
+/* Type of the fourth argument to the `ptrace' system call. */
+#define PTRACE_XFER_TYPE long
/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */
#define FETCH_INFERIOR_REGISTERS
+\f
+/* FIXME: kettenis/20030416: Why? */
#undef PREPARE_TO_PROCEED
-#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 */
+#endif /* NM_X86_64_LINUX_H */
Index: config/i386/tm-x86-64linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-x86-64linux.h,v
retrieving revision 1.1
diff -u -p -r1.1 tm-x86-64linux.h
--- config/i386/tm-x86-64linux.h 1 Jul 2002 22:09:52 -0000 1.1
+++ config/i386/tm-x86-64linux.h 17 May 2003 14:58:43 -0000
@@ -1,6 +1,6 @@
/* Definitions to target GDB to GNU/Linux on x86-64.
- Copyright 2002 Free Software Foundation, Inc.
+ Copyright 2002, 2003 Free Software Foundation, Inc.
Contributed by Michal Ludvig, SuSE Labs.
@@ -25,10 +25,10 @@
#define TM_X86_64LINUX_H
/* We define SVR4_SHARED_LIBS unconditionally, on the assumption that
- * link.h is available on all linux platforms. For I386 and SH3/4,
- * we hard-code the information rather than use link.h anyway (for
- * the benefit of cross-debugging). We may move to doing that for
- * other architectures as well. */
+ link.h is available on all linux platforms. For I386 and SH3/4, we
+ hard-code the information rather than use link.h anyway (for the
+ benefit of cross-debugging). We may move to doing that for other
+ architectures as well. */
#define SVR4_SHARED_LIBS
#include "solib.h" /* Support for shared libraries. */
Index: config/i386/x86-64linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/x86-64linux.mh,v
retrieving revision 1.7
diff -u -p -r1.7 x86-64linux.mh
--- config/i386/x86-64linux.mh 1 Jul 2002 22:09:52 -0000 1.7
+++ config/i386/x86-64linux.mh 17 May 2003 14:58:43 -0000
@@ -4,8 +4,9 @@ XM_FILE= xm-i386.h
NAT_FILE= nm-x86-64linux.h
NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
- core-aout.o i386-nat.o x86-64-linux-nat.o \
- proc-service.o thread-db.o lin-lwp.o \
- linux-proc.o gcore.o
+ core-regset.o i386-nat.o x86-64-linux-nat.o \
+ proc-service.o thread-db.o lin-lwp.o inux-proc.o gcore.o
+# The dynamically loaded libthread_db needs access to symbols in the
+# gdb executable.
LOADLIBES = -ldl -rdynamic
Index: config/i386/x86-64linux.mt
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/x86-64linux.mt,v
retrieving revision 1.6
diff -u -p -r1.6 x86-64linux.mt
--- config/i386/x86-64linux.mt 21 Dec 2002 21:09:58 -0000 1.6
+++ config/i386/x86-64linux.mt 17 May 2003 14:58:43 -0000
@@ -1,8 +1,5 @@
# Target: AMD x86-64 running GNU/Linux
-TDEPFILES= x86-64-tdep.o x86-64-linux-tdep.o dwarf2cfi.o \
+TDEPFILES= x86-64-tdep.o x86-64-linux-tdep.o \
i386-tdep.o i387-tdep.o \
solib.o solib-svr4.o solib-legacy.o
-
-GDB_MULTI_ARCH=GDB_MULTI_ARCH_TM
-
TM_FILE=tm-x86-64linux.h
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-17 15:19 [PATCH/i386newframe] amd64newframe Mark Kettenis
@ 2003-05-19 15:31 ` Elena Zannoni
2003-05-19 17:11 ` Mark Kettenis
0 siblings, 1 reply; 14+ messages in thread
From: Elena Zannoni @ 2003-05-19 15:31 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches, mludvig, aj
Mark Kettenis writes:
> Folks,
>
> I've checked in on my i386newframe branch a major overhaul of the
> x86-64 (sub)target to make it fit into the new frame unwindig
> framework. I've tried very hard to reduce the gratuitous differences
> between the i386 and x86_64 stuff, and cleaned things up quite a bit.
> However, this code is *untested*. The code compiles, that is, I can
> build a x86_64-linux cross-debugger on my i386-unknown-freebsd4.7
> system (actually I can't since the final link fails because of a
> problem with the way we do our shared library support). It would be
> great if someone could provide me with access to an amd64 system. If
> it's running *BSD, I can probably add the necessary support for it to
> GDB. Otherwise I'd appreciate it if someone could test this code on
> x86_64-linux.
>
> Mark
>
>
> Index: ChangeLog
> from Mark Kettenis <kettenis@gnu.org>
>
> Revise the x86_64 (sub)taget.
^^^^^^^
typo (meager contribution...:)
I don't know if I can grant you access to some hardware, I'll see what
I can do. However I have tried to run the gdb testsuite.
It is not running too well, I had to kill it because it was hanging,
like this below:
Breakpoint 26, marker2 (a=99) at /home/ezannoni/kettenis-branch/src/gdb/testsuite/gdb.base/break.c:49
49 int marker2 (a) int a; { return (1); }
The program being debugged stopped while in a function called from GDB.
When the function (marker2) is done executing, GDB will silently
stop (instead of continuing to evaluate the expression containing
the function call).
(gdb) PASS: gdb.base/break.exp: hit breakpoint on called function
bt
#0 marker2 (a=99) at /home/ezannoni/kettenis-branch/src/gdb/testsuite/gdb.base/break.c:49
#1 <function called from gdb>
This frame inner-to next frame (corrupt stack?)
(gdb) PASS: gdb.base/break.exp: backtrace while in called function
finish
Run till exit from #0 marker2 (a=99) at /home/ezannoni/kettenis-branch/src/gdb/testsuite/gdb.base/break.c:49
/home/ezannoni/kettenis-branch/src/gdb/dummy-frame.c:317: internal-error: dummy_frame_prev_register: Assertion `dummy != NULL' failed.
A problem internal to GDB has been detected. Further
debugging may prove unreliable.
Quit this debugging session? (y or n) FAIL: gdb.base/break.exp: (timeout) finish from called function
delete breakpoints
Please answer y or n.
Quit this debugging session? (y or n) ERROR: Delete all breakpoints in delete_breakpoints (timeout)
break main
Please answer y or n.
Quit this debugging session? (y or n) UNRESOLVED: gdb.base/break.exp: setting breakpoint at main (timeout)
I get the same internal error also in the inferior function calls tests:
(gdb) PASS: gdb.base/call-ar-st.exp: run until breakpoint set at a line
print print_double_array(double_array)
array_d :
=========
0.000000
23.456700 46.913400 70.370100 93.826800 117.283500 140.740200 164.196900 187.653600
/home/ezannoni/kettenis-branch/src/gdb/dummy-frame.c:317: internal-error: dummy_frame_prev_register: Assertion `dummy != NULL' failed.
A problem internal to GDB has been detected. Further
debugging may prove unreliable.
Quit this debugging session? (y or n) FAIL: gdb.base/call-ar-st.exp: print print_double_array(double_array) (pattern 5 + sentinel) (timeout)
print print_char_array(char_array)
(gdb) p t_char_values(0,0)
/home/ezannoni/kettenis-branch/src/gdb/dummy-frame.c:317: internal-error: dummy_frame_prev_register: Assertion `dummy != NULL' failed.
A problem internal to GDB has been detected. Further
debugging may prove unreliable.
Quit this debugging session? (y or n) ERROR: Got interactive prompt.
UNRESOLVED: gdb.base/callfuncs.exp: p t_char_values(0,0)
print 'A' == iso_8859_1_string[8]
$9 = 0
(gdb) FAIL: gdb.base/charset.exp: check value of parsed character literal in ISO-8859-1
print "abcdefABCDEF012345"
/home/ezannoni/kettenis-branch/src/gdb/dummy-frame.c:317: internal-error: dummy_frame_prev_register: Assertion `dummy != NULL' failed.
A problem internal to GDB has been detected. Further
debugging may prove unreliable.
Quit this debugging session? (y or n) Please answer y or n.
Quit this debugging session? (y or n) Create a core file of GDB? (y or n) Please answer y or n.
Create a core file of GDB? (y or n) Please answer y or n.
Create a core file of GDB? (y or n) ERROR: Got interactive prompt.
UNRESOLVED: gdb.base/charset.exp: parse string literal in ISO-8859-1
ERROR: Got interactive prompt.
It seems to occur at any inferior function call.
Let me see if I can dig further.
elena
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 15:31 ` Elena Zannoni
@ 2003-05-19 17:11 ` Mark Kettenis
2003-05-19 21:24 ` Michal Ludvig
0 siblings, 1 reply; 14+ messages in thread
From: Mark Kettenis @ 2003-05-19 17:11 UTC (permalink / raw)
To: ezannoni; +Cc: gdb-patches, mludvig, aj
From: Elena Zannoni <ezannoni@redhat.com>
Date: Mon, 19 May 2003 11:36:36 -0400
Mark Kettenis writes:
>
> Index: ChangeLog
> from Mark Kettenis <kettenis@gnu.org>
>
> Revise the x86_64 (sub)taget.
^^^^^^^
typo (meager contribution...:)
Lucky me! I get another chance to correct this when I check things in
on mainline.
I don't know if I can grant you access to some hardware, I'll see what
I can do. However I have tried to run the gdb testsuite.
Thanks.
It is not running too well, I had to kill it because it was hanging,
like this below:
Well, at least some things work.
Hmm. Your problems looks very similar to a problem I had on i386.
Looks like the DWARF CFI unwinder and the dummy code don't agree on
the definition of the top of a stack frame. I checked in a patch that
implements a solution that's similar to what I did on i386 (and forgot
to move over to amd64).
Anyway, if you can spare the time to run the testsuite again...
Mark
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 17:11 ` Mark Kettenis
@ 2003-05-19 21:24 ` Michal Ludvig
2003-05-19 21:40 ` Daniel Jacobowitz
2003-05-19 22:24 ` Elena Zannoni
0 siblings, 2 replies; 14+ messages in thread
From: Michal Ludvig @ 2003-05-19 21:24 UTC (permalink / raw)
To: Mark Kettenis; +Cc: ezannoni, gdb-patches, aj
Mark Kettenis wrote:
> Anyway, if you can spare the time to run the testsuite again...
make check always fails for me after a while:
[...]
Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/overlays.exp ...
Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/page.exp ...
Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/pc-fp.exp ...
Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/pointers.exp ...
Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/printcmds.exp ...
ERROR: (DejaGnu) proc "setup_kfail gdb/538 *-*-*" does not exist.
The error code is NONE
The info on the error is:
close: spawn id exp8 not open
while executing
"close -i exp8"
invoked from within
"catch "close -i $spawn_id""
=== gdb Summary ===
# of expected passes 3461
# of unexpected failures 35
# of expected failures 10
# of unresolved testcases 1
# of unsupported tests 1
/tmp/gdbb/gdb/testsuite/../../gdb/gdb version 2003-05-17-cvs -nx
make[1]: *** [just-check] Error 1
make[1]: Leaving directory `/tmp/gdbb/gdb/testsuite'
make: *** [check] Error 2
mludvig@ozzy:/tmp/gdbb/gdb $
What's wrong?
Michal Ludvig
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 21:24 ` Michal Ludvig
@ 2003-05-19 21:40 ` Daniel Jacobowitz
2003-05-19 22:24 ` Elena Zannoni
1 sibling, 0 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2003-05-19 21:40 UTC (permalink / raw)
To: Michal Ludvig; +Cc: Mark Kettenis, ezannoni, gdb-patches, aj
On Mon, May 19, 2003 at 11:18:06PM +0200, Michal Ludvig wrote:
> Mark Kettenis wrote:
> >Anyway, if you can spare the time to run the testsuite again...
>
> make check always fails for me after a while:
> [...]
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/overlays.exp ...
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/page.exp ...
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/pc-fp.exp ...
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/pointers.exp ...
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/printcmds.exp ...
> ERROR: (DejaGnu) proc "setup_kfail gdb/538 *-*-*" does not exist.
> The error code is NONE
> The info on the error is:
> close: spawn id exp8 not open
> while executing
> "close -i exp8"
> invoked from within
> "catch "close -i $spawn_id""
You need a newer version of DejaGNU. Either use the one provided in
the src repository, or install 1.4.3.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 21:24 ` Michal Ludvig
2003-05-19 21:40 ` Daniel Jacobowitz
@ 2003-05-19 22:24 ` Elena Zannoni
1 sibling, 0 replies; 14+ messages in thread
From: Elena Zannoni @ 2003-05-19 22:24 UTC (permalink / raw)
To: Michal Ludvig; +Cc: Mark Kettenis, ezannoni, gdb-patches, aj
Michal Ludvig writes:
> Mark Kettenis wrote:
> > Anyway, if you can spare the time to run the testsuite again...
>
> make check always fails for me after a while:
> [...]
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/overlays.exp ...
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/page.exp ...
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/pc-fp.exp ...
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/pointers.exp ...
> Running /ttt/64/gdb-i386newframe/gdb/testsuite/gdb.base/printcmds.exp ...
> ERROR: (DejaGnu) proc "setup_kfail gdb/538 *-*-*" does not exist.
> The error code is NONE
> The info on the error is:
> close: spawn id exp8 not open
> while executing
> "close -i exp8"
> invoked from within
> "catch "close -i $spawn_id""
>
> === gdb Summary ===
>
> # of expected passes 3461
> # of unexpected failures 35
> # of expected failures 10
> # of unresolved testcases 1
> # of unsupported tests 1
> /tmp/gdbb/gdb/testsuite/../../gdb/gdb version 2003-05-17-cvs -nx
>
> make[1]: *** [just-check] Error 1
> make[1]: Leaving directory `/tmp/gdbb/gdb/testsuite'
> make: *** [check] Error 2
> mludvig@ozzy:/tmp/gdbb/gdb $
>
> What's wrong?
>
> Michal Ludvig
The problem is that the branch was cut w/o dejagnu, tcl, expect. What
I did was this: I copied the dejagnu, expect, tcl source directories
from the mainline onto the checked out branch.
elena
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 17:15 ` Mark Kettenis
2003-05-19 19:54 ` Elena Zannoni
@ 2003-05-20 5:49 ` Michal Ludvig
1 sibling, 0 replies; 14+ messages in thread
From: Michal Ludvig @ 2003-05-20 5:49 UTC (permalink / raw)
To: Mark Kettenis; +Cc: aj, gdb-patches
Mark Kettenis wrote:
> Yes, that would be great. As soon as it performs better than the old
> stuff, I'd like to move things over to mainline.
It's definitely much better than the mainline. I confirm what Elena
pointed out - mainline dies with:
/ttt/64/gdb-head-new/gdb/regcache.c:172: internal-error:
init_regcache_descr: Assertion `!REGISTER_VIRTUAL_TYPE_P ()' failed.
BTW Here is a log of the testsuite of the branch:
http://tmp.logix.cz/gdb/gdb-branch.log
It's the version where last Changelog entry was:
2003-05-19 Mark Kettenis <kettenis@gnu.org>
* x86-64-tdep.c (x86_64_frame_this_id,
x86_64_sigtramp_frame_this_id, x86_64_unwind_dummy_id): Add offset
to the frame base such that we use the same defenition for the top
of stack as DWARF CFI does.
Michal Ludvig
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 19:54 ` Elena Zannoni
@ 2003-05-19 22:31 ` Elena Zannoni
0 siblings, 0 replies; 14+ messages in thread
From: Elena Zannoni @ 2003-05-19 22:31 UTC (permalink / raw)
To: kettenis; +Cc: aj, mludvig, gdb-patches
Elena Zannoni writes:
> Mark Kettenis writes:
> >
> > Yes, that would be great. As soon as it performs better than the old
> > stuff, I'd like to move things over to mainline.
> >
> > Mark
>
>
> For me, I get:
>
> 63 failures in gdb.base
> 25 in gdb.c++
> 50 in gdb.threads
> 24 in gdb.mi
> 6 in gdb.asm
>
> and
>
> 40 ERROR's
>
> === gdb Summary ===
>
> # of expected passes 8523
> # of unexpected failures 177
> # of unexpected successes 3
> # of expected failures 46
> # of known failures 19
> # of unresolved testcases 38
> # of unsupported tests 2
>
>
> not perfect, but, I say, pretty close.
>
> Hmm, I should run the testsuite for mainline too, doh.
>
hmm, gdb in mainline dies at startup:
(gdb) dir /home/ezannoni/gdb-sources/src/gdb/testsuite/gdb.asm
Source directories searched: /home/ezannoni/gdb-sources/src/gdb/testsuite/gdb.asm:$cdir:$cwd
(gdb) file /home/ezannoni/gdb-sources/torrent/gdb/testsuite/gdb.asm/asm-source
/home/ezannoni/gdb-sources/src/gdb/regcache.c:172: internal-error: init_regcache_descr: Assertion `!REGISTER_VIRTUAL_TYPE_P ()' failed.
A problem internal to GDB has been detected. Further
debugging may prove unreliable.
Quit this debugging session? (y or n) ERROR: couldn't load /home/ezannoni/gdb-sources/torrent/gdb/testsuite/gdb.asm/asm-source into /home/ezannoni/gdb-sources/torrent/gdb/testsuite/../../gdb/gdb (timed out).
I think we can merge, if Michal can verify this.
elena
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 17:15 ` Mark Kettenis
@ 2003-05-19 19:54 ` Elena Zannoni
2003-05-19 22:31 ` Elena Zannoni
2003-05-20 5:49 ` Michal Ludvig
1 sibling, 1 reply; 14+ messages in thread
From: Elena Zannoni @ 2003-05-19 19:54 UTC (permalink / raw)
To: Mark Kettenis; +Cc: aj, mludvig, gdb-patches
Mark Kettenis writes:
>
> Yes, that would be great. As soon as it performs better than the old
> stuff, I'd like to move things over to mainline.
>
> Mark
For me, I get:
63 failures in gdb.base
25 in gdb.c++
50 in gdb.threads
24 in gdb.mi
6 in gdb.asm
and
40 ERROR's
=== gdb Summary ===
# of expected passes 8523
# of unexpected failures 177
# of unexpected successes 3
# of expected failures 46
# of known failures 19
# of unresolved testcases 38
# of unsupported tests 2
not perfect, but, I say, pretty close.
Hmm, I should run the testsuite for mainline too, doh.
elena
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 7:09 ` Andreas Jaeger
@ 2003-05-19 17:15 ` Mark Kettenis
2003-05-19 19:54 ` Elena Zannoni
2003-05-20 5:49 ` Michal Ludvig
0 siblings, 2 replies; 14+ messages in thread
From: Mark Kettenis @ 2003-05-19 17:15 UTC (permalink / raw)
To: aj; +Cc: mludvig, gdb-patches
Cc: Mark Kettenis <kettenis@chello.nl>, gdb-patches@sources.redhat.com
From: Andreas Jaeger <aj@suse.de>
Date: Mon, 19 May 2003 09:09:33 +0200
User-Agent: Gnus/5.1003 (Gnus v5.10.3) XEmacs/21.4 (Portable Code, linux)
Content-Type: text/plain; charset=us-ascii
Michal Ludvig <mludvig@suse.cz> writes:
> Mark Kettenis told me that:
>> (gdb) warning: Unmapped DWARF Register #16 encountered
>> 6 return 0;
>> (gdb) warning: Unmapped DWARF Register #16 encountered
>> 7 }
>> Ah, that must be the new DWARF CFI frame unwinder. The return
>> address
>> RA isn't mapped. I could change the DWARF register mapping in
>> x86-64-tdep.c, but this really is a problem with the DWARF CFI frame
>> unwinder since the compiler is free to choose any number it wants for
>> the return address column. Should be fixed now.
>
> IMHO compiler shouldn't choose whatever it wants - RA column is
> defined in the Amd64 ABI (sec.3.6).
Ah, but the DWARF specification allows the compiler to choose the
number of the RA column. Even if the amd64 ABI says the RA is in
column 16, there might be other platforms where the column number
changes from frame to frame. The current code is more correct than
the old code regardless of what we choose to do on amd64.
> Anyway thanks for moving amd64 target to the new unwinder!
Yes, thanks! Michal, can you help testing, please?
Yes, that would be great. As soon as it performs better than the old
stuff, I'd like to move things over to mainline.
Mark
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-19 7:00 ` Michal Ludvig
@ 2003-05-19 7:09 ` Andreas Jaeger
2003-05-19 17:15 ` Mark Kettenis
0 siblings, 1 reply; 14+ messages in thread
From: Andreas Jaeger @ 2003-05-19 7:09 UTC (permalink / raw)
To: Michal Ludvig; +Cc: Mark Kettenis, gdb-patches
Michal Ludvig <mludvig@suse.cz> writes:
> Mark Kettenis told me that:
>> (gdb) warning: Unmapped DWARF Register #16 encountered
>> 6 return 0;
>> (gdb) warning: Unmapped DWARF Register #16 encountered
>> 7 }
>> Ah, that must be the new DWARF CFI frame unwinder. The return
>> address
>> RA isn't mapped. I could change the DWARF register mapping in
>> x86-64-tdep.c, but this really is a problem with the DWARF CFI frame
>> unwinder since the compiler is free to choose any number it wants for
>> the return address column. Should be fixed now.
>
> IMHO compiler shouldn't choose whatever it wants - RA column is
> defined in the Amd64 ABI (sec.3.6).
>
> Anyway thanks for moving amd64 target to the new unwinder!
Yes, thanks! Michal, can you help testing, please?
> BTW could we add amd64 as an alias to x86_64 for configure scripts?
config.* handles it already correctly,
Andreas
--
Andreas Jaeger
SuSE Labs aj@suse.de
private aj@arthur.inka.de
http://www.suse.de/~aj
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-17 22:26 ` Mark Kettenis
@ 2003-05-19 7:00 ` Michal Ludvig
2003-05-19 7:09 ` Andreas Jaeger
0 siblings, 1 reply; 14+ messages in thread
From: Michal Ludvig @ 2003-05-19 7:00 UTC (permalink / raw)
To: Mark Kettenis; +Cc: aj, gdb-patches
Mark Kettenis told me that:
> (gdb)
> warning: Unmapped DWARF Register #16 encountered
>
> 6 return 0;
> (gdb)
> warning: Unmapped DWARF Register #16 encountered
>
> 7 }
>
> Ah, that must be the new DWARF CFI frame unwinder. The return address
> RA isn't mapped. I could change the DWARF register mapping in
> x86-64-tdep.c, but this really is a problem with the DWARF CFI frame
> unwinder since the compiler is free to choose any number it wants for
> the return address column. Should be fixed now.
IMHO compiler shouldn't choose whatever it wants - RA column is defined
in the Amd64 ABI (sec.3.6).
Anyway thanks for moving amd64 target to the new unwinder!
BTW could we add amd64 as an alias to x86_64 for configure scripts?
Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
2003-05-17 18:34 Andreas Jaeger
@ 2003-05-17 22:26 ` Mark Kettenis
2003-05-19 7:00 ` Michal Ludvig
0 siblings, 1 reply; 14+ messages in thread
From: Mark Kettenis @ 2003-05-17 22:26 UTC (permalink / raw)
To: aj; +Cc: gdb-patches, mludvig
From: Andreas Jaeger <aj@suse.de>
Date: Sat, 17 May 2003 20:33:56 +0200
Andreas, thanks for testing this.
building the kettenis-newframe-branch on x86-64 I get:
make[1]: *** No rule to make target `inux-proc.o', needed by `libgdb.a'. Stop.
make[1]: Leaving directory `/usr/src/aj/gdb-test/build/gdb'
make: *** [all-gdb] Error 2
Note the following:
./config/i386/x86-64linux.mh: proc-service.o thread-db.o lin-lwp.o inux-proc.o gcore.o
Oops! Thanks, fixed now.
After fixing this problem, gdb build fine but running it I got:
byrd:/usr/src/aj/gdb-test/build/gdb:[0]$ ./gdb ~/tmp/a.out
A handler for the OS ABI "GNU/Linux" is not built into this configuration of GDB. Attempting to continue with the default i386 settings
Ah, GDB is trying to build a default architecture vector, for which it
happens to choose Linux/i386. This can be solved by linking in
i386-linux-tdep.o. I'll fix this too.
GNU gdb 2003-05-04-cvs
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...
Setting up the environment for debugging gdb.
.gdbinit:5: Error in sourced command file:
Function "internal_error" not defined.
(gdb) b main
Breakpoint 1 at 0x40040c: file b.c, line 4.
(gdb) r
Starting program: /suse/aj/tmp/a.out
Breakpoint 1, main () at b.c:4
4 lg1[1] = 1;
(gdb) n
warning: Unmapped DWARF Register #16 encountered
warning: Unmapped DWARF Register #16 encountered
5 lg2[1] = 1;
(gdb)
warning: Unmapped DWARF Register #16 encountered
6 return 0;
(gdb)
warning: Unmapped DWARF Register #16 encountered
7 }
Ah, that must be the new DWARF CFI frame unwinder. The return address
RA isn't mapped. I could change the DWARF register mapping in
x86-64-tdep.c, but this really is a problem with the DWARF CFI frame
unwinder since the compiler is free to choose any number it wants for
the return address column. Should be fixed now.
And this also:
$ ./gdb /bin/ls
A handler for the OS ABI "GNU/Linux" is not built into this configuration of GDB. Attempting to continue with the default i386 settingsGNU gdb 2003-05-04-cvs
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...
(no debugging symbols found)...
Setting up the environment for debugging gdb.
.gdbinit:5: Error in sourced command file:
Function "internal_error" not defined.
(gdb) b main
Function "main" not defined.
(gdb) r
Starting program: /bin/ls
(no debugging symbols found)...[New Thread 16384 (LWP 4561)]
../../src/gdb/arch-utils.c:443: internal-error: generic_register_size: Assertion `regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS' failed.
A problem internal to GDB has been detected. Further
debugging may prove unreliable.
Hmm. Something is defenitely wrong here. Hard to tell without a
backtrace though what's really wrong.
I don't have time to go into details here but hope that Michal can.
Hope he can.
Thanks again,
Mark
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH/i386newframe] amd64newframe
@ 2003-05-17 18:34 Andreas Jaeger
2003-05-17 22:26 ` Mark Kettenis
0 siblings, 1 reply; 14+ messages in thread
From: Andreas Jaeger @ 2003-05-17 18:34 UTC (permalink / raw)
To: Mark M. Kettenis; +Cc: gdb-patches, Michal Ludvig
Mark,
building the kettenis-newframe-branch on x86-64 I get:
make[1]: *** No rule to make target `inux-proc.o', needed by `libgdb.a'. Stop.
make[1]: Leaving directory `/usr/src/aj/gdb-test/build/gdb'
make: *** [all-gdb] Error 2
Note the following:
./config/i386/x86-64linux.mh: proc-service.o thread-db.o lin-lwp.o inux-proc.o gcore.o
After fixing this problem, gdb build fine but running it I got:
byrd:/usr/src/aj/gdb-test/build/gdb:[0]$ ./gdb ~/tmp/a.out
A handler for the OS ABI "GNU/Linux" is not built into this configuration of GDB. Attempting to continue with the default i386 settingsGNU gdb 2003-05-04-cvs
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...
Setting up the environment for debugging gdb.
.gdbinit:5: Error in sourced command file:
Function "internal_error" not defined.
(gdb) b main
Breakpoint 1 at 0x40040c: file b.c, line 4.
(gdb) r
Starting program: /suse/aj/tmp/a.out
Breakpoint 1, main () at b.c:4
4 lg1[1] = 1;
(gdb) n
warning: Unmapped DWARF Register #16 encountered
warning: Unmapped DWARF Register #16 encountered
5 lg2[1] = 1;
(gdb)
warning: Unmapped DWARF Register #16 encountered
6 return 0;
(gdb)
warning: Unmapped DWARF Register #16 encountered
7 }
And this also:
$ ./gdb /bin/ls
A handler for the OS ABI "GNU/Linux" is not built into this configuration of GDB. Attempting to continue with the default i386 settingsGNU gdb 2003-05-04-cvs
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...
(no debugging symbols found)...
Setting up the environment for debugging gdb.
.gdbinit:5: Error in sourced command file:
Function "internal_error" not defined.
(gdb) b main
Function "main" not defined.
(gdb) r
Starting program: /bin/ls
(no debugging symbols found)...[New Thread 16384 (LWP 4561)]
../../src/gdb/arch-utils.c:443: internal-error: generic_register_size: Assertion `regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS' failed.
A problem internal to GDB has been detected. Further
debugging may prove unreliable.
I don't have time to go into details here but hope that Michal can.
Andreas
--
Andreas Jaeger
SuSE Labs aj@suse.de
private aj@arthur.inka.de
http://www.suse.de/~aj
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2003-05-20 5:49 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-17 15:19 [PATCH/i386newframe] amd64newframe Mark Kettenis
2003-05-19 15:31 ` Elena Zannoni
2003-05-19 17:11 ` Mark Kettenis
2003-05-19 21:24 ` Michal Ludvig
2003-05-19 21:40 ` Daniel Jacobowitz
2003-05-19 22:24 ` Elena Zannoni
2003-05-17 18:34 Andreas Jaeger
2003-05-17 22:26 ` Mark Kettenis
2003-05-19 7:00 ` Michal Ludvig
2003-05-19 7:09 ` Andreas Jaeger
2003-05-19 17:15 ` Mark Kettenis
2003-05-19 19:54 ` Elena Zannoni
2003-05-19 22:31 ` Elena Zannoni
2003-05-20 5:49 ` Michal Ludvig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox