diff mbox series

Simplify testing symbol sections

Message ID CAC-ggsEmdWw4bcbm+_3CpS2a_CGnU_cCzw8u2_eoEWcitgStzg@mail.gmail.com
State New
Headers show
Series Simplify testing symbol sections | expand

Commit Message

Strager Neds Nov. 21, 2019, 6:08 a.m. UTC
While fixing some bugs in __attribute__((section)), I found it difficult
to write tests. Make testing easier: introduce the
scan-assembler-symbol-section and scan-symbol-section helpers. See
in-line documentation for details.

Testing:

* Run `make check` on x86_64-linux-gnu with --disable-multilib
  --enable-checking=release --enable-languages=c,c++. Observe no new
  failures in test results.
* Run `make check` on macOS x86_64-apple-darwin16.7.0 with
  --disable-multilib --enable-checking=release --enable-languages=c,c++.
  Observe no new failures in test results.
* Run test-framework.exp with CHECK_TEST_FRAMEWORK=1, and post-process
  results with test-framework.awk. Observe no new failures test
  results.

2019-11-12  Matthew Glazar <strager.nds@gmail.com>

* gcc/testsuite/lib/scanasm.exp (dg-scan): Extract file globbing
code ...
(dg_glob_remote): ... into this new procedure.
(scan-assembler-symbol-section): Define.
(scan-symbol-section): Define.
---
 gcc/testsuite/g++.dg/gomp/tls-5.C             |   2 +
 gcc/testsuite/g++.dg/opt/const4.C             |   3 +-
 gcc/testsuite/gcc.dg/20021029-1.c             |   1 +
 gcc/testsuite/gcc.dg/array-quals-1.c          |  20 ++
 gcc/testsuite/gcc.dg/darwin-sections.c        |   2 +
 gcc/testsuite/gcc.dg/pr25376.c                |   1 +
 .../dg-scan-symbol-section-1-exp-F.S          |  13 ++
 .../dg-scan-symbol-section-2-exp-F.S          |   9 +
 .../dg-scan-symbol-section-3-exp-F.S          |  10 +
 .../dg-scan-symbol-section-exp-P.S            |  50 +++++
 .../gcc.test-framework/test-framework.exp     |   3 +-
 gcc/testsuite/lib/scanasm.exp                 | 184 +++++++++++++++++-
 12 files changed, 292 insertions(+), 6 deletions(-)
 create mode 100644
gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-1-exp-F.S
 create mode 100644
gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-2-exp-F.S
 create mode 100644
gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-3-exp-F.S
 create mode 100644
gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-exp-P.S

     unresolved "$testcase $name $printable_pattern"
@@ -73,6 +70,13 @@ proc dg-scan { name positive testcase output_file
orig_args } {
     }
 }

+proc dg_glob_remote { file_pattern } {
+    if { [is_remote host] } {
+    remote_upload host $file_pattern
+    }
+    return [glob -nocomplain $file_pattern]
+}
+
 # Look for a pattern in the .s file produced by the compiler.  See
 # dg-scan for details.

@@ -155,6 +159,178 @@ proc scan-not-hidden { args } {
     dg-scan "scan-not-hidden" 0 $testcase $output_file $args
 }

