--- old/usr/src/cmd/savecore/savecore.c	Fri May  3 08:03:58 2019
+++ new/usr/src/cmd/savecore/savecore.c	Fri May  3 08:03:58 2019
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
  */
 /*
  * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
@@ -92,6 +92,7 @@
 static long	coreblksize;		/* preferred write size (st_blksize) */
 static int	cflag;			/* run as savecore -c */
 static int	mflag;			/* run as savecore -m */
+static int	rflag;			/* run as savecore -r */
 
 /*
  * Payload information for the events we raise.  These are used
@@ -164,7 +165,7 @@
 usage(void)
 {
 	(void) fprintf(stderr,
-	    "usage: %s [-Lvd] [-f dumpfile] [dirname]\n", progname);
+	    "usage: %s [-L | -r] [-vd] [-f dumpfile] [dirname]\n", progname);
 	exit(1);
 }
 
@@ -229,7 +230,7 @@
 		 * raise if run as savecore -m.  If something in the
 		 * raise_event codepath calls logprint avoid recursion.
 		 */
-		if (!mflag && logprint_raised++ == 0)
+		if (!mflag && !rflag && logprint_raised++ == 0)
 			raise_event(SC_EVENT_SAVECORE_FAILURE, buf);
 		code = 2;
 		break;
@@ -240,7 +241,7 @@
 
 	case SC_EXIT_ERR:
 	default:
-		if (!mflag && logprint_raised++ == 0 && have_dumpfile)
+		if (!mflag && !rflag && logprint_raised++ == 0 && have_dumpfile)
 			raise_event(SC_EVENT_SAVECORE_FAILURE, buf);
 		code = 1;
 		break;
@@ -355,7 +356,7 @@
 static void
 read_dumphdr(void)
 {
-	if (filemode)
+	if (filemode || rflag)
 		dumpfd = Open(dumpfile, O_RDONLY, 0644);
 	else
 		dumpfd = Open(dumpfile, O_RDWR | O_DSYNC, 0644);
@@ -408,7 +409,7 @@
 		/*
 		 * Clear valid bit so we don't complain on every invocation.
 		 */
-		if (!filemode)
+		if (!filemode && !rflag)
 			Pwrite(dumpfd, &dumphdr, sizeof (dumphdr), endoff);
 		logprint(SC_SL_ERR | SC_EXIT_ERR,
 		    "initial dump header corrupt");
@@ -660,7 +661,7 @@
 	 * Write out the modified dump header to the dump device.
 	 * The dump device has been processed, so DF_VALID is clear.
 	 */
-	if (!filemode)
+	if (!filemode && !rflag)
 		Pwrite(dumpfd, &dumphdr, sizeof (dumphdr), endoff);
 
 	(void) close(corefd);
@@ -1422,7 +1423,7 @@
 	 * Write out the modified dump headers.
 	 */
 	Pwrite(corefd, &corehdr, sizeof (corehdr), 0);
-	if (!filemode)
+	if (!filemode && !rflag)
 		Pwrite(dumpfd, &dumphdr, sizeof (dumphdr), endoff);
 
 	(void) close(corefd);
@@ -1531,7 +1532,10 @@
 	    DUMP_ERPTSIZE);
 	dumpoff -= DUMP_SUMMARYSIZE;
 
-	dumpfd = Open(dumpfile, O_RDWR | O_DSYNC, 0644);
+	if (rflag)
+		dumpfd = Open(dumpfile, O_RDONLY, 0644);
+	else
+		dumpfd = Open(dumpfile, O_RDWR | O_DSYNC, 0644);
 	dumpoff = llseek(dumpfd, dumpoff, SEEK_END) & -DUMP_OFFSET;
 
 	Pread(dumpfd, &sd, sizeof (summary_dump_t), dumpoff);
@@ -1668,7 +1672,7 @@
 	if (savedir != NULL)
 		savedir = strdup(savedir);
 
