Fix interrupt.exp fails with m32 in x86_64
Commit Message
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.
@@ -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) ®s) < 0)
perror_with_name (_("Couldn't get registers"));
- amd64_collect_native_gregset (regcache, ®s, regnum);
+ fill_gregset (regcache, ®s, regnum);
if (ptrace (PTRACE_SETREGS, tid, 0, (long) ®s) < 0)
perror_with_name (_("Couldn't write registers"));
@@ -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;
@@ -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. */