Fix interrupt.exp fails with m32 in x86_64

Message ID 53566A17.4060109@mentor.com
State Superseded
Headers

Commit Message

Hui Zhu April 22, 2014, 1:09 p.m. UTC
  On 04/22/14 02:27, Mark Kettenis wrote:
>> Date: Tue, 22 Apr 2014 00:16:53 +0800
>> From: Hui Zhu<hui_zhu@mentor.com>
>>
>> I make a patch that let eax sign-extend in function
>> amd64_collect_native_gregset
>> that can handle this issue.
>> It can handle the issue and pass the regression test.
>> Please help me review it.
> I don't think the generic amd64 target code is the proper place to
> work around Linux kernel bugs.  If you really want to work around this
> bug in GDB, it should probably be done in the Linux-specific
> i386/amd64 native code.
>
> Mark

Hi Mark,

Thanks for your review.
I will keep work on the patch for Linux kernel to Linux can handle it.
But I worried about even if this issue is fixed in Linux kernel.
A lot of GDB will still work with the old Linux kernel.  So I make this 
patch.

I make a new patch the move %eax sign-extend code to amd64-linux-nat.c.

Thanks,
Hui

2014-04-22  Hui Zhu <hui@codesourcery.com>

     * amd64-linux-nat.c (fill_gregset): Make %eax
     sign-extended.
     (amd64_linux_store_inferior_registers): Change
     amd64_collect_native_gregset to fill_gregset.
     * amd64-nat.c (amd64_native_gregset_reg_offset): Remove static.
     * amd64-nat.h (amd64_native_gregset_reg_offset): Add extern.
  

Patch

--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -126,7 +126,27 @@  void
  fill_gregset (const struct regcache *regcache,
            elf_gregset_t *gregsetp, int regnum)
  {
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+
    amd64_collect_native_gregset (regcache, gregsetp, regnum);
+
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32
+      && (regnum == I386_EAX_REGNUM || regnum == -1))
+    {
+      /* Make %eax get sign-extended to 64 bits.  */
+      LONGEST val;
+      char *regs = (char *) gregsetp;
+      int offset = amd64_native_gregset_reg_offset (gdbarch,
+                            I386_EAX_REGNUM);
+
+      regcache_raw_collect (regcache, I386_EAX_REGNUM,
+                regs + offset);
+      val = extract_signed_integer ((gdb_byte *)(regs + offset),
+                    4,
+                    gdbarch_byte_order (gdbarch));
+      store_signed_integer ((gdb_byte *)(regs + offset), 8,
+                gdbarch_byte_order (gdbarch), val);
+    }
  }

  /* Transfering floating-point registers between GDB, inferiors and 
cores.  */
@@ -232,7 +252,7 @@  amd64_linux_store_inferior_registers (st
        if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
      perror_with_name (_("Couldn't get registers"));

-      amd64_collect_native_gregset (regcache, &regs, regnum);
+      fill_gregset (regcache, &regs, regnum);

        if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
      perror_with_name (_("Couldn't write registers"));
--- a/gdb/amd64-nat.c
+++ b/gdb/amd64-nat.c
@@ -51,7 +51,7 @@  int amd64_native_gregset64_num_regs = AM
  /* Return the offset of REGNUM within the appropriate native
     general-purpose register set.  */

-static int
+int
  amd64_native_gregset_reg_offset (struct gdbarch *gdbarch, int regnum)
  {
    int *reg_offset = amd64_native_gregset64_reg_offset;
--- a/gdb/amd64-nat.h
+++ b/gdb/amd64-nat.h
@@ -30,6 +30,12 @@  extern int amd64_native_gregset32_num_re
  extern int *amd64_native_gregset64_reg_offset;
  extern int amd64_native_gregset64_num_regs;

+/* Return the offset of REGNUM within the appropriate native
+   general-purpose register set.  */
+
+extern int amd64_native_gregset_reg_offset (struct gdbarch *gdbarch,
+                        int regnum);
+
  /* Return whether the native general-purpose register set supplies
     register REGNUM.  */