-# Copyright (C) 1993-2019 Free Software Foundation, Inc.
+# Copyright (C) 1993-2021 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
# True if the object format is known to be PE COFF.
#
-proc is_pecoff_format {} {
- if { [istarget *-*-beospe*]
- || [istarget *-*-cegcc*]
- || [istarget *-*-cygwin*]
- || [istarget *-*-interix*]
- || [istarget *-*-mingw*]
- || [istarget *-*-netbsdpe*]
- || [istarget *-*-pe*]
- || [istarget *-*-winnt*] } {
+proc is_pecoff_format args {
+ if { [llength $args] == 1 } {
+ set m_os [lindex $args 0]
+ } else {
+ set m_os *-*
+ }
+ if { [istarget $m_os-beospe*]
+ || [istarget $m_os-cegcc*]
+ || [istarget $m_os-cygwin*]
+ || [istarget $m_os-interix*]
+ || [istarget $m_os-mingw*]
+ || [istarget $m_os-netbsdpe*]
+ || [istarget $m_os-pe*]
+ || [istarget $m_os-winnt*] } {
return 1
}
return 0
return 0;
}
+proc is_xcoff_format {} {
+ if { [istarget rs6000-*-*]
+ || [istarget powerpc*-*-aix*]
+ || [istarget powerpc*-*-beos*]
+ || [istarget powerpc*-*-macos*] } {
+ return 1;
+ }
+ return 0;
+}
+
# True if the object format is known to be 64-bit ELF.
#
proc is_elf64 { binary_file } {
# in square brackets or as machine triplet otherwise.
#
proc match_target { target } {
- if [string match {\[*\]} $target] {
+ if [regexp {^!?\[.*\]$} $target] {
return $target
} else {
return [istarget $target]
}
}
-# True if the ELF target supports STB_GNU_UNIQUE with the ELF header's
-# OSABI field set to ELFOSABI_GNU.
+# True if the ELF target supports setting the ELF header OSABI field
+# to ELFOSABI_GNU or ELFOSABI_FREEBSD, a requirement for STT_GNU_IFUNC
+# symbol and SHF_GNU_MBIND or SHF_GNU_RETAIN section support.
#
# This generally depends on the target OS only, however there are a
# number of exceptions for bare metal targets as follows. The MSP430
-# and Visium targets set OSABI to ELFOSABI_STANDALONE and cannot
-# support STB_GNU_UNIQUE. Likewise non-EABI ARM targets set OSABI to
-# ELFOSABI_ARM, and TI C6X targets to ELFOSABI_C6000_*. Finally
-# rather than `bfd_elf_final_link' a number of targets use
-# `_bfd_generic_final_link', which does not support STB_GNU_UNIQUE
-# symbol binding causing assertion failures.
+# and Visium targets set OSABI to ELFOSABI_STANDALONE. Likewise
+# non-EABI ARM targets set OSABI to ELFOSABI_ARM
#
-proc supports_gnu_unique {} {
+# Non-Linux HPPA defaults to ELFOSABI_HPUX.
+#
+# Note that some TI C6X targets use ELFOSABI_C6000_* but one doesn't,
+# so we don't try to sort out tic6x here. (The effect is that linker
+# testcases will generally need to exclude tic6x or use a -m option.)
+#
+proc supports_gnu_osabi {} {
if { [istarget *-*-gnu*]
|| [istarget *-*-linux*]
- || [istarget *-*-nacl*] } {
- return 1
- }
- if { [istarget "arm*-*-*eabi*"] } {
+ || [istarget *-*-nacl*]
+ || ( [istarget *-*-*bsd*] && ![istarget arm*-*-netbsd*] )
+ || [istarget *-*-symbianelf]
+ || [istarget *-*-lynxos]
+ || ( [istarget *-*-nto*] && ![istarget arm*-*-*] )
+ || [istarget *-*-irix*]
+ || [istarget *-*-*eabi*]
+ || [istarget *-*-rtems*] } {
return 1
}
if { [istarget "wasm32*-*-*"] } {
}
if { [istarget "arm*-*-*"]
|| [istarget "msp430-*-*"]
- || [istarget "tic6x-*-*"]
+ || [istarget "hppa-unknown-elf"]
|| [istarget "visium-*-*"] } {
return 0
}
- if { [istarget "am33_2.0-*-*"]
- || [istarget "d30v-*-*"]
+ return 1
+}
+
+# Return true if target uses the generic_link_hash_table linker.
+proc is_generic { } {
+ if { [istarget "d30v-*-*"]
|| [istarget "dlx-*-*"]
|| [istarget "pj*-*-*"]
|| [istarget "s12z-*-*"]
|| [istarget "xgate-*-*"] } {
+ return 1
+ }
+ return 0
+}
+
+# True if the ELF target supports STB_GNU_UNIQUE.
+#
+# This require ELFOSABI_GNU, and `bfd_elf_final_link'.
+#
+proc supports_gnu_unique {} {
+ if { [istarget *-*-freebsd*] } {
return 0
}
- return 1
+ if { [supports_gnu_osabi] && ![is_generic] } {
+ return 1
+ }
+ return 0
}
# True for targets that do not sort .symtab as per the ELF standard.
return $shared_available_saved
}
+# Returns true if -pie is supported on the target
+
+proc check_pie_support { } {
+ global pie_available_saved
+ global ld
+
+ if {![info exists pie_available_saved]} {
+ set ld_output [remote_exec host $ld "-pie"]
+ if { [ string first "not supported" $ld_output ] >= 0 } {
+ set pie_available_saved 0
+ } else {
+ set pie_available_saved 1
+ }
+ }
+ return $pie_available_saved
+}
+
+proc check_relro_support { } {
+ global relro_available_saved
+ global ld
+
+ if {![info exists relro_available_saved]} {
+ remote_file host delete norelro
+ set ld_output [remote_exec host $ld "-z norelro"]
+ if { [string first "not supported" $ld_output] >= 0
+ || [string first "unrecognized option" $ld_output] >= 0
+ || [string first "-z norelro ignored" $ld_output] >= 0
+ || [string first "cannot find norelro" $ld_output] >= 0 } {
+ set relro_available_saved 0
+ } else {
+ set relro_available_saved 1
+ }
+ }
+ return $relro_available_saved
+}
+
+# Check for support of the .noinit section, used for data that is not
+# initialized at load, or during the application's initialization sequence.
+proc supports_noinit_section {} {
+ # .noinit is only supported by ELF targets.
+ if { ![is_elf_format] } {
+ return 0;
+ }
+
+ # Targets that set HAVE_NOINIT=yes in their emulparams script utilizing
+ # elf.sc, or explicitly define a .noinit section in their linker script.
+ #
+ # arc-*-* is not included here, since it only supports .noinit with the
+ # non-default arcv2elf emulation.
+ if {[istarget "arm-*-*"]
+ || [istarget "avr-*-*"]
+ || [istarget "msp430-*-*"]
+ || [istarget "pru-*-*"] } {
+ return 1;
+ }
+ return 0;
+}
+
+# Check for support of the .persistent section, used for data that is
+# initialized at load, but not during the application's initialization sequence.
+proc supports_persistent_section {} {
+ # .persistent is only supported by ELF targets.
+ if { ![is_elf_format] } {
+ return 0;
+ }
+
+ # Targets that set HAVE_PERSISTENT=yes in their emulparams script utilizing
+ # elf.sc, or explicitly define a .persistent section in their linker script.
+ if { [istarget "arm-*-*"]
+ || [istarget "msp430-*-*"] } {
+ return 1;
+ }
+ return 0;
+}
+
# Compare two files line-by-line. FILE_1 is the actual output and FILE_2
# is the expected output. Ignore blank lines in either file.
#
# REGEXP
# Skip all lines in FILE_1 until the first that matches REGEXP.
#
+# #?REGEXP
+# Optionally match REGEXP against line from FILE_1. If the REGEXP
+# does not match then the next line from FILE_2 is tried.
+#
# Other # lines are comments. Regexp lines starting with the `!' character
# specify inverse matching (use `\!' for literal matching against a leading
# `!'). Skip empty lines in both files.
}
}
break
+ } elseif { [string match "#\\?*" $line_b] } {
+ if { ! $end_1 } {
+ set line_b [string replace $line_b 0 1]
+ set negated [expr { [string index $line_b 0] == "!" }]
+ set line_bx [string range $line_b $negated end]
+ set n [expr { $negated ? "! " : "" }]
+ # Substitute on the reference.
+ foreach {name value} $ref_subst {
+ regsub -- $name $line_bx $value line_bx
+ }
+ verbose "optional match for $n\"^$line_bx$\"" 3
+ if { [expr [regexp "^$line_bx$" "$line_a"] != $negated] } {
+ break
+ }
+ }
}
if { [gets $file_b line_b] == $eof } {
set end_2 1
# run_dump_test FILE (optional:) EXTRA_OPTIONS
#
# Assemble a .s file, then run some utility on it and check the output.
+# Optionally generate the .s file first by running the compiler.
#
# There should be an assembly language file named FILE.s in the test
# suite directory, and a pattern file called FILE.d. run_dump_test
# ld_after_inputfiles: FLAGS
# Similar to "ld", but put FLAGS after all input files.
#
+# cc: FLAGS
+# Run the compiler with FLAGS (to which -S is added) to generate assembler
+# source first. source: must be provided and should consist of .c files.
+# Source-specific CC flags are not supported.
+#
# objcopy_objects: FLAGS
# Run objcopy with the specified flags after assembling any source
# that has the special marker RUN_OBJCOPY in the source specific
# regexps in FILE.d.
#
proc run_dump_test { name {extra_options {}} } {
- global ADDR2LINE ADDR2LINEFLAGS AS ASFLAGS ELFEDIT ELFEDITFLAGS LD LDFLAGS
- global NM NMFLAGS OBJCOPY OBJCOPYFLAGS OBJDUMP OBJDUMPFLAGS
+ global ADDR2LINE ADDR2LINEFLAGS AS ASFLAGS CC CFLAGS ELFEDIT ELFEDITFLAGS
+ global LD LDFLAGS NM NMFLAGS OBJCOPY OBJCOPYFLAGS OBJDUMP OBJDUMPFLAGS
global READELF READELFFLAGS STRIP STRIPFLAGS
- global copyfile env ld_elf_shared_opt runtests srcdir subdir verbose
+ global copyfile env runtests srcdir subdir verbose
if [string match "*/*" $name] {
set file $name
set opts(as) {}
set as_final_flags {}
set as_additional_flags {}
+ set opts(cc) {}
set opts(dump) {}
set opts(elfedit) {}
set opts(error) {}
return
}
- # Allow more substitutions, including tcl functions, for as and ld.
- # Not done in general because extra quoting is needed for glob
+ # Allow more substitutions, including tcl functions, for as, ld,
+ # and cc. Not done in general because extra quoting is needed for glob
# args used for example in binutils-all/remove-relocs-04.d.
- if { $opt_name == "as" || $opt_name == "ld" } {
+ if { $opt_name == "as" || $opt_name == "ld" || $opt_name == "cc" } {
set opt_val [subst $opt_val]
} else {
# Just substitute $srcdir and $subdir
}
}
+ # Possibly compile some of the inputs, and build up a replacement
+ # for opts(source) with the output .s names substituted in as we go.
+ # Set the .s names from the objfile_names to take advantage of the
+ # uniquification that happened earlier.
+ if { $opts(cc) != ""} {
+ set cmdret 0
+ set new_source ""
+
+ foreach cfile $opts(source) ofile $objfile_names {
+ if { [file extension $cfile] != ".c" } {
+ lappend new_source "$cfile"
+ continue
+ }
+
+ if { ! [string match "./*" $cfile] } {
+ set cfile "$srcdir/$subdir/$cfile"
+ }
+ # ofile is never absolute, so this always works to protect sfile
+ # from later absolutization.
+ set sfile "./[file rootname $ofile].s"
+ set cmd "$CC $CFLAGS -S $opts(cc) -o $sfile $cfile"
+ send_log "$cmd\n"
+ set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "dump.tmp"]
+ remote_upload host "dump.tmp"
+ set comp_output [prune_warnings [file_contents "dump.tmp"]]
+ remote_file host delete "dump.tmp"
+ remote_file build delete "dump.tmp"
+ lappend new_source "$sfile"
+ set cmdret [lindex $cmdret 0]
+
+ regsub "\n$" $comp_output "" comp_output
+ if { $cmdret != 0} {
+ send_log "compilation of $cfile failed, exit status $cmdret with <$comp_output>"
+ # Should this be 'unresolved', or is that too silent?
+ fail $testname
+ return 0
+ }
+ }
+ set opts(source) $new_source
+ }
+
if { $opts(source) == "" } {
set sourcefiles [list ${file}.s]
set asflags [list ""]
set ld_extra_opt ""
global ld
set ld "$LD"
- if { [is_elf_format] && [check_shared_lib_support] } {
- set ld_extra_opt "$ld_elf_shared_opt"
- }
+ if [check_relro_support] {
+ set ld_extra_opt "-z norelro"
+ }
# Add -L$srcdir/$subdir so that the linker command can use
# linker scripts in the source directory.
set tmp_flags " [board_info [target_info name] multilib_flags]"
foreach x $tmp_flags {
- case $x in {
- {*big*endian eb EB -eb -EB -mb -meb} {
+ switch -glob $x {
+ *big*endian -
+ eb -
+ EB -
+ -eb -
+ -EB -
+ -mb -
+ -meb {
set flags " -EB"
return $flags
}
- {*little*endian el EL -el -EL -ml -mel} {
+ *little*endian -
+ el -
+ EL -
+ -el -
+ -EL -
+ -ml -
+ -mel {
set flags " -EL"
return $flags
}