Re: PING: PATCH: PR backtrace/14646: [x32] backtrace doesn't work

H.J. Lu
2012-10-11T22:34:26Z

On Tue, Oct 09, 2012 at 05:47:53PM +0200, Mark Kettenis wrote:
> > >
> > > X32 needs to set RSP/RIP to 32-bit. Othewise, it won't work with gdbserver
> > > since gdbserver will send 64-bit RSP/RIP while gdb sets size of RSP/RIP
> > > to pointer size, which is 32-bit for x32. It works for x32 since the
> > > upper 32bits of RSP/RIP are always zero for x32. OK for trunk and 7.5
> > > branch.
> >
> > At least you figured out that your previous diff didn't work all by
> > yourself. How about actually testing your diffs *before* you mail
> > them out?
>
> Oh, and even if this diff accidentally happens to work, it is a really
> bad idea. You won't be able to diagnose problems caused by one of the
> upper 32 bits getting set in %rsp or %rip.
>

Here is a patch to use 32-bit %esp/%eip with read-only 64-bit %rsp and
%rip for x32. GDB will treat SP and PC as 32-bits for x32. Read-only
64-bit %rsp and %rip are provided in case ones want to see them. They are
retrieved as RSP/RIP registers from kernel, not updated by GDB itself.
As the result, read-only %rip is different from %eip by one byte:

[hjl@gnu-tools-1 x32-1]$ ./gdb-x32 ./a.out
GNU gdb (GDB) 7.5.50.20121011-cvs
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show
copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /export/home/hjl/bugs/gdb/x32-1/a.out...done.
(gdb) b main
Breakpoint 1 at 0x400394: file foo.c, line 9.
(gdb) r
Starting program: /export/home/hjl/bugs/gdb/x32-1/a.out

Breakpoint 1, main () at foo.c:9
9 bar ();
(gdb) p $pc
$1 = (void (*)()) 0x400394 <main+3>
(gdb) p $eip
$2 = (void (*)()) 0x400394 <main+3>
(gdb) p/x $rip
$3 = 0x400395
(gdb) disass
Dump of assembler code for function main:
0x00400391 <+0>: push %rbp
0x00400392 <+1>: mov %esp,%ebp
=> 0x00400394 <+3>: mov $0x0,%eax
0x00400399 <+8>: callq 0x40038c <bar>
0x0040039e <+13>: mov $0x0,%eax
0x004003a3 <+18>: pop %rbp
0x004003a4 <+19>: retq
End of assembler dump.
(gdb) p $sp
$4 = (void *) 0xffffd090
(gdb) p $esp
$5 = (void *) 0xffffd090
(gdb) p/x $rsp
$6 = 0xffffd090
(gdb)

It fixed 2507 failures in GDB testsuite on Linux/x32 with no
regressions on Linux/ia32 and Linux/x86-64. OK to install?

Thanks.

H.J.
---
gdb/

2012-10-11 H.J. Lu <hongjiu.lu@intel.com>

PR backtrace/14646
PR gdb/14647
* amd64-linux-tdep.c (amd64_linux_gregset_reg_offset): Add
read-only %rsp and %rip.
(amd64_linux_register_reggroup_p): Ignore read-only rsp/rip
registers.
(amd64_linux_init_abi): Exclude read-only rsp/rip when
setting gregset_num_regs and calling set_gdbarch_num_regs.
(amd64_x32_linux_cannot_store_register): New function.
(amd64_x32_linux_init_abi): Use it. Handle read-only rsp/rip
registers.
* amd64-linux-tdep.h (AMD64_LINUX_READONLY_RSP_REGNUM): New.
(AMD64_LINUX_READONLY_RIP_REGNUM): Likewise.
(AMD64_LINUX_NUM_REGS): Replace AMD64_LINUX_ORIG_RAX_REGNUM
with AMD64_LINUX_READONLY_RIP_REGNUM.
* amd64-tdep.c (amd64_x32_register_names): New.
(amd64_dword_names): Remove "eip".
(amd64_x32_pseudo_register_type): Don't handle %esp/%eip here.
(amd64_x32_init_abi): Use it. Don't set num_dword_regs,
sp_regnum_from_eax nor pc_regnum_from_eax.
* i386-tdep.h (gdbarch_tdep): Remove sp_regnum_from_eax and
pc_regnum_from_eax.
* i386-tdep.c (i386_gdbarch_init): Don't use sp_regnum_from_eax
nor pc_regnum_from_eax.
* features/Makefile (i386/x32-expedite): Relace rsp,rip with
esp,eip.
(i386/x32-linux-expedite): Likewise.
(i386/x32-avx-expedite): Likewise.
(i386/x32-avx-linux-expedite): Likewise.
* features/i386/x32-avx-linux.xml: Include x32-readonly.xml.
* features/i386/x32-linux.xml: Likewise.
* features/i386/x32-core.xml: Replace 64-bit rsp/rip with
32-bit esp/eip.
* features/i386/x32-readonly.xml: New file.
* features/i386/x32-avx-linux.c: Regenerated.
* features/i386/x32-avx.c: Likewise.
* features/i386/x32-linux.c: Likewise.
* features/i386/x32.c: Likewise.
* regformats/i386/x32-avx-linux.dat: Likewise.
* regformats/i386/x32-avx.dat: Likewise.
* regformats/i386/x32-linux.dat: Likewise.
* regformats/i386/x32.dat: Likewise.

