AArch64 (Debugging with GDB)

#### 21.4.1 AArch64 ¶

When GDB is debugging the AArch64 architecture, it provides the following special commands:

`set debug aarch64` ¶

  This command determines whether AArch64 architecture-specific debugging messages are to be displayed.

`show debug aarch64`

  Show whether AArch64 debugging messages are displayed.

#### 21.4.1.1 AArch64 SVE. ¶

When GDB is debugging the AArch64 architecture, if the Scalable Vector Extension (SVE) is present, then GDB will provide the vector registers `$z0` through `$z31`, vector predicate registers `$p0` through `$p15`, and the `$ffr` register. In addition, the pseudo register `$vg` will be provided. This is the vector granule for the current thread and represents the number of 64-bit chunks in an SVE `z` register.

If the vector length changes, then the `$vg` register will be updated, but the lengths of the `z` and `p` registers will not change. This is a known limitation of GDB and does not affect the execution of the target process.

For SVE, the following definitions are used throughout GDB’s source code and in this document:

- vl: The vector length, in bytes. It defines the size of each `Z` register.
- vq: The number of 128 bit units in vl. This is mostly used internally by GDB and the Linux Kernel.
- vg: The number of 64 bit units in vl. This is mostly used internally by GDB and the Linux Kernel.

#### 21.4.1.2 AArch64 SME. ¶

The Scalable Matrix Extension (SME) is an AArch64 architecture extension that expands on the concept of the Scalable Vector Extension (SVE) by providing a 2-dimensional register `ZA`, which is a square matrix of variable size, just like SVE provides a group of vector registers of variable size.

Similarly to SVE, where the size of each `Z` register is directly related to the vector length (vl for short), the SME `ZA` matrix register’s size is directly related to the streaming vector length (svl for short). See vl. See svl.

The `ZA` register state can be either active or inactive, if it is not in use.

SME also introduces a new execution mode called streaming SVE mode (streaming mode for short). When streaming mode is enabled, the program supports execution of SVE2 instructions and the SVE registers will have vector length svl. When streaming mode is disabled, the SVE registers have vector length vl.

For more information about SME and SVE, please refer to official architecture documentation.

The following definitions are used throughout GDB’s source code and in this document:

- svl: The streaming vector length, in bytes. It defines the size of each dimension of the 2-dimensional square `ZA` matrix. The total size of `ZA` is therefore svl by svl.

  When streaming mode is enabled, it defines the size of the SVE registers as well.

- svq: The number of 128 bit units in svl, also known as streaming vector granule. This is mostly used internally by GDB and the Linux Kernel.
- svg: The number of 64 bit units in svl. This is mostly used internally by GDB and the Linux Kernel.

When GDB is debugging the AArch64 architecture, if the Scalable Matrix Extension (SME) is present, then GDB will make the `ZA` register available. GDB will also make the `SVG` register and `SVCR` pseudo-register available.

The `ZA` register is a 2-dimensional square svl by svl matrix of bytes. To simplify the representation and access to the `ZA` register in GDB, it is defined as a vector of svlxsvl bytes.

If the user wants to index the `ZA` register as a matrix, it is possible to reference `ZA` as `ZA[i][j]`, where i is the row number and j is the column number.

The `SVG` register always contains the streaming vector granule (svg) for the current thread. From the value of register `SVG` we can easily derive the svl value.

The `SVCR` pseudo-register (streaming vector control register) is a status register that holds two state bits: SM in bit 0 and ZA in bit 1.

If the SM bit is 1, it means the current thread is in streaming mode, and the SVE registers will use svl for their sizes. If the SM bit is 0, the current thread is not in streaming mode, and the SVE registers will use vl for their sizes. See vl.

If the ZA bit is 1, it means the `ZA` register is being used and has meaningful contents. If the ZA bit is 0, the `ZA` register is unavailable and its contents are undefined.

For convenience and simplicity, if the ZA bit is 0, the `ZA` register and all of its pseudo-registers will read as zero.

If svl changes during the execution of a program, then the `ZA` register size and the bits in the `SVCR` pseudo-register will be updated to reflect it.

It is possible for users to change svl during the execution of a program by modifying the `SVG` register value.

Whenever the `SVG` register is modified with a new value, the following will be observed:

- The ZA and SM bits will be cleared in the `SVCR` pseudo-register.
- The `ZA` register will have a new size and its state will be cleared, forcing its contents and the contents of all of its pseudo-registers back to zero.
- If the SM bit was 1, the SVE registers will be reset to having their sizes based on vl as opposed to svl. If the SM bit was 0 prior to modifying the `SVG` register, there will be no observable effect on the SVE registers.

The possible values for the `SVG` register are 2, 4, 8, 16, 32. These numbers correspond to streaming vector length (svl) values of 16 bytes, 32 bytes, 64 bytes, 128 bytes and 256 bytes respectively.

The minimum size of the `ZA` register is 16 x 16 (256) bytes, and the maximum size is 256 x 256 (65536) bytes. In streaming mode, with bit SM set, the size of the `ZA` register is the size of all the SVE `Z` registers combined.

The `ZA` register can also be accessed using tiles and tile slices.

Tile pseudo-registers are square, 2-dimensional sub-arrays of elements within the `ZA` register.

The tile pseudo-registers have the following naming pattern: `ZA<tile number><qualifier>`.

There is a total of 31 `ZA` tile pseudo-registers. They are `ZA0B`, `ZA0H` through `ZA1H`, `ZA0S` through `ZA3S`, `ZA0D` through `ZA7D` and `ZA0Q` through `ZA15Q`.

