Index: src/cmd/link/internal/ld/elf.go
--- src/cmd/link/internal/ld/elf.go.orig
+++ src/cmd/link/internal/ld/elf.go
@@ -1475,11 +1475,20 @@ func (ctxt *Link) doelf() {
 		dynamic := ldr.CreateSymForUpdate(".dynamic", 0)
 		dynamic.SetType(sym.SELFSECT) // writable
 
+		// In the absence of a DT_MIPS_RLD_MAP entry, the openbsd/mips64
+		// dynamic loader marks the pages surrounding the DT_DEBUG entry
+		// as writeable, updates it, then marks the pages as read only.
+		// This leads to bad things happening if .dynamic is in a
+		// writeable section.
+		if ctxt.IsMIPS64() && ctxt.HeadType == objabi.Hopenbsd {
+			dynamic.SetType(sym.SELFROSECT)
+		}
+
 		if ctxt.IsS390X() {
 			// S390X uses .got instead of .got.plt
 			gotplt = got
 		}
-		thearch.Elfsetupplt(ctxt, plt, gotplt, dynamic.Sym())
+		thearch.Elfsetupplt(ctxt, ctxt.loader, plt, gotplt, dynamic.Sym())
 
 		/*
 		 * .dynamic table
@@ -1524,6 +1533,7 @@ func (ctxt *Link) doelf() {
 		// DT_JMPREL is emitted so we have to defer generation of elf.DT_PLTREL,
 		// DT_PLTRELSZ, and elf.DT_JMPREL dynamic entries until after we know the
 		// size of .rel(a).plt section.
+
 		Elfwritedynent(ctxt.Arch, dynamic, elf.DT_DEBUG, 0)
 	}
 