gdb/gdbserver/

2012-10-11 H.J. Lu <hongjiu.lu@intel.com>

* configure.srv (srv_i386_64bit_xmlfiles): Add
i386/x32-readonly.xml.

* linux-x86-low.c (linux_is_elf64): Moved forward.
(x86_store_gregset): Supply read-only rsp and rsp registers for
x32.

diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index d919216..f5e87f4 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -96,7 +96,9 @@ int amd64_linux_gregset_reg_offset[] =
-1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 15 * 8 /* "orig_rax" */
+ 15 * 8, /* "orig_rax" */
+ 19 * 8, /* read-only %rsp */
+ 16 * 8 /* read-only %rip */
};
\f

@@ -281,6 +283,12 @@ amd64_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
return (group == system_reggroup
|| group == save_reggroup
|| group == restore_reggroup);
+ else if (regnum == AMD64_LINUX_READONLY_RSP_REGNUM
+ || regnum == AMD64_LINUX_READONLY_RIP_REGNUM)
+ {
+ /* Ignore read-only %rsp and %rip. */
+ return 0;
+ }
return i386_register_reggroup_p (gdbarch, regnum, group);
}

@@ -1538,13 +1546,14 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
gdb_assert (tdesc_data);

tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset;
- tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
+ /* Exclude read-only rsp/rip. */
+ tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset) - 2;
tdep->sizeof_gregset = 27 * 8;

amd64_init_abi (info, gdbarch);

- /* Reserve a number for orig_rax. */
- set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS);
+ /* Reserve a number for orig_rax without read-only rsp/rip. */
+ set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS - 2);

if (! tdesc_has_registers (tdesc))
tdesc = tdesc_amd64_linux;
@@ -1567,6 +1576,15 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
(gdbarch, svr4_lp64_fetch_link_map_offsets);
}

+/* Nonzero if regno should not be written to the target. */
+
+static int
+amd64_x32_linux_cannot_store_register (struct gdbarch *gdbarch, int regno)
+{
+ return (regno == AMD64_LINUX_READONLY_RSP_REGNUM
+ || regno == AMD64_LINUX_READONLY_RIP_REGNUM);
+}
+
static void
amd64_x32_linux_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -1584,7 +1602,10 @@ amd64_x32_linux_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)

amd64_x32_init_abi (info, gdbarch);

- /* Reserve a number for orig_rax. */
+ set_gdbarch_cannot_store_register
+ (gdbarch, amd64_x32_linux_cannot_store_register);
+
+ /* Reserve numbers for orig_rax and read-only rsp/rip. */
set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS);

if (! tdesc_has_registers (tdesc))
@@ -1601,6 +1622,22 @@ amd64_x32_linux_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
if (!valid_p)
return;

+ feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.readonly");
+ if (feature == NULL)
+ return;
+
+ valid_p = tdesc_numbered_register (feature, tdesc_data,
+ AMD64_LINUX_READONLY_RSP_REGNUM,
+ "rsp");
+ if (!valid_p)
+ return;
+
+ valid_p = tdesc_numbered_register (feature, tdesc_data,
+ AMD64_LINUX_READONLY_RIP_REGNUM,
+ "rip");
+ if (!valid_p)
+ return;
+
amd64_linux_init_abi_common (info, gdbarch);

