[00/24] Fix reading and writing pseudo registers in non-current frames

Message ID 20231108051222.1275306-1-simon.marchi@polymtl.ca
Headers
Series Fix reading and writing pseudo registers in non-current frames |

Message

Simon Marchi Nov. 8, 2023, 5 a.m. UTC
  This series fixes reading/writing pseudo registers from/to non-current
frames (that is, frames other than frame 0).  Currently, we get this:

    (gdb) frame 0
    #0  break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:38
    38              pop %rbx
    (gdb) p/x $rbx
    $1 = 0x2021222324252627
    (gdb) p/x $ebx
    $2 = 0x24252627
    (gdb) frame 1
    #1  0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:58
    58              call callee
    (gdb) p/x $rbx
    $3 = 0x1011121314151617
    (gdb) p/x $ebx
    $4 = 0x24252627

This is a bit surprising, we would expect the last value to be
0x14151617, the bottom half of the rbx value from frame 1 (the currently
selected frame at that point).  Instead, we got the bottom half of the
rbx value from frame 0.  This is because pseudo registers are always
read/written from/to the current thread's regcache.

This series fixes this (as well as writing to pseudo registers) by
making it so pseudo registers are read/written using a frame.

Simon Marchi (24):
  gdb: don't handle i386 k registers as pseudo registers
  gdb: use reg_buffer_common throughout gdbsupport/common-regcache.h
  gdb: make store_integer take an array_view
  gdb: simplify conditions in
    regcache::{read,write,raw_collect,raw_supply}_part
  gdb: change regcache interface to use array_view
  gdb: fix bugs in {get,put}_frame_register_bytes
  gdb: make put_frame_register take an array_view
  gdb: change value_of_register and value_of_register_lazy to take the
    next frame
  gdb: remove frame_register
  gdb: make put_frame_register take the next frame
  gdb: make put_frame_register_bytes take the next frame
  gdb: make get_frame_register_bytes take the next frame
  gdb: add value::allocate_register
  gdb: read pseudo register through frame
  gdb: change parameter name in frame_unwind_register_unsigned
    declaration
  gdb: rename gdbarch_pseudo_register_write to
    gdbarch_deprecated_pseudo_register_write
  gdb: add gdbarch_pseudo_register_write that takes a frame
  gdb: migrate i386 and amd64 to the new gdbarch_pseudo_register_write
  gdb: make aarch64_za_offsets_from_regnum return za_offsets
  gdb: add missing raw register read in
    aarch64_sme_pseudo_register_write
  gdb: migrate aarch64 to new gdbarch_pseudo_register_write
  gdb: migrate arm to gdbarch_pseudo_register_read_value
  gdb: migrate arm to new gdbarch_pseudo_register_write
  gdb/testsuite: add tests for unwinding of pseudo registers

 gdb/aarch64-tdep.c                            | 297 +++++-----
 gdb/alpha-tdep.c                              |  11 +-
 gdb/amd64-tdep.c                              |  82 +--
 gdb/arch/arm-get-next-pcs.c                   |   6 +-
 gdb/arch/arm-get-next-pcs.h                   |   5 +-
 gdb/arch/arm.c                                |   2 +-
 gdb/arch/arm.h                                |   4 +-
 gdb/arm-linux-tdep.c                          |  11 +-
 gdb/arm-tdep.c                                | 145 +++--
 gdb/avr-tdep.c                                |   3 +-
 gdb/bfin-tdep.c                               |   3 +-
 gdb/csky-tdep.c                               |   4 +-
 gdb/defs.h                                    |  39 +-
 gdb/dwarf2/expr.c                             |  22 +-
 gdb/dwarf2/frame.c                            |   5 +-
 gdb/eval.c                                    |   3 +-
 gdb/findvar.c                                 |  50 +-
 gdb/frame-unwind.c                            |   3 +-
 gdb/frame.c                                   | 174 +++---
 gdb/frame.h                                   |  28 +-
 gdb/frv-tdep.c                                |   3 +-
 gdb/gdbarch-gen.h                             |  28 +-
 gdb/gdbarch.c                                 |  40 +-
 gdb/gdbarch_components.py                     |  29 +-
 gdb/guile/scm-frame.c                         |   3 +-
 gdb/h8300-tdep.c                              |   3 +-
 gdb/i386-tdep.c                               | 380 ++++--------
 gdb/i386-tdep.h                               |  15 +-
 gdb/i387-tdep.c                               |  16 +-
 gdb/ia64-tdep.c                               |  18 +-
 gdb/infcmd.c                                  |   6 +-
 gdb/loongarch-tdep.c                          |   3 +-
 gdb/m32c-tdep.c                               |   3 +-
 gdb/m68hc11-tdep.c                            |   3 +-
 gdb/m68k-tdep.c                               |  17 +-
 gdb/mep-tdep.c                                |   3 +-
 gdb/mi/mi-main.c                              |   3 +-
 gdb/mips-tdep.c                               |  29 +-
 gdb/msp430-tdep.c                             |   3 +-
 gdb/nat/aarch64-hw-point.c                    |   3 +-
 gdb/nat/aarch64-scalable-linux-ptrace.c       |  20 +-
 gdb/nat/linux-btrace.c                        |   3 +-
 gdb/nds32-tdep.c                              |   8 +-
 gdb/python/py-frame.c                         |   3 +-
 gdb/python/py-unwind.c                        |   4 +-
 gdb/regcache.c                                | 548 +++++++++++-------
 gdb/regcache.h                                | 113 +++-
 gdb/riscv-tdep.c                              |  13 +-
 gdb/rl78-tdep.c                               |   3 +-
 gdb/rs6000-tdep.c                             |  21 +-
 gdb/s12z-tdep.c                               |   2 +-
 gdb/s390-tdep.c                               |   3 +-
 gdb/sh-tdep.c                                 |   9 +-
 gdb/sparc-tdep.c                              |   3 +-
 gdb/sparc64-tdep.c                            |   3 +-
 gdb/std-regs.c                                |  11 +-
 .../gdb.arch/aarch64-pseudo-unwind-asm.S      |  82 +++
 .../gdb.arch/aarch64-pseudo-unwind.c          |  33 ++
 .../gdb.arch/aarch64-pseudo-unwind.exp        |  90 +++
 .../gdb.arch/amd64-pseudo-unwind-asm.S        |  66 +++
 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c  |  33 ++
 .../gdb.arch/amd64-pseudo-unwind.exp          |  91 +++
 .../gdb.arch/arm-pseudo-unwind-asm.S          |  81 +++
 .../gdb.arch/arm-pseudo-unwind-legacy-asm.S   |  84 +++
 .../gdb.arch/arm-pseudo-unwind-legacy.c       |  33 ++
 .../gdb.arch/arm-pseudo-unwind-legacy.exp     |  86 +++
 gdb/testsuite/gdb.arch/arm-pseudo-unwind.c    |  33 ++
 gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp  |  88 +++
 gdb/valops.c                                  |  31 +-
 gdb/value.c                                   | 149 +++++
 gdb/value.h                                   |  64 +-
 gdb/xtensa-tdep.c                             |   3 +-
 gdbserver/linux-arm-low.cc                    |   4 +-
 gdbserver/regcache.cc                         |  69 ++-
 gdbserver/regcache.h                          |   6 +-
 gdbsupport/common-regcache.cc                 |   2 +-
 gdbsupport/common-regcache.h                  |  58 +-
 gdbsupport/rsp-low.cc                         |   8 +
 gdbsupport/rsp-low.h                          |   2 +
 79 files changed, 2324 insertions(+), 1144 deletions(-)
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c
 create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp
 create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S
 create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c
 create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp
 create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S
 create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S
 create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c
 create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp
 create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.c
 create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp


base-commit: 1185b5b79a12ba67eb60bee3f75babf7a222fde0
  

Comments

Simon Marchi Nov. 8, 2023, 5:16 a.m. UTC | #1
On 2023-11-08 00:00, Simon Marchi wrote:
> This series fixes reading/writing pseudo registers from/to non-current
> frames (that is, frames other than frame 0).  Currently, we get this:
> 
>     (gdb) frame 0
>     #0  break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:38
>     38              pop %rbx
>     (gdb) p/x $rbx
>     $1 = 0x2021222324252627
>     (gdb) p/x $ebx
>     $2 = 0x24252627
>     (gdb) frame 1
>     #1  0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:58
>     58              call callee
>     (gdb) p/x $rbx
>     $3 = 0x1011121314151617
>     (gdb) p/x $ebx
>     $4 = 0x24252627
> 
> This is a bit surprising, we would expect the last value to be
> 0x14151617, the bottom half of the rbx value from frame 1 (the currently
> selected frame at that point).  Instead, we got the bottom half of the
> rbx value from frame 0.  This is because pseudo registers are always
> read/written from/to the current thread's regcache.
> 
> This series fixes this (as well as writing to pseudo registers) by
> making it so pseudo registers are read/written using a frame.

