[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(-)
  

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
+}