[1/2] testsuite: Extend object-readelf beyond attributes

Message ID 20260408091202.13538-2-muhammad.kamran@arm.com
State New
Headers
Series aarch64/testsuite: improve object-readelf and add LTO branch-protection tests |

Commit Message

Muhammad Kamran April 8, 2026, 9:12 a.m. UTC
  object-readelf in lib/lto.exp was hard-wired to use readelf -A,
limiting it to attribute checks. Extend it to accept a readelf option and
a regex, where the option selects the readelf flag and the regex is
matched against the output.

Add wrapper procedures for common use cases:

	• attribute checks, and
	• note checks.

Also add support for negative checks via an "is-negative" argument,
which requires that the regex is not present in the output.

gcc/ChangeLog:

	* doc/sourcebuild.texi (Scan object metadata with readelf): Document
	object-readelf-attributes, object-readelf-attributes-not,
	object-readelf-notes, and object-readelf-notes-not as regex-based
	checks with optional target/xfail selectors.

gcc/testsuite/ChangeLog:

	* lib/lto.exp (object-readelf): Accept a readelf option and a single
	regex; match against full readelf output. Keep positive/negative
	behaviour via wrappers.
	(object-readelf-attributes, object-readelf-attributes-not,
	object-readelf-notes, object-readelf-notes-not): Implement as wrappers
	over the generic matcher.
	* gcc.dg-selftests/dg-final.exp (dg_final_directive_check_num_args):
	Update for object-readelf-* wrappers to regex-style arguments (1..3).
	* gcc.target/arm/lto/pr61123-enum-size_0.c: Update to use
	object-readelf-attributes with a single regex.
---
 gcc/doc/sourcebuild.texi                      | 23 ++++++
 gcc/testsuite/gcc.dg-selftests/dg-final.exp   |  5 +-
 .../gcc.target/arm/lto/pr61123-enum-size_0.c  |  2 +-
 gcc/testsuite/lib/lto.exp                     | 77 ++++++++++---------
 4 files changed, 68 insertions(+), 39 deletions(-)
  

Comments

Tamar Christina April 20, 2026, 7:13 a.m. UTC | #1
Hi Muhammad,

> -----Original Message-----
> From: Muhammad Kamran <muhammad.kamran@arm.com>
> Sent: 08 April 2026 10:12
> To: gcc-patches@gcc.gnu.org
> Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>; Tamar Christina
> <Tamar.Christina@arm.com>; Kyrylo Tkachov <ktkachov@nvidia.com>; Alice
> Carlotti <Alice.Carlotti@arm.com>; Alex Coplan <Alex.Coplan@arm.com>;
> Andrew Pinski <andrew.pinski@oss.qualcomm.com>; Wilco Dijkstra
> <Wilco.Dijkstra@arm.com>; Jakub Jelinek <jakub@redhat.com>; Rainer Orth
> <ro@CeBiTec.Uni-Bielefeld.DE>; Mike Stump <mikestump@comcast.net>;
> Muhammad Kamran <Muhammad.Kamran@arm.com>
> Subject: [PATCH 1/2] testsuite: Extend object-readelf beyond attributes
> 
> object-readelf in lib/lto.exp was hard-wired to use readelf -A,
> limiting it to attribute checks. Extend it to accept a readelf option and
> a regex, where the option selects the readelf flag and the regex is
> matched against the output.
> 
> Add wrapper procedures for common use cases:
> 
> 	• attribute checks, and
> 	• note checks.
> 
> Also add support for negative checks via an "is-negative" argument,
> which requires that the regex is not present in the output.

The changes look good to me, however since this is a general testsuite change
I can't approve it, you'll need a global or testsuite maintainer.

Thanks,
Tamar