Ah, I forgot because it's been so long, but this can be considered a v3
of this series  here...

  https://inbox.sourceware.org/gdb-patches/20181024014333.14143-1-simon.marchi@polymtl.ca/

Simon
  
Luis Machado Nov. 8, 2023, 11:57 a.m. UTC | #2
Hi Simon,

On 11/8/23 05:00, Simon Marchi wrote:
> This series fixes reading/writing pseudo registers from/to non-current
> frames (that is, frames other than frame 0).  Currently, we get this:
> 
>     (gdb) frame 0
>     #0  break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:38
>     38              pop %rbx
>     (gdb) p/x $rbx
>     $1 = 0x2021222324252627
>     (gdb) p/x $ebx
>     $2 = 0x24252627
>     (gdb) frame 1
>     #1  0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:58
>     58              call callee
>     (gdb) p/x $rbx
>     $3 = 0x1011121314151617
>     (gdb) p/x $ebx
>     $4 = 0x24252627
> 
> This is a bit surprising, we would expect the last value to be
> 0x14151617, the bottom half of the rbx value from frame 1 (the currently
> selected frame at that point).  Instead, we got the bottom half of the
> rbx value from frame 0.  This is because pseudo registers are always
> read/written from/to the current thread's regcache.
> 
> This series fixes this (as well as writing to pseudo registers) by
> making it so pseudo registers are read/written using a frame.
> 
> Simon Marchi (24):
>   gdb: don't handle i386 k registers as pseudo registers
>   gdb: use reg_buffer_common throughout gdbsupport/common-regcache.h
>   gdb: make store_integer take an array_view
>   gdb: simplify conditions in
>     regcache::{read,write,raw_collect,raw_supply}_part
>   gdb: change regcache interface to use array_view
>   gdb: fix bugs in {get,put}_frame_register_bytes
>   gdb: make put_frame_register take an array_view
>   gdb: change value_of_register and value_of_register_lazy to take the
>     next frame
>   gdb: remove frame_register
>   gdb: make put_frame_register take the next frame
>   gdb: make put_frame_register_bytes take the next frame
>   gdb: make get_frame_register_bytes take the next frame
>   gdb: add value::allocate_register
>   gdb: read pseudo register through frame
>   gdb: change parameter name in frame_unwind_register_unsigned
>     declaration
>   gdb: rename gdbarch_pseudo_register_write to
>     gdbarch_deprecated_pseudo_register_write
>   gdb: add gdbarch_pseudo_register_write that takes a frame
>   gdb: migrate i386 and amd64 to the new gdbarch_pseudo_register_write
>   gdb: make aarch64_za_offsets_from_regnum return za_offsets
>   gdb: add missing raw register read in
>     aarch64_sme_pseudo_register_write
>   gdb: migrate aarch64 to new gdbarch_pseudo_register_write
>   gdb: migrate arm to gdbarch_pseudo_register_read_value
>   gdb: migrate arm to new gdbarch_pseudo_register_write
>   gdb/testsuite: add tests for unwinding of pseudo registers
> 
>  gdb/aarch64-tdep.c                            | 297 +++++-----
>  gdb/alpha-tdep.c                              |  11 +-
>  gdb/amd64-tdep.c                              |  82 +--
>  gdb/arch/arm-get-next-pcs.c                   |   6 +-
>  gdb/arch/arm-get-next-pcs.h                   |   5 +-
>  gdb/arch/arm.c                                |   2 +-
>  gdb/arch/arm.h                                |   4 +-
>  gdb/arm-linux-tdep.c                          |  11 +-
>  gdb/arm-tdep.c                                | 145 +++--
>  gdb/avr-tdep.c                                |   3 +-
>  gdb/bfin-tdep.c                               |   3 +-
>  gdb/csky-tdep.c                               |   4 +-
>  gdb/defs.h                                    |  39 +-
>  gdb/dwarf2/expr.c                             |  22 +-
>  gdb/dwarf2/frame.c                            |   5 +-
>  gdb/eval.c                                    |   3 +-
>  gdb/findvar.c                                 |  50 +-
>  gdb/frame-unwind.c                            |   3 +-
>  gdb/frame.c                                   | 174 +++---
>  gdb/frame.h                                   |  28 +-
>  gdb/frv-tdep.c                                |   3 +-
>  gdb/gdbarch-gen.h                             |  28 +-
>  gdb/gdbarch.c                                 |  40 +-
>  gdb/gdbarch_components.py                     |  29 +-
>  gdb/guile/scm-frame.c                         |   3 +-
>  gdb/h8300-tdep.c                              |   3 +-
>  gdb/i386-tdep.c                               | 380 ++++--------
>  gdb/i386-tdep.h                               |  15 +-
>  gdb/i387-tdep.c                               |  16 +-
>  gdb/ia64-tdep.c                               |  18 +-
>  gdb/infcmd.c                                  |   6 +-
>  gdb/loongarch-tdep.c                          |   3 +-
>  gdb/m32c-tdep.c                               |   3 +-
>  gdb/m68hc11-tdep.c                            |   3 +-
>  gdb/m68k-tdep.c                               |  17 +-
>  gdb/mep-tdep.c                                |   3 +-
>  gdb/mi/mi-main.c                              |   3 +-
>  gdb/mips-tdep.c                               |  29 +-
>  gdb/msp430-tdep.c                             |   3 +-
>  gdb/nat/aarch64-hw-point.c                    |   3 +-
>  gdb/nat/aarch64-scalable-linux-ptrace.c       |  20 +-
>  gdb/nat/linux-btrace.c                        |   3 +-
>  gdb/nds32-tdep.c                              |   8 +-
>  gdb/python/py-frame.c                         |   3 +-
>  gdb/python/py-unwind.c                        |   4 +-
>  gdb/regcache.c                                | 548 +++++++++++-------
>  gdb/regcache.h                                | 113 +++-
>  gdb/riscv-tdep.c                              |  13 +-
>  gdb/rl78-tdep.c                               |   3 +-
>  gdb/rs6000-tdep.c                             |  21 +-
>  gdb/s12z-tdep.c                               |   2 +-
>  gdb/s390-tdep.c                               |   3 +-
>  gdb/sh-tdep.c                                 |   9 +-
>  gdb/sparc-tdep.c                              |   3 +-
>  gdb/sparc64-tdep.c                            |   3 +-
>  gdb/std-regs.c                                |  11 +-
>  .../gdb.arch/aarch64-pseudo-unwind-asm.S      |  82 +++
>  .../gdb.arch/aarch64-pseudo-unwind.c          |  33 ++
>  .../gdb.arch/aarch64-pseudo-unwind.exp        |  90 +++
>  .../gdb.arch/amd64-pseudo-unwind-asm.S        |  66 +++
>  gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c  |  33 ++
>  .../gdb.arch/amd64-pseudo-unwind.exp          |  91 +++
>  .../gdb.arch/arm-pseudo-unwind-asm.S          |  81 +++
>  .../gdb.arch/arm-pseudo-unwind-legacy-asm.S   |  84 +++
>  .../gdb.arch/arm-pseudo-unwind-legacy.c       |  33 ++
>  .../gdb.arch/arm-pseudo-unwind-legacy.exp     |  86 +++
>  gdb/testsuite/gdb.arch/arm-pseudo-unwind.c    |  33 ++
>  gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp  |  88 +++
>  gdb/valops.c                                  |  31 +-
>  gdb/value.c                                   | 149 +++++
>  gdb/value.h                                   |  64 +-
>  gdb/xtensa-tdep.c                             |   3 +-
>  gdbserver/linux-arm-low.cc                    |   4 +-
>  gdbserver/regcache.cc                         |  69 ++-
>  gdbserver/regcache.h                          |   6 +-
>  gdbsupport/common-regcache.cc                 |   2 +-
>  gdbsupport/common-regcache.h                  |  58 +-
>  gdbsupport/rsp-low.cc                         |   8 +
>  gdbsupport/rsp-low.h                          |   2 +
>  79 files changed, 2324 insertions(+), 1144 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S
>  create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c
>  create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp
>  create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S
>  create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c
>  create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp
>  create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S
>  create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S
>  create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c
>  create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp
>  create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.c
>  create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp
> 
> 
> base-commit: 1185b5b79a12ba67eb60bee3f75babf7a222fde0

I haven't tracked the particular patch that causes this, but for aarch64 systems supporting SVE
(and probably SME as well) I'm seeing internal errors related to one assertion:

Running gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp ...
PASS: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to callee
PASS: gdb.arch/aarch64-pseudo-unwind.exp: callee, before change: p/x $v8.q.u
PASS: gdb.arch/aarch64-pseudo-unwind.exp: callee, before change: p/x $s8.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x34353637 (GDB internal error)
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $v8.q.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $s8.u
PASS: gdb.arch/aarch64-pseudo-unwind.exp: up
PASS: gdb.arch/aarch64-pseudo-unwind.exp: caller, before change: p/x $v8.q.u
PASS: gdb.arch/aarch64-pseudo-unwind.exp: caller, before change: p/x $s8.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x44454647 (GDB internal error)
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
PASS: gdb.arch/aarch64-pseudo-unwind.exp: down
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $v8.q.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $s8.u
PASS: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
Running gdb/testsuite/gdb.arch/aarch64-fp.exp ...
PASS: gdb.arch/aarch64-fp.exp: set the breakpoint after setting the fp registers
PASS: gdb.arch/aarch64-fp.exp: continue until breakpoint
PASS: gdb.arch/aarch64-fp.exp: check register q0 value
PASS: gdb.arch/aarch64-fp.exp: check register q1 value
PASS: gdb.arch/aarch64-fp.exp: check register v0 value
PASS: gdb.arch/aarch64-fp.exp: check register v1 value
PASS: gdb.arch/aarch64-fp.exp: check register fpsr value
PASS: gdb.arch/aarch64-fp.exp: check register fpcr value
FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set h0.bf to 129 (GDB internal error)
FAIL: gdb.arch/aarch64-fp.exp: bfloat16: h0 fields are valid
FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set v0.h.bf[0] to 0 (GDB internal error)
FAIL: gdb.arch/aarch64-fp.exp: bfloat16: v0.h.s[0] is 0
FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set v0.h.bf[0] to 129 (GDB internal error)
FAIL: gdb.arch/aarch64-fp.exp: bfloat16: v0.h.s[0] is 129

The failure mode is:

set $s8.u = 0x34353637^M
../../../repos/binutils-gdb/gdb/frame.c:1441: internal-error: put_frame_register: Assertion `buf.size () == size' failed.^M
A problem internal to GDB has been detected,^M
further debugging may prove unreliable.^M
----- Backtrace -----^M
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x34353637 (GDB internal error)
Resyncing due to internal error.
0xaaaaabd6e08f gdb_internal_backtrace_1^M
        ../../../repos/binutils-gdb/gdb/bt-utils.c:122^M
0xaaaaabd6e08f _Z22gdb_internal_backtracev^M
        ../../../repos/binutils-gdb/gdb/bt-utils.c:168^M
0xaaaaac315307 internal_vproblem^M
        ../../../repos/binutils-gdb/gdb/utils.c:396^M
0xaaaaac31556f _Z15internal_verrorPKciS0_St9__va_list^M
        ../../../repos/binutils-gdb/gdb/utils.c:476^M
0xaaaaac8604e3 _Z18internal_error_locPKciS0_z^M
        ../../../repos/binutils-gdb/gdbsupport/errors.cc:58^M
0xaaaaabec89c7 _Z18put_frame_register14frame_info_ptriN3gdb10array_viewIKhEE^M
        ../../../repos/binutils-gdb/gdb/frame.c:1441^M
0xaaaaabc55243 aarch64_pseudo_write_1^M
        ../../../repos/binutils-gdb/gdb/aarch64-tdep.c:3316^M
0xaaaaabc5c943 aarch64_pseudo_write^M
        ../../../repos/binutils-gdb/gdb/aarch64-tdep.c:3414^M
0xaaaaabce0913 _Z29gdbarch_pseudo_register_writeP7gdbarch14frame_info_ptriN3gdb10array_viewIKhEE^M
        ../../../repos/binutils-gdb/gdb/gdbarch.c:1927^M
0xaaaaabec892f _Z18put_frame_register14frame_info_ptriN3gdb10array_viewIKhEE^M
        ../../../repos/binutils-gdb/gdb/frame.c:1462^M
0xaaaaabed0fa7 _Z24put_frame_register_bytes14frame_info_ptrimN3gdb10array_viewIKhEE^M
        ../../../repos/binutils-gdb/gdb/frame.c:1592^M
0xaaaaac33092b _Z12value_assignP5valueS0_^M
        ../../../repos/binutils-gdb/gdb/valops.c:1260^M
0xaaaaabe8fcdf _ZN10expression8evaluateEP4type6noside^M
        ../../../repos/binutils-gdb/gdb/eval.c:111^M
0xaaaaac0cba9f set_command^M
        ../../../repos/binutils-gdb/gdb/printcmd.c:1542^M
0xaaaaabd9d91b _Z8cmd_funcP16cmd_list_elementPKci^M
        ../../../repos/binutils-gdb/gdb/cli/cli-decode.c:2735^M
0xaaaaac2af583 _Z15execute_commandPKci^M
        ../../../repos/binutils-gdb/gdb/top.c:575^M
0xaaaaabe97413 _Z15command_handlerPKc^M
        ../../../repos/binutils-gdb/gdb/event-top.c:552^M
0xaaaaabe9869f _Z20command_line_handlerOSt10unique_ptrIcN3gdb13xfree_deleterIcEEE^M
        ../../../repos/binutils-gdb/gdb/event-top.c:788^M
0xaaaaabe97f17 gdb_rl_callback_handler^M
        ../../../repos/binutils-gdb/gdb/event-top.c:259^M
0xaaaaac3ce363 rl_callback_read_char^M
        ../../../../repos/binutils-gdb/readline/readline/callback.c:290^M
0xaaaaabe96e93 gdb_rl_callback_read_char_wrapper_noexcept^M
        ../../../repos/binutils-gdb/gdb/event-top.c:195^M
0xaaaaabe97d7b gdb_rl_callback_read_char_wrapper^M
        ../../../repos/binutils-gdb/gdb/event-top.c:234^M
0xaaaaac2ea1f7 stdin_event_handler^M
        ../../../repos/binutils-gdb/gdb/ui.c:155^M
0xaaaaac860ecf gdb_wait_for_event^M
        ../../../repos/binutils-gdb/gdbsupport/event-loop.cc:694^M
0xaaaaac8618af gdb_wait_for_event^M
        ../../../repos/binutils-gdb/gdbsupport/event-loop.cc:593^M
0xaaaaac8618af _Z16gdb_do_one_eventi^M
        ../../../repos/binutils-gdb/gdbsupport/event-loop.cc:264^M
0xaaaaabffe02f start_event_loop^M
        ../../../repos/binutils-gdb/gdb/main.c:407^M
0xaaaaabffe02f captured_command_loop^M
        ../../../repos/binutils-gdb/gdb/main.c:471^M
0xaaaaabfffc73 captured_main^M
        ../../../repos/binutils-gdb/gdb/main.c:1324^M
0xaaaaabfffc73 _Z8gdb_mainP18captured_main_args^M
        ../../../repos/binutils-gdb/gdb/main.c:1343^M
0xaaaaabc3b457 main^M
        ../../../repos/binutils-gdb/gdb/gdb.c:39^M

It is also worth noting that the v registers are *not* pseudo-registers when the aarch64-fpu feature is used. If SVE
is available though, then that means the v registers are pseudo-registers as well. You can tell them apart by their types.

Real register (no SVE support):

type = union aarch64v {
    vnd d;
    vns s;
    vnh h;
    vnb b;
    vnq q;
}

Pseudo-register (SVE support):

union __gdb_builtin_type_vnv {
    __gdb_builtin_type_vnd d;
    __gdb_builtin_type_vns s;
    __gdb_builtin_type_vnh h;
    __gdb_builtin_type_vnb b;
    __gdb_builtin_type_vnq q;
}

Please let me know if you want me to narrow this down or provide more info.
  
Simon Marchi Nov. 8, 2023, 3:47 p.m. UTC | #3
> I haven't tracked the particular patch that causes this, but for aarch64 systems supporting SVE
> (and probably SME as well) I'm seeing internal errors related to one assertion:
Thanks a lot for testing.

> Running gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp ...
> PASS: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to callee
> PASS: gdb.arch/aarch64-pseudo-unwind.exp: callee, before change: p/x $v8.q.u
> PASS: gdb.arch/aarch64-pseudo-unwind.exp: callee, before change: p/x $s8.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x34353637 (GDB internal error)
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $v8.q.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $s8.u
> PASS: gdb.arch/aarch64-pseudo-unwind.exp: up
> PASS: gdb.arch/aarch64-pseudo-unwind.exp: caller, before change: p/x $v8.q.u
> PASS: gdb.arch/aarch64-pseudo-unwind.exp: caller, before change: p/x $s8.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x44454647 (GDB internal error)
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
> PASS: gdb.arch/aarch64-pseudo-unwind.exp: down
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $v8.q.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $s8.u
> PASS: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
> Running gdb/testsuite/gdb.arch/aarch64-fp.exp ...
> PASS: gdb.arch/aarch64-fp.exp: set the breakpoint after setting the fp registers
> PASS: gdb.arch/aarch64-fp.exp: continue until breakpoint
> PASS: gdb.arch/aarch64-fp.exp: check register q0 value
> PASS: gdb.arch/aarch64-fp.exp: check register q1 value
> PASS: gdb.arch/aarch64-fp.exp: check register v0 value
> PASS: gdb.arch/aarch64-fp.exp: check register v1 value
> PASS: gdb.arch/aarch64-fp.exp: check register fpsr value
> PASS: gdb.arch/aarch64-fp.exp: check register fpcr value
> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set h0.bf to 129 (GDB internal error)
> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: h0 fields are valid
> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set v0.h.bf[0] to 0 (GDB internal error)
> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: v0.h.s[0] is 0
> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set v0.h.bf[0] to 129 (GDB internal error)
> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: v0.h.s[0] is 129
> 
> The failure mode is:
> 
> set $s8.u = 0x34353637^M
> ../../../repos/binutils-gdb/gdb/frame.c:1441: internal-error: put_frame_register: Assertion `buf.size () == size' failed.^M
> A problem internal to GDB has been detected,^M
> further debugging may prove unreliable.^M
> ----- Backtrace -----^M
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x34353637 (GDB internal error)
> Resyncing due to internal error.
> 0xaaaaabd6e08f gdb_internal_backtrace_1^M
>         ../../../repos/binutils-gdb/gdb/bt-utils.c:122^M
> 0xaaaaabd6e08f _Z22gdb_internal_backtracev^M
>         ../../../repos/binutils-gdb/gdb/bt-utils.c:168^M
> 0xaaaaac315307 internal_vproblem^M
>         ../../../repos/binutils-gdb/gdb/utils.c:396^M
> 0xaaaaac31556f _Z15internal_verrorPKciS0_St9__va_list^M
>         ../../../repos/binutils-gdb/gdb/utils.c:476^M
> 0xaaaaac8604e3 _Z18internal_error_locPKciS0_z^M
>         ../../../repos/binutils-gdb/gdbsupport/errors.cc:58^M
> 0xaaaaabec89c7 _Z18put_frame_register14frame_info_ptriN3gdb10array_viewIKhEE^M
>         ../../../repos/binutils-gdb/gdb/frame.c:1441^M
> 0xaaaaabc55243 aarch64_pseudo_write_1^M
>         ../../../repos/binutils-gdb/gdb/aarch64-tdep.c:3316^M
> 0xaaaaabc5c943 aarch64_pseudo_write^M
>         ../../../repos/binutils-gdb/gdb/aarch64-tdep.c:3414^M

