File gdb-testsuite-pie-no-pie.patch of Package gdb.11430

- Testsuite: Remove pie from trace tests
- [gdb/testsuite] Fail in gdb_compile if nopie results in PIE executable
- [gdb/testsuite] Fail in gdb_compile if pie results in non-PIE executable

---------------------------------------------------------

[gdb/testsuite] Fail in gdb_compile if pie results in non-PIE executable

When running gdb.base/break-idempotent.exp with
--target_board=unix/-fno-PIE/-no-pie, we get:
...
nr of expected passes            140
...

The test-case is compiled once with nopie and once with pie, but in both cases
we end up with a non-PIE executable.  The "-fno-PIE -no-pie" options specified
using the target_board are interpreted by dejagnu as multilib_flags, and end up
overriding the pie flags.

Fix this by checking in gdb_compile if the resulting exec is non-PIE despite of
a pie setting, and if so return an error:
...
Running gdb/testsuite/gdb.base/break-idempotent.exp ...
gdb compile failed, pie failed to generate PIE executable

                === gdb Summary ===

nr of expected passes            70
nr of untested testcases         1
...

Tested on x86_64-linux.

gdb/testsuite/ChangeLog:

2019-08-05  Tom de Vries  <tdevries@suse.de>

	* lib/gdb.exp (version_at_least): Factor out of ...
	(tcl_version_at_least): ... here.
	(gdb_compile): Fail if pie results in non-PIE executable.
	(readelf_version, readelf_prints_pie): New proc.
	(exec_is_pie): Return -1 if unknown.

---------------------------------------------------------

[gdb/testsuite] Fail in gdb_compile if nopie results in PIE executable

When running gdb.base/dump.exp with --target_board=unix/-fPIE/-pie, we get:
...
Running gdb/testsuite/gdb.base/dump.exp ...
FAIL: gdb.base/dump.exp: dump array as value, intel hex
...

The FAIL happens because although the test specifies nopie, the exec is
in fact compiled as PIE.  The "-fPIE -pie" options specified using the
target_board are interpreted by dejagnu as multilib_flags, and end up
overriding the nopie flags.

Fix this by checking in gdb_compile if the resulting exec is PIE despite of
a nopie setting, and if so return an error:
...
Running gdb/testsuite/gdb.base/dump.exp ...
gdb compile failed, nopie failed to prevent PIE executable

                === gdb Summary ===

nr of untested testcases         1
...

Tested on x86_64-linux.

gdb/testsuite/ChangeLog:

2019-07-30  Tom de Vries  <tdevries@suse.de>

	PR testsuite/24834
	* lib/gdb.exp (gdb_compile): Fail if nopie results in PIE executable.
	(exec_is_pie): New proc.

---------------------------------------------------------

Testsuite: Remove pie from trace tests

Ubuntu/Debian defaults PIE to enabled.  This causes the trace tests
to fall over due to variables being returned as "unavailable".  The
tests were never designed to work with pie.

Simply ensure the nopie flag is always used for the failing tests.

This removes 100+ failures when running native-gdbserver on Ubuntu 18.04.

gdb/testsuite/ChangeLog:

	* gdb.trace/backtrace.exp: Use nopie flag.
	* gdb.trace/circ.exp: Likewise.
	* gdb.trace/collection.exp: Likewise.
	* gdb.trace/ftrace.exp: Likewise.
	* gdb.trace/mi-trace-unavailable.exp: Likewise.
	* gdb.trace/mi-traceframe-changed.exp: Likewise.
	* gdb.trace/qtro.exp: Likewise.
	* gdb.trace/read-memory.exp: Likewise.
	* gdb.trace/report.exp: Likewise.
	* gdb.trace/tfile.exp: Likewise.
	* gdb.trace/tfind.exp: Likewise.
	* gdb.trace/unavailable.exp: Likewise.

---------------------------------------------------------

diff --git a/gdb/testsuite/gdb.trace/backtrace.exp b/gdb/testsuite/gdb.trace/backtrace.exp
index 0f60153cb5..24e097135f 100644
--- a/gdb/testsuite/gdb.trace/backtrace.exp
+++ b/gdb/testsuite/gdb.trace/backtrace.exp
@@ -27,7 +27,7 @@ if ![gdb_trace_common_supports_arch] {
 }
 
 if [prepare_for_testing "failed to prepare" $executable $srcfile \
-	[list debug nowarnings]] {
+	[list debug nowarnings nopie]] {
     return -1
 }
 
diff --git a/gdb/testsuite/gdb.trace/circ.exp b/gdb/testsuite/gdb.trace/circ.exp
index d48eca5deb..30ec9b47fc 100644
--- a/gdb/testsuite/gdb.trace/circ.exp
+++ b/gdb/testsuite/gdb.trace/circ.exp
@@ -17,7 +17,7 @@ load_lib "trace-support.exp"
 
 standard_testfile
 
-if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug nowarnings}]} {
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug nowarnings nopie}]} {
     return -1
 }
 
