cmd/link: make .dynamic section read-only for MIPS ELF

For #36435

Change-Id: Ie733b641f20ca5bcee3784c088eb27699890a151
Reviewed-on: https://go-review.googlesource.com/c/go/+/463982
Reviewed-by: Joel Sing <joel@sing.id.au>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 738bea1..2c6ea64 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -209,6 +209,11 @@
 	Elfreloc1    func(*Link, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int, int64) bool
 	ElfrelocSize uint32 // size of an ELF relocation record, must match Elfreloc1.
 	Elfsetupplt  func(ctxt *Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym)
+
+	// DynamicReadOnly can be set to true to make the .dynamic
+	// section read-only. By default it is writable.
+	// This is used by MIPS targets.
+	DynamicReadOnly bool
 }
 
 type Elfstring struct {
@@ -1563,7 +1568,11 @@
 
 		/* define dynamic elf table */
 		dynamic := ldr.CreateSymForUpdate(".dynamic", 0)
-		dynamic.SetType(sym.SELFSECT) // writable
+		if thearch.ELF.DynamicReadOnly {
+			dynamic.SetType(sym.SELFROSECT)
+		} else {
+			dynamic.SetType(sym.SELFSECT)
+		}
 
 		if ctxt.IsS390X() {
 			// S390X uses .got instead of .got.plt
diff --git a/src/cmd/link/internal/mips/obj.go b/src/cmd/link/internal/mips/obj.go
index 709c493..61c22d9 100644
--- a/src/cmd/link/internal/mips/obj.go
+++ b/src/cmd/link/internal/mips/obj.go
@@ -72,6 +72,10 @@
 			Elfreloc1:    elfreloc1,
 			ElfrelocSize: 8,
 			Elfsetupplt:  elfsetupplt,
+
+			// Historically GNU ld creates a read-only
+			// .dynamic section.
+			DynamicReadOnly: true,
 		},
 	}
 
diff --git a/src/cmd/link/internal/mips64/obj.go b/src/cmd/link/internal/mips64/obj.go
index 986cd07..ce4494c 100644
--- a/src/cmd/link/internal/mips64/obj.go
+++ b/src/cmd/link/internal/mips64/obj.go
@@ -70,6 +70,10 @@
 			Elfreloc1:    elfreloc1,
 			ElfrelocSize: 24,
 			Elfsetupplt:  elfsetupplt,
+
+			// Historically GNU ld creates a read-only
+			// .dynamic section.
+			DynamicReadOnly: true,
 		},
 	}