This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2] Fix interrupt.exp fails with m32 in x86_64


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) &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.  */
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]