[1/2] testsuite: Extend object-readelf beyond attributes
Commit Message
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
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
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.
@@ -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},
@@ -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
@@ -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 } } } */
@@ -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
+}