cmd/link/internal/ld: revised bindnow/relro test for ELF

This patch re-enables the portion of the TestElfBindNow test that
verifies that selected sections are in a read-only segment. Turns out
we can't always check for read-only ".got" on all architectures (on
ppc64le for example ".got" will only turn up if there is CGO use), so
always look for readonly ".dynamic", but only look for readonly ".got"
if the section is present.

Updates #45681.

Change-Id: I4687ae3cf9a81818268925e17700170ba34204a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/581115
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/src/cmd/link/internal/ld/elf_test.go b/src/cmd/link/internal/ld/elf_test.go
index ad4149d..46af762 100644
--- a/src/cmd/link/internal/ld/elf_test.go
+++ b/src/cmd/link/internal/ld/elf_test.go
@@ -194,11 +194,19 @@
 		progC = `package main; import "C"; func main() {}`
 	)
 
+	// Note: for linux/amd64 and linux/arm64, for relro we'll always see
+	// a .got section when building with -buildmode=pie (in addition
+	// to .dynamic); for some other less mainstream archs (ppc64le,
+	// s390) this is not the case (on ppc64le for example we only see
+	// got refs from C objects). Hence we put ".dynamic" in the 'want RO'
+	// list below and ".got" in the 'want RO if present".
+
 	tests := []struct {
 		name                 string
 		args                 []string
 		prog                 string
 		wantSecsRO           []string
+		wantSecsROIfPresent  []string
 		mustHaveBuildModePIE bool
 		mustHaveCGO          bool
 		mustInternalLink     bool
@@ -214,7 +222,8 @@
 			mustHaveBuildModePIE: true,
 			mustInternalLink:     true,
 			wantDf1Pie:           true,
-			wantSecsRO:           []string{".dynamic", ".got"},
+			wantSecsRO:           []string{".dynamic"},
+			wantSecsROIfPresent:  []string{".got"},
 		},
 		{
 			name:             "bindnow-linkmode-internal",
@@ -234,7 +243,8 @@
 			wantDfBindNow:        true,
 			wantDf1Now:           true,
 			wantDf1Pie:           true,
-			wantSecsRO:           []string{".dynamic", ".got", ".got.plt"},
+			wantSecsRO:           []string{".dynamic"},
+			wantSecsROIfPresent:  []string{".got", ".got.plt"},
 		},
 		{
 			name:                 "bindnow-pie-linkmode-external",
@@ -245,8 +255,9 @@
 			wantDfBindNow:        true,
 			wantDf1Now:           true,
 			wantDf1Pie:           true,
+			wantSecsRO:           []string{".dynamic"},
 			// NB: external linker produces .plt.got, not .got.plt
-			wantSecsRO: []string{".dynamic", ".got"},
+			wantSecsROIfPresent: []string{".got", ".got.plt"},
 		},
 	}
 
@@ -339,10 +350,9 @@
 				t.Fatalf("DT_FLAGS_1 DF_1_PIE got: %v, want: %v", gotDf1Pie, test.wantDf1Pie)
 			}
 
-			// Skipping this newer portion of the test temporarily pending resolution of problems on ppc64le, loonpg64, possibly others.
-			if false {
-
-				for _, wsroname := range test.wantSecsRO {
+			wsrolists := [][]string{test.wantSecsRO, test.wantSecsROIfPresent}
+			for k, wsrolist := range wsrolists {
+				for _, wsroname := range wsrolist {
 					// Locate section of interest.
 					var wsro *elf.Section
 					for _, s := range elfFile.Sections {
@@ -352,8 +362,11 @@
 						}
 					}
 					if wsro == nil {
-						t.Fatalf("test %s: can't locate %q section",
-							test.name, wsroname)
+						if k == 0 {
+							t.Fatalf("test %s: can't locate %q section",
+								test.name, wsroname)
+						}
+						continue
 					}
 
 					// Now walk the program headers. Section should be part of