/* GNU/Linux uses SVR4-style shared libraries. */
diff --git a/gdb/amd64-linux-tdep.h b/gdb/amd64-linux-tdep.h
index 49bb95e..5046941 100644
--- a/gdb/amd64-linux-tdep.h
+++ b/gdb/amd64-linux-tdep.h
@@ -28,8 +28,14 @@
that the kernel is supposed to restart. */
#define AMD64_LINUX_ORIG_RAX_REGNUM (AMD64_YMM15H_REGNUM + 1)

+/* Read-only %rsp for x32. */
+#define AMD64_LINUX_READONLY_RSP_REGNUM (AMD64_LINUX_ORIG_RAX_REGNUM + 1)
+
+/* Read-only %rip for x32. */
+#define AMD64_LINUX_READONLY_RIP_REGNUM (AMD64_LINUX_READONLY_RSP_REGNUM + 1)
+
/* Total number of registers for GNU/Linux. */
-#define AMD64_LINUX_NUM_REGS (AMD64_LINUX_ORIG_RAX_REGNUM + 1)
+#define AMD64_LINUX_NUM_REGS (AMD64_LINUX_READONLY_RIP_REGNUM + 1)

/* Linux target description. */
extern struct target_desc *tdesc_amd64_linux;
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 8c5b6cc..dc66381 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -76,6 +76,26 @@ static const char *amd64_register_names[] =
"mxcsr",
};

+/* Similar to amd64_register_names, except for esp/eip vs. rsp/rip. */
+
+static const char *amd64_x32_register_names[] =
+{
+ "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "esp",
+
+ /* %r8 is indeed register number 8. */
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "eip", "eflags", "cs", "ss", "ds", "es", "fs", "gs",
+
+ /* %st0 is register number 24. */
+ "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7",
+ "fctrl", "fstat", "ftag", "fiseg", "fioff", "foseg", "fooff", "fop",
+
+ /* %xmm0 is register number 40. */
+ "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
+ "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
+ "mxcsr",
+};
+
static const char *amd64_ymm_names[] =
{
"ymm0", "ymm1", "ymm2", "ymm3",
@@ -258,8 +278,7 @@ static const char *amd64_word_names[] =
static const char *amd64_dword_names[] =
{
"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp",
- "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
- "eip"
+ "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
};

/* Return the name of register REGNUM. */
@@ -2922,10 +2941,7 @@ amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
switch (regnum - tdep->eax_regnum)
{
case AMD64_RBP_REGNUM: /* %ebp */
- case AMD64_RSP_REGNUM: /* %esp */
return builtin_type (gdbarch)->builtin_data_ptr;
- case AMD64_RIP_REGNUM: /* %eip */
- return builtin_type (gdbarch)->builtin_func_ptr;
}

return i386_pseudo_register_type (gdbarch, regnum);
@@ -2943,10 +2959,7 @@ amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdesc = tdesc_x32;
tdep->tdesc = tdesc;

- tdep->sp_regnum_from_eax = AMD64_RSP_REGNUM;
- tdep->pc_regnum_from_eax = AMD64_RIP_REGNUM;
-
- tdep->num_dword_regs = 17;
+ tdep->register_names = amd64_x32_register_names;
set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type);