Ok, then I presume the regression is introduced with patch "gdb: migrate
aarch64 to new gdbarch_pseudo_register_write".

> It is also worth noting that the v registers are *not* pseudo-registers when the aarch64-fpu feature is used. If SVE
> is available though, then that means the v registers are pseudo-registers as well. You can tell them apart by their types.
> 
> Real register (no SVE support):
> 
> type = union aarch64v {
>     vnd d;
>     vns s;
>     vnh h;
>     vnb b;
>     vnq q;
> }
> 
> Pseudo-register (SVE support):
> 
> union __gdb_builtin_type_vnv {
>     __gdb_builtin_type_vnd d;
>     __gdb_builtin_type_vns s;
>     __gdb_builtin_type_vnh h;
>     __gdb_builtin_type_vnb b;
>     __gdb_builtin_type_vnq q;
> }

Ok, thanks for that explanation.  If you recall, I asked you on IRC if
the V registers were always 16 bytes long, and you said yes.  That's why
I hardcoded the size of 16 in aarch64_pseudo_write_1.  But then
according to your explanation, when SVE is available, the raw register
behind S registers, for instance, is an SVE register whose length is
unknown at compile time.  That's why the existing code calls
register_size to get the size of the raw register.

If you apply the patch below, does it help?

Simon


diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 1815d78dec40..87e6f9e10ae2 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -3300,7 +3300,7 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
 			int regnum_offset,
 			gdb::array_view<const gdb_byte> buf)
 {
-  unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset;
+  unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
   gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);

   /* Enough space for a full vector register.
@@ -3309,11 +3309,11 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
      various 'scalar' pseudo registers to behavior like architectural
      writes, register width bytes are written the remainder are set to
      zero.  */
-  constexpr int raw_reg_size = 16;
-  gdb_byte raw_buf[raw_reg_size] {};
+  int raw_reg_size = register_size (gdbarch, raw_regnum);
+  gdb::byte_vector raw_buf (raw_reg_size);
   gdb::array_view<gdb_byte> raw_view (raw_buf);
   copy (buf, raw_view.slice (0, buf.size ()));
