mbox series

[v3,0/7] Add another way to check tagged addresses on remote targets

Message ID 20240404064819.2848899-1-gustavo.romero@linaro.org
Headers show
Series Add another way to check tagged addresses on remote targets | expand

Message

Gustavo Romero April 4, 2024, 6:48 a.m. UTC
This series introduces a new method to check for memory tagged addresses
on remote targets.

A new remote packet, qMemTagAddrCheck, is introduced along with a
feature associated with it, 'memory-tagging-check-add.' GDB will only
use the new packet to query if an address is tagged when the
'memory-tagging-check-add+' feature is advertised.

This new mechanism allows for checking memory tagged addresses in an
OS-agnostic way, which is necessary when debugging targets that do not
support '/proc/<PID>/smaps', as the current method of reading the smaps
contents fails in such cases.

Since v1:
 - Fixed build error "no match for ‘operator!=’ (operand types are ‘packet_result’ and ‘packet_status’)"
   reported by Linaro CI bot, caused by a last-minute rebase
 - Added instructions on how to test the series on a remote target using
   QEMU gdbstub (-g option) -- see below
 
Since v2:
 - Changed packet name to qMemTagCheckAddr for consistence
 - Documented the new packet in gdb.texinfo and NEWS
 - Changed target hook name to is_address_tagged
 - Fixed several GNU Style nonconformities
 - Split commit that adds the target hook and the qMemTagCheckAddr in
   two commits
 - Tested fallback mechanism using gdbserver (use of vFile requests
   instead of qMemTagCheckAddr)
 - Fixed off-by-one error
 - Changed targe hook signature to take gdbarch as an argument for
   better modularity
 
----

This series can be tested with the 'mte_t' binary found in:
https://people.linaro.org/~gustavo.romero/gdb, using the GDB
'memory-tag print-allocation-tag' command to show the allocation
tag for array pointer 'a'. To download mte_t:

$ wget https://people.linaro.org/~gustavo.romero/gdb/mte_t
$ chmod +x ./mte_t

... or build it from source:

$ wget https://people.linaro.org/~gustavo.romero/gdb/mte_t.c
$ gcc -march=armv8.5-a+memtag -static -g3 -O0 mte_t.c -o mte_t

For example, testing the address check for the aarch64_linux_nat.c
target:

gromero@arm64:~/code$ ~/git/binutils-gdb_remote/build/gdb/gdb -q ./mte_t
Reading symbols from ./mte_t...
(gdb) run
Starting program: /home/gromero/code/mte_t 
a[] address is 0xfffff7ffc000
a[0] = 1 a[1] = 2
0x100fffff7ffc000
a[0] = 3 a[1] = 2
Expecting SIGSEGV...

Program received signal SIGSEGV, Segmentation fault
Memory tag violation
Fault address unavailable.
0x0000000000418658 in write ()
(gdb) bt
#0  0x0000000000418658 in write ()
#1  0x000000000040a3bc in _IO_new_file_write ()
#2  0x0000000000409574 in new_do_write ()
#3  0x000000000040ae20 in _IO_new_do_write ()
#4  0x000000000040b55c in _IO_new_file_overflow ()
#5  0x0000000000407414 in puts ()
#6  0x000000000040088c in main () at mte_t.c:119
(gdb) frame 6
#6  0x000000000040088c in main () at mte_t.c:119
119	            printf("...haven't got one\n");
(gdb) memory-tag print-logical-tag a
$1 = 0x1
(gdb) memory-tag print-allocation-tag &a[16]
$2 = 0x0
(gdb)  # Tag mismatch
(gdb) 


Testing address check on a core file:

gromero@arm64:~/code$ ulimit -c unlimited
gromero@arm64:~/code$ ./mte_t
a[] address is 0xffffb3bcc000
a[0] = 1 a[1] = 2
0x900ffffb3bcc000
a[0] = 3 a[1] = 2
Expecting SIGSEGV...
Segmentation fault (core dumped)
gromero@arm64:~/code$ ~/git/binutils-gdb_remote/build/gdb/gdb -q ./mte_t ./core
Reading symbols from ./mte_t...
[New LWP 256036]
Core was generated by `./mte_t'.
Program terminated with signal SIGSEGV, Segmentation fault
Memory tag violation
Fault address unavailable.
#0  0x0000000000418658 in write ()
(gdb) bt
#0  0x0000000000418658 in write ()
#1  0x000000000040a3bc in _IO_new_file_write ()
#2  0x0000000000409574 in new_do_write ()
#3  0x000000000040ae20 in _IO_new_do_write ()
#4  0x000000000040b55c in _IO_new_file_overflow ()
#5  0x0000000000407414 in puts ()
#6  0x000000000040088c in main () at mte_t.c:119
(gdb) frame 6
#6  0x000000000040088c in main () at mte_t.c:119
119	            printf("...haven't got one\n");
(gdb) memory-tag print-logical-tag a
$1 = 0x9
(gdb) memory-tag print-allocation-tag &a[16]
$2 = 0x0
(gdb) # Tag mismatch 
(gdb) 


Finally, testing the new packet on a remote target using QEMU gdbstub
which supports the new 'memory-tagging-check-add+' feature (WIP).

Clone and build QEMU:

$ git clone --depth=1 --single-branch -b mte https://github.com/gromero/qemu.git
$ mkdir qemu/build && cd qemu/build
$ ../configure --target-list=aarch64-linux-user --disable-docs
$ make -j
$ wget https://people.linaro.org/~gustavo.romero/gdb/mte_t
$ chmod +x ./mte_t
$ ./qemu-aarch64 -g 1234 ./mte_t

... and connect to QEMU gdbstub from GDB:

gromero@amd:~/git/binutils-gdb/build$ ./gdb/gdb -q
(gdb) target remote localhost:1234 
Remote debugging using localhost:1234
Reading /tmp/qemu/build/mte_t from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /tmp/qemu/build/mte_t from remote target...
Reading symbols from target:/tmp/qemu/build/mte_t...
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault
Memory tag violation
Fault address unavailable.
0x0000000000407290 in puts ()
(gdb) bt
#0  0x0000000000407290 in puts ()
#1  0x000000000040088c in main () at mte_t.c:119
(gdb) frame 1 
#1  0x000000000040088c in main () at mte_t.c:119
119	
(gdb) memory-tag print-allocation-tag a
$1 = 0x2
(gdb) set debug remote on
(gdb) memory-tag print-allocation-tag a
[remote] Sending packet: $qMemTagAddrCheck:200400000802000#1f
[remote] Received Ack
[remote] Packet received: 01
[remote] Sending packet: $qMemTags:400000802000,1:1#6f
[remote] Received Ack
[remote] Packet received: m02
$2 = 0x2
(gdb) 


Also, below is a test of the fallback mechanism using the gdbserver,
which must use vFile requests instead of the new packet:

In one terminal:

gromero@arm64:~/git/binutils-gdb_remote/build$ ./gdbserver/gdbserver localhost:1234 /home/gromero/code/mte_t

... in another terminal:

gromero@arm64:~/git/binutils-gdb_remote/build$ gdb/gdb -q 
(gdb) target remote localhost:1234 
Remote debugging using localhost:1234
Reading /home/gromero/code/mte_t from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /home/gromero/code/mte_t from remote target...
Reading symbols from target:/home/gromero/code/mte_t...
Reading /home/gromero/.local/lib/debug/.build-id/a1/fb8db7731a11f85efa2ae80005bdb590796021.debug from remote target...
Reading /usr/lib/debug/.build-id/a1/fb8db7731a11f85efa2ae80005bdb590796021.debug from remote target...
0x0000000000400580 in _start ()
(gdb) b 103
Breakpoint 1 at 0x400818: file mte_t.c, line 103.
(gdb) c
Continuing.

Breakpoint 1, main () at mte_t.c:103
103	            set_tag(a);
(gdb) n
105	            printf("%p\n", a);
(gdb) set debug remote on 
(gdb) memory-tag print-allocation-tag a 
[remote] Sending packet: $m400948,4#06
[remote] Packet received: 3f030094
[remote] Sending packet: $m400944,4#02
[remote] Packet received: 60003fd6
[remote] Sending packet: $m400948,4#06
[remote] Packet received: 3f030094
[remote] Sending packet: $vFile:setfs:0#bf
[remote] Packet received: F0
[remote] Sending packet: $vFile:open:2f70726f632f3236353634362f736d617073,0,1c0#b0
[remote] Packet received: F8
[remote] remote_hostio_pread: readahead cache miss 28
[remote] Sending packet: $vFile:pread:8,2001f,0#5f
[remote] Packet received: Feaa;00400000-0047e000 r-xp 00000000 fe:02 5663492                            /home/gromero/code/mte_t\nSize:                504 kB\nKernelPageSize:        4 kB\nMMUPageSize:           4 kB\nRss:                 440 kB\nPss:                 440 kB\nPss_Dirty:            12 kB\nShared_Clean:          0 kB\nShared_Dirty:          0 kB\nPrivate_Clean:       428 kB\nPrivate_Dirty:        12 kB\nReferenced:          440 kB\nAnonymous:            12 kB\nKSM:                   0 kB\nLazyFree:              0 kB\nAnonHugePages:    [3247 bytes omitted]
[remote] remote_hostio_pread: readahead cache miss 29
[remote] Sending packet: $vFile:pread:8,2001f,eaa#56
[remote] Packet received: Fb96;fffff7ffc000-fffff7ffd000 rw-p 00000000 00:00 0 \nSize:                  4 kB\nKernelPageSize:        4 kB\nMMUPageSize:           4 kB\nRss:                   4 kB\nPss:                   4 kB\nPss_Dirty:             4 kB\nShared_Clean:          0 kB\nShared_Dirty:          0 kB\nPrivate_Clean:         0 kB\nPrivate_Dirty:         4 kB\nReferenced:            4 kB\nAnonymous:             4 kB\nKSM:                   0 kB\nLazyFree:              0 kB\nAnonHugePages:         0 kB\nShmemPmdMapped:        0 kB\nFilePmdMap [2459 bytes omitted]
[remote] remote_hostio_pread: readahead cache miss 30
[remote] Sending packet: $vFile:pread:8,2001f,1a40#25
[remote] Packet received: F0;
[remote] Sending packet: $vFile:close:8#b8
[remote] Packet received: F0
[remote] Sending packet: $qMemTags:fffff7ffc000,1:1#15
[remote] Packet received: m0e
$1 = 0xe
(gdb)


Cheers,
Gustavo

Gustavo Romero (7):
  gdb: aarch64: Remove MTE address checking from get_memtag
  gdb: aarch64: Move MTE address check out of set_memtag
  gdb: aarch64: Remove MTE address checking from memtag_matches_p
  gdb: Use passed gdbarch instead of calling current_inferior
  gdb: Introduce is_address_tagged target hook
  gdb: Add qMemTagAddrCheck packet
  gdb: Document qMemTagCheckAddr packet

 gdb/NEWS                  |  9 ++++++
 gdb/aarch64-linux-nat.c   |  8 +++++
 gdb/aarch64-linux-tdep.c  | 22 +++-----------
 gdb/arch-utils.c          |  2 +-
 gdb/arch-utils.h          |  2 +-
 gdb/corelow.c             |  8 +++++
 gdb/doc/gdb.texinfo       | 50 +++++++++++++++++++++++++++++--
 gdb/gdbarch-gen.h         |  4 +--
 gdb/gdbarch.c             |  2 +-
 gdb/gdbarch_components.py |  2 +-
 gdb/printcmd.c            | 32 ++++++++++++--------
 gdb/remote.c              | 62 +++++++++++++++++++++++++++++++++++++++
 gdb/target-delegates.c    | 30 +++++++++++++++++++
 gdb/target.c              |  6 ++++
 gdb/target.h              |  6 ++++
 15 files changed, 206 insertions(+), 39 deletions(-)