+# Check that symbols are emitted in the desired section.
+# Like scan-symbol-section, but using the assembly output generated by
+# the compiler.
+#
+# Example:
+#
+# // All numbered functions (func1, func2, etc.) must be in the .text
section or
+# // in a .text sub-section (like .text._func1).
+# { dg-final { scan-assembler-symbol-section {^_func[1-5]$} {^\.text($|\.)} } }
+
+proc scan-assembler-symbol-section { args } {
+    set testcase [testname-for-summary]
+    set filename [lindex $testcase 0]
+    set output_file "[file rootname [file tail $filename]].s"
+    set symbol_pattern [lindex $args 0]
+    set expected_section_pattern [lindex $args 1]
+    dg-scan-symbol-section \
+    "scan-assembler-symbol-section" \
+    $testcase \
+    $output_file \
+    $symbol_pattern \
+    $expected_section_pattern
+}
+
+# Check that symbols are emitted in the desired section.
+#
+# Symbols and sections are interpreted as regexp patterns.
+#
+# If no matching symbol is found, scan-symbol-section reports a FAILure.
+#
+# Usage:
+#
+# { dg-final { scan-symbol-section FILENAME SYMBOL SECTION } }
+#
+# Examples:
+#
+# // The my_var C symbol must be in the .data section (or in a
.data._my_var section
+# // if -ffunction-sections is in use).
+# { dg-final { scan-symbol-section "my-test.s" {^_my_var$}
{^\.data(\._my_var)?$} } }
+#
+# // All numbered functions (func1, func2, etc.) must be in the .text section
+# // (and not in any other section like .text._func1).
+# { dg-final { scan-symbol-section "my-test.s" {^_func[1-5]$} {^\.text$} } }
+#
+# Caveats:
+#
+# * Only ELF and Mach-O targets are supported. Other
+#   targets, like PE/COFF, might appear to work.
+# * For Mach-O targets, the section name matched by scan-symbol-section has one
+#   of two forms:
+#   * The Mach-O segment name followed by a comma (',') followed by the Mach-O
+#     section name. For example, "__TEXT,__text". (There is no whitespace
+#     between the Mach-O segment name and the Mach-O section name.)
+#   * ".const", ".data", or ".text". For example, the .text assembler directive
+#     causes the section name to be ".text" (not "__TEXT,__text"). (However, a
+#     directive such as .section __TEXT,__text will cause the section
name to be
+#     "__TEXT,__text".)
+# * Because scan-symbol-section parses assembly code, scan-symbol-section is
+#   unaware of section rewriting performed by the linker. For example, the
+#   sections .text._f1 and .text._f2 would normally be merged by binutils'
+#   linker into one section called .text, but scan-symbol-section reports the
+#   sections as .text._f1 and .text._f2 (and not .text).
+# * The symbol pattern matches any assembly label, including local labels which
+#   begin with `.L`.
+
+proc scan-symbol-section { args } {
+    set testcase [testname-for-summary]
+    set output_file [lindex $args 0]
+    set symbol_pattern [lindex $args 1]
+    set expected_section_pattern [lindex $args 2]
+    dg-scan-symbol-section \
+    "scan-symbol-section" \
+    $testcase \
+    $output_file \
+    $symbol_pattern \
+    $expected_section_pattern
+}
+
+# Check that symbols are emitted in the desired section.
+#
+# Avoid calling this function directly. In tests, use scan-symbol-section,
+# scan-assembler-symbol-section, or scan-lto-assembler-symbol-section instead.
+
+proc dg-scan-symbol-section { name testcase output_file
symbol_pattern expected_section_pattern } {
+    set printable_symbol_pattern [make_pattern_printable $symbol_pattern]
+    set printable_expected_section_pattern [make_pattern_printable
$expected_section_pattern]
+
+    set files [dg_glob_remote $output_file]
+    if { $files == "" } {
+    verbose -log "$testcase: output file does not exist"
+    unresolved "$testcase $name symbol $printable_symbol_pattern has
section $printable_expected_section_pattern"
+    return
+    }
+
+    parse_section_of_symbols $output_file section_by_symbol
+
+    set found_symbol 0
+    foreach symbol_name [lsort [array names section_by_symbol]] {
+        if { [regexp -- $symbol_pattern $symbol_name] } {
+            set section $section_by_symbol($symbol_name)
+            set description "$testcase $name symbol
$printable_symbol_pattern (found $symbol_name) has section
$printable_expected_section_pattern"
+            if { $section == "" } {
+                fail "$description (no section detected)"
+            } else {
+                set description "$description (found $section)"
+                if { [regexp -- $expected_section_pattern $section] } {
+                    pass $description
+                } else {
+                    fail $description
+                }
+            }
+            set found_symbol 1
+        }
+    }
+    if { ! $found_symbol } {
+        fail "$testcase $name symbol $printable_symbol_pattern
(symbol not found) has section $printable_expected_section_pattern"
+    }
+}
+
+# Extract a symbol and section names from pre-processed assembly source code.
+#
+# This function adds entries in the RESULT array where the key is the symbol's
+# name (including any leading underscores) and the value is the section's name
+# (including any leading periods).
+#
+# For example, given the following assembly source code in file.s:
+#
+#         .text
+#         .function _my_function
+# _my_function:
+#         nop
+#         .data
+# _my_data:
+#         .long 42
+#
+# Executing 'parse_section_of_symbols "file.s" symbols' would have the same
+# effect as the following code:
+#
+# set $result(_my_function) .text
+# set $result(_my_data) .data
+
+proc parse_section_of_symbols { filename result } {
+    upvar $result up_result
+
+    set section_pattern {^\s*(?:\.section\s+(.*)|(\.const|\.data|\.text)\s*)$}
+    set label_pattern {^(\S+):$}
+
+    set fd [open $filename r]
+    set current_section ""
+    while { [gets $fd line] >= 0 } {
+        if { [regexp -- $label_pattern $line dummy symbol_name] } {
+            set up_result($symbol_name) $current_section
+        } elseif { [regexp -- $section_pattern $line dummy
section_directive_arguments full_section_directive] } {
+            if { $full_section_directive eq "" } {
+                # Example: .section .text,"ax",progbits
+                # Example: .section __TEXT,__text
+                set arguments [split $section_directive_arguments ","]
+                set current_section [string trim [lindex $arguments 0]]
+                set arg_1 [string trim [lindex $arguments 1]]
+                if { [regexp {^_} $arg_1] } {
+                    # The second argument looks like a Mach-O section name.
+                    set current_section "$current_section,$arg_1"
+                }
+            } else {
+                # Example: .text
+                set current_section "$full_section_directive"
+            }
+        }
+    }
+    close $fd
+}
+
 # Look for a pattern in OUTPUT_FILE.  See dg-scan for details.

 proc scan-file { output_file args } {

Comments

Jeff Law Nov. 14, 2020, 4:56 a.m. UTC | #1
On 11/20/19 11:08 PM, Strager Neds wrote:
> While fixing some bugs in __attribute__((section)), I found it difficult
> to write tests. Make testing easier: introduce the
> scan-assembler-symbol-section and scan-symbol-section helpers. See
> in-line documentation for details.
>
> Testing:
>
> * Run `make check` on x86_64-linux-gnu with --disable-multilib
>   --enable-checking=release --enable-languages=c,c++. Observe no new
>   failures in test results.
> * Run `make check` on macOS x86_64-apple-darwin16.7.0 with
>   --disable-multilib --enable-checking=release --enable-languages=c,c++.
>   Observe no new failures in test results.
> * Run test-framework.exp with CHECK_TEST_FRAMEWORK=1, and post-process
>   results with test-framework.awk. Observe no new failures test
>   results.
>
> 2019-11-12  Matthew Glazar <strager.nds@gmail.com>
>
> * gcc/testsuite/lib/scanasm.exp (dg-scan): Extract file globbing
> code ...
> (dg_glob_remote): ... into this new procedure.
> (scan-assembler-symbol-section): Define.
> (scan-symbol-section): Define.

[ ... ]

So this was marginally painful due to the mangling from your mailer. 
But after a fair amount of hand-editing the patch file I got it to
apply.  I actually botched that ever-so-slightly resulting in pr25376
not being updated properly which the testsuite naturally complained
about -- good ;-)  The darwin test has changed slightly since you
originally submitted this patch.  Hopefully I updated that properly as well.


