This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[rfa] Add 32 bit (i386) support to x86-64-pc-linux-gnu
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Sat, 26 Jul 2003 10:27:54 -0400
- Subject: [rfa] Add 32 bit (i386) support to x86-64-pc-linux-gnu
Hello,
This patch gets 32 (i386) debugging working with an x86-64-pc-linux-gnu
configured GDB.
I should note that there are several ways of doing this. The attached
uses the technique of modifying x86-64 linux nat/tdep files so that they
can supply values to either a 32 or 64 bit formatted register cache.
I know of two problems:
- corefiles
I noticed a combination of problems: i386 linux core file support is in
i386-linux-nat.c so isn't linked into x86-64; x86-64-linux-tdep does
include core file support but it fails to "do the right thing" with 32
bit core files (it should either reject it, or handle it completly).
- threads
The 64 bit libthread db gets loaded, it doesn't recognize the 32 bit
libthread db target. The glibc maintainers know about this problem.
BTW, it also fixes a problem with the old code, the original map table
included "CS" and "SS" but x86-64-pc-linux-gnu doesn't.
Thoughts? 6.0?
Andrew
2003-07-25 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_regnum_to_gnum): Declare.
* 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_regnum_to_gnum): New function.
(user_to_gdb_regmap): Delete.
(x86_64_linux_supply_gregset, x86_64_linux_fill_gregset): Use
x86_64_linux_regnum_to_gnum.
* 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.
* x86-64-linux-nat.c (GETREGS_SUPPLIES): Delete macro.
(fetch_inferior_registers): Use x86_64_linux_regnum_to_gnum.
(store_inferior_registers): Ditto.
* Makefile.in (x86-64-linux-tdep.o): Update dependencies.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.421
diff -u -r1.421 Makefile.in
--- Makefile.in 22 Jul 2003 15:41:59 -0000 1.421
+++ Makefile.in 26 Jul 2003 14:00:17 -0000
@@ -2377,7 +2377,8 @@
$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(gregset_h) \
$(x86_64_tdep_h) $(gdb_proc_service_h)
x86-64-linux-tdep.o: x86-64-linux-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \
- $(regcache_h) $(osabi_h) $(gdb_string_h) $(x86_64_tdep_h)
+ $(regcache_h) $(osabi_h) $(gdb_string_h) $(gdb_assert_h) \
+ $(x86_64_tdep_h) $(x86_64_linux_tdep_h) $(i386_linux_tdep_h)
x86-64-tdep.o: x86-64-tdep.c $(defs_h) \
$(inferior_h) $(gdbcore_h) $(arch_utils_h) $(block_h) \
$(dummy_frame_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \
Index: i386-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.h,v
retrieving revision 1.24
diff -u -r1.24 i386-tdep.h
--- i386-tdep.h 31 May 2003 16:08:05 -0000 1.24
+++ i386-tdep.h 26 Jul 2003 14:00:18 -0000
@@ -142,15 +142,53 @@
#define FDS_REGNUM FOSEG_REGNUM
#define FDOFF_REGNUM FOOFF_REGNUM
-/* Register numbers of various important registers. */
+/* Register numbers for the fixed i386 registers. */
-#define I386_EAX_REGNUM 0 /* %eax */
-#define I386_EDX_REGNUM 2 /* %edx */
-#define I386_ESP_REGNUM 4 /* %esp */
-#define I386_EBP_REGNUM 5 /* %ebp */
-#define I386_EIP_REGNUM 8 /* %eip */
-#define I386_EFLAGS_REGNUM 9 /* %eflags */
-#define I386_ST0_REGNUM 16 /* %st(0) */
+enum i386_regnums
+{
+ I386_EAX_REGNUM,
+ I386_ECX_REGNUM,
+ I386_EDX_REGNUM,
+ I386_EBX_REGNUM,
+ I386_ESP_REGNUM,
+ I386_EBP_REGNUM,
+ I386_ESI_REGNUM,
+ I386_EDI_REGNUM,
+ I386_EIP_REGNUM,
+ I386_EFLAGS_REGNUM,
+ I386_CS_REGNUM,
+ I386_SS_REGNUM,
+ I386_DS_REGNUM,
+ I386_ES_REGNUM,
+ I386_FS_REGNUM,
+ I386_GS_REGNUM,
+ I386_ST0_REGNUM,
+ I386_ST1_REGNUM,
+ I386_ST2_REGNUM,
+ I386_ST3_REGNUM,
+ I386_ST4_REGNUM,
+ I386_ST5_REGNUM,
+ I386_ST6_REGNUM,
+ I386_ST7_REGNUM,
+ I386_FCTRL_REGNUM,
+ I386_FSTAT_REGNUM,
+ I386_FTAG_REGNUM,
+ I386_FISEG_REGNUM,
+ I386_FIOFF_REGNUM,
+ I386_FOSEG_REGNUM,
+ I386_FOOFF_REGNUM,
+ I386_FOP_REGNUM,
+ I386_XMM0_REGNUM,
+ I386_XMM1_REGNUM,
+ I386_XMM2_REGNUM,
+ I386_XMM3_REGNUM,
+ I386_XMM4_REGNUM,
+ I386_XMM5_REGNUM,
+ I386_XMM6_REGNUM,
+ I386_XMM7_REGNUM,
+ I386_MXCSR_REGNUM,
+ I386_ORIG_EAX_REGNUM
+};
#define I386_NUM_GREGS 16
#define I386_NUM_FREGS 16
Index: x86-64-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-linux-nat.c,v
retrieving revision 1.25
diff -u -r1.25 x86-64-linux-nat.c
--- x86-64-linux-nat.c 17 Jul 2003 12:49:52 -0000 1.25
+++ x86-64-linux-nat.c 26 Jul 2003 14:00:18 -0000
@@ -53,12 +53,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. */
@@ -190,7 +186,7 @@
return;
}
- if (GETREGS_SUPPLIES (regno))
+ if (x86_64_linux_regnum_to_gnum (regno) >= 0)
{
fetch_regs (tid);
return;
@@ -227,7 +223,7 @@
return;
}
- if (GETREGS_SUPPLIES (regno))
+ if (x86_64_linux_regnum_to_gnum (regno) >= 0)
{
store_regs (tid, regno);
return;
Index: x86-64-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-linux-tdep.c,v
retrieving revision 1.20
diff -u -r1.20 x86-64-linux-tdep.c
--- x86-64-linux-tdep.c 15 Jul 2003 11:33:59 -0000 1.20
+++ x86-64-linux-tdep.c 26 Jul 2003 14:00:18 -0000
@@ -28,50 +28,169 @@
#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[] =
-{
- 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
+enum user_regs
+{
+ 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
+};
+
+/* 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;
+};
+
+int
+x86_64_linux_regnum_to_gnum (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");
+ }
+ gdb_assert (regnum >= 0);
+ if (regnum >= regnum_to_user->nr)
+ return -1;
+ gdb_assert (regnum_to_user->map[regnum].regnum == regnum);
+ return (regnum_to_user->map[regnum].user);
+}
+
/* Fill GDB's register array with the general-purpose register values
in *GREGSETP. */
@@ -79,9 +198,13 @@
x86_64_linux_supply_gregset (char *regp)
{
int i;
+ char buf[MAX_REGISTER_SIZE];
- 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++)
+ {
+ if (x86_64_linux_regnum_to_gnum (i) >= 0)
+ supply_register (i, regp + (x86_64_linux_regnum_to_gnum (i) * 8));
+ }
}
/* Fill register REGNO (if it is a general-purpose register) in
@@ -93,9 +216,19 @@
{
int i;
- for (i = 0; i < X86_64_NUM_GREGS; i++)
- if (regno == -1 || regno == i)
- regcache_collect (i, regp + (user_to_gdb_regmap[i] * 8));
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ if (regno == -1 || regno == i)
+ if (x86_64_linux_regnum_to_gnum (i) >= 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 + (x86_64_linux_regnum_to_gnum (i) * 8), buf, 8);
+ }
+ }
}
/* The register sets used in GNU/Linux ELF core-dumps are identical to
Index: x86-64-linux-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-linux-tdep.h,v
retrieving revision 1.1
diff -u -r1.1 x86-64-linux-tdep.h
--- x86-64-linux-tdep.h 15 Jul 2003 12:34:08 -0000 1.1
+++ x86-64-linux-tdep.h 26 Jul 2003 14:00:18 -0000
@@ -36,4 +36,10 @@
void x86_64_linux_fill_gregset (char *regp, int regno);
+/* Given a GDB REGNUM, return the corresponding GREGSET / FPREGSET
+ register number, or -1 if there is no corresponding GREGSET /
+ FPREGSET number. */
+
+extern int x86_64_linux_regnum_to_gnum (int regnum);
+
#endif /* x86-64-linux-tdep.h */
Index: x86-64-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.h,v
retrieving revision 1.16
diff -u -r1.16 x86-64-tdep.h
--- x86-64-tdep.h 9 Jul 2003 22:10:58 -0000 1.16
+++ x86-64-tdep.h 26 Jul 2003 14:00:18 -0000
@@ -30,18 +30,66 @@
#include "i386-tdep.h"
-/* Register numbers of various important registers. */
+/* Register numbers of x86-64 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 */
+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