mbox series

[v2,0/4] Add another way to check for MTE-tagged addresses on remote targets

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

Message

Gustavo Romero March 28, 2024, 10:48 p.m. UTC
This series introduces a new method to check for MTE-tagged addresses on
remote targets.

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

This new mechanism allows for checking MTE 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.
 
----

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) 


And, finally, testing it 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) 


Cheers,
Gustavo

Gustavo Romero (4):
  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: Add new remote packet to check if address is tagged

 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/gdbarch-gen.h         |  4 +--
 gdb/gdbarch.c             |  2 +-
 gdb/gdbarch_components.py |  2 +-
 gdb/printcmd.c            | 29 +++++++++++-------
 gdb/remote.c              | 62 +++++++++++++++++++++++++++++++++++++++
 gdb/target-delegates.c    | 28 ++++++++++++++++++
 gdb/target.c              |  6 ++++
 gdb/target.h              |  6 ++++
 13 files changed, 147 insertions(+), 34 deletions(-)

Comments

Luis Machado April 3, 2024, 11:51 a.m. UTC | #1
Hi,

On 3/28/24 22:48, Gustavo Romero wrote:
> This series introduces a new method to check for MTE-tagged addresses on
> remote targets.
> 
> A new remote packet, qMemTagAddrCheck, is introduced, along with a new
> remote feature associated with it, 'memory-tagging-check-add+'. Only
> when 'memory-tagging-check-add+' feature is advertised GDB will use the
> new packet to query if an address is tagged.
> 
> This new mechanism allows for checking MTE 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.
>  
> ----
> 
> 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) 
> 
> 
> And, finally, testing it 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) 

Out of curiosity, I see you exercised native, core and QEMU-based remote debugging. Did you give the gdbserver-based remote debugging a try?

I think that is an important check given a gdb + gdbserver debugging session will also use the remote target, but will instead rely on accessing the remote smaps file.
Gustavo Romero April 3, 2024, 2:29 p.m. UTC | #2
Hi Luis,

On 4/3/24 8:51 AM, Luis Machado wrote:
> Hi,
> 
> On 3/28/24 22:48, Gustavo Romero wrote:
>> This series introduces a new method to check for MTE-tagged addresses on
>> remote targets.
>>
>> A new remote packet, qMemTagAddrCheck, is introduced, along with a new
>> remote feature associated with it, 'memory-tagging-check-add+'. Only
>> when 'memory-tagging-check-add+' feature is advertised GDB will use the
>> new packet to query if an address is tagged.
>>
>> This new mechanism allows for checking MTE 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.
>>   
>> ----
>>
>> 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)
>>
>>
>> And, finally, testing it 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)
> 
> Out of curiosity, I see you exercised native, core and QEMU-based remote debugging. Did you give the gdbserver-based remote debugging a try?
> 
> I think that is an important check given a gdb + gdbserver debugging session will also use the remote target, but will instead rely on accessing the remote smaps file.

Nope. I'll give it a try before sending v3 today.
  

Cheers,
Gustavo
Luis Machado April 3, 2024, 2:39 p.m. UTC | #3
On 4/3/24 15:29, Gustavo Romero wrote:
> Hi Luis,
> 
> On 4/3/24 8:51 AM, Luis Machado wrote:
>> Hi,
>>
>> On 3/28/24 22:48, Gustavo Romero wrote:
>>> This series introduces a new method to check for MTE-tagged addresses on
>>> remote targets.
>>>
>>> A new remote packet, qMemTagAddrCheck, is introduced, along with a new
>>> remote feature associated with it, 'memory-tagging-check-add+'. Only
>>> when 'memory-tagging-check-add+' feature is advertised GDB will use the
>>> new packet to query if an address is tagged.
>>>
>>> This new mechanism allows for checking MTE 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.
>>>   ----
>>>
>>> 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)
>>>
>>>
>>> And, finally, testing it 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)
>>
>> Out of curiosity, I see you exercised native, core and QEMU-based remote debugging. Did you give the gdbserver-based remote debugging a try?
>>
>> I think that is an important check given a gdb + gdbserver debugging session will also use the remote target, but will instead rely on accessing the remote smaps file.
> 
> Nope. I'll give it a try before sending v3 today.

Awesome. Thanks.

I'll do some checking locally with system emulation.
Gustavo Romero April 4, 2024, 5:35 a.m. UTC | #4
On 4/3/24 11:39 AM, Luis Machado wrote:
> On 4/3/24 15:29, Gustavo Romero wrote:
>> Hi Luis,
>>
>> On 4/3/24 8:51 AM, Luis Machado wrote:
>>> Hi,
>>>
>>> On 3/28/24 22:48, Gustavo Romero wrote:
>>>> This series introduces a new method to check for MTE-tagged addresses on
>>>> remote targets.
>>>>
>>>> A new remote packet, qMemTagAddrCheck, is introduced, along with a new
>>>> remote feature associated with it, 'memory-tagging-check-add+'. Only
>>>> when 'memory-tagging-check-add+' feature is advertised GDB will use the
>>>> new packet to query if an address is tagged.
>>>>
>>>> This new mechanism allows for checking MTE 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.
>>>>    ----
>>>>
>>>> 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)
>>>>
>>>>
>>>> And, finally, testing it 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)
>>>
>>> Out of curiosity, I see you exercised native, core and QEMU-based remote debugging. Did you give the gdbserver-based remote debugging a try?
>>>
>>> I think that is an important check given a gdb + gdbserver debugging session will also use the remote target, but will instead rely on accessing the remote smaps file.
>>
>> Nope. I'll give it a try before sending v3 today.
> 
> Awesome. Thanks.

The fallback mechanism works when tested against the gdbserver.

I'll paste the results into the cover letter for v3. That's a nice test, thanks!


Cheers,
Gustavo