I could then generate a fresh diff with proper formatting ;-)  Things
look generally OK.  A few caveats worth mentioning.


This may fail on targets that silently put certain objects into
nonstandard sections.  I don't think that's a problem with your patch,
but more a note that it's likely someone could write a test with this
new bit of framework and find that it fails on some targets.  I did
throw this into my tester just to see if any of the existing tests might
tickle this issue on one of the crosses, but it  didn't flag anything
(well, there is one msp430 failure, but I'm pretty sure that's not your
change).


I worry a bit about the less common native targets -- aix, hpux and the
like.  But testing them is too painful to contemplate these days.  I'm
sure those with access to suitable hardware will chime in if something
is amiss.


I'm going to go ahead and push the patch to the trunk.  Thanks again for
your patience.


jeff
diff mbox series

Patch

diff --git gcc/testsuite/g++.dg/gomp/tls-5.C gcc/testsuite/g++.dg/gomp/tls-5.C
index e83ff1179e6..a1d3120fbfb 100644
--- gcc/testsuite/g++.dg/gomp/tls-5.C
+++ gcc/testsuite/g++.dg/gomp/tls-5.C
@@ -1,6 +1,8 @@ 
 // The reference temp should be TLS, not normal data.
 // { dg-require-effective-target c++11 }
 // { dg-final { scan-assembler-not "\\.data" { target tls_native
xfail powerpc-*-aix* } } }
+// { dg-final { scan-assembler-symbol-section {^_?ir$} {^\.tbss} } }
+// { dg-final { scan-assembler-symbol-section {^_?_ZGR2ir_$} {^\.tdata} } }

 extern int&& ir;
 #pragma omp threadprivate (ir)
