summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-08-21 20:37:30 +0000
committerAndrew Cagney <cagney@redhat.com>2003-08-21 20:37:30 +0000
commit6d333b5ce72ee0126720d4954b0a624559b6fa47 (patch)
tree2f43aee69f46d18303a10877a667e78babbefcca
parentdcdd58b5c48f8ed212d4f5c9db31a46a10c8580d (diff)
downloadgdb-6d333b5ce72ee0126720d4954b0a624559b6fa47.tar.gz
2003-08-21 Andrew Cagney <cagney@redhat.com>
* x86-64-tdep.h (enum x86_64_regnums): Replace #define of X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, X86_64_RDI_REGNUM, X86_64_RBP_REGNUM, X86_64_RSP_REGNUM, X86_64_RIP_REGNUM, X86_64_EFLAGS_REGNUM, X86_64_ST0_REGNUM, X86_64_XMM0_REGNUM, X86_64_XMM1_REGNUM. * x86-64-linux-tdep.h (x86_64_linux_greg_offset): Declare. (x86_64_linux_supply_gregset): Add "sizeof_gregs" param. (x86_64_linux_fill_gregset): Add "sizeof_gregs" param. * x86-64-linux-tdep.c: Include "gdb_assert.h" and "i386-linux-tdep.h". (enum user_regs): Replace user reg #defines, add USER_ORIG_RAX, USER_FS_BASE and USER_GS_BASE. (struct regnum_map, struct regnum_to_user): Define. (x86_64_linux_greg_offset): New function. (user_to_gdb_regmap): Delete. (x86_64_linux_supply_gregset, x86_64_linux_fill_gregset): Use x86_64_linux_greg_offset. (x86_64_core_sniffer): New function (x86_64_core_fns): Set the sniffer to x86_64_core_sniffer. (fetch_core_registers): Pass "core_reg_size" to the supply functions. * x86-64-linux-nat.c (GETREGS_SUPPLIES): Delete macro. (fetch_inferior_registers): Use x86_64_linux_greg_offset. (store_inferior_registers): Ditto. * Makefile.in (x86-64-linux-tdep.o): Update dependencies.
-rw-r--r--gdb/ChangeLog28
-rw-r--r--gdb/x86-64-linux-nat.c8
-rw-r--r--gdb/x86-64-linux-tdep.c234
-rw-r--r--gdb/x86-64-linux-tdep.h6
-rw-r--r--gdb/x86-64-tdep.h72
5 files changed, 289 insertions, 59 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2939178459c..1fe2dc5b612 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,33 @@
2003-08-21 Andrew Cagney <cagney@redhat.com>
+ * x86-64-tdep.h (enum x86_64_regnums): Replace #define of
+ X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, X86_64_RDI_REGNUM,
+ X86_64_RBP_REGNUM, X86_64_RSP_REGNUM, X86_64_RIP_REGNUM,
+ X86_64_EFLAGS_REGNUM, X86_64_ST0_REGNUM, X86_64_XMM0_REGNUM,
+ X86_64_XMM1_REGNUM.
+ * x86-64-linux-tdep.h (x86_64_linux_greg_offset): Declare.
+ (x86_64_linux_supply_gregset): Add "sizeof_gregs" param.
+ (x86_64_linux_fill_gregset): Add "sizeof_gregs" param.
+ * x86-64-linux-tdep.c: Include "gdb_assert.h" and
+ "i386-linux-tdep.h".
+ (enum user_regs): Replace user reg #defines, add USER_ORIG_RAX,
+ USER_FS_BASE and USER_GS_BASE.
+ (struct regnum_map, struct regnum_to_user): Define.
+ (x86_64_linux_greg_offset): New function.
+ (user_to_gdb_regmap): Delete.
+ (x86_64_linux_supply_gregset, x86_64_linux_fill_gregset): Use
+ x86_64_linux_greg_offset.
+ (x86_64_core_sniffer): New function
+ (x86_64_core_fns): Set the sniffer to x86_64_core_sniffer.
+ (fetch_core_registers): Pass "core_reg_size" to the supply
+ functions.
+ * x86-64-linux-nat.c (GETREGS_SUPPLIES): Delete macro.
+ (fetch_inferior_registers): Use x86_64_linux_greg_offset.
+ (store_inferior_registers): Ditto.
+ * Makefile.in (x86-64-linux-tdep.o): Update dependencies.
+
+2003-08-21 Andrew Cagney <cagney@redhat.com>
+
* i386-tdep.h (i386_regnums): Replace I386_EAX_REGNUM,
I386_EDX_REGNUM, I386_ESP_REGNUM, I386_EBP_REGNUM,
I386_EIP_REGNUM, I386_EFLAGS_REGNUM, I386_ST0_REGNUM.
diff --git a/gdb/x86-64-linux-nat.c b/gdb/x86-64-linux-nat.c
index 66a1b68b08a..f589463b61d 100644
--- a/gdb/x86-64-linux-nat.c
+++ b/gdb/x86-64-linux-nat.c
@@ -54,12 +54,8 @@
/* 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)
-
#define GETFPREGS_SUPPLIES(regno) \
(FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
-
/* Transfering the general-purpose registers between GDB, inferiors
and core files. */
@@ -191,7 +187,7 @@ fetch_inferior_registers (int regno)
return;
}
- if (GETREGS_SUPPLIES (regno))
+ if (x86_64_linux_greg_offset (regno) >= 0)
{
fetch_regs (tid);
return;
@@ -228,7 +224,7 @@ store_inferior_registers (int regno)
return;
}
- if (GETREGS_SUPPLIES (regno))
+ if (x86_64_linux_greg_offset (regno) >= 0)
{
store_regs (tid, regno);
return;
diff --git a/gdb/x86-64-linux-tdep.c b/gdb/x86-64-linux-tdep.c
index 7aab1d4e2fa..d01f542339c 100644
--- a/gdb/x86-64-linux-tdep.c
+++ b/gdb/x86-64-linux-tdep.c
@@ -28,50 +28,173 @@
#include "osabi.h"
#include "gdb_string.h"
+#include "gdb_assert.h"
#include "x86-64-tdep.h"
#include "x86-64-linux-tdep.h"
+#include "i386-linux-tdep.h" /* For I386_LINUX_ORIG_EAX_REGNUM. */
/* Register indexes to 'struct user' come from <sys/reg.h>. */
-#define USER_R15 0
-#define USER_R14 1
-#define USER_R13 2
-#define USER_R12 3
-#define USER_RBP 4
-#define USER_RBX 5
-#define USER_R11 6
-#define USER_R10 7
-#define USER_R9 8
-#define USER_R8 9
-#define USER_RAX 10
-#define USER_RCX 11
-#define USER_RDX 12
-#define USER_RSI 13
-#define USER_RDI 14
-#define USER_RIP 16
-#define USER_CS 17
-#define USER_EFLAGS 18
-#define USER_RSP 19
-#define USER_SS 20
-#define USER_DS 23
-#define USER_ES 24
-#define USER_FS 25
-#define USER_GS 26
-
-/* Mapping between the general-purpose registers in `struct user'
- format and GDB's register array layout. */
-
-static int user_to_gdb_regmap[] =
+enum user_regs
{
- USER_RAX, USER_RBX, USER_RCX, USER_RDX,
- USER_RSI, USER_RDI, USER_RBP, USER_RSP,
- USER_R8, USER_R9, USER_R10, USER_R11,
- USER_R12, USER_R13, USER_R14, USER_R15,
- USER_RIP, USER_EFLAGS, USER_CS, USER_SS,
- USER_DS, USER_ES, USER_FS, USER_GS
+ USER_R15,
+ USER_R14,
+ USER_R13,
+ USER_R12,
+ USER_RBP,
+ USER_RBX,
+ USER_R11,
+ USER_R10,
+ USER_R9,
+ USER_R8,
+ USER_RAX,
+ USER_RCX,
+ USER_RDX,
+ USER_RSI,
+ USER_RDI,
+ USER_ORIG_RAX,
+ USER_RIP,
+ USER_CS,
+ USER_EFLAGS,
+ USER_RSP,
+ USER_SS,
+ USER_FS_BASE,
+ USER_GS_BASE,
+ USER_DS,
+ USER_ES,
+ USER_FS,
+ USER_GS,
+ USER_MAX
};
+/* Map from GDB's i386/x86-64 REGNUM indexed general-purpose registers
+ to a `struct user' array of registers.. */
+
+struct regnum_map
+{
+ int regnum;
+ int user;
+};
+
+struct regnum_to_user
+{
+ long nr;
+ const struct regnum_map *map;
+};
+
+long
+x86_64_linux_greg_offset (int regnum)
+{
+ const static struct regnum_map i386_regnum_map[] =
+ {
+ { I386_EAX_REGNUM, USER_RAX },
+ { I386_ECX_REGNUM, USER_RCX },
+ { I386_EDX_REGNUM, USER_RDX },
+ { I386_EBX_REGNUM, USER_RBX },
+ { I386_ESP_REGNUM, USER_RSP },
+ { I386_EBP_REGNUM, USER_RBP },
+ { I386_ESI_REGNUM, USER_RSI },
+ { I386_EDI_REGNUM, USER_RDI },
+ { I386_EIP_REGNUM, USER_RIP },
+ { I386_EFLAGS_REGNUM, USER_EFLAGS },
+ { I386_CS_REGNUM, USER_CS },
+ { I386_SS_REGNUM, USER_SS },
+ { I386_DS_REGNUM, USER_DS },
+ { I386_ES_REGNUM, USER_ES },
+ { I386_FS_REGNUM, USER_FS },
+ { I386_GS_REGNUM, USER_GS },
+ { I386_ST0_REGNUM, -1 },
+ { I386_ST1_REGNUM, -1 },
+ { I386_ST2_REGNUM, -1 },
+ { I386_ST3_REGNUM, -1 },
+ { I386_ST4_REGNUM, -1 },
+ { I386_ST5_REGNUM, -1 },
+ { I386_ST6_REGNUM, -1 },
+ { I386_ST7_REGNUM, -1 },
+ { I386_FCTRL_REGNUM, -1 },
+ { I386_FSTAT_REGNUM, -1 },
+ { I386_FTAG_REGNUM, -1 },
+ { I386_FISEG_REGNUM, -1 },
+ { I386_FIOFF_REGNUM, -1 },
+ { I386_FOSEG_REGNUM, -1 },
+ { I386_FOOFF_REGNUM, -1 },
+ { I386_FOP_REGNUM, -1 },
+ { I386_XMM0_REGNUM, -1 },
+ { I386_XMM1_REGNUM, -1 },
+ { I386_XMM2_REGNUM, -1 },
+ { I386_XMM3_REGNUM, -1 },
+ { I386_XMM4_REGNUM, -1 },
+ { I386_XMM5_REGNUM, -1 },
+ { I386_XMM6_REGNUM, -1 },
+ { I386_XMM7_REGNUM, -1 },
+ { I386_MXCSR_REGNUM, -1 },
+ { I386_LINUX_ORIG_EAX_REGNUM, USER_ORIG_RAX },
+ };
+ const static struct regnum_to_user i386_regnum_to_user =
+ {
+ ARRAY_SIZE (i386_regnum_map), i386_regnum_map
+ };
+ const static struct regnum_map x86_64_regnum_map[] =
+ {
+ { X86_64_RAX_REGNUM, USER_RAX },
+ { X86_64_RBX_REGNUM, USER_RBX },
+ { X86_64_RCX_REGNUM, USER_RCX },
+ { X86_64_RDX_REGNUM, USER_RDX },
+ { X86_64_RSI_REGNUM, USER_RSI },
+ { X86_64_RDI_REGNUM, USER_RDI },
+ { X86_64_RBP_REGNUM, USER_RBP },
+ { X86_64_RSP_REGNUM, USER_RSP },
+ { X86_64_R8_REGNUM, USER_R8 },
+ { X86_64_R9_REGNUM, USER_R9 },
+ { X86_64_R10_REGNUM, USER_R10 },
+ { X86_64_R11_REGNUM, USER_R11 },
+ { X86_64_R12_REGNUM, USER_R12 },
+ { X86_64_R13_REGNUM, USER_R13 },
+ { X86_64_R14_REGNUM, USER_R14 },
+ { X86_64_R15_REGNUM, USER_R15 },
+ { X86_64_RIP_REGNUM, USER_RIP },
+ { X86_64_EFLAGS_REGNUM, USER_EFLAGS },
+ /* { X86_64_CS_REGNUM, USER_CS }, */
+ /* { X86_64_SS_REGNUM, USER_SS }, */
+ { X86_64_DS_REGNUM, USER_DS },
+ { X86_64_ES_REGNUM, USER_ES },
+ { X86_64_FS_REGNUM, USER_FS },
+ { X86_64_GS_REGNUM, USER_GS },
+ };
+ const static struct regnum_to_user x86_64_regnum_to_user =
+ {
+ ARRAY_SIZE (x86_64_regnum_map), x86_64_regnum_map
+ };
+ const struct regnum_to_user *regnum_to_user;
+
+ gdb_assert (TARGET_ARCHITECTURE->arch == bfd_arch_i386);
+ switch (TARGET_ARCHITECTURE->mach)
+ {
+ case bfd_mach_i386_i386:
+ case bfd_mach_i386_i386_intel_syntax:
+ regnum_to_user = &i386_regnum_to_user;
+ break;
+ case bfd_mach_x86_64:
+ case bfd_mach_x86_64_intel_syntax:
+ regnum_to_user = &x86_64_regnum_to_user;
+ break;
+ case bfd_mach_i386_i8086:
+ /* Better suggestion? */
+ return -1;
+ default:
+ internal_error (__FILE__, __LINE__, "bad_switch");
+ }
+ if (regnum < 0)
+ return USER_MAX * 8;
+ if (regnum >= regnum_to_user->nr)
+ return -1;
+ gdb_assert (regnum_to_user->map[regnum].regnum == regnum);
+ if (regnum_to_user->map[regnum].user < 0)
+ return -1;
+ return regnum_to_user->map[regnum].user * 8;
+}
+
/* Fill GDB's register array with the general-purpose register values
in *GREGSETP. */
@@ -79,9 +202,15 @@ void
x86_64_linux_supply_gregset (char *regp)
{
int i;
+ char buf[MAX_REGISTER_SIZE];
+ int bad = 0;
- for (i = 0; i < X86_64_NUM_GREGS; i++)
- supply_register (i, regp + (user_to_gdb_regmap[i] * 8));
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ long offset = x86_64_linux_greg_offset (i);
+ if (offset >= 0)
+ supply_register (i, regp + offset);
+ }
}
/* Fill register REGNO (if it is a general-purpose register) in
@@ -93,9 +222,20 @@ x86_64_linux_fill_gregset (char *regp, int regno)
{
int i;
- for (i = 0; i < X86_64_NUM_GREGS; i++)
+ for (i = 0; i < NUM_REGS; i++)
if (regno == -1 || regno == i)
- regcache_collect (i, regp + (user_to_gdb_regmap[i] * 8));
+ {
+ long offset = x86_64_linux_greg_offset (i);
+ if (offset >= 0)
+ {
+ char buf[MAX_REGISTER_SIZE];
+ memset (buf, 0, sizeof buf);
+ /* Assume little endian - LHS of buffer is the correct
+ place to put the collected bytes. */
+ regcache_collect (i, buf);
+ memcpy (regp + offset, buf, 8);
+ }
+ }
}
/* The register sets used in GNU/Linux ELF core-dumps are identical to
@@ -111,7 +251,7 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
switch (which)
{
case 0: /* Integer registers. */
- if (core_reg_size != 216)
+ if (x86_64_linux_greg_offset (-1) > core_reg_size)
warning ("Wrong size register set in core file.");
else
x86_64_linux_supply_gregset (core_reg_sect);
@@ -132,11 +272,23 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
}
}
+static int
+x86_64_core_sniffer (struct core_fns *our_fns, bfd *abfd)
+{
+ int result;
+
+ result = ((bfd_get_flavour (abfd) == our_fns -> core_flavour)
+ && bfd_get_arch (abfd) == bfd_arch_i386
+ && (bfd_get_mach (abfd) == bfd_mach_x86_64
+ || bfd_get_mach (abfd) == bfd_mach_x86_64_intel_syntax));
+ return (result);
+}
+
static struct core_fns x86_64_core_fns =
{
bfd_target_elf_flavour, /* core_flavour */
default_check_format, /* check_format */
- default_core_sniffer, /* core_sniffer */
+ x86_64_core_sniffer, /* core_sniffer */
fetch_core_registers, /* core_read_registers */
NULL /* next */
};
diff --git a/gdb/x86-64-linux-tdep.h b/gdb/x86-64-linux-tdep.h
index a135cfafb88..c8324c87b3a 100644
--- a/gdb/x86-64-linux-tdep.h
+++ b/gdb/x86-64-linux-tdep.h
@@ -36,4 +36,10 @@ void x86_64_linux_supply_gregset (char *regp);
void x86_64_linux_fill_gregset (char *regp, int regno);
+/* Given a GDB REGNUM, return the byte offset in the target's GREGs
+ buffer, or -1 if there is no corresponding GREGSET / FPREGSET
+ entry. Given a -ve REGNUM, returns the GREG's upper bound. */
+
+extern long x86_64_linux_greg_offset (int regnum);
+
#endif /* x86-64-linux-tdep.h */
diff --git a/gdb/x86-64-tdep.h b/gdb/x86-64-tdep.h
index 608219c578f..4e013f88333 100644
--- a/gdb/x86-64-tdep.h
+++ b/gdb/x86-64-tdep.h
@@ -30,18 +30,66 @@ struct frame_info;
#include "i386-tdep.h"
-/* Register numbers of various important registers. */
-
-#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 */
+/* Register numbers of x86-64 registers. */
+
+enum x86_64_regnums
+{
+ X86_64_RAX_REGNUM,
+ X86_64_RBX_REGNUM,
+ X86_64_RCX_REGNUM,
+ X86_64_RDX_REGNUM,
+ X86_64_RSI_REGNUM,
+ X86_64_RDI_REGNUM,
+ X86_64_RBP_REGNUM,
+ X86_64_RSP_REGNUM,
+ X86_64_R8_REGNUM,
+ X86_64_R9_REGNUM,
+ X86_64_R10_REGNUM,
+ X86_64_R11_REGNUM,
+ X86_64_R12_REGNUM,
+ X86_64_R13_REGNUM,
+ X86_64_R14_REGNUM,
+ X86_64_R15_REGNUM,
+ X86_64_RIP_REGNUM,
+ X86_64_EFLAGS_REGNUM,
+ X86_64_DS_REGNUM,
+ X86_64_ES_REGNUM,
+ X86_64_FS_REGNUM,
+ X86_64_GS_REGNUM,
+ X86_64_ST0_REGNUM,
+ X86_64_ST1_REGNUM,
+ X86_64_ST2_REGNUM,
+ X86_64_ST3_REGNUM,
+ X86_64_ST4_REGNUM,
+ X86_64_ST5_REGNUM,
+ X86_64_ST6_REGNUM,
+ X86_64_ST7_REGNUM,
+ X86_64_FCTRL_REGNUM,
+ X86_64_FSTAT_REGNUM,
+ X86_64_FTAG_REGNUM,
+ X86_64_FISEG_REGNUM,
+ X86_64_FIOFF_REGNUM,
+ X86_64_FOSEG_REGNUM,
+ X86_64_FOOFF_REGNUM,
+ X86_64_FOP_REGNUM,
+ X86_64_XMM0_REGNUM,
+ X86_64_XMM1_REGNUM,
+ X86_64_XMM2_REGNUM,
+ X86_64_XMM3_REGNUM,
+ X86_64_XMM4_REGNUM,
+ X86_64_XMM5_REGNUM,
+ X86_64_XMM6_REGNUM,
+ X86_64_XMM7_REGNUM,
+ X86_64_XMM8_REGNUM,
+ X86_64_XMM9_REGNUM,
+ X86_64_XMM10_REGNUM,
+ X86_64_XMM11_REGNUM,
+ X86_64_XMM12_REGNUM,
+ X86_64_XMM13_REGNUM,
+ X86_64_XMM14_REGNUM,
+ X86_64_XMM15_REGNUM,
+ X86_64_MXCSR_REGNUM
+};
/* Number of general purpose registers. */
#define X86_64_NUM_GREGS 22