-  put_frame_register (next_frame, v_regnum, raw_view);
+  put_frame_register (next_frame, raw_regnum, raw_view);
 }

 /* Given REGNUM, a SME pseudo-register number, store the bytes from DATA to the
  
Luis Machado Nov. 8, 2023, 5:08 p.m. UTC | #4
On 11/8/23 15:47, Simon Marchi wrote:
>> I haven't tracked the particular patch that causes this, but for aarch64 systems supporting SVE
>> (and probably SME as well) I'm seeing internal errors related to one assertion:
> Thanks a lot for testing.
> 
>> Running gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp ...
>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to callee
>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: callee, before change: p/x $v8.q.u
>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: callee, before change: p/x $s8.u
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x34353637 (GDB internal error)
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $v8.q.u
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $s8.u
>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: up
>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: caller, before change: p/x $v8.q.u
>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: caller, before change: p/x $s8.u
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x44454647 (GDB internal error)
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: down
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $v8.q.u
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $s8.u
>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
>> Running gdb/testsuite/gdb.arch/aarch64-fp.exp ...
>> PASS: gdb.arch/aarch64-fp.exp: set the breakpoint after setting the fp registers
>> PASS: gdb.arch/aarch64-fp.exp: continue until breakpoint
>> PASS: gdb.arch/aarch64-fp.exp: check register q0 value
>> PASS: gdb.arch/aarch64-fp.exp: check register q1 value
>> PASS: gdb.arch/aarch64-fp.exp: check register v0 value
>> PASS: gdb.arch/aarch64-fp.exp: check register v1 value
>> PASS: gdb.arch/aarch64-fp.exp: check register fpsr value
>> PASS: gdb.arch/aarch64-fp.exp: check register fpcr value
>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set h0.bf to 129 (GDB internal error)
>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: h0 fields are valid
>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set v0.h.bf[0] to 0 (GDB internal error)
>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: v0.h.s[0] is 0
>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set v0.h.bf[0] to 129 (GDB internal error)
>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: v0.h.s[0] is 129
>>
>> The failure mode is:
>>
>> set $s8.u = 0x34353637^M
>> ../../../repos/binutils-gdb/gdb/frame.c:1441: internal-error: put_frame_register: Assertion `buf.size () == size' failed.^M
>> A problem internal to GDB has been detected,^M
>> further debugging may prove unreliable.^M
>> ----- Backtrace -----^M
>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x34353637 (GDB internal error)
>> Resyncing due to internal error.
>> 0xaaaaabd6e08f gdb_internal_backtrace_1^M
>>         ../../../repos/binutils-gdb/gdb/bt-utils.c:122^M
>> 0xaaaaabd6e08f _Z22gdb_internal_backtracev^M
>>         ../../../repos/binutils-gdb/gdb/bt-utils.c:168^M
>> 0xaaaaac315307 internal_vproblem^M
>>         ../../../repos/binutils-gdb/gdb/utils.c:396^M
>> 0xaaaaac31556f _Z15internal_verrorPKciS0_St9__va_list^M
>>         ../../../repos/binutils-gdb/gdb/utils.c:476^M
>> 0xaaaaac8604e3 _Z18internal_error_locPKciS0_z^M
>>         ../../../repos/binutils-gdb/gdbsupport/errors.cc:58^M
>> 0xaaaaabec89c7 _Z18put_frame_register14frame_info_ptriN3gdb10array_viewIKhEE^M
>>         ../../../repos/binutils-gdb/gdb/frame.c:1441^M
>> 0xaaaaabc55243 aarch64_pseudo_write_1^M
>>         ../../../repos/binutils-gdb/gdb/aarch64-tdep.c:3316^M
>> 0xaaaaabc5c943 aarch64_pseudo_write^M
>>         ../../../repos/binutils-gdb/gdb/aarch64-tdep.c:3414^M
> 
> Ok, then I presume the regression is introduced with patch "gdb: migrate
> aarch64 to new gdbarch_pseudo_register_write".
> 
>> It is also worth noting that the v registers are *not* pseudo-registers when the aarch64-fpu feature is used. If SVE
>> is available though, then that means the v registers are pseudo-registers as well. You can tell them apart by their types.
>>
>> Real register (no SVE support):
>>
>> type = union aarch64v {
>>     vnd d;
>>     vns s;
>>     vnh h;
>>     vnb b;
>>     vnq q;
>> }
>>
>> Pseudo-register (SVE support):
>>
>> union __gdb_builtin_type_vnv {
>>     __gdb_builtin_type_vnd d;
>>     __gdb_builtin_type_vns s;
>>     __gdb_builtin_type_vnh h;
>>     __gdb_builtin_type_vnb b;
>>     __gdb_builtin_type_vnq q;
>> }
> 
> Ok, thanks for that explanation.  If you recall, I asked you on IRC if
> the V registers were always 16 bytes long, and you said yes.  That's why
> I hardcoded the size of 16 in aarch64_pseudo_write_1.  But then

Right. The V registers are always 16 bytes long, being real or pseudo-registers. So
their sizes are fixed.

The other pseudo-registers are also fixed size. What chages is the size of the SVE
register the V/Q/D/S/H/B pseudo-registers map to.

> according to your explanation, when SVE is available, the raw register
> behind S registers, for instance, is an SVE register whose length is
> unknown at compile time.  That's why the existing code calls
> register_size to get the size of the raw register.
> 
> If you apply the patch below, does it help?

It gets rid of the internal error due to the assertion, but I still see FAIL's due to wrong
values being printed.

FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $v8.q.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $v8.q.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
FAIL: gdb.arch/aarch64-fp.exp: bfloat16: h0 fields are valid

p/x $v8.q.u
$3 = {0xaaab34353637}
(gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $v8.q.u
--
p/x $v8.q.u
$7 = {0xaaab34353637}
(gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
--
p/x $s8.u
$8 = 0x34353637
(gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
--
p/x $v8.q.u
$9 = {0xaaab34353637}
(gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $v8.q.u
--
Program received signal SIGSEGV, Segmentation fault.
0x0000aaab0fad6e60 in ?? ()
(gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
p/x value
No symbol "value" in current context.
(gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
testcase binutils-gdb/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp completed in 1 seconds
Running binutils-gdb/gdb/testsuite/gdb.arch/aarch64-fp.exp ...
--
p $h0
$7 = {bf = 1.136e-28, f = 0.00061798, u = 4368, s = 4368}
(gdb) FAIL: gdb.arch/aarch64-fp.exp: bfloat16: h0 fields are valid

> 
> Simon
> 
> 
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index 1815d78dec40..87e6f9e10ae2 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -3300,7 +3300,7 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>  			int regnum_offset,
>  			gdb::array_view<const gdb_byte> buf)
>  {
> -  unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset;
> +  unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
>    gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
> 
>    /* Enough space for a full vector register.
> @@ -3309,11 +3309,11 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>       various 'scalar' pseudo registers to behavior like architectural
>       writes, register width bytes are written the remainder are set to
>       zero.  */
> -  constexpr int raw_reg_size = 16;
> -  gdb_byte raw_buf[raw_reg_size] {};
> +  int raw_reg_size = register_size (gdbarch, raw_regnum);
> +  gdb::byte_vector raw_buf (raw_reg_size);
>    gdb::array_view<gdb_byte> raw_view (raw_buf);
>    copy (buf, raw_view.slice (0, buf.size ()));
> -  put_frame_register (next_frame, v_regnum, raw_view);
> +  put_frame_register (next_frame, raw_regnum, raw_view);
>  }
> 
>  /* Given REGNUM, a SME pseudo-register number, store the bytes from DATA to the
>
  
Simon Marchi Nov. 8, 2023, 7:34 p.m. UTC | #5
On 11/8/23 12:08, Luis Machado wrote:
> On 11/8/23 15:47, Simon Marchi wrote:
>>> I haven't tracked the particular patch that causes this, but for aarch64 systems supporting SVE
>>> (and probably SME as well) I'm seeing internal errors related to one assertion:
>> Thanks a lot for testing.
>>
>>> Running gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp ...
>>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to callee
>>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: callee, before change: p/x $v8.q.u
>>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: callee, before change: p/x $s8.u
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x34353637 (GDB internal error)
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $v8.q.u
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $s8.u
>>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: up
>>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: caller, before change: p/x $v8.q.u
>>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: caller, before change: p/x $s8.u
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x44454647 (GDB internal error)
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
>>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: down
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $v8.q.u
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $s8.u
>>> PASS: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
>>> Running gdb/testsuite/gdb.arch/aarch64-fp.exp ...
>>> PASS: gdb.arch/aarch64-fp.exp: set the breakpoint after setting the fp registers
>>> PASS: gdb.arch/aarch64-fp.exp: continue until breakpoint
>>> PASS: gdb.arch/aarch64-fp.exp: check register q0 value
>>> PASS: gdb.arch/aarch64-fp.exp: check register q1 value
>>> PASS: gdb.arch/aarch64-fp.exp: check register v0 value
>>> PASS: gdb.arch/aarch64-fp.exp: check register v1 value
>>> PASS: gdb.arch/aarch64-fp.exp: check register fpsr value
>>> PASS: gdb.arch/aarch64-fp.exp: check register fpcr value
>>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set h0.bf to 129 (GDB internal error)
>>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: h0 fields are valid
>>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set v0.h.bf[0] to 0 (GDB internal error)
>>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: v0.h.s[0] is 0
>>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: set v0.h.bf[0] to 129 (GDB internal error)
>>> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: v0.h.s[0] is 129
>>>
>>> The failure mode is:
>>>
>>> set $s8.u = 0x34353637^M
>>> ../../../repos/binutils-gdb/gdb/frame.c:1441: internal-error: put_frame_register: Assertion `buf.size () == size' failed.^M
>>> A problem internal to GDB has been detected,^M
>>> further debugging may prove unreliable.^M
>>> ----- Backtrace -----^M
>>> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: set $s8.u = 0x34353637 (GDB internal error)
>>> Resyncing due to internal error.
>>> 0xaaaaabd6e08f gdb_internal_backtrace_1^M
>>>         ../../../repos/binutils-gdb/gdb/bt-utils.c:122^M
>>> 0xaaaaabd6e08f _Z22gdb_internal_backtracev^M
>>>         ../../../repos/binutils-gdb/gdb/bt-utils.c:168^M
>>> 0xaaaaac315307 internal_vproblem^M
>>>         ../../../repos/binutils-gdb/gdb/utils.c:396^M
>>> 0xaaaaac31556f _Z15internal_verrorPKciS0_St9__va_list^M
>>>         ../../../repos/binutils-gdb/gdb/utils.c:476^M
>>> 0xaaaaac8604e3 _Z18internal_error_locPKciS0_z^M
>>>         ../../../repos/binutils-gdb/gdbsupport/errors.cc:58^M
>>> 0xaaaaabec89c7 _Z18put_frame_register14frame_info_ptriN3gdb10array_viewIKhEE^M
>>>         ../../../repos/binutils-gdb/gdb/frame.c:1441^M
>>> 0xaaaaabc55243 aarch64_pseudo_write_1^M
>>>         ../../../repos/binutils-gdb/gdb/aarch64-tdep.c:3316^M
>>> 0xaaaaabc5c943 aarch64_pseudo_write^M
>>>         ../../../repos/binutils-gdb/gdb/aarch64-tdep.c:3414^M
>>
>> Ok, then I presume the regression is introduced with patch "gdb: migrate
>> aarch64 to new gdbarch_pseudo_register_write".
>>
>>> It is also worth noting that the v registers are *not* pseudo-registers when the aarch64-fpu feature is used. If SVE
>>> is available though, then that means the v registers are pseudo-registers as well. You can tell them apart by their types.
>>>
>>> Real register (no SVE support):
>>>
>>> type = union aarch64v {
>>>     vnd d;
>>>     vns s;
>>>     vnh h;
>>>     vnb b;
>>>     vnq q;
>>> }
>>>
>>> Pseudo-register (SVE support):
>>>
>>> union __gdb_builtin_type_vnv {
>>>     __gdb_builtin_type_vnd d;
>>>     __gdb_builtin_type_vns s;
>>>     __gdb_builtin_type_vnh h;
>>>     __gdb_builtin_type_vnb b;
>>>     __gdb_builtin_type_vnq q;
>>> }
>>
>> Ok, thanks for that explanation.  If you recall, I asked you on IRC if
>> the V registers were always 16 bytes long, and you said yes.  That's why
>> I hardcoded the size of 16 in aarch64_pseudo_write_1.  But then
> 
> Right. The V registers are always 16 bytes long, being real or pseudo-registers. So
> their sizes are fixed.
> 
> The other pseudo-registers are also fixed size. What chages is the size of the SVE
> register the V/Q/D/S/H/B pseudo-registers map to.
> 
>> according to your explanation, when SVE is available, the raw register
>> behind S registers, for instance, is an SVE register whose length is
>> unknown at compile time.  That's why the existing code calls
>> register_size to get the size of the raw register.
>>
>> If you apply the patch below, does it help?
> 
> It gets rid of the internal error due to the assertion, but I still see FAIL's due to wrong
> values being printed.
> 
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $v8.q.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $v8.q.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
> FAIL: gdb.arch/aarch64-fp.exp: bfloat16: h0 fields are valid
> 
> p/x $v8.q.u
> $3 = {0xaaab34353637}
> (gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change: p/x $v8.q.u
> --
> p/x $v8.q.u
> $7 = {0xaaab34353637}
> (gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
> --
> p/x $s8.u
> $8 = 0x34353637
> (gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
> --
> p/x $v8.q.u
> $9 = {0xaaab34353637}
> (gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: callee, after change in caller: p/x $v8.q.u
> --
> Program received signal SIGSEGV, Segmentation fault.
> 0x0000aaab0fad6e60 in ?? ()
> (gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
> p/x value
> No symbol "value" in current context.
> (gdb) FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
> testcase binutils-gdb/gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp completed in 1 seconds
> Running binutils-gdb/gdb/testsuite/gdb.arch/aarch64-fp.exp ...
> --
> p $h0
> $7 = {bf = 1.136e-28, f = 0.00061798, u = 4368, s = 4368}
> (gdb) FAIL: gdb.arch/aarch64-fp.exp: bfloat16: h0 fields are valid


Ah, damn, probably because I switched to byte_vector,  which doesn't do
the zero-initialization we want to do.  Here's a new patch (that applies
on the series directly) that doesn't use byte_vector.

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 1815d78dec4..200e740e013 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -3300,7 +3300,7 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
                        int regnum_offset,
                        gdb::array_view<const gdb_byte> buf)
 {
-  unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset;
+  unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
   gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);

   /* Enough space for a full vector register.
@@ -3309,11 +3309,11 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
      various 'scalar' pseudo registers to behavior like architectural
      writes, register width bytes are written the remainder are set to
      zero.  */