Tile slice pseudo-registers are vectors of horizontally or vertically contiguous elements within the `ZA` register.

The tile slice pseudo-registers have the following naming pattern: `ZA<tile number><direction><qualifier> <slice number>`.

There are up to 16 tiles (0 ~ 15), the direction can be either `v` (vertical) or `h` (horizontal), the qualifiers can be `b` (byte), `h` (halfword), `s` (word), `d` (doubleword) and `q` (quadword) and there are up to 256 slices (0 ~ 255) depending on the value of svl. The number of slices is the same as the value of svl.

The number of available tile slice pseudo-registers can be large. For a minimum svl of 16 bytes, there are 5 (number of qualifiers) x 2 (number of directions) x 16 (svl) pseudo-registers. For the maximum svl of 256 bytes, there are 5 x 2 x 256 pseudo-registers.

When listing all the available registers, users will see the currently-available `ZA` pseudo-registers. Pseudo-registers that don’t exist for a given svl value will not be displayed.

For more information on SME and its terminology, please refer to the Arm Architecture Reference Manual Supplement, The Scalable Matrix Extension (SME), for Armv9-A.

Some features are still under development and rely on ACLE and ABI definitions, so there are known limitations to the current SME support in GDB.

One such example is calling functions in the program being debugged by GDB. Such calls are not SME-aware and thus don’t take into account the `SVCR` pseudo-register bits nor the `ZA` register contents. See Calling Program Functions.

The lazy saving scheme involving the `TPIDR2` register is not yet supported by GDB, though the `TPIDR2` register is known and supported by GDB.

Lastly, an important limitation for `gdbserver` is its inability to communicate svl changes to GDB. This means `gdbserver`, even though it is capable of adjusting its internal caches to reflect a change in the value of svl mid-execution, will operate with a potentially different svl value compared to GDB. This can lead to GDB showing incorrect values for the `ZA` register and incorrect values for SVE registers (when in streaming mode).

This is the same limitation we have for the SVE registers, and there are plans to address this limitation going forward.

#### 21.4.1.3 AArch64 SME2. ¶

The Scalable Matrix Extension 2 is an AArch64 architecture extension that further expands the SME extension with the following:

- The ability to address the `ZA` array through groups of one-dimensional `ZA` array vectors, as opposed to `ZA` tiles with 2 dimensions.
- Instructions to operate on groups of SVE `Z` registers and `ZA` array vectors.
- A new 512 bit `ZT0` lookup table register, for data decompression.

When GDB is debugging the AArch64 architecture, if the Scalable Matrix Extension 2 (SME2) is present, then GDB will make the `ZT0` register available.

The `ZT0` register is only considered active when the `ZA` register state is active, therefore when the ZA bit of the `SVCR` is 1.

When the ZA bit of `SVCR` is 0, that means the `ZA` register state is not active, which means the `ZT0` register state is also not active.

When `ZT0` is not active, it is comprised of zeroes, just like `ZA`.

Similarly to the `ZA` register, if the `ZT0` state is not active and the user attempts to modify its value such that any of its bytes is non-zero, then GDB will initialize the `ZA` register state as well, which means the `SVCR` ZA bit gets set to 1.

For more information about SME2, please refer to the official architecture documentation.

#### 21.4.1.4 AArch64 Pointer Authentication. ¶

When GDB is debugging the AArch64 architecture, and the program is using the v8.3-A feature Pointer Authentication (PAC), then whenever the link register `$lr` is pointing to an PAC function its value will be masked. When GDB prints a backtrace, any addresses that required unmasking will be postfixed with the marker [PAC]. When using the MI, this is printed as part of the `addr_flags` field.

#### 21.4.1.5 AArch64 Memory Tagging Extension. ¶

When GDB is debugging the AArch64 architecture, the program is using the v8.5-A feature Memory Tagging Extension (MTE) and there is support in the kernel for MTE, GDB will make memory tagging functionality available for inspection and editing of logical and allocation tags. See Memory Tagging.

To aid debugging, GDB will output additional information when SIGSEGV signals are generated as a result of memory tag failures.

If the tag violation is synchronous, the following will be shown:

    Program received signal SIGSEGV, Segmentation fault
    Memory tag violation while accessing address 0x0500fffff7ff8000
    Allocation tag 0x1
    Logical tag 0x5.

If the tag violation is asynchronous, the fault address is not available. In this case GDB will show the following:

    Program received signal SIGSEGV, Segmentation fault
    Memory tag violation
    Fault address unavailable.

A special register, `tag_ctl`, is made available through the `org.gnu.gdb.aarch64.mte` feature. This register exposes some options that can be controlled at runtime and emulates the `prctl` option `PR_SET_TAGGED_ADDR_CTRL`. For further information, see the documentation in the Linux kernel.

GDB supports dumping memory tag data to core files through the `gcore` command and reading memory tag data from core files generated by the `gcore` command or the Linux kernel.

When a process uses memory-mapped pages protected by memory tags (for example, AArch64 MTE), this additional information will be recorded in the core file in the event of a crash or if GDB generates a core file from the current process state.

The memory tag data will be used so developers can display the memory tags from a particular memory region (using the ‘`m`’ modifier to the `x` command, using the `print` command or using the various `memory-tag` subcommands.

In the case of a crash, GDB will attempt to retrieve the memory tag information automatically from the core file, and will show one of the above messages depending on whether the synchronous or asynchronous mode is selected. See Memory Tagging. See Examining Memory.