set_gdbarch_long_bit (gdbarch, 32);
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 79803a5..c8603fb 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -63,10 +63,10 @@ i386/i386-mmx-expedite = ebp,esp,eip
i386/i386-mmx-linux-expedite = ebp,esp,eip
i386/amd64-avx-expedite = rbp,rsp,rip
i386/amd64-avx-linux-expedite = rbp,rsp,rip
-i386/x32-expedite = rbp,rsp,rip
-i386/x32-linux-expedite = rbp,rsp,rip
-i386/x32-avx-expedite = rbp,rsp,rip
-i386/x32-avx-linux-expedite = rbp,rsp,rip
+i386/x32-expedite = rbp,esp,eip
+i386/x32-linux-expedite = rbp,esp,eip
+i386/x32-avx-expedite = rbp,esp,eip
+i386/x32-avx-linux-expedite = rbp,esp,eip
mips-expedite = r29,pc
mips-dsp-expedite = r29,pc
mips64-expedite = r29,pc
diff --git a/gdb/features/i386/x32-avx-linux.c b/gdb/features/i386/x32-avx-linux.c
index 1f39610..1763f5d 100644
--- a/gdb/features/i386/x32-avx-linux.c
+++ b/gdb/features/i386/x32-avx-linux.c
@@ -45,7 +45,7 @@ initialize_tdesc_x32_avx_linux (void)
tdesc_create_reg (feature, "rsi", 4, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "rdi", 5, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "rbp", 6, 1, NULL, 64, "int64");
- tdesc_create_reg (feature, "rsp", 7, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "esp", 7, 1, NULL, 32, "data_ptr");
tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int64");
@@ -54,7 +54,7 @@ initialize_tdesc_x32_avx_linux (void)
tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int64");
- tdesc_create_reg (feature, "rip", 16, 1, NULL, 64, "uint64");
+ tdesc_create_reg (feature, "eip", 16, 1, NULL, 32, "code_ptr");
tdesc_create_reg (feature, "eflags", 17, 1, NULL, 32, "i386_eflags");
tdesc_create_reg (feature, "cs", 18, 1, NULL, 32, "int32");
tdesc_create_reg (feature, "ss", 19, 1, NULL, 32, "int32");
@@ -151,23 +151,27 @@ initialize_tdesc_x32_avx_linux (void)
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux");
tdesc_create_reg (feature, "orig_rax", 57, 1, NULL, 64, "int");

+ feature = tdesc_create_feature (result, "org.gnu.gdb.i386.readonly");
+ tdesc_create_reg (feature, "rsp", 58, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "rip", 59, 1, NULL, 64, "int64");
+
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx");
- tdesc_create_reg (feature, "ymm0h", 58, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm1h", 59, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm2h", 60, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm3h", 61, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm4h", 62, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm5h", 63, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm6h", 64, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm7h", 65, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm8h", 66, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm9h", 67, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm10h", 68, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm11h", 69, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm12h", 70, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm13h", 71, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm14h", 72, 1, NULL, 128, "uint128");
- tdesc_create_reg (feature, "ymm15h", 73, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm0h", 60, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm1h", 61, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm2h", 62, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm3h", 63, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm4h", 64, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm5h", 65, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm6h", 66, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm7h", 67, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm8h", 68, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm9h", 69, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm10h", 70, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm11h", 71, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm12h", 72, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm13h", 73, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm14h", 74, 1, NULL, 128, "uint128");
+ tdesc_create_reg (feature, "ymm15h", 75, 1, NULL, 128, "uint128");

tdesc_x32_avx_linux = result;
}
diff --git a/gdb/features/i386/x32-avx-linux.xml b/gdb/features/i386/x32-avx-linux.xml
index 9ce4b2a..99e5744 100644
--- a/gdb/features/i386/x32-avx-linux.xml
+++ b/gdb/features/i386/x32-avx-linux.xml
@@ -14,5 +14,6 @@
<xi:include href="x32-core.xml"/>
<xi:include href="64bit-sse.xml"/>
<xi:include href="64bit-linux.xml"/>
+ <xi:include href="x32-readonly.xml"/>
<xi:include href="64bit-avx.xml"/>
</target>
diff --git a/gdb/features/i386/x32-avx.c b/gdb/features/i386/x32-avx.c
index fb7a12c..6e6974c 100644
--- a/gdb/features/i386/x32-avx.c
+++ b/gdb/features/i386/x32-avx.c
@@ -43,7 +43,7 @@ initialize_tdesc_x32_avx (void)
tdesc_create_reg (feature, "rsi", 4, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "rdi", 5, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "rbp", 6, 1, NULL, 64, "int64");
- tdesc_create_reg (feature, "rsp", 7, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "esp", 7, 1, NULL, 32, "data_ptr");
tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int64");
@@ -52,7 +52,7 @@ initialize_tdesc_x32_avx (void)
tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int64");
- tdesc_create_reg (feature, "rip", 16, 1, NULL, 64, "uint64");
+ tdesc_create_reg (feature, "eip", 16, 1, NULL, 32, "code_ptr");
tdesc_create_reg (feature, "eflags", 17, 1, NULL, 32, "i386_eflags");
tdesc_create_reg (feature, "cs", 18, 1, NULL, 32, "int32");
tdesc_create_reg (feature, "ss", 19, 1, NULL, 32, "int32");
diff --git a/gdb/features/i386/x32-core.xml b/gdb/features/i386/x32-core.xml
index 1e41417..67c5166 100644
--- a/gdb/features/i386/x32-core.xml
+++ b/gdb/features/i386/x32-core.xml
@@ -34,7 +34,7 @@
<reg name="rsi" bitsize="64" type="int64"/>
<reg name="rdi" bitsize="64" type="int64"/>
<reg name="rbp" bitsize="64" type="int64"/>
- <reg name="rsp" bitsize="64" type="int64"/>
+ <reg name="esp" bitsize="32" type="data_ptr"/>
<reg name="r8" bitsize="64" type="int64"/>
<reg name="r9" bitsize="64" type="int64"/>
<reg name="r10" bitsize="64" type="int64"/>
@@ -44,7 +44,7 @@
<reg name="r14" bitsize="64" type="int64"/>
<reg name="r15" bitsize="64" type="int64"/>