> 
> gcc/ChangeLog:
> 
> 	* doc/sourcebuild.texi (Scan object metadata with readelf): Document
> 	object-readelf-attributes, object-readelf-attributes-not,
> 	object-readelf-notes, and object-readelf-notes-not as regex-based
> 	checks with optional target/xfail selectors.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* lib/lto.exp (object-readelf): Accept a readelf option and a single
> 	regex; match against full readelf output. Keep positive/negative
> 	behaviour via wrappers.
> 	(object-readelf-attributes, object-readelf-attributes-not,
> 	object-readelf-notes, object-readelf-notes-not): Implement as
> wrappers
> 	over the generic matcher.
> 	* gcc.dg-selftests/dg-final.exp (dg_final_directive_check_num_args):
> 	Update for object-readelf-* wrappers to regex-style arguments (1..3).
> 	* gcc.target/arm/lto/pr61123-enum-size_0.c: Update to use
> 	object-readelf-attributes with a single regex.
> ---
>  gcc/doc/sourcebuild.texi                      | 23 ++++++
>  gcc/testsuite/gcc.dg-selftests/dg-final.exp   |  5 +-
>  .../gcc.target/arm/lto/pr61123-enum-size_0.c  |  2 +-
>  gcc/testsuite/lib/lto.exp                     | 77 ++++++++++---------
>  4 files changed, 68 insertions(+), 39 deletions(-)
> 
> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> index 3bccb1384d9..958682907cb 100644
> --- a/gcc/doc/sourcebuild.texi
> +++ b/gcc/doc/sourcebuild.texi
> @@ -3729,6 +3729,29 @@ stands for zero or more unmatched lines; the
> whitespace after
> 
>  @end table
> 
> +@subsubsection Scan object metadata with readelf
> +
> +These commands inspect the linked test output file with
> @command{readelf}.
> +They are mainly intended for LTO tests.
> +
> +These commands take a single @var{regex} and test whether it is present
> +in (or absent from, for @samp{-not}) the corresponding
> @command{readelf}
> +output.
> +
> +@table @code
> +@item object-readelf-attributes @var{regex} [@{ target/xfail @var{selector}
> @}]
> +Runs @command{readelf -A} and checks that @var{regex} matches.
> +
> +@item object-readelf-attributes-not @var{regex} [@{ target/xfail
> @var{selector} @}]
> +Runs @command{readelf -A} and checks that @var{regex} does not match.
> +
> +@item object-readelf-notes @var{regex} [@{ target/xfail @var{selector} @}]
> +Runs @command{readelf -n} and checks that @var{regex} matches.
> +
> +@item object-readelf-notes-not @var{regex} [@{ target/xfail @var{selector}
> @}]
> +Runs @command{readelf -n} and checks that @var{regex} does not match.
> +@end table
> +
>  @subsubsection Scan optimization dump files
> 
>  These commands are available for @var{kind} of @code{tree}, @code{ltrans-
> tree},
> diff --git a/gcc/testsuite/gcc.dg-selftests/dg-final.exp b/gcc/testsuite/gcc.dg-
> selftests/dg-final.exp
> index 6dcfd3340a8..ff8fdf6d77a 100644
> --- a/gcc/testsuite/gcc.dg-selftests/dg-final.exp
> +++ b/gcc/testsuite/gcc.dg-selftests/dg-final.exp
> @@ -94,7 +94,10 @@ proc dg_final_directive_check_num_args {} {
> 
>      verify_args scan-lang-dump 2 3
> 
> -    verify_args object-readelf 2 3
> +    verify_args object-readelf-attributes 1 3
> +    verify_args object-readelf-attributes-not 1 3
> +    verify_args object-readelf-notes 1 3
> +    verify_args object-readelf-notes-not 1 3
> 
>      verify_args scan-assembler-times 2 3
>      verify_args scan-assembler-dem 1 2
> diff --git a/gcc/testsuite/gcc.target/arm/lto/pr61123-enum-size_0.c
> b/gcc/testsuite/gcc.target/arm/lto/pr61123-enum-size_0.c
> index 4ccbeb39f43..36013040cdf 100644
> --- a/gcc/testsuite/gcc.target/arm/lto/pr61123-enum-size_0.c
> +++ b/gcc/testsuite/gcc.target/arm/lto/pr61123-enum-size_0.c
> @@ -20,4 +20,4 @@ foo1 (struct debug_ABI_enum_size *x)
>    return sizeof (x->es);
>  }
> 
> -/* { dg-final { object-readelf Tag_ABI_enum_size int { target arm_eabi } } } */
> +/* { dg-final { object-readelf-attributes {Tag_ABI_enum_size:\s+int} { target
> arm_eabi } } } */
> diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp
> index 2a7b8b0de93..b36ccded5d6 100644
> --- a/gcc/testsuite/lib/lto.exp
> +++ b/gcc/testsuite/lib/lto.exp
> @@ -915,23 +915,21 @@ proc lto-execute { src1 sid } {
>      initialize_prune_notes
>  }
> 
> -# Call pass if object readelf is ok, otherwise fail.
> -# example: /* { dg-final { object-readelf Tag_ABI_enum_size int} } */
> -proc object-readelf { args } {
> +proc object-readelf { option is_negative directive args } {
>      global readelf
>      global base_dir
> -    upvar 2 execname execname
> +    upvar 3 execname execname
> 
> -    if { [llength $args] < 2 } {
> -	error "object-readelf: too few arguments"
> +    if { [llength $args] < 1 } {
> +	error "$directive: too few arguments"
>  	return
>      }
> -    if { [llength $args] > 3 } {
> -	error "object-readelf: too many arguments"
> +    if { [llength $args] > 2 } {
> +	error "$directive: too many arguments"
>  	return
>      }
> -    if { [llength $args] >= 3 } {
> -	switch [dg-process-target [lindex $args 2]] {
> +    if { [llength $args] >= 2 } {
> +	switch [dg-process-target [lindex $args 1]] {
>  	    "S" { }
>  	    "N" { return }
>  	    "F" { setup_xfail "*-*-*" }
> @@ -939,7 +937,7 @@ proc object-readelf { args } {
>  	}
>      }
> 
> -    # Find size like we find g++ in g++.exp.
> +    # Find readelf like we find g++ in g++.exp.
>      if ![info exists readelf]  {
>  	set readelf [findfile $base_dir/../../../binutils/readelf \
>  		$base_dir/../../../binutils/readelf \
> @@ -949,47 +947,52 @@ proc object-readelf { args } {
>  	verbose -log "readelf is $readelf"
>      }
> 
> -    set what [lindex $args 0]
> -    set with [lindex $args 1]
> +    set regex [lindex $args 0]
> 
>      if ![file_on_host exists $execname] {
>  	verbose -log "$execname does not exist"
> -	unresolved "object-readelf $what "
> +	unresolved "$directive $regex "
>  	return
>      }
> 
> -    set output [remote_exec host "$readelf -A" "$execname"]
> +    set output [remote_exec host "$readelf $option" "$execname"]
>      set status [lindex $output 0]
>      if { $status != 0 } {
> -	verbose -log "object-readelf: $readelf failed"
> -	unresolved "object-readelf $what $execname"
> +	verbose -log "$directive: $readelf failed"
> +	unresolved "$directive $regex $execname"
>  	return
>      }
> 
>      set text [lindex $output 1]
> -    set lines [split $text "\n"]
> +    set match [regexp -- $regex $text]
> 
> -    set done 0
> -    set i 0
> -    while { !$done } {
> -	set line_tex [lindex $lines $i]
> -	if { [llength ${line_tex}] > 1} {
> -	    incr i
> -	    if [regexp -- $what $line_tex] {
> -	        set match [regexp -- $with $line_tex]
> -		set done 1
> -	    }
> -	} else {
> -	    set done 1
> -	}
> -    }
> -
> -    verbose -log "$what size is $with;"
> -    if { $match == 1 } {
> -	pass "object-readelf $what size is correct."
> +    if { ($is_negative && $match == 0) || (!$is_negative && $match == 1) } {
> +	pass "$directive $regex pattern is correct."
>      } else {
> -	fail "object-readelf $what size is incorrect."
> +	fail "$directive $regex pattern is incorrect."
>      }
>  }
> 
> +# Call pass if regex ($args 0) matches readelf -A output, otherwise fail.
> +# example: /* { dg-final { object-readelf-attributes
> {Tag_ABI_enum_size:\s+int} } } */
> +proc object-readelf-attributes { args } {
> +    object-readelf "-A" 0 object-readelf-attributes {*}$args
> +}
> +
> +# Call pass if regex ($args 0) does not match readelf -A output, otherwise fail.
> +# example: /* { dg-final { object-readelf-attributes
> {Tag_ABI_enum_size:\s+int} } } */
> +proc object-readelf-attributes-not { args } {
> +    object-readelf "-A" 1 object-readelf-attributes-not {*}$args
> +}
> 
> +# Call pass if regex ($args 0) matches readelf -n output, otherwise fail.
> +# example: /* { dg-final { object-readelf-notes {AArch64
> feature:\s+BTI,\s+PAC,\s+GCS} } } */
> +proc object-readelf-notes { args } {
> +    object-readelf "-n" 0 object-readelf-notes {*}$args
> +}
> +
> +# Call pass if regex ($args 0) does not match readelf -n output, otherwise fail.
> +# example: /* { dg-final { object-readelf-notes-not {AArch64
> feature:\s+BTI,\s+PAC,\s+GCS} } } */
> +proc object-readelf-notes-not { args } {
> +    object-readelf "-n" 1 object-readelf-notes-not {*}$args
> +}
> --
> 2.43.0
  