-  constexpr int raw_reg_size = 16;
+  int raw_reg_size = register_size (gdbarch, raw_regnum);
   gdb_byte raw_buf[raw_reg_size] {};
-  gdb::array_view<gdb_byte> raw_view (raw_buf);
+  gdb::array_view<gdb_byte> raw_view (raw_buf, raw_reg_size);
   copy (buf, raw_view.slice (0, buf.size ()));
-  put_frame_register (next_frame, v_regnum, raw_view);
+  put_frame_register (next_frame, raw_regnum, raw_view);
 }

 /* Given REGNUM, a SME pseudo-register number, store the bytes from DATA to the

Simon
  
Simon Marchi Nov. 9, 2023, 3:05 a.m. UTC | #6
On 2023-11-08 00:16, Simon Marchi wrote:
> 
> 
> On 2023-11-08 00:00, Simon Marchi wrote:
>> This series fixes reading/writing pseudo registers from/to non-current
>> frames (that is, frames other than frame 0).  Currently, we get this:
>>
>>     (gdb) frame 0
>>     #0  break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:38
>>     38              pop %rbx
>>     (gdb) p/x $rbx
>>     $1 = 0x2021222324252627
>>     (gdb) p/x $ebx
>>     $2 = 0x24252627
>>     (gdb) frame 1
>>     #1  0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:58
>>     58              call callee
>>     (gdb) p/x $rbx
>>     $3 = 0x1011121314151617
>>     (gdb) p/x $ebx
>>     $4 = 0x24252627
>>
>> This is a bit surprising, we would expect the last value to be
>> 0x14151617, the bottom half of the rbx value from frame 1 (the currently
>> selected frame at that point).  Instead, we got the bottom half of the
>> rbx value from frame 0.  This is because pseudo registers are always
>> read/written from/to the current thread's regcache.
>>
>> This series fixes this (as well as writing to pseudo registers) by
>> making it so pseudo registers are read/written using a frame.
> 
> Ah, I forgot because it's been so long, but this can be considered a v3
> of this series  here...
> 
>   https://inbox.sourceware.org/gdb-patches/20181024014333.14143-1-simon.marchi@polymtl.ca/
> 
> Simon

A bit more information that I realized I left out: this series fixes the
behavior for AArch64, ARM and AMD64/i386, because those are the three
architectures I had tests already written for.  It shouldn't be too hard
to update other architectures, the slightly more difficult part is to
write a test, since it involves writing assembly and CFI directives, not
something most people do everyday.

Simon
  
Simon Marchi Nov. 9, 2023, 7:04 p.m. UTC | #7
On 11/8/23 14:34, Simon Marchi wrote:
> Ah, damn, probably because I switched to byte_vector,  which doesn't do
> the zero-initialization we want to do.  Here's a new patch (that applies
> on the series directly) that doesn't use byte_vector.
> 
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index 1815d78dec4..200e740e013 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -3300,7 +3300,7 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>                         int regnum_offset,
>                         gdb::array_view<const gdb_byte> buf)
>  {
> -  unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset;
> +  unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
>    gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
> 
>    /* Enough space for a full vector register.
> @@ -3309,11 +3309,11 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>       various 'scalar' pseudo registers to behavior like architectural
>       writes, register width bytes are written the remainder are set to
>       zero.  */
> -  constexpr int raw_reg_size = 16;
> +  int raw_reg_size = register_size (gdbarch, raw_regnum);
>    gdb_byte raw_buf[raw_reg_size] {};
> -  gdb::array_view<gdb_byte> raw_view (raw_buf);
> +  gdb::array_view<gdb_byte> raw_view (raw_buf, raw_reg_size);
>    copy (buf, raw_view.slice (0, buf.size ()));
> -  put_frame_register (next_frame, v_regnum, raw_view);
> +  put_frame_register (next_frame, raw_regnum, raw_view);
>  }
> 
>  /* Given REGNUM, a SME pseudo-register number, store the bytes from DATA to the
> 
> Simon

I managed to run a Debian AArch64 image in qemu, with SVE support, so I
was able to reproduce the failures you mentioned.  In the end, here's a
version of aarch64_pseudo_write_1 that works for me (written as to
minimize the number of unnecessary changes, since that seems to
introduce unexpected bugs...).

static void
aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
			int regnum_offset,
			gdb::array_view<const gdb_byte> buf)
{
  unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;

  /* Enough space for a full vector register.  */
  int raw_reg_size = register_size (gdbarch, raw_regnum);
  gdb_byte raw_buf[raw_reg_size];
  gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);

  /* Ensure the register buffer is zero, we want gdb writes of the
     various 'scalar' pseudo registers to behavior like architectural
     writes, register width bytes are written the remainder are set to
     zero.  */
  memset (raw_buf, 0, register_size (gdbarch, AARCH64_V0_REGNUM));

  gdb::array_view<gdb_byte> raw_view (raw_buf, raw_reg_size);
  copy (buf, raw_view.slice (0, buf.size ()));
  put_frame_register (next_frame, raw_regnum, raw_view);
}

Simon
  