diff --git a/gdb/testsuite/gdb.trace/collection.exp b/gdb/testsuite/gdb.trace/collection.exp
index 8c064385ba..44eccbe865 100644
--- a/gdb/testsuite/gdb.trace/collection.exp
+++ b/gdb/testsuite/gdb.trace/collection.exp
@@ -19,7 +19,7 @@ load_lib "trace-support.exp"
 standard_testfile
 set executable $testfile
 
-if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug nowarnings}]} {
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug nowarnings nopie}]} {
     return -1
 }
 
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index f97c2c6193..702efe76bb 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -53,7 +53,7 @@ set remote_libipa [gdb_load_shlib $libipa]
 # file unused because linking not done" when building the object.
 
 if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
-	  executable [list debug $additional_flags shlib=$libipa] ] != "" } {
+	  executable [list debug nopie $additional_flags shlib=$libipa] ] != "" } {
     untested "failed to compile"
     return -1
 }
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index 5ec4bbc152..f0b3c52728 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -17,7 +17,7 @@ load_lib trace-support.exp
 
 standard_testfile trace-unavailable.c
 
-if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {debug}] } {
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {debug nopie}] } {
     return -1
 }
 
diff --git a/gdb/testsuite/gdb.trace/mi-traceframe-changed.exp b/gdb/testsuite/gdb.trace/mi-traceframe-changed.exp
index 781d3646cb..1244b5b273 100644
--- a/gdb/testsuite/gdb.trace/mi-traceframe-changed.exp
+++ b/gdb/testsuite/gdb.trace/mi-traceframe-changed.exp
@@ -32,7 +32,7 @@ if {![is_remote host] && ![is_remote target]} {
 
 if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
 	   executable \
-	   [list debug nowarnings \
+	   [list debug nowarnings nopie\
 		"additional_flags=-DTFILE_DIR=\"$tfile_dir\""]] \
 	  != "" } {
      untested "failed to compile"
diff --git a/gdb/testsuite/gdb.trace/qtro.exp b/gdb/testsuite/gdb.trace/qtro.exp
index 9eabfeb51e..d5d912b5b9 100644
--- a/gdb/testsuite/gdb.trace/qtro.exp
+++ b/gdb/testsuite/gdb.trace/qtro.exp
@@ -22,7 +22,7 @@ load_lib trace-support.exp
 
 standard_testfile
 
-if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug nopie}]} {
     return -1
 }
 clean_restart $testfile
diff --git a/gdb/testsuite/gdb.trace/read-memory.exp b/gdb/testsuite/gdb.trace/read-memory.exp
index 61fc137916..4d19f0074d 100644
--- a/gdb/testsuite/gdb.trace/read-memory.exp
+++ b/gdb/testsuite/gdb.trace/read-memory.exp
@@ -17,7 +17,7 @@ load_lib "trace-support.exp"
 
 standard_testfile
 
-if {[prepare_for_testing "failed to prepare" $testfile $srcfile debug]} {
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug nopie}]} {
     return -1
 }
 
diff --git a/gdb/testsuite/gdb.trace/report.exp b/gdb/testsuite/gdb.trace/report.exp
index f43fbb7c62..c847ab0c5b 100644
--- a/gdb/testsuite/gdb.trace/report.exp
+++ b/gdb/testsuite/gdb.trace/report.exp
@@ -27,7 +27,7 @@ if ![gdb_trace_common_supports_arch] {
     return -1
 }
 if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
-	  executable {debug nowarnings}] != "" } {
+	  executable {debug nowarnings nopie}] != "" } {
     untested "failed to compile"
     return -1
 }
diff --git a/gdb/testsuite/gdb.trace/tfile.exp b/gdb/testsuite/gdb.trace/tfile.exp
index 04f3e98e99..23f4fc58d0 100644
--- a/gdb/testsuite/gdb.trace/tfile.exp
+++ b/gdb/testsuite/gdb.trace/tfile.exp
@@ -37,7 +37,7 @@ if {![is_remote host] && ![is_remote target]} {
 standard_testfile
 if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
 	  executable \
-	  [list debug \
+	  [list debug nopie\
 	       "additional_flags=-DTFILE_DIR=\"$tfile_dir\""]] \
 	 != "" } {
     untested "failed to compile"
diff --git a/gdb/testsuite/gdb.trace/tfind.exp b/gdb/testsuite/gdb.trace/tfind.exp
index 2c9996b040..fb58f80196 100644
--- a/gdb/testsuite/gdb.trace/tfind.exp
+++ b/gdb/testsuite/gdb.trace/tfind.exp
@@ -29,7 +29,7 @@ if ![gdb_trace_common_supports_arch] {
 }
 
 if { [gdb_compile "$srcdir/$subdir/$srcfile" "$binfile" \
-	  executable {debug nowarnings}] != "" } {
+	  executable {debug nowarnings nopie}] != "" } {
     untested "failed to compile"
     return -1
 }
diff --git a/gdb/testsuite/gdb.trace/unavailable.exp b/gdb/testsuite/gdb.trace/unavailable.exp
index 23d593e7d3..f3bb54db34 100644
--- a/gdb/testsuite/gdb.trace/unavailable.exp
+++ b/gdb/testsuite/gdb.trace/unavailable.exp
@@ -19,7 +19,7 @@ standard_testfile unavailable.cc
 set executable $testfile
 
 if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