Mike Stump April 22, 2026, 11:44 p.m. UTC | #2
On Apr 8, 2026, at 2:12 AM, Muhammad Kamran <muhammad.kamran@arm.com> wrote:
> 
> object-readelf in lib/lto.exp was hard-wired to use readelf -A,
> limiting it to attribute checks. Extend it to accept a readelf option and
> a regex, where the option selects the readelf flag and the regex is
> matched against the output.

Ok post release branch creation.
  

Patch

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 3bccb1384d9..958682907cb 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -3729,6 +3729,29 @@  stands for zero or more unmatched lines; the whitespace after
 
 @end table
 
+@subsubsection Scan object metadata with readelf
+
+These commands inspect the linked test output file with @command{readelf}.
+They are mainly intended for LTO tests.
+
+These commands take a single @var{regex} and test whether it is present
+in (or absent from, for @samp{-not}) the corresponding @command{readelf}
+output.
+
+@table @code
+@item object-readelf-attributes @var{regex} [@{ target/xfail @var{selector} @}]
+Runs @command{readelf -A} and checks that @var{regex} matches.
+
+@item object-readelf-attributes-not @var{regex} [@{ target/xfail @var{selector} @}]
+Runs @command{readelf -A} and checks that @var{regex} does not match.
+
+@item object-readelf-notes @var{regex} [@{ target/xfail @var{selector} @}]
+Runs @command{readelf -n} and checks that @var{regex} matches.
+
+@item object-readelf-notes-not @var{regex} [@{ target/xfail @var{selector} @}]
+Runs @command{readelf -n} and checks that @var{regex} does not match.
+@end table
+
 @subsubsection Scan optimization dump files
 
 These commands are available for @var{kind} of @code{tree}, @code{ltrans-tree},