diff --git gcc/testsuite/g++.dg/opt/const4.C gcc/testsuite/g++.dg/opt/const4.C
index 883c24b55fc..51d5313a312 100644
--- gcc/testsuite/g++.dg/opt/const4.C
+++ gcc/testsuite/g++.dg/opt/const4.C
@@ -3,7 +3,8 @@ 
 // that have it.
 // { dg-do compile }

-const int a[] __attribute__ ((__used__)) = { 0, 1, 2, 3 };
+// { dg-final { scan-assembler-symbol-section {constant_variable}
{^\.(const|rodata)} } }
+const int constant_variable[] __attribute__ ((__used__)) = { 0, 1, 2, 3 };

 // The MMIX port always switches to the .data section at the end of a file.
 // { dg-final { scan-assembler-not "\\.data(?!\\.rel\\.ro)" { xfail
powerpc*-*-aix* mmix-*-* } } }
diff --git gcc/testsuite/gcc.dg/20021029-1.c gcc/testsuite/gcc.dg/20021029-1.c
index f11a6e4a920..c8ae4aa60e2 100644
--- gcc/testsuite/gcc.dg/20021029-1.c
+++ gcc/testsuite/gcc.dg/20021029-1.c
@@ -3,6 +3,7 @@ 
 /* { dg-do compile { target fpic } } */
 /* { dg-options "-O2 -fpic" } */
 /* { dg-final { scan-assembler-not ".data.rel.ro.local" } } */
+/* { dg-final { scan-assembler-symbol-section {ar} {^\.(const|rodata)} } } */
 /* { dg-require-effective-target label_values } */
 /* { dg-require-effective-target indirect_jumps } */

diff --git gcc/testsuite/gcc.dg/array-quals-1.c
gcc/testsuite/gcc.dg/array-quals-1.c
index 3981c916021..819bd24af76 100644
--- gcc/testsuite/gcc.dg/array-quals-1.c
+++ gcc/testsuite/gcc.dg/array-quals-1.c
@@ -6,26 +6,46 @@ 
 /* { dg-options "-Wno-discarded-array-qualifiers" } */
 /* The MMIX port always switches to the .data section at the end of a file.  */
 /* { dg-final { scan-assembler-not "\\.data(?!\\.rel\\.ro)" { xfail
powerpc*-*-aix* mmix-*-* x86_64-*-mingw* } } } */
+/* { dg-final { scan-assembler-symbol-section {^_?a$}
{^\.(const|rodata)} } } */
 static const int a[2] = { 1, 2 };
+/* { dg-final { scan-assembler-symbol-section {^_?a1$}
{^\.(const|rodata)} } } */
 const int a1[2] = { 1, 2 };
 typedef const int ci;
+/* { dg-final { scan-assembler-symbol-section {^_?b$}
{^\.(const|rodata)} } } */
 static ci b[2] = { 3, 4 };
+/* { dg-final { scan-assembler-symbol-section {^_?b1$}
{^\.(const|rodata)} } } */
 ci b1[2] = { 3, 4 };
 typedef int ia[2];
+/* { dg-final { scan-assembler-symbol-section {^_?c$}
{^\.(const|rodata)} } } */
 static const ia c = { 5, 6 };
+/* { dg-final { scan-assembler-symbol-section {^_?c1$}
{^\.(const|rodata)} } } */
 const ia c1 = { 5, 6 };
 typedef const int cia[2];
+/* { dg-final { scan-assembler-symbol-section {^_?d$}
{^\.(const|rodata)} } } */
 static cia d = { 7, 8 };
+/* { dg-final { scan-assembler-symbol-section {^_?d1$}
{^\.(const|rodata)} } } */
 cia d1 = { 7, 8 };
+/* { dg-final { scan-assembler-symbol-section {^_?e$}
{^\.(const|rodata)} } } */
 static cia e[2] = { { 1, 2 }, { 3, 4 } };
+/* { dg-final { scan-assembler-symbol-section {^_?e1$}
{^\.(const|rodata)} } } */
 cia e1[2] = { { 1, 2 }, { 3, 4 } };
+/* { dg-final { scan-assembler-symbol-section {^_?p$}
{^\.(const|rodata)} } } */
 void *const p = &a;
+/* { dg-final { scan-assembler-symbol-section {^_?q$}
{^\.(const|rodata)} } } */
 void *const q = &b;
+/* { dg-final { scan-assembler-symbol-section {^_?r$}
{^\.(const|rodata)} } } */
 void *const r = &c;