John Baldwin Nov. 11, 2023, 8:26 p.m. UTC | #8
On 11/7/23 9:00 PM, Simon Marchi wrote:
> This series fixes reading/writing pseudo registers from/to non-current
> frames (that is, frames other than frame 0).  Currently, we get this:
> 
>      (gdb) frame 0
>      #0  break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:38
>      38              pop %rbx
>      (gdb) p/x $rbx
>      $1 = 0x2021222324252627
>      (gdb) p/x $ebx
>      $2 = 0x24252627
>      (gdb) frame 1
>      #1  0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:58
>      58              call callee
>      (gdb) p/x $rbx
>      $3 = 0x1011121314151617
>      (gdb) p/x $ebx
>      $4 = 0x24252627
> 
> This is a bit surprising, we would expect the last value to be
> 0x14151617, the bottom half of the rbx value from frame 1 (the currently
> selected frame at that point).  Instead, we got the bottom half of the
> rbx value from frame 0.  This is because pseudo registers are always
> read/written from/to the current thread's regcache.
> 
> This series fixes this (as well as writing to pseudo registers) by
> making it so pseudo registers are read/written using a frame.
> 
> Simon Marchi (24):
>    gdb: don't handle i386 k registers as pseudo registers
>    gdb: use reg_buffer_common throughout gdbsupport/common-regcache.h
>    gdb: make store_integer take an array_view
>    gdb: simplify conditions in
>      regcache::{read,write,raw_collect,raw_supply}_part
>    gdb: change regcache interface to use array_view
>    gdb: fix bugs in {get,put}_frame_register_bytes
>    gdb: make put_frame_register take an array_view
>    gdb: change value_of_register and value_of_register_lazy to take the
>      next frame
>    gdb: remove frame_register
>    gdb: make put_frame_register take the next frame
>    gdb: make put_frame_register_bytes take the next frame
>    gdb: make get_frame_register_bytes take the next frame
>    gdb: add value::allocate_register
>    gdb: read pseudo register through frame
>    gdb: change parameter name in frame_unwind_register_unsigned
>      declaration
>    gdb: rename gdbarch_pseudo_register_write to
>      gdbarch_deprecated_pseudo_register_write
>    gdb: add gdbarch_pseudo_register_write that takes a frame
>    gdb: migrate i386 and amd64 to the new gdbarch_pseudo_register_write
>    gdb: make aarch64_za_offsets_from_regnum return za_offsets
>    gdb: add missing raw register read in
>      aarch64_sme_pseudo_register_write
>    gdb: migrate aarch64 to new gdbarch_pseudo_register_write
>    gdb: migrate arm to gdbarch_pseudo_register_read_value
>    gdb: migrate arm to new gdbarch_pseudo_register_write
>    gdb/testsuite: add tests for unwinding of pseudo registers
> 
>   gdb/aarch64-tdep.c                            | 297 +++++-----
>   gdb/alpha-tdep.c                              |  11 +-
>   gdb/amd64-tdep.c                              |  82 +--
>   gdb/arch/arm-get-next-pcs.c                   |   6 +-
>   gdb/arch/arm-get-next-pcs.h                   |   5 +-
>   gdb/arch/arm.c                                |   2 +-
>   gdb/arch/arm.h                                |   4 +-
>   gdb/arm-linux-tdep.c                          |  11 +-
>   gdb/arm-tdep.c                                | 145 +++--
>   gdb/avr-tdep.c                                |   3 +-
>   gdb/bfin-tdep.c                               |   3 +-
>   gdb/csky-tdep.c                               |   4 +-
>   gdb/defs.h                                    |  39 +-
>   gdb/dwarf2/expr.c                             |  22 +-
>   gdb/dwarf2/frame.c                            |   5 +-
>   gdb/eval.c                                    |   3 +-
>   gdb/findvar.c                                 |  50 +-
>   gdb/frame-unwind.c                            |   3 +-
>   gdb/frame.c                                   | 174 +++---
>   gdb/frame.h                                   |  28 +-
>   gdb/frv-tdep.c                                |   3 +-
>   gdb/gdbarch-gen.h                             |  28 +-
>   gdb/gdbarch.c                                 |  40 +-
>   gdb/gdbarch_components.py                     |  29 +-
>   gdb/guile/scm-frame.c                         |   3 +-
>   gdb/h8300-tdep.c                              |   3 +-
>   gdb/i386-tdep.c                               | 380 ++++--------
>   gdb/i386-tdep.h                               |  15 +-
>   gdb/i387-tdep.c                               |  16 +-
>   gdb/ia64-tdep.c                               |  18 +-
>   gdb/infcmd.c                                  |   6 +-
>   gdb/loongarch-tdep.c                          |   3 +-
>   gdb/m32c-tdep.c                               |   3 +-
>   gdb/m68hc11-tdep.c                            |   3 +-
>   gdb/m68k-tdep.c                               |  17 +-
>   gdb/mep-tdep.c                                |   3 +-
>   gdb/mi/mi-main.c                              |   3 +-
>   gdb/mips-tdep.c                               |  29 +-
>   gdb/msp430-tdep.c                             |   3 +-
>   gdb/nat/aarch64-hw-point.c                    |   3 +-
>   gdb/nat/aarch64-scalable-linux-ptrace.c       |  20 +-
>   gdb/nat/linux-btrace.c                        |   3 +-
>   gdb/nds32-tdep.c                              |   8 +-
>   gdb/python/py-frame.c                         |   3 +-
>   gdb/python/py-unwind.c                        |   4 +-
>   gdb/regcache.c                                | 548 +++++++++++-------
>   gdb/regcache.h                                | 113 +++-
>   gdb/riscv-tdep.c                              |  13 +-
>   gdb/rl78-tdep.c                               |   3 +-
>   gdb/rs6000-tdep.c                             |  21 +-
>   gdb/s12z-tdep.c                               |   2 +-
>   gdb/s390-tdep.c                               |   3 +-
>   gdb/sh-tdep.c                                 |   9 +-
>   gdb/sparc-tdep.c                              |   3 +-
>   gdb/sparc64-tdep.c                            |   3 +-
>   gdb/std-regs.c                                |  11 +-
>   .../gdb.arch/aarch64-pseudo-unwind-asm.S      |  82 +++
>   .../gdb.arch/aarch64-pseudo-unwind.c          |  33 ++
>   .../gdb.arch/aarch64-pseudo-unwind.exp        |  90 +++
>   .../gdb.arch/amd64-pseudo-unwind-asm.S        |  66 +++
>   gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c  |  33 ++
>   .../gdb.arch/amd64-pseudo-unwind.exp          |  91 +++
>   .../gdb.arch/arm-pseudo-unwind-asm.S          |  81 +++
>   .../gdb.arch/arm-pseudo-unwind-legacy-asm.S   |  84 +++
>   .../gdb.arch/arm-pseudo-unwind-legacy.c       |  33 ++
>   .../gdb.arch/arm-pseudo-unwind-legacy.exp     |  86 +++
>   gdb/testsuite/gdb.arch/arm-pseudo-unwind.c    |  33 ++
>   gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp  |  88 +++
>   gdb/valops.c                                  |  31 +-
>   gdb/value.c                                   | 149 +++++
>   gdb/value.h                                   |  64 +-
>   gdb/xtensa-tdep.c                             |   3 +-
>   gdbserver/linux-arm-low.cc                    |   4 +-
>   gdbserver/regcache.cc                         |  69 ++-
>   gdbserver/regcache.h                          |   6 +-
>   gdbsupport/common-regcache.cc                 |   2 +-
>   gdbsupport/common-regcache.h                  |  58 +-
>   gdbsupport/rsp-low.cc                         |   8 +
>   gdbsupport/rsp-low.h                          |   2 +
>   79 files changed, 2324 insertions(+), 1144 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind-asm.S
>   create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.c
>   create mode 100644 gdb/testsuite/gdb.arch/aarch64-pseudo-unwind.exp
>   create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S
>   create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.c
>   create mode 100644 gdb/testsuite/gdb.arch/amd64-pseudo-unwind.exp
>   create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-asm.S
>   create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy-asm.S
>   create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.c
>   create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind-legacy.exp
>   create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.c
>   create mode 100644 gdb/testsuite/gdb.arch/arm-pseudo-unwind.exp
> 
> 
> base-commit: 1185b5b79a12ba67eb60bee3f75babf7a222fde0

I did not review the aarch64/arm changes very thoroughly (patches 19-23),
but the rest all look fine to me aside from the one comment I had on
patch 18.

(So to be clear, you can add my Reviewed-by on all of 1-18.)  Looks like
Luis is helping to validate the arm changes.

I certainly have a use case for this for CHERI support where GPRs are
also extended (so ideally I'd like to treat the 64-bit GPRs as pseudos
of the 129-bit capability registers), and also for Morello in particular
where the stack pointer is banked in userland and can vary by stack
frame depending on a permission in the PC as to which real register it
maps on to.
  
Simon Marchi Nov. 13, 2023, 3:03 a.m. UTC | #9
On 11/11/23 15:26, John Baldwin wrote:
> I did not review the aarch64/arm changes very thoroughly (patches 19-23),
> but the rest all look fine to me aside from the one comment I had on
> patch 18.
> 
> (So to be clear, you can add my Reviewed-by on all of 1-18.)  Looks like
> Luis is helping to validate the arm changes.

Thanks for reviewing, will add.

Simon
  
Luis Machado Nov. 13, 2023, 1:10 p.m. UTC | #10
Simon,