- <reg name="rip" bitsize="64" type="uint64"/>
+ <reg name="eip" bitsize="32" type="code_ptr"/>
<reg name="eflags" bitsize="32" type="i386_eflags"/>
<reg name="cs" bitsize="32" type="int32"/>
<reg name="ss" bitsize="32" type="int32"/>
diff --git a/gdb/features/i386/x32-linux.c b/gdb/features/i386/x32-linux.c
index 387436f..d9c7ecf 100644
--- a/gdb/features/i386/x32-linux.c
+++ b/gdb/features/i386/x32-linux.c
@@ -45,7 +45,7 @@ initialize_tdesc_x32_linux (void)
tdesc_create_reg (feature, "rsi", 4, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "rdi", 5, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "rbp", 6, 1, NULL, 64, "int64");
- tdesc_create_reg (feature, "rsp", 7, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "esp", 7, 1, NULL, 32, "data_ptr");
tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int64");
@@ -54,7 +54,7 @@ initialize_tdesc_x32_linux (void)
tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int64");
- tdesc_create_reg (feature, "rip", 16, 1, NULL, 64, "uint64");
+ tdesc_create_reg (feature, "eip", 16, 1, NULL, 32, "code_ptr");
tdesc_create_reg (feature, "eflags", 17, 1, NULL, 32, "i386_eflags");
tdesc_create_reg (feature, "cs", 18, 1, NULL, 32, "int32");
tdesc_create_reg (feature, "ss", 19, 1, NULL, 32, "int32");
@@ -151,5 +151,9 @@ initialize_tdesc_x32_linux (void)
feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux");
tdesc_create_reg (feature, "orig_rax", 57, 1, NULL, 64, "int");

+ feature = tdesc_create_feature (result, "org.gnu.gdb.i386.readonly");
+ tdesc_create_reg (feature, "rsp", 58, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "rip", 59, 1, NULL, 64, "int64");
+
tdesc_x32_linux = result;
}
diff --git a/gdb/features/i386/x32-linux.xml b/gdb/features/i386/x32-linux.xml
index 6a1bc7f..f4d7c2d 100644
--- a/gdb/features/i386/x32-linux.xml
+++ b/gdb/features/i386/x32-linux.xml
@@ -14,4 +14,5 @@
<xi:include href="x32-core.xml"/>
<xi:include href="64bit-sse.xml"/>
<xi:include href="64bit-linux.xml"/>
+ <xi:include href="x32-readonly.xml"/>
</target>
diff --git a/gdb/features/i386/x32-readonly.xml b/gdb/features/i386/x32-readonly.xml
new file mode 100644
index 0000000..ee3e1e4
--- /dev/null
+++ b/gdb/features/i386/x32-readonly.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2012 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+
+<feature name="org.gnu.gdb.i386.readonly">
+ <reg name="rsp" bitsize="64" type="int64"/>
+ <reg name="rip" bitsize="64" type="int64"/>
+</feature>
diff --git a/gdb/features/i386/x32.c b/gdb/features/i386/x32.c
index 34e5087..f7a2895 100644
--- a/gdb/features/i386/x32.c
+++ b/gdb/features/i386/x32.c
@@ -43,7 +43,7 @@ initialize_tdesc_x32 (void)
tdesc_create_reg (feature, "rsi", 4, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "rdi", 5, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "rbp", 6, 1, NULL, 64, "int64");
- tdesc_create_reg (feature, "rsp", 7, 1, NULL, 64, "int64");
+ tdesc_create_reg (feature, "esp", 7, 1, NULL, 32, "data_ptr");
tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int64");
@@ -52,7 +52,7 @@ initialize_tdesc_x32 (void)
tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int64");
tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int64");
- tdesc_create_reg (feature, "rip", 16, 1, NULL, 64, "uint64");
+ tdesc_create_reg (feature, "eip", 16, 1, NULL, 32, "code_ptr");
tdesc_create_reg (feature, "eflags", 17, 1, NULL, 32, "i386_eflags");
tdesc_create_reg (feature, "cs", 18, 1, NULL, 32, "int32");
tdesc_create_reg (feature, "ss", 19, 1, NULL, 32, "int32");
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index d1e04a9..3a216a9 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -33,7 +33,7 @@ ipa_i386_linux_regobj=i386-linux-ipa.o
ipa_amd64_linux_regobj=amd64-linux-ipa.o