-	while ((c = getopt(argc, argv, "Lvcdmf:")) != EOF) {
+	while ((c = getopt(argc, argv, "Lvcdmf:r")) != EOF) {
 		switch (c) {
 		case 'L':
 			livedump++;
@@ -1685,6 +1689,9 @@
 		case 'm':
 			mflag++;
 			break;
+		case 'r':
+			rflag++;
+			break;
 		case 'f':
 			dumpfile = optarg;
 			filebounds = getbounds(dumpfile);
@@ -1709,6 +1716,9 @@
 	if (cflag && livedump)
 		usage();
 
+	if (rflag && (cflag || mflag || livedump))
+		usage();
+
 	if (dumpfile == NULL || livedump)
 		dumpfd = Open("/dev/dump", O_RDONLY, 0444);
 
@@ -1752,7 +1762,7 @@
 	 * We could extend it to handle this, but there doesn't seem to be
 	 * a general need for it, so we isolate the complexity here instead.
 	 */
-	if (dumphdr.dump_panicstring[0] != '\0') {
+	if (dumphdr.dump_panicstring[0] != '\0' && !rflag) {
 		int logfd = Open("/dev/conslog", O_WRONLY, 0644);
 		log_ctl_t lc;
 		struct strbuf ctl, dat;
@@ -1801,7 +1811,7 @@
 	 * for the same event.  Also avoid raising an event for a
 	 * livedump, or when we inflating a compressed dump.
 	 */
-	if (!fm_panic && !livedump && !filemode)
+	if (!fm_panic && !livedump && !filemode && !rflag)
 		raise_event(SC_EVENT_DUMP_PENDING, NULL);
 
 	logprint(SC_SL_WARN, "System dump time: %s",
@@ -1857,7 +1867,7 @@
 		 * has panicked. We know a reasonable amount about the
 		 * condition at this time, but the dump is still compressed.
 		 */
-		if (!livedump && !fm_panic)
+		if (!livedump && !fm_panic && !rflag)
 			raise_event(SC_EVENT_DUMP_AVAILABLE, NULL);
 
 		if (metrics_size > 0) {
@@ -1926,7 +1936,7 @@
 
 		build_corefile(namelist, corefile);
 
-		if (!livedump && !filemode && !fm_panic)
+		if (!livedump && !filemode && !fm_panic && !rflag)
 			raise_event(SC_EVENT_DUMP_AVAILABLE, NULL);
 
 		if (access(METRICSFILE, F_OK) == 0) {
--- old/usr/src/man/man1m/savecore.1m	Fri May  3 08:03:58 2019
+++ new/usr/src/man/man1m/savecore.1m	Fri May  3 08:03:58 2019
@@ -2,17 +2,17 @@
 .\" Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved.
 .\" Copyright (c) 1983 Regents of the University of California. All rights reserved. The Berkeley software License Agreement specifies the terms and conditions for redistribution.
 .\" Copyright 2013 Nexenta Systems, Inc.  All Rights Reserved.
-.TH SAVECORE 1M "Jan 30, 2013"
+.\" Copyright 2019 Joyent, Inc.
+.TH SAVECORE 1M "February 22, 2019"
 .SH NAME
 savecore \- save a crash dump of the operating system
 .SH SYNOPSIS
 .LP
 .nf
-\fB/usr/bin/savecore\fR [\fB-Lvd\fR] [\fB-f\fR \fIdumpfile\fR] [\fIdirectory\fR]
+\fB/usr/bin/savecore\fR [\fB-L\fR | \fB-r\fR] [\fB-vd\fR] [\fB-f\fR \fIdumpfile\fR] [\fIdirectory\fR]
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBsavecore\fR utility saves a crash dump of the kernel (assuming that one
 was made) and writes a reboot message in the shutdown log. By default, it is
@@ -42,7 +42,6 @@
 \fBLOG_AUTH\fR (see \fBsyslog\fR(3C)). If the system crashed as a result of a
 panic, \fBsavecore\fR logs the panic string too.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -90,6 +89,18 @@
 .sp
 .ne 2
 .na
+\fB\fB-r\fR\fR
+.ad
+.RS 15n
+Open the dump device or file as read-only, and don't update the dump header
+or do anything else that might modify the crash dump. This option can be used
+to recover a crash dump from a read-only device. This flag cannot be used in
+conjunction with \fB\fB-L\fR\fR.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-v\fR\fR
 .ad
 .RS 15n
@@ -97,7 +108,6 @@
 .RE
 
 .SH OPERANDS
-.sp
 .LP
 The following operands are supported:
 .sp
@@ -112,7 +122,6 @@
 .RE
 
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fIdirectory\fR\fB/vmdump.\fR\fIn\fR\fR
@@ -167,12 +176,10 @@
 .RE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBadb\fR(1), \fBmdb\fR(1), \fBsvcs\fR(1), \fBdd\fR(1M), \fBdumpadm\fR(1M),
 \fBsvcadm\fR(1M), \fBsyslog\fR(3C), \fBattributes\fR(5), \fBsmf\fR(5)
 .SH NOTES
-.sp
 .LP
 The system crash dump service is managed by the service management facility,
 \fBsmf\fR(5), under the service identifier:
