This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH v2] Fix interrupt.exp fails with m32 in x86_64
- From: Hui Zhu <teawater at gmail dot com>
- To: Hui Zhu <hui at codesourcery dot com>
- Cc: Mark Kettenis <mark dot kettenis at xs4all dot nl>, Pedro Alves <palves at redhat dot com>, "H.Peter Anvin" <hpa at zytor dot com>, gdb-patches ml <gdb-patches at sourceware dot org>
- Date: Thu, 12 Jun 2014 16:39:49 +0800
- Subject: Re: [PATCH v2] Fix interrupt.exp fails with m32 in x86_64
- Authentication-results: sourceware.org; auth=none
- References: <0a87ce80-983c-4a0e-a5be-f931581873e8 at SVR-ORW-FEM-02 dot mgc dot mentorg dot com>
Ping.
Thanks,
Hui
On Tue, May 6, 2014 at 4:21 PM, Hui Zhu <hui@codesourcery.com> wrote:
> According to your comments in the discussion thread about Linux kernel
> patch. I make a new patch for GDB that let %eax sign-extend if %orig_eax >= 0.
>
> Thanks,
> Hui
>
> 2014-05-06 Hui Zhu <hui@codesourcery.com>
>
> * amd64-linux-nat.c (fill_gregset): Make %eax
> sign-extended if need.
> (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.
>
> --- a/gdb/amd64-linux-nat.c
> +++ b/gdb/amd64-linux-nat.c
> @@ -128,7 +128,52 @@ 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 target arch is 32 bits and GDB interrupt a system call of
> + inferior (%orig_rax >= 0), %rax is the errno of this system call.
> + amd64_collect_native_gregset let %eax zero-extend put %rax from
> + negative to positive.
> + If Linux cannot convert value of %rax back, the system call of
> + inferior will got errno -ERESTARTNOHAND, -ERESTARTSYS, -ERESTARTNOINTR
> + or -ERESTART_RESTARTBLOCK.
> + So if this is a 32 bits system call and fill value to %orig_eax
> + (not %eax to make sure REGCACHE has the right value of %orig_rax)
> + or all registers, let %eax sign-extend. */
> + if (regcache_register_status (regcache, I386_LINUX_ORIG_EAX_REGNUM)
> + == REG_VALID
> + && regcache_register_status (regcache, I386_EAX_REGNUM) == REG_VALID
> + && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32
> + && (regnum == I386_LINUX_ORIG_EAX_REGNUM || regnum == -1))
> + {
> + LONGEST val;
> + gdb_byte buf[MAX_REGISTER_SIZE];
> + int orig_eax_size;
> +
> + /* Get value of orig_eax and put it to val. */
> + regcache_raw_collect (regcache, I386_LINUX_ORIG_EAX_REGNUM,
> + buf);
> + orig_eax_size = register_size (gdbarch,
> + I386_LINUX_ORIG_EAX_REGNUM);
> + val = extract_signed_integer (buf, orig_eax_size,
> + gdbarch_byte_order (gdbarch));
> + if (val >= 0)
> + {
> + /* Make %eax get sign-extended to 64 bits. */
> + 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. */
> @@ -234,7 +279,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"));
> --- 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. */
>