Simplify testing symbol sections
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. * g++.dg/gomp/tls-5.C: Add symbol section test. * g++.dg/opt/const4.C: Likewise. * gcc.dg/20021029-1.c: Likewise. * gcc.dg/array-quals-1.c: Likewise. * gcc.dg/darwin-sections.c: Likewise. * gcc.dg/pr25376.c: Likewise. * gcc.test-framework/test-framework.exp: Load scanasm and test .S files. * gcc.test-framework/dg-scan-symbol-section-1-exp-F.S: New test. * gcc.test-framework/dg-scan-symbol-section-2-exp-F.S: New test. * gcc.test-framework/dg-scan-symbol-section-3-exp-F.S: New test. * gcc.test-framework/dg-scan-symbol-section-exp-P.S: New test.
This commit is contained in:
parent
207de83922
commit
8270a7238b
12 changed files with 292 additions and 6 deletions
|
@ -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)
|
||||
|
|
|
@ -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-*-* } } }
|
||||
|
|
|
@ -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 } */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -10,7 +10,9 @@ typedef struct _empty {} e_s;
|
|||
/* These should go in .comm */
|
||||
char ub;
|
||||
e_s ea;
|
||||
/* { dg-final { scan-assembler-symbol-section {^_a$} {\.data} } } */
|
||||
/* { dg-final { scan-assembler ".comm\[\t \]_ub,1" } } */
|
||||
/* { dg-final { scan-assembler-symbol-section {^_b$} {\.data} } } */
|
||||
/* { dg-final { scan-assembler ".comm\[\t \]_ea,1" } } */
|
||||
|
||||
/* These should go into __DATA,__common */
|
||||
|
|
|
@ -7,3 +7,4 @@ void simple (void)
|
|||
}
|
||||
|
||||
/* { dg-final { scan-assembler "my_named_section" } } */
|
||||
/* { dg-final { scan-assembler-symbol-section {simple$} {^my_named_section$} } } */
|
||||
|
|
|
@ -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:
|
|
@ -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:
|
|
@ -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:
|
|
@ -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} } }
|
|
@ -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 } {
|
||||
|
|
|
@ -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"
|
||||
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 } {
|
||||
|
|
Loading…
Add table
Reference in a new issue