On 11/9/23 19:04, Simon Marchi wrote:
> On 11/8/23 14:34, Simon Marchi wrote:
>> Ah, damn, probably because I switched to byte_vector,  which doesn't do
>> the zero-initialization we want to do.  Here's a new patch (that applies
>> on the series directly) that doesn't use byte_vector.
>>
>> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
>> index 1815d78dec4..200e740e013 100644
>> --- a/gdb/aarch64-tdep.c
>> +++ b/gdb/aarch64-tdep.c
>> @@ -3300,7 +3300,7 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>>                         int regnum_offset,
>>                         gdb::array_view<const gdb_byte> buf)
>>  {
>> -  unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset;
>> +  unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
>>    gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
>>
>>    /* Enough space for a full vector register.
>> @@ -3309,11 +3309,11 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>>       various 'scalar' pseudo registers to behavior like architectural
>>       writes, register width bytes are written the remainder are set to
>>       zero.  */
>> -  constexpr int raw_reg_size = 16;
>> +  int raw_reg_size = register_size (gdbarch, raw_regnum);
>>    gdb_byte raw_buf[raw_reg_size] {};
>> -  gdb::array_view<gdb_byte> raw_view (raw_buf);
>> +  gdb::array_view<gdb_byte> raw_view (raw_buf, raw_reg_size);
>>    copy (buf, raw_view.slice (0, buf.size ()));
>> -  put_frame_register (next_frame, v_regnum, raw_view);
>> +  put_frame_register (next_frame, raw_regnum, raw_view);
>>  }
>>
>>  /* Given REGNUM, a SME pseudo-register number, store the bytes from DATA to the
>>
>> Simon
> 
> I managed to run a Debian AArch64 image in qemu, with SVE support, so I
> was able to reproduce the failures you mentioned.  In the end, here's a
> version of aarch64_pseudo_write_1 that works for me (written as to
> minimize the number of unnecessary changes, since that seems to
> introduce unexpected bugs...).
> 
> static void
> aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
> 			int regnum_offset,
> 			gdb::array_view<const gdb_byte> buf)
> {
>   unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
> 
>   /* Enough space for a full vector register.  */
>   int raw_reg_size = register_size (gdbarch, raw_regnum);
>   gdb_byte raw_buf[raw_reg_size];
>   gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
> 
>   /* Ensure the register buffer is zero, we want gdb writes of the
>      various 'scalar' pseudo registers to behavior like architectural
>      writes, register width bytes are written the remainder are set to
>      zero.  */
>   memset (raw_buf, 0, register_size (gdbarch, AARCH64_V0_REGNUM));
> 
>   gdb::array_view<gdb_byte> raw_view (raw_buf, raw_reg_size);
>   copy (buf, raw_view.slice (0, buf.size ()));
>   put_frame_register (next_frame, raw_regnum, raw_view);
> }
> 
> Simon

Sorry for the late reply. I was out a couple days last week.

The above seems to make gdb.arch/aarch64-fp.exp happy, but gdb.arch/aarch64-pseudo-unwind.exp is still slightly unhappy:

FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value

This was tested on hardware (AWS's Graviton 3). Let me play with it a bit to understand what's up. I also see a
SIGSEGV in the test that shouldn't be there. I'm guessing some sort of raw register corruption, as it leads to
pc == 0x0.
  
Luis Machado Nov. 13, 2023, 3:08 p.m. UTC | #11
On 11/13/23 13:10, Luis Machado wrote:
> Simon,
> 
> On 11/9/23 19:04, Simon Marchi wrote:
>> On 11/8/23 14:34, Simon Marchi wrote:
>>> Ah, damn, probably because I switched to byte_vector,  which doesn't do
>>> the zero-initialization we want to do.  Here's a new patch (that applies
>>> on the series directly) that doesn't use byte_vector.
>>>
>>> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
>>> index 1815d78dec4..200e740e013 100644
>>> --- a/gdb/aarch64-tdep.c
>>> +++ b/gdb/aarch64-tdep.c
>>> @@ -3300,7 +3300,7 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>>>                         int regnum_offset,
>>>                         gdb::array_view<const gdb_byte> buf)
>>>  {
>>> -  unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset;
>>> +  unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
>>>    gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
>>>
>>>    /* Enough space for a full vector register.
>>> @@ -3309,11 +3309,11 @@ aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>>>       various 'scalar' pseudo registers to behavior like architectural
>>>       writes, register width bytes are written the remainder are set to
>>>       zero.  */
>>> -  constexpr int raw_reg_size = 16;
>>> +  int raw_reg_size = register_size (gdbarch, raw_regnum);
>>>    gdb_byte raw_buf[raw_reg_size] {};
>>> -  gdb::array_view<gdb_byte> raw_view (raw_buf);
>>> +  gdb::array_view<gdb_byte> raw_view (raw_buf, raw_reg_size);
>>>    copy (buf, raw_view.slice (0, buf.size ()));
>>> -  put_frame_register (next_frame, v_regnum, raw_view);
>>> +  put_frame_register (next_frame, raw_regnum, raw_view);
>>>  }
>>>
>>>  /* Given REGNUM, a SME pseudo-register number, store the bytes from DATA to the
>>>
>>> Simon
>>
>> I managed to run a Debian AArch64 image in qemu, with SVE support, so I
>> was able to reproduce the failures you mentioned.  In the end, here's a
>> version of aarch64_pseudo_write_1 that works for me (written as to
>> minimize the number of unnecessary changes, since that seems to
>> introduce unexpected bugs...).
>>
>> static void
>> aarch64_pseudo_write_1 (gdbarch *gdbarch, frame_info_ptr next_frame,
>> 			int regnum_offset,
>> 			gdb::array_view<const gdb_byte> buf)
>> {
>>   unsigned raw_regnum = AARCH64_V0_REGNUM + regnum_offset;
>>
>>   /* Enough space for a full vector register.  */
>>   int raw_reg_size = register_size (gdbarch, raw_regnum);
>>   gdb_byte raw_buf[raw_reg_size];
>>   gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
>>
>>   /* Ensure the register buffer is zero, we want gdb writes of the
>>      various 'scalar' pseudo registers to behavior like architectural
>>      writes, register width bytes are written the remainder are set to
>>      zero.  */
>>   memset (raw_buf, 0, register_size (gdbarch, AARCH64_V0_REGNUM));
>>
>>   gdb::array_view<gdb_byte> raw_view (raw_buf, raw_reg_size);
>>   copy (buf, raw_view.slice (0, buf.size ()));
>>   put_frame_register (next_frame, raw_regnum, raw_view);
>> }
>>
>> Simon
> 
> Sorry for the late reply. I was out a couple days last week.
> 
> The above seems to make gdb.arch/aarch64-fp.exp happy, but gdb.arch/aarch64-pseudo-unwind.exp is still slightly unhappy:
> 
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $v8.q.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: caller, after change: p/x $s8.u
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: continue to breakpoint: continue to break_here_c
> FAIL: gdb.arch/aarch64-pseudo-unwind.exp: p/x value
> 
> This was tested on hardware (AWS's Graviton 3). Let me play with it a bit to understand what's up. I also see a
> SIGSEGV in the test that shouldn't be there. I'm guessing some sort of raw register corruption, as it leads to
> pc == 0x0.

I think I understand what's going on here. In the callee, we have CFI stating we're saving the following registers:

.cfi_offset 29, -16  // x29 (SP)
.cfi_offset 30, -8   // x30 (LR)
.cfi_offset 72, -32  // v8 -> 128-bit in size

So we're reserving a slot of 16 bytes to save v8, which is fine. But later, when we go up a frame and try to put a v8 pseudo-register
value to the frame there are two distinct scenarios.

The first one is on a sytem that doesn't support SVE or that does support SVE but the vector length is 128-bit, which
means z8 (the raw register) is the same size as v8 (the pseudo-register). This works fine, because we use the size of
the raw register to put the pseudo-register value to the frame.

Now, if we have SVE support and the vector length is bigger than 128-bit (in my case it is 256-bit), then using the
size of the raw register (z8) will put 32 bytes into a slot of 16 bytes, corrupting (IIUC) both SP and LR, and leading
to a segfault.

Technically we would be fine with using the correct size of the slot when putting a pseudo-register to a frame, but
I think there are further complications.

Take, for instance, the following text from the aadwarf64 (https://github.com/ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst),
note 5 from DWARF registers 64-95:

"In a similar manner to the general register file the size of an FP/Advanced SIMD register is taken from some external context to the register
number. If no context is available then only the least significant 64 bits of the register are referenced. In particular this means that the most
significant part of a SIMD register is unrecoverable by frame unwinding."

So this makes me think we might have situations where we don't know exactly what the size of the slot is. We may have saved all 128 bits of
a v register, but it may also be the case we only saved 64 bits. How we distinguish what size to use for putting a v pseudo-register to a frame
isn't completely clear to me at this point.

I'm wondering if we should instead use x/w registers for testing this functionality for aarch64.