srv_i386_32bit_xmlfiles="i386/32bit-core.xml i386/32bit-sse.xml i386/32bit-avx.xml"
-srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml i386/64bit-avx.xml i386/x32-core.xml"
+srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml i386/64bit-avx.xml i386/x32-core.xml i386/x32-readonly.xml"
srv_i386_xmlfiles="i386/i386.xml i386/i386-avx.xml i386/i386-mmx.xml $srv_i386_32bit_xmlfiles"
srv_amd64_xmlfiles="i386/amd64.xml i386/amd64-avx.xml i386/x32.xml i386/x32-avx.xml $srv_i386_64bit_xmlfiles"
srv_i386_linux_xmlfiles="i386/i386-linux.xml i386/i386-avx-linux.xml i386/i386-mmx-linux.xml i386/32bit-linux.xml $srv_i386_32bit_xmlfiles"
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 1215bae..a4e99b2 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -112,6 +112,9 @@ struct arch_lwp_info

#ifdef __x86_64__

+/* Is this process 64-bit? */
+static int linux_is_elf64;
+
/* Mapping between the general-purpose registers in `struct user'
format and GDB's register array layout.
Note that the transfer layout uses 64-bit regs. */
@@ -294,6 +297,14 @@ x86_store_gregset (struct regcache *regcache, const void *buf)
for (i = 0; i < X86_64_NUM_REGS; i++)
if (x86_64_regmap[i] != -1)
supply_register (regcache, i, ((char *) buf) + x86_64_regmap[i]);
+ if (!linux_is_elf64)
+ {
+ /* Supply read-only rsp and rsp registers for x32. */
+ supply_register_by_name (regcache, "rsp",
+ ((char *) buf) + RSP * 8);
+ supply_register_by_name (regcache, "rip",
+ ((char *) buf) + RIP * 8);
+ }
return;
}
#endif
@@ -1090,9 +1101,6 @@ siginfo_from_compat_x32_siginfo (siginfo_t *to,
}
}
}
-
-/* Is this process 64-bit? */
-static int linux_is_elf64;
#endif /* __x86_64__ */

/* Convert a native/host siginfo object, into/from the siginfo in the
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 84e9794..ddb20aa 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -7705,9 +7705,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->num_mmx_regs = 8;
tdep->num_ymm_regs = 0;

- tdep->sp_regnum_from_eax = -1;
- tdep->pc_regnum_from_eax = -1;
-
tdesc_data = tdesc_data_alloc ();

set_gdbarch_relocate_instruction (gdbarch, i386_relocate_instruction);
@@ -7752,14 +7749,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* Support dword pseudo-register if it hasn't been disabled. */
tdep->eax_regnum = ymm0_regnum;
ymm0_regnum += tdep->num_dword_regs;
- if (tdep->sp_regnum_from_eax != -1)
- set_gdbarch_sp_regnum (gdbarch,
- (tdep->eax_regnum
- + tdep->sp_regnum_from_eax));
- if (tdep->pc_regnum_from_eax != -1)
- set_gdbarch_pc_regnum (gdbarch,
- (tdep->eax_regnum
- + tdep->pc_regnum_from_eax));
}
else
tdep->eax_regnum = -1;
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 76afdce..5f233f5 100644
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -149,14 +149,6 @@ struct gdbarch_tdep
of pseudo dword register support. */
int eax_regnum;

- /* Register number for SP, relative to %eax. Set this to -1 to
- indicate the absence of pseudo SP register support. */
- int sp_regnum_from_eax;
-
- /* Register number for PC, relative to %eax. Set this to -1 to
- indicate the absence of pseudo PC register support. */
- int pc_regnum_from_eax;
-
/* Number of core registers. */
int num_core_regs;

