git: 32bfffcb9adf - stable/13 - gcore: add option to dump core using kernel facility

Konstantin Belousov kib at FreeBSD.org
Mon May 10 01:14:59 UTC 2021


The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=32bfffcb9adfe146f0e852d997717fd3982eda36

commit 32bfffcb9adfe146f0e852d997717fd3982eda36
Author:     Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-04-24 11:20:24 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-05-10 01:03:19 +0000

    gcore: add option to dump core using kernel facility
    
    (cherry picked from commit 73e8f06ac523ee4b530e17d50cc580dc366f7ad8)
---
 usr.bin/gcore/gcore.1 | 16 +++++++++--
 usr.bin/gcore/gcore.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 80 insertions(+), 11 deletions(-)

diff --git a/usr.bin/gcore/gcore.1 b/usr.bin/gcore/gcore.1
index 55db2aed3e3a..aa93a5ef1fe0 100644
--- a/usr.bin/gcore/gcore.1
+++ b/usr.bin/gcore/gcore.1
@@ -28,7 +28,7 @@
 .\"	@(#)gcore.1	8.2 (Berkeley) 4/18/94
 .\" $FreeBSD$
 .\"
-.Dd July 13, 2016
+.Dd April 24, 2021
 .Dt GCORE 1
 .Os
 .Sh NAME
@@ -37,6 +37,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl f
+.Op Fl k
 .Op Fl c Ar core
 .Op Ar executable
 .Ar pid
@@ -58,13 +59,24 @@ The following options are available:
 Write the core file to the specified file instead of
 .Dq Pa core.<pid> .
 .It Fl f
-Dumps all available segments, excluding only malformed and undumpable segments.
+Dumps all available segments, excluding only malformed and undumpable
+segments.
 Unlike the default invocation, this flag dumps mappings of devices which
 may invalidate the state of device transactions or trigger other unexpected
 behavior.
 As a result, this flag should only be used when the behavior of the
 application and any devices it has mapped is fully understood and any side
 effects can be controlled or tolerated.
+.It Fl k
+Use the
+.Xr ptrace 2
+.Dv PT_COREDUMP
+kernel facility to write the core dump, instead of reading the process'
+memory and constructing the dump file in
+.Nm
+itself.
+This is faster, and the dump is written by the
+same kernel code that writes core dumps upon fatal signals.
 .El
 .Sh FILES
 .Bl -tag -width /var/log/messages -compact
diff --git a/usr.bin/gcore/gcore.c b/usr.bin/gcore/gcore.c
index cbbfea82085b..8055193625f9 100644
--- a/usr.bin/gcore/gcore.c
+++ b/usr.bin/gcore/gcore.c
@@ -56,13 +56,16 @@ __FBSDID("$FreeBSD$");
  */
 
 #include <sys/param.h>
+#include <sys/ptrace.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/linker_set.h>
 #include <sys/sysctl.h>
+#include <sys/wait.h>
 
 #include <err.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -75,6 +78,7 @@ static void	killed(int);
 static void	usage(void) __dead2;
 
 static pid_t pid;
+static bool kflag = false;
 
 SET_DECLARE(dumpset, struct dumpers);
 
@@ -82,6 +86,7 @@ static int
 open_corefile(char *corefile)
 {
 	char fname[MAXPATHLEN];
+	int fd;
 
 	if (corefile == NULL) {
 		(void)snprintf(fname, sizeof(fname), "core.%d", pid);
@@ -93,6 +98,45 @@ open_corefile(char *corefile)
 	return (fd);
 }
 
+static void
+kcoredump(int fd, pid_t pid)
+{
+	struct ptrace_coredump pc;
+	int error, res, ret, waited;
+
+	error = ptrace(PT_ATTACH, pid, NULL, 0);
+	if (error != 0)
+		err(1, "attach");
+
+	waited = waitpid(pid, &res, 0);
+	if (waited == -1)
+		err(1, "wait for STOP");
+
+	ret = 0;
+	memset(&pc, 0, sizeof(pc));
+	pc.pc_fd = fd;
+	pc.pc_flags = (pflags & PFLAGS_FULL) != 0 ? PC_ALL : 0;
+	error = ptrace(PT_COREDUMP, pid, (void *)&pc, sizeof(pc));
+	if (error == -1) {
+		warn("coredump");
+		ret = 1;
+	}
+
+	waited = waitpid(pid, &res, WNOHANG);
+	if (waited == -1) {
+		warn("wait after coredump");
+		ret = 1;
+	}
+
+	error = ptrace(PT_DETACH, pid, NULL, 0);
+	if (error == -1) {
+		warn("detach failed, check process status");
+		ret = 1;
+	}
+
+	exit(ret);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -104,7 +148,7 @@ main(int argc, char *argv[])
 
 	pflags = 0;
 	corefile = NULL;
-        while ((ch = getopt(argc, argv, "c:f")) != -1) {
+        while ((ch = getopt(argc, argv, "c:fk")) != -1) {
                 switch (ch) {
                 case 'c':
 			corefile = optarg;
@@ -112,6 +156,9 @@ main(int argc, char *argv[])
 		case 'f':
 			pflags |= PFLAGS_FULL;
 			break;
+		case 'k':
+			kflag = true;
+			break;
 		default:
 			usage();
 			break;
@@ -119,10 +166,26 @@ main(int argc, char *argv[])
 	}
 	argv += optind;
 	argc -= optind;
+
 	/* XXX we should check that the pid argument is really a number */
 	switch (argc) {
 	case 1:
 		pid = atoi(argv[0]);
+		break;
+	case 2:
+		binfile = argv[0];
+		pid = atoi(argv[1]);
+		break;
+	default:
+		usage();
+	}
+
+	if (kflag) {
+		fd = open_corefile(corefile);
+		kcoredump(fd, pid);
+	}
+
+	if (argc == 1) {
 		name[0] = CTL_KERN;
 		name[1] = KERN_PROC;
 		name[2] = KERN_PROC_PATHNAME;
@@ -131,13 +194,6 @@ main(int argc, char *argv[])
 		if (sysctl(name, 4, passpath, &len, NULL, 0) == -1)
 			errx(1, "kern.proc.pathname failure");
 		binfile = passpath;
-		break;
-	case 2:
-		pid = atoi(argv[1]);
-		binfile = argv[0];
-		break;
-	default:
-		usage();
 	}
 	efd = open(binfile, O_RDONLY, 0);
 	if (efd < 0)
@@ -165,6 +221,7 @@ void
 usage(void)
 {
 
-	(void)fprintf(stderr, "usage: gcore [-c core] [executable] pid\n");
+	(void)fprintf(stderr,
+	    "usage: gcore [-kf] [-c core] [executable] pid\n");
 	exit(1);
 }


More information about the dev-commits-src-all mailing list