-	 {debug nowarnings c++}]} {
+	 {debug nowarnings c++ nopie}]} {
     return -1
 }
 
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 3d5f8726f7..cf7739aee3 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -3722,6 +3722,12 @@ proc gdb_compile {source dest type options} {
     regsub "\[\r\n\]*$" "$result" "" result
     regsub "^\[\r\n\]*" "$result" "" result
     
+    if { $type == "executable" && $result == "" && $nopie != -1 } {
+	if { [exec_is_pie "$dest"] } {
+	    set result "nopie failed to prevent PIE executable"
+	}
+    }
+
     if {[lsearch $options quiet] < 0} {
 	# We shall update this on a per language basis, to avoid
 	# changing the entire testsuite in one go.
@@ -5083,6 +5089,18 @@ proc rerun_to_main {} {
   }
 }
 
+# Return true if EXECUTABLE is a Position Independent Executable.
+
+proc exec_is_pie { executable } {
+    set readelf_program [gdb_find_readelf]
+    set res [catch {exec $readelf_program -d $executable \
+			| grep -E "(FLAGS_1).*Flags:.* PIE($| )" }]
+    if { $res == 0 } {
+	return 1
+    }
+    return 0
+}
+
 # Return true if a test should be skipped due to lack of floating
 # point support or GDB can't fetch the contents from floating point
 # registers.
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index cf7739aee3..896e0f1b40 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1097,6 +1097,18 @@ proc gdb_test { args } {
      }]
 }
 
+# Return 1 if version MAJOR.MINOR is at least AT_LEAST_MAJOR.AT_LEAST_MINOR.
+proc version_at_least { major minor at_least_major at_least_minor} {
+    if { $major > $at_least_major } {
+        return 1
+    } elseif { $major == $at_least_major \
+		   && $minor >= $at_least_minor } {
+        return 1
+    } else {
+        return 0
+    }
+}
+
 # gdb_test_no_output COMMAND MESSAGE
 # Send a command to GDB and verify that this command generated no output.
 #
@@ -3722,9 +3734,13 @@ proc gdb_compile {source dest type options} {
     regsub "\[\r\n\]*$" "$result" "" result
     regsub "^\[\r\n\]*" "$result" "" result
     
-    if { $type == "executable" && $result == "" && $nopie != -1 } {
-	if { [exec_is_pie "$dest"] } {
+    if { $type == "executable" && $result == "" \
+	     && ($nopie != -1 || $pie != -1) } {
+	set is_pie [exec_is_pie "$dest"]
+	if { $nopie != -1 && $is_pie == 1 } {
 	    set result "nopie failed to prevent PIE executable"
+	} elseif { $pie != -1 && $is_pie == 0 } {
+	    set result "pie failed to generate PIE executable"
 	}
     }
 
@@ -5089,13 +5105,53 @@ proc rerun_to_main {} {
   }
 }
 
-# Return true if EXECUTABLE is a Position Independent Executable.
+# Return list with major and minor version of readelf, or an empty list.
+gdb_caching_proc readelf_version {
+    set readelf_program [gdb_find_readelf]
+    set res [catch {exec $readelf_program --version} output]
+    if { $res != 0 } {
+	return [list]
+    }
+    set lines [split $output \n]
+    set line [lindex $lines 0]
+    set res [regexp {[ \t]+([0-9]+)[.]([0-9]+)[^ \t]*$} \
+		 $line dummy major minor]
+    if { $res != 1 } {
+	return [list]
+    }
+    return [list $major $minor]
+}
+
+# Return 1 if readelf prints the PIE flag, 0 if is doesn't, and -1 if unknown.
+proc readelf_prints_pie { } {
+    set version [readelf_version]
+    if { [llength $version] == 0 } {
+	return -1
+    }
+    set major [lindex $version 0]
+    set minor [lindex $version 1]
+    # It would be better to construct a PIE executable and test if the PIE
+    # flag is printed by readelf, but we cannot reliably construct a PIE
+    # executable if the multilib_flags dictate otherwise
+    # (--target_board=unix/-no-pie/-fno-PIE).
+    return [version_at_least $major $minor 2 26]
+}
+
+# Return 1 if EXECUTABLE is a Position Independent Executable, 0 if it is not,
+# and -1 if unknown.
 
 proc exec_is_pie { executable } {
+    set res [readelf_prints_pie]
+    if { $res != 1 } {
+	return -1
+    }
     set readelf_program [gdb_find_readelf]
-    set res [catch {exec $readelf_program -d $executable \
-			| grep -E "(FLAGS_1).*Flags:.* PIE($| )" }]
-    if { $res == 0 } {
+    set res [catch {exec $readelf_program -d $executable} output]
+    if { $res != 0 } {
+	return -1
+    }
+    set res [regexp -line {\(FLAGS_1\).*Flags:.* PIE($| )} $output]
+    if { $res == 1 } {
 	return 1
     }
     return 0