diff --git a/gdb/regformats/i386/x32-avx-linux.dat b/gdb/regformats/i386/x32-avx-linux.dat
index 1203806..9f52d3b 100644
--- a/gdb/regformats/i386/x32-avx-linux.dat
+++ b/gdb/regformats/i386/x32-avx-linux.dat
@@ -1,7 +1,7 @@
# DO NOT EDIT: generated from i386/x32-avx-linux.xml
name:x32_avx_linux
xmltarget:x32-avx-linux.xml
-expedite:rbp,rsp,rip
+expedite:rbp,esp,eip
64:rax
64:rbx
64:rcx
@@ -9,7 +9,7 @@ expedite:rbp,rsp,rip
64:rsi
64:rdi
64:rbp
-64:rsp
+32:esp
64:r8
64:r9
64:r10
@@ -18,7 +18,7 @@ expedite:rbp,rsp,rip
64:r13
64:r14
64:r15
-64:rip
+32:eip
32:eflags
32:cs
32:ss
@@ -60,6 +60,8 @@ expedite:rbp,rsp,rip
128:xmm15
32:mxcsr
64:orig_rax
+64:rsp
+64:rip
128:ymm0h
128:ymm1h
128:ymm2h
diff --git a/gdb/regformats/i386/x32-avx.dat b/gdb/regformats/i386/x32-avx.dat
index f13bf28..e48741d 100644
--- a/gdb/regformats/i386/x32-avx.dat
+++ b/gdb/regformats/i386/x32-avx.dat
@@ -1,7 +1,7 @@
# DO NOT EDIT: generated from i386/x32-avx.xml
name:x32_avx
xmltarget:x32-avx.xml
-expedite:rbp,rsp,rip
+expedite:rbp,esp,eip
64:rax
64:rbx
64:rcx
@@ -9,7 +9,7 @@ expedite:rbp,rsp,rip
64:rsi
64:rdi
64:rbp
-64:rsp
+32:esp
64:r8
64:r9
64:r10
@@ -18,7 +18,7 @@ expedite:rbp,rsp,rip
64:r13
64:r14
64:r15
-64:rip
+32:eip
32:eflags
32:cs
32:ss
diff --git a/gdb/regformats/i386/x32-linux.dat b/gdb/regformats/i386/x32-linux.dat
index 6eda64a..00911b7 100644
--- a/gdb/regformats/i386/x32-linux.dat
+++ b/gdb/regformats/i386/x32-linux.dat
@@ -1,7 +1,7 @@
# DO NOT EDIT: generated from i386/x32-linux.xml
name:x32_linux
xmltarget:x32-linux.xml
-expedite:rbp,rsp,rip
+expedite:rbp,esp,eip
64:rax
64:rbx
64:rcx
@@ -9,7 +9,7 @@ expedite:rbp,rsp,rip
64:rsi
64:rdi
64:rbp
-64:rsp
+32:esp
64:r8
64:r9
64:r10
@@ -18,7 +18,7 @@ expedite:rbp,rsp,rip
64:r13
64:r14
64:r15
-64:rip
+32:eip
32:eflags
32:cs
32:ss
@@ -60,3 +60,5 @@ expedite:rbp,rsp,rip
128:xmm15
32:mxcsr
64:orig_rax
+64:rsp
+64:rip
diff --git a/gdb/regformats/i386/x32.dat b/gdb/regformats/i386/x32.dat
index 6c63a8a..8e265e6 100644
--- a/gdb/regformats/i386/x32.dat
+++ b/gdb/regformats/i386/x32.dat
@@ -1,7 +1,7 @@
# DO NOT EDIT: generated from i386/x32.xml
name:x32
xmltarget:x32.xml
-expedite:rbp,rsp,rip
+expedite:rbp,esp,eip
64:rax
64:rbx
64:rcx
@@ -9,7 +9,7 @@ expedite:rbp,rsp,rip
64:rsi
64:rdi
64:rbp
-64:rsp
+32:esp
64:r8
64:r9
64:r10
@@ -18,7 +18,7 @@ expedite:rbp,rsp,rip
64:r13
64:r14
64:r15
-64:rip
+32:eip
32:eflags
32:cs
32:ss