diff --git a/gcc/testsuite/gcc.dg-selftests/dg-final.exp b/gcc/testsuite/gcc.dg-selftests/dg-final.exp
index 6dcfd3340a8..ff8fdf6d77a 100644
--- a/gcc/testsuite/gcc.dg-selftests/dg-final.exp
+++ b/gcc/testsuite/gcc.dg-selftests/dg-final.exp
@@ -94,7 +94,10 @@  proc dg_final_directive_check_num_args {} {
 
     verify_args scan-lang-dump 2 3
 
-    verify_args object-readelf 2 3
+    verify_args object-readelf-attributes 1 3
+    verify_args object-readelf-attributes-not 1 3
+    verify_args object-readelf-notes 1 3
+    verify_args object-readelf-notes-not 1 3
 
     verify_args scan-assembler-times 2 3
     verify_args scan-assembler-dem 1 2
diff --git a/gcc/testsuite/gcc.target/arm/lto/pr61123-enum-size_0.c b/gcc/testsuite/gcc.target/arm/lto/pr61123-enum-size_0.c
index 4ccbeb39f43..36013040cdf 100644
--- a/gcc/testsuite/gcc.target/arm/lto/pr61123-enum-size_0.c
+++ b/gcc/testsuite/gcc.target/arm/lto/pr61123-enum-size_0.c
@@ -20,4 +20,4 @@  foo1 (struct debug_ABI_enum_size *x)
   return sizeof (x->es);
 }
 
-/* { dg-final { object-readelf Tag_ABI_enum_size int { target arm_eabi } } } */
+/* { dg-final { object-readelf-attributes {Tag_ABI_enum_size:\s+int} { target arm_eabi } } } */
diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp
index 2a7b8b0de93..b36ccded5d6 100644
--- a/gcc/testsuite/lib/lto.exp
+++ b/gcc/testsuite/lib/lto.exp
@@ -915,23 +915,21 @@  proc lto-execute { src1 sid } {
     initialize_prune_notes
 }
 
-# Call pass if object readelf is ok, otherwise fail.
-# example: /* { dg-final { object-readelf Tag_ABI_enum_size int} } */
-proc object-readelf { args } {
+proc object-readelf { option is_negative directive args } {
     global readelf
     global base_dir
-    upvar 2 execname execname
+    upvar 3 execname execname
 
-    if { [llength $args] < 2 } {
-	error "object-readelf: too few arguments"
+    if { [llength $args] < 1 } {
+	error "$directive: too few arguments"
 	return
     }
-    if { [llength $args] > 3 } {
-	error "object-readelf: too many arguments"
+    if { [llength $args] > 2 } {
+	error "$directive: too many arguments"
 	return
     }
-    if { [llength $args] >= 3 } {
-	switch [dg-process-target [lindex $args 2]] {
+    if { [llength $args] >= 2 } {
+	switch [dg-process-target [lindex $args 1]] {
 	    "S" { }
 	    "N" { return }
 	    "F" { setup_xfail "*-*-*" }
@@ -939,7 +937,7 @@  proc object-readelf { args } {
 	}
     }
 
-    # Find size like we find g++ in g++.exp.
+    # Find readelf like we find g++ in g++.exp.
     if ![info exists readelf]  {
 	set readelf [findfile $base_dir/../../../binutils/readelf \
 		$base_dir/../../../binutils/readelf \
@@ -949,47 +947,52 @@  proc object-readelf { args } {
 	verbose -log "readelf is $readelf"
     }
 
-    set what [lindex $args 0]
-    set with [lindex $args 1]
+    set regex [lindex $args 0]
 
     if ![file_on_host exists $execname] {
 	verbose -log "$execname does not exist"
-	unresolved "object-readelf $what "
+	unresolved "$directive $regex "
 	return
     }
 
-    set output [remote_exec host "$readelf -A" "$execname"]
+    set output [remote_exec host "$readelf $option" "$execname"]
     set status [lindex $output 0]
     if { $status != 0 } {
-	verbose -log "object-readelf: $readelf failed"
-	unresolved "object-readelf $what $execname"
+	verbose -log "$directive: $readelf failed"
+	unresolved "$directive $regex $execname"
 	return
     }
 
     set text [lindex $output 1]
-    set lines [split $text "\n"]
+    set match [regexp -- $regex $text]
 
-    set done 0
-    set i 0
-    while { !$done } {
-	set line_tex [lindex $lines $i]
-	if { [llength ${line_tex}] > 1} {
-	    incr i
-	    if [regexp -- $what $line_tex] {
-	        set match [regexp -- $with $line_tex]
-		set done 1
-	    }
-	} else {
-	    set done 1
-	}
-    }
-
-    verbose -log "$what size is $with;"
-    if { $match == 1 } {
-	pass "object-readelf $what size is correct."
+    if { ($is_negative && $match == 0) || (!$is_negative && $match == 1) } {
+	pass "$directive $regex pattern is correct."
     } else {
-	fail "object-readelf $what size is incorrect."
+	fail "$directive $regex pattern is incorrect."
     }
 }
 
+# Call pass if regex ($args 0) matches readelf -A output, otherwise fail.
+# example: /* { dg-final { object-readelf-attributes {Tag_ABI_enum_size:\s+int} } } */
+proc object-readelf-attributes { args } {
+    object-readelf "-A" 0 object-readelf-attributes {*}$args
+}
+
+# Call pass if regex ($args 0) does not match readelf -A output, otherwise fail.
+# example: /* { dg-final { object-readelf-attributes {Tag_ABI_enum_size:\s+int} } } */
+proc object-readelf-attributes-not { args } {
+    object-readelf "-A" 1 object-readelf-attributes-not {*}$args
+}
 
+# Call pass if regex ($args 0) matches readelf -n output, otherwise fail.
+# example: /* { dg-final { object-readelf-notes {AArch64 feature:\s+BTI,\s+PAC,\s+GCS} } } */
+proc object-readelf-notes { args } {
+    object-readelf "-n" 0 object-readelf-notes {*}$args
+}
+
+# Call pass if regex ($args 0) does not match readelf -n output, otherwise fail.
+# example: /* { dg-final { object-readelf-notes-not {AArch64 feature:\s+BTI,\s+PAC,\s+GCS} } } */
+proc object-readelf-notes-not { args } {
+    object-readelf "-n" 1 object-readelf-notes-not {*}$args
+}