+/* { dg-final { scan-assembler-symbol-section {^_?s$}
{^\.(const|rodata)} } } */
 void *const s = &d;
+/* { dg-final { scan-assembler-symbol-section {^_?t$}
{^\.(const|rodata)} } } */
 void *const t = &e;
+/* { dg-final { scan-assembler-symbol-section {^_?p1$}
{^\.(const|rodata)} } } */
 void *const p1 = &a1;
+/* { dg-final { scan-assembler-symbol-section {^_?q1$}
{^\.(const|rodata)} } } */
 void *const q1 = &b1;
+/* { dg-final { scan-assembler-symbol-section {^_?r1$}
{^\.(const|rodata)} } } */
 void *const r1 = &c1;
+/* { dg-final { scan-assembler-symbol-section {^_?s1$}
{^\.(const|rodata)} } } */
 void *const s1 = &d1;
+/* { dg-final { scan-assembler-symbol-section {^_?t1$}
{^\.(const|rodata)} } } */
 void *const t1 = &e1;
diff --git gcc/testsuite/gcc.dg/darwin-sections.c
gcc/testsuite/gcc.dg/darwin-sections.c
index 79d48bd7da2..8d3a8f47b20 100644
--- gcc/testsuite/gcc.dg/darwin-sections.c
+++ gcc/testsuite/gcc.dg/darwin-sections.c
@@ -16,7 +16,9 @@  e_s ea;
 /* These should go into .data */
 char a = 0;
 short b = 0;
+/* { dg-final { scan-assembler-symbol-section {^_a$} {\.data} } } */
 /* { dg-final { scan-assembler ".globl _a.*.data.*.space\[\t \]1" } } */
+/* { dg-final { scan-assembler-symbol-section {^_b$} {\.data} } } */
 /* { dg-final { scan-assembler ".globl _b.*.data.*.space\[\t \]2" } } */

 /* These should go into __pu_bssN */
diff --git gcc/testsuite/gcc.dg/pr25376.c gcc/testsuite/gcc.dg/pr25376.c
index 3008b091dc2..25f1b66c9bd 100644
--- gcc/testsuite/gcc.dg/pr25376.c
+++ gcc/testsuite/gcc.dg/pr25376.c
@@ -7,3 +7,4 @@  void simple (void)
 }

 /* { dg-final { scan-assembler "my_named_section" } } */
+/* { dg-final { scan-assembler-symbol-section {simple$}
{^my_named_section$} } } */
diff --git gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-1-exp-F.S
gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-1-exp-F.S
new file mode 100644
index 00000000000..70b69271f8f
--- /dev/null
+++ gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-1-exp-F.S
@@ -0,0 +1,13 @@ 
+// Test the scan-symbol-section directive.
+// scan-symbol-section should fail with 'FAIL' if a symbol has a different
+// section than expected.
+
+// { dg-do preprocess }
+// { dg-final { scan-symbol-section
"dg-scan-symbol-section-1-exp-F.i" {^_test_symbol_.*$} {nomatch} } }
+// The above assertion should fail with the following messages:
+// FAIL: gcc.test-framework/dg-scan-symbol-section-1-exp-F.S
scan-symbol-section symbol ^_test_symbol_.*$ (found _test_symbol_1)
has section nomatch (found .text)
+// FAIL: gcc.test-framework/dg-scan-symbol-section-1-exp-F.S
scan-symbol-section symbol ^_test_symbol_.*$ (found _test_symbol_2)
has section nomatch (found .data)
+    .text
+_test_symbol_1:
+    .data
+_test_symbol_2:
diff --git gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-2-exp-F.S
gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-2-exp-F.S
new file mode 100644
index 00000000000..01872751d4d
--- /dev/null
+++ gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-2-exp-F.S
@@ -0,0 +1,9 @@ 
+// Test the scan-symbol-section directive.
+// scan-symbol-section should fail with 'UNSUPPORTED' if a symbol has no
+// associated section.
+
+// { dg-do preprocess }
+// { dg-final { scan-symbol-section
"dg-scan-symbol-section-2-exp-F.i" {^_test_symbol$} {^\.text$} } }
+// The above assertion should fail with the following message:
+// FAIL: gcc.test-framework/dg-scan-symbol-section-2-exp-F.S
scan-symbol-section symbol ^_test_symbol$ (found _test_symbol) has
section ^\\.text$ (no section detected)
+_test_symbol:
diff --git gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-3-exp-F.S
gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-3-exp-F.S
new file mode 100644
index 00000000000..87b09a33948
--- /dev/null
+++ gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-3-exp-F.S
@@ -0,0 +1,10 @@ 
+// Test the scan-symbol-section directive.
+// scan-symbol-section should fail with 'UNSUPPORTED' if a symbol has no
+// associated section.
+
+// { dg-do preprocess }
+// { dg-final { scan-symbol-section
"dg-scan-symbol-section-3-exp-F.i" {^_test_symbol$} {^\.text$} } }
+// The above assertion should fail with the following message:
+// FAIL: gcc.test-framework/dg-scan-symbol-section-3-exp-F.S
scan-symbol-section symbol ^_test_symbol$ (no symbol detected) has
section ^\\.text$
+    .text
+_test_wrong_symbol:
diff --git gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-exp-P.S
gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-exp-P.S
new file mode 100644
index 00000000000..1166b74b376
--- /dev/null
+++ gcc/testsuite/gcc.test-framework/dg-scan-symbol-section-exp-P.S
@@ -0,0 +1,50 @@ 
+// Test the scan-symbol-section directive.
+
+// { dg-do preprocess }
+
+// The .section directive changes the section for all following symbols.
+    .section .text
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_function_1$} {^\.text$} } }
+_test_function_1:
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_function_2$} {^\.text$} } }
+_test_function_2:
+
+// For ELF targets, the .section directive can take multiple arguments.
+    .section .other_text_section,"ax",progbits
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_elf_function$} {^\.other_text_section$} } }
+_test_elf_function:
+
+// For Mach-O targets, the .section directive takes a segment name
and a section name.
+    .section __TEXT,__my_text_section
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_macho_function$} {^__TEXT,__my_text_section$} } }
+_test_macho_function:
+// Extra whitespace between .section arguments should be ignored.
+    .section  __DATA , __testsection
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_macho_var$} {^__DATA,__testsection$} } }
+_test_macho_var:
+
+// The .data directive sets the section for all following symbols to '.data'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_var_1$} {^\.data$} } }
+    .data
+_test_var_1:
+
+// The .text directive sets the section for all following symbols to '.text'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_function_3$} {^\.text$} } }
+    .text
+_test_function_3:
+
+// The .const directive sets the section for all following symbols to '.const'.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_data_1$} {^\.const$} } }
+    .const
+_test_data_1:
+
+// Other directives do not affect the section of following symbols.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_var_2$} {^\.data$} } }
+    .data
+    .p2align 2
+    .size _test_var_2, 4
+_test_var_2:
+
+// Symbol name patterns can match multiple symbols, and section name patterns
+// can match multiple sections.
+// { dg-final { scan-symbol-section "dg-scan-symbol-section-exp-P.i"
{^_test_function_} {^(\.|__TEXT,).*text} } }
diff --git gcc/testsuite/gcc.test-framework/test-framework.exp
gcc/testsuite/gcc.test-framework/test-framework.exp
index db4b8665258..69a0aca0933 100644
--- gcc/testsuite/gcc.test-framework/test-framework.exp
+++ gcc/testsuite/gcc.test-framework/test-framework.exp
@@ -23,6 +23,7 @@  if { ![info exists env(CHECK_TEST_FRAMEWORK)] } {
 }

 load_lib gcc-dg.exp
+load_lib scanasm.exp

 proc dg-require-true { args } {
     verbose "dg-require-true" 2
@@ -59,7 +60,7 @@  set dg-do-what-default compile
 dg-init

 # Run tests from the source directory.
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dg-*.c]] "" ""
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dg-*.S
$srcdir/$subdir/dg-*.c]] "" ""

 # Skip generated tests unless CHECK_TEST_FRAMEWORK is 1.
 if { $env(CHECK_TEST_FRAMEWORK) != 1 } {
diff --git gcc/testsuite/lib/scanasm.exp gcc/testsuite/lib/scanasm.exp
index 0f1b246b8dc..e9ebf52d77e 100644
--- gcc/testsuite/lib/scanasm.exp
+++ gcc/testsuite/lib/scanasm.exp
@@ -52,10 +52,7 @@  proc dg-scan { name positive testcase output_file
orig_args } {
     set pattern [lindex $orig_args 0]
     set printable_pattern [make_pattern_printable $pattern]

-    if { [is_remote host] } {
-    remote_upload host "$output_file"
-    }
-    set files [glob -nocomplain $output_file]
+    set files [dg_glob_remote $output_file]
     if { $files == "" } {
     verbose -log "$